% ==== 1. ====
% The section prologue.  Give the section a title and provide some
% meta-information.  References to the module should use
% \refbimodindex, \refstmodindex, \refexmodindex or \refmodindex, as
% appropriate.

\section{\module{FixedPoint} ---
         Fixed decimal object with settable precision and user definable rounding}

\declaremodule{standard}{FixedPoint}		% standard library, in Python

% Portability statement:  Uncomment and fill in the parameter to specify the
% availability of the module.  The parameter can be Unix, IRIX, SunOS, Mac,
% Windows, or lots of other stuff.  When ``Mac'' is specified, the availability
% statement will say ``Macintosh'' and the Module Index may say ``Mac''.
% Please use a name that has already been used whenever applicable.  If this
% is omitted, no availability statement is produced or implied.
%
%   \platform{Unix}

% These apply to all modules, and may be given more than once:

\moduleauthor{Tim Peters}{tim.one@comcast.net}	% Author of the module code;
\moduleauthor{Doug Fort}{dougfort@dougfort.net}	% Author of the module code;

\sectionauthor{Joe Griffin}{joeg@downright.com}		% Author of the documentation,
							% even if not a module section.

% Documentation strongly based on documentation strings left in code by Tim Peters.

% Leave at least one blank line after this, to simplify ad-hoc tools
% that are sometimes used to massage these files.
\modulesynopsis{FixedPoint objects provide support for fixed decimal arithmetic}


% ==== 2. ====
% Give a short overview of what the module does.
% If it is platform specific, mention this.
% Mention other important restrictions or general operating principles.
The \module{fixedpoint} module defines the \class{FixedPoint} class which provides a fixed decimal data type that supports python operators and standard functions. \class{FixedPoint} objects are useful when computing financial transactions where precision is critical.

\begin{classdesc} {FixedPoint}{\optional{value=0\optional{, precision=DEFAULT_PRECISION}}}
A \class{Fixedpoint} instance is a fixed decimal data type with support for the standard python operators and functions.

\class{FixedPoint} objects support decimal arithmetic with a fixed number of
digits (called the object's precision) after the decimal point.  The
number of digits before the decimal point is variable and unbounded.
 
The precision is user-settable on a per-object basis when a \class{FixedPoint}
is constructed, and may vary across \class{FixedPoint} objects.  The precision
may also be changed after construction via \class{FixedPoint}\code{.set_precision(\var{p})}.
Note that if the precision of a \class{FixedPoint} object is reduced via \code{.set_precision},
information may be lost to rounding.

The \class{FixedPoint} constructor can be passed an \code{int, long, string, float,
FixedPoint}, or any object convertible to a \code{float} via \code{float()} or to a
\code{long} via \code{long()}.  Passing a precision is optional; if specified, the
precision must be a non-negative \code{int}.  There is no inherent limit on
the size of the precision, but if very very large you'll probably run
out of memory.

 
The following Python operators and functions accept \class{FixedPoint}s in the
expected ways:

\hspace{8em}
\begin{tabular}{p{.5in}p{2.5in}p{6in}}
    & \code{+ - * / \% divmod()}& with auto-coercion of other types to \class{FixedPoint}.\\
    & \code{+ - \% divmod()}& of \class{FixedPoints} are always exact.\\
    & \code{* /}& of \class{FixedPoints} may lose information to rounding, in which case the result is the infinitely precise answer rounded to the result's precision.\\
    & unary \code{-}\\
    & \code{== != < > <= >=  cmp}\\
    & \code{min()  max()}\\
    & \code{float()  int()  long()} & \code{int} and \code{long} truncate\\
    & \code{abs()}\\
    & \code{str()  repr()}\\
    &\code{hash()}\\
    & use as dict keys\\
    & \multicolumn{2}{l}{use as boolean (e.g. "\code{if some_FixedPoint:}" -- true iff not zero)}\\
    & \multicolumn{2}{l}{\code{divmod(\var{x},\var{ y})} returns \code{(\var{q},\var{r})} where \var{q} is a \code{long} equal to \code{floor(\var{x}/\var{y})} as if x/y were computed to infinite precision, and \var{r} is a \class{FixedPoint} equal to \code{\var{x} - \var{q} * \var{y}}; no information is lost.  Note that \var{q} has the sign of \var{y}, and \code{abs(\var{r}) < abs(\var{y})}.}\\
\end{tabular}

\end{classdesc}

When \class{FixedPoint} objects of different precision are combined via \code{+ - * /},
the result is computed to the larger of the inputs' precisions, which also
becomes the precision of the resulting \class{FixedPoint} object.

\begin{verbatim} 
>>> print FixedPoint("3.42") + FixedPoint("100.005", 3)
103.425
>>>
\end{verbatim}

When a \class{FixedPoint} is combined with other numeric types (\code{ints}, \code{floats},
strings representing a number) via \code{+ - * /}, then similarly the computation
is carried out using-- and the result inherits --the \class{FixedPoint}'s
precision.

\begin{verbatim}  
>>> print FixedPoint(1) / 7
0.14
>>> print FixedPoint(1, 30) / 7
0.142857142857142857142857142857
>>>
\end{verbatim}

The string produced by \code{str(\var{x})} (implicitly invoked by "\code{print}") always
contains at least one digit before the decimal point, followed by a
decimal point, followed by exactly \code{x.get_precision()} digits.  If \var{x} is
negative, \code{str(\var{x})[0] == "-"}.
 
Note that conversion of \code{floats} to \class{FixedPoint} can be surprising, and
should be avoided whenever possible.  Conversion from string is exact
(up to final rounding to the requested precision), so is greatly
preferred.
 
\begin{verbatim} 
>>> print FixedPoint(1.1e30)
1099999999999999993725589651456.00
>>> print FixedPoint("1.1e30")
1100000000000000000000000000000.00
>>>
\end{verbatim} 


\class{FixedPoint} objects have the following public methods:

\begin{methoddesc}[FixedPoint]{copy}{}
Return a copy of this \class{FixedPoint} object.
\end{methoddesc}

\begin{methoddesc}[FixedPoint]{frac}{}
Return fractional part of this \class{FixedPoint} object. (\code{x.frac() + long(x)} == \code{x})
\end{methoddesc}

\begin{methoddesc}[FixedPoint]{get_precision}{}
Return the precision of this \class{FixedPoint} object. The precision is the number of decimal digits carried after the decimal point, and is an int >= 0.
\end{methoddesc}

\begin{methoddesc}[FixedPoint]{set_precision}{\optional{precision=DEFAULT_PRECISION}}
Change the precision carried by this FixedPoint to \var{precision}. \var{precision} must be an \code{int} >= 0, and defaults to \code{DEFAULT_PRECISION}. If \var{precision} is less than this \class{FixedPoint}'s current precision, information may be lost to rounding.
\end{methoddesc}

The \module{fixedpoint} module also defines the following (private) functions:

\begin{funcdesc}{_mkFP}{n,p}
Make a \class{FixedPoint} object - Return a new \class{FixedPoint} with the indicated value \var{n} and precision \var{p}.
\end{funcdesc}

\begin{funcdesc}{_norm}{x,y}
Return \var{xn}, \var{yn}, \var{p} such that:
\begin{tabular}{l}
\hspace{16em}\var{p} = max(\var{x.p},\var{ y.p})\\
\hspace{16em}\var{x} = \var{xn} / 10**\var{p}\\
\hspace{16em}\var{y} = \var{yn} / 10**\var{p}\\
\end{tabular}
    
\var{x} must be \class{FixedPoint} to begin with; if \var{y} is not \class{FixedPoint},it inherits its precision from \var{x}.

Note that this method is called a lot, so default-arg tricks are helpful.
\end{funcdesc}

\begin{funcdesc}{_roundquotient}{x,y}
Divide \var{x} by \var{y}, rounding to int via nearest-even. \var{y} must be > 0.
\end{funcdesc}

\begin{funcdesc}{_string2exact}{s}
Return \var{n}, \var{p} such that \code{float string value == n * 10**p} exactly.
\end{funcdesc}

\begin{funcdesc}{_tento}{n\optional{,cache=[]}}
Cached computation of 10**n.
\end{funcdesc}

\begin{funcdesc}{_test}{}
Interface to unit testing framework. Invoked automatically if module run standalone.
\end{funcdesc}

The \module{fixedpoint} module exports the following data item(s):

\begin{datadesc}{DEFAULT_PRECISION}
The default \class{FixedPoint} precision size, in places to the right of the decimal point. The default is initially set to 2. Usually only interesting at compile time to set the constructor's default precision.
\end{datadesc}

% ---- 3.4. ----
% Other standard environments:
%
%  classdesc	- Python classes; same arguments are funcdesc
%  methoddesc	- methods, like funcdesc but has an optional parameter 
%		  to give the type name: \begin{methoddesc}[mytype]{name}{args}
%		  By default, the type name will be the name of the
%		  last class defined using classdesc.  The type name
%		  is required if the type is implemented in C (because 
%		  there's no classdesc) or if the class isn't directly 
%		  documented (if it's private).
%  memberdesc	- data members, like datadesc, but with an optional
%		  type name like methoddesc.

\subsection{FixedPoint Rounding\label{fixedpoint-rounding}}
The rounding algorithm used by \class{FixedPoint} when coercing floating point values to \class{FixedPoint} values can be set or re-defined by the developer to meet the requirements of the application. By default, \class{FixedPoint} objects use a type of rounding typically referred to as "Banker's Rounding" which is useful in financial applications. The available rounding algorithms include:
\begin{funcdesc}{bankersRounding}{dividend, divisor, quotient, remainder}
The default rounding algorithn, bankersRounding, rounds the last digit of precision up when a) the remainder is greater than 1/2 the divisor or b) the remainder is equal to 1/2 the divisor and the last digit to be kept is odd. This algorithm smoothly allocates possible rounding errors over the universe of possible results. 
\end{funcdesc}

\begin{funcdesc}{addHalfAndChop}{dividend, divisor, quotient, remainder}
This rounding algorithm ALWAYS rounds "up" when the remainder is greater than or equal to 1/2 the divisor. In this case, round "up" means that the absolute value of the quotient will increase when rounded. This implementation of rounding is sometimes referred to as "add half and chop."
\end{funcdesc}

To change the rounding algorithm used by the \class{FixedPoint} class, set the value of the class method \code{FixedPoint.round}; e.g.,
\begin{verbatim} 
>>>
>>> from fixedpoint import FixedPoint, addHalfAndChop
>>>
>>> # Demonstrate the default rounding
...  
>>> print FixedPoint("1.555")
1.56
>>> print FixedPoint("1.565")
1.56
>>> print FixedPoint("1.575")
1.58
>>> # Use a "round up" algorithm
... FixedPoint.round = addHalfAndChop
>>> 
>>> print FixedPoint("1.555")
1.56
>>> print FixedPoint("1.565")
1.57
>>> print FixedPoint("1.575")
1.58
>>> print FixedPoint("-1.555")
-1.56
>>> print FixedPoint("-1.565")
-1.57
>>> print FixedPoint("-1.575")
-1.58
>>> 
\end{verbatim} 

Developers may customize the \class{FixedPoint} rounding algorithm by defining a \code{newRoundingAlgorithm} function as follows: 

\begin{funcdesc}{newRoundingAlgorithm}{dividend, divisor, quotient, remainder}
The arguments to the rounding algorithm are all \code{long} values representing normalized values of the dividend, divisor, quotient and remainder. The function returns the rounded value for the quotient.

The normalizing process insures that the sign of the result is carried in the quotient, that the remainder is greater than or equal to 0 and that the divisor is greater than 0. This normalization process results in a reduction in "sign-bit headaches." The only real "decision" that the rounding algorithm variant needs to make is whether or not to add 1 to the quotient. 
\end{funcdesc}

For example:
\begin{verbatim}
>>> from fixedpoint import FixedPoint
>>> def truncate(dividend, divisor, quotient, remainder):
...     """Don't round: truncate"""
...     return quotient
... 
>>> FixedPoint.round = truncate
>>> print FixedPoint("1.555")
1.55
>>> print FixedPoint("1.565")
1.56
>>> print FixedPoint("1.575")
1.57
>>> 
\end{verbatim}

Note that changing the rounding algorithm changes the algorithm for ALL new instances of FixedPoint objects including those created as the result of operations on \class{FixedPoint} objects. It is a good practice to set the rounding algorithm right after importing FixedPoint, and to avoid changing it in the body of the program.

\subsection{FixedPoint Exceptions\label{fixedpoint-exceptions}}
% This label is generally useful for referencing this section, but is
% also used to give a filename when generating HTML.
\class{FixedPoint} objects can raise the following exceptions:

\begin{excdesc}{TypeError("can't convert complex to FixedPoint...")}
Exception raised during instantiation when a complex number is passed to \class{FixedPoint} as the initial value. \class{FixedPoint} cannot convert complex numbers. Exception string includes the complex number passed as the initial value.
\end{excdesc}

\begin{excdesc}{TypeError("can't convert to FixedPoint:...")}
Exception raised during instantiation when an initial value is passed to \class{FixedPoint} that cannot be coerced into a \code{float} or \code{int}. Exception string includes the number passed as the initial value.
\end{excdesc}

\begin{excdesc}{TypeError("precision not convertable to int:...")}
Exception raised by \code{set_precision()} when the value of the precision argument could not be coerced into an integer. Exception string includes the value passed as the precision.
\end{excdesc}

\begin{excdesc} {ValueError("precision must be >= 0:...")}
Exception raised by \code{set_precision()} when the value of the precision argument is less than 0. Exception string includes the value passed as the precision.
\end{excdesc}

\begin{excdesc}{ZeroDivisionError("FixedPoint division")}
Exception raised during a \class{FixedPoint} division operation when the value of the divisor is 0. 
\end{excdesc}

\begin{excdesc}{ZeroDivisionError("FixedPoint modulo")}
Exception raised during a \class{FixedPoint} \code{divmod()} operation when the value of the divisor is 0.
\end{excdesc}

\begin{excdesc}{ValueError("can't parse as number:...")}
Exception raised during a \class{FixedPoint} operation when a string passed as a value cannot be converted into a numeric value. Exception string includes the string passed as the value. 
\end{excdesc}

% ==== 4. ==== Note: Moved to Last
% Now is probably a good time for a complete example.  (Alternatively,
% an example giving the flavor of the module may be given before the
% detailed list of functions.)

\subsection{FixedPoint Examples \label{fixedpoint-example}}

The following examples demonstrate various ways include \class{FixedPoint} objects in your programming solutions.

\begin{verbatim}
>>> from fixedpoint import FixedPoint
>>> 
>>> print FixedPoint("3.14159")  # defaults to 2 decimal places
3.14
>>> print FixedPoint("3.14159",3)
3.142
>>> print FixedPoint("3.14159",6)
3.141590
>>>print 1.00 + FixedPoint("3.14159",4)
4.1416
>>>
>>>
>>> x = FixedPoint("3.14159",5)
>>> print x
3.14159
>>> x.get_precision()
5
>>> x.set_precision(7)
>>> print x
3.1415900
>>> y = x.copy()
>>> x += 1
>>> y += FixedPoint("1.2e-6",7)
>>> print x,y
4.1415900 3.1415912
>>> print y.frac()
0.1415912
>>> z = y.frac() - x.frac()
>>> print z
0.0000012
>>>
>>>
>>> r = FixedPoint("3.14159",5)
>>> print 'Result is: %s (accurate to %i decimal points.)' % (r,r.get_precision())
Result is: 3.14159 (accurate to 5 decimal points.)
>>>
>>>
>>> # Note the difference between str() and repr()
... print r     # or print str(r)
3.14159
>>> print `r`   # or print repr(r)
FixedPoint('3.14159', 5)
>>>
\end{verbatim}


