SpeedCrunch  0.11
/usr/src/RPM/BUILD/speedcrunch-0.11/src/math/floatnum.h
Go to the documentation of this file.
00001 /* floatnum.h: Arbitrary precision floating point numbers header file. */
00002 /*
00003     Copyright (C) 2007, 2008 Wolf Lammen.
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License , or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; see the file COPYING.  If not, write to:
00017 
00018       The Free Software Foundation, Inc.
00019       59 Temple Place, Suite 330
00020       Boston, MA 02111-1307 USA.
00021 
00022 
00023     You may contact the author by:
00024        e-mail:  ookami1 <at> gmx <dot> de
00025        mail:  Wolf Lammen
00026               Oertzweg 45
00027               22307 Hamburg
00028               Germany
00029 
00030 *************************************************************************/
00031 #ifndef FLOATNUM_H
00032 # define FLOATNUM_H
00033 
00034 #include "number.h"
00035 #include "floatconfig.h"
00036 #include "floatio.h"
00037 
00038 #define NULLTERMINATED (-20)
00039 #define UNORDERED (-2)
00040 
00041 #define EXACT (-101)
00042 #define INTQUOT (-102)
00043 
00044 #define float_free(f) float_setnan(f)
00045 
00046 #ifdef __cplusplus
00047 extern "C" {
00048 #endif
00049 
00050 extern int maxdigits;
00051 
00052 typedef struct {
00053   bc_num significand;
00054   int exponent;
00055 #ifdef FLOATDEBUG
00056   char value[110];
00057 #endif /* FLOATDEBUG */
00058 } floatstruct;
00059 
00060 typedef floatstruct* floatnum;
00061 typedef const floatstruct* cfloatnum;
00062 
00063 typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode;
00064 
00065 /* initializes this module. Has to be called prior to the first
00066    use of any of the following functions */
00067 void floatnum_init();
00068 
00069 /* sets the error to `code' unless it is already set */
00070 void float_seterror(Error code);
00071 
00072 /* gets the last error and clears the error afterwards */
00073 Error float_geterror();
00074 
00075 /* returns the current overflow limit. It is the maximum possible
00076    exponent. The smallest exponent is -`return value' - 1.
00077    This function never reports an error */
00078 int float_getrange();
00079 
00080 /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents
00081    between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others
00082    trigger overflow/underflow errors.
00083    `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding
00084    arguments are replaced by the respective limit.
00085    The return value is the old overflow limit.
00086    This function affects future results only. Current stored values are
00087    not subject to overflow/underflow checking, even when they are used as
00088    parameters to an operation.
00089    This function never reports an error */
00090 int float_setrange(int maxexp);
00091 
00092 /* returns the current precision limit. Arithmetic results may be cut off
00093    after this number of decimal digits */
00094 int float_getprecision();
00095 
00096 /* sets the current maximum precision (in decimal digits) that is used by basic
00097    arithmetic operations. The precision is at least 1 and at most MAXDIGITS.
00098    An exceeding argument is replaced by the respective limit.
00099    Setting a new precision affects future operations only; currently set
00100    variables are kept unmodified.
00101    The return value is the old precision limit.
00102    This function never reports an error */
00103 int float_setprecision(int digits);
00104 
00105 /* checks whether the submitted exponent is within the current overflow and
00106    underflow limits.
00107    This function never reports an error */
00108 char float_isvalidexp(int exp);
00109 
00110 /* initializes a new floatnum to NaN. Call this before
00111    the first use of a floatnum variable.
00112    The destructing function is float_setnan or its alias, float_free.
00113    This function never reports an error. */
00114 void float_create(floatnum f);
00115 
00116 /* finalizes a variable. To avoid memory leaks, call this before a floatnum
00117    is freed. A special value (NaN = not a number) is loaded into `f', so
00118    any subsequent arithmetic operation on this variable will fail.
00119    However, a variable such finalized can still be re-used without prior
00120    initialization, by making it the destination of an operation.
00121    If you wish to deliberately "empty" a variable, without detroying it,
00122    call this function.
00123    An alias "float_free" to this function is defined that you
00124    may use anywhere as a replacement for float_setnan.
00125    This function never reports an error. */
00126 void float_setnan(floatnum f);
00127 
00128 /* returns the base 10 exponent of the value in `f'. If `f' is zero or
00129    NaN, the returned exponent is 0.
00130    This function never reports an error. */
00131 int float_getexponent(cfloatnum f);
00132 
00133 /* fills the buffer `buf' of size `bufsz' with an ASCII string
00134    representing the significand of `f'.
00135    No zeros are padded to the right to fill the buffer in case
00136    of a short significand.
00137    If `bufsz' <= 0, the function returns immediately with result 0.
00138    If the significand does not fit completely into the buffer,
00139    the output is stopped when the last buffer byte is written to.
00140    A non-zero significand yields a sequence of digits, without
00141    a decimal point; zero yields "0" and NaN "N".
00142    On truncation, no trailing zeros are removed.
00143    Exponent and sign are ignored, and no decimal point is written.
00144    No '\0' character is appended to the right.
00145    The return value are the number of characters written to the buffer.
00146    This function never reports an error. */
00147 int float_getsignificand(char* buf, int bufsz, cfloatnum f);
00148 
00149 /* returns the number of digits in the significand, or 0 for NaN and zero.
00150    This function never reports an error. */
00151 int float_getlength(cfloatnum f);
00152 
00153 /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is
00154    zero or NaN.
00155    This function never reports an error. */
00156 signed char float_getsign(cfloatnum f);
00157 
00158 /* writes the value stored in `f' as an ASCIIZ string into a buffer of
00159    size `bufsz'. If the buffer is too small to hold the full value,
00160    the significand is truncated appropriately. If the buffer is too small
00161    to even store the most significant digit of the significand besides
00162    exponent and sign, nothing is stored at all, and -1 is returned.
00163    Else, the length of the output, but without the trailing \0
00164    character, is returned.
00165    The output format is the usual scientific format. On truncation,
00166    no trailing zeros are removed from the output of the significand.
00167    Examples of an output:
00168 
00169    value  output
00170    -----  ------
00171    NaN    NaN\0
00172    0      0\0
00173    1      1.e0\0
00174    1.2    1.2e0\0
00175    0.5    5.e-1\0
00176    -1     -1.e0\0
00177    1.009  1.00e0\0 (truncated to 3 digits)
00178    10^10  1.e10\0
00179 
00180    This function does not touch the adjacent bytes of the final
00181    output. If no reasonable output is possible, the complete buffer
00182    is left unchanged, not even the final \0 character is written.
00183    This function never reports an error. */
00184 int float_getscientific(char* buf, int bufsz, cfloatnum f);
00185 
00186 /* gets the `ofs'-th digit from the decimal representation
00187    of the significand of `f'. If `ofs' is negative or greater
00188    equal to the length of the significand, 0 is returned.
00189    The return value is between 0 and 9 (not the ASCII representation
00190    of these digits (0x30 - 0x39)).
00191    This function never returns an error */
00192 char float_getdigit(cfloatnum f, int ofs);
00193 
00194 /* sets the significand according to the the ASCII text in buffer buf
00195    of size `bufsz'.
00196    The buffer must contain digits '0' -'9' only, with one possible
00197    exception: A single decimal point ('.') may be placed anywhere in
00198    the buffer. It is skipped while encoding the significand.
00199    The function searches the buffer for the first non-zero digit,
00200    and starts the encoding from there.
00201    `f' is set to NaN, if the buffer fails to fulfill the above conditions.
00202    If the resulting significand exceeds <maxdigits> digits, it is truncated.
00203    The exponent of `f' is set to 0, so the result is always NaN, 0 or a
00204    number between 1 and 9.99...
00205    If you want to set both the significand and the exponent of f,
00206    set the significand first.
00207    If `leadingzeros' is not NULL, and the result in `f' is neither zero nor
00208    NaN, the number of leading (and skipped) zeros are stored here.
00209    In case of NaN or zero, this value is 0.
00210    All trailing zeros in the significand of `f' are removed.
00211    The result is the position of the decimal point in `buf', or -1
00212    if either none was found, or if it is not relevant (NaN or 0.0).
00213    This function never reports an error. */
00214 int float_setsignificand(floatnum f, int* leadingzeros, const char* buf,
00215                          int bufsz);
00216 
00217 /* sets the base 10 exponent of f to exponent. The significand is
00218    only changed when this operation fails.
00219    Integers greater than EXPMAX or smaller than EXPMIN are not accepted as
00220    exponent and let the operation fail, setting `f' to NaN.
00221    You cannot change the exponent of 0 or NaN, this is ignored.
00222    If you want to set both the significand and the exponent of `f',
00223    set the significand first.
00224    This function never reports an error. */
00225 void float_setexponent(floatnum f, int exponent);
00226 
00227 /* converts an ASCII string of length `bufsz' in `buf' to `f'.
00228    `bufsz' may assume the special value NULLTERMINATED, in which case
00229    the first found \0 character terminates the input.
00230    The input format is
00231    [+|-][digit...][.[digit...][(e|E)[+|-]digit...]]
00232    At least one digit of the significand has to be present.
00233    Any non-valid input is converted into a NaN.
00234    This function never reports an error. */
00235 void float_setscientific(floatnum f, const char* buf, int bufsz);
00236 
00237 /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if
00238    `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1.
00239    This function never reports an error. */
00240 void float_setsign(floatnum f, signed char s);
00241 
00242 /* sets dest to the value in `value'.
00243    This function never reports an error. */
00244 void float_setinteger(floatnum dest, int value);
00245 
00246 /* sets a variable to the numerical value zero.
00247    This function never reports an error. */
00248 void float_setzero (floatnum f);
00249 
00250 /* returns 1, if f contains the special NaN value, 0 otherwise.
00251    This function never reports an error. */
00252 char float_isnan(cfloatnum f);
00253 
00254 /* returns 1, if f contains the value zero, 0 otherwise.
00255    This function never reports an error. */
00256 char float_iszero(cfloatnum f);
00257 
00258 /* copies source to dest, limiting the significand to at most `digits' digits.
00259    The parameter `digits' may assume the value EXACT, in which case a full
00260    copy is made.
00261    If source and dest coincide, float_copy tries to re-use the significand.
00262    This prevents unnecessary copying.
00263    If a copy has to be made, the allocated space is just big enough to hold
00264    the significand, so no memory is wasted.
00265    A return value of 0 indicates an error.
00266    errors: InvalidPrecision,   if `digits', or the length of the copy,
00267                                exceeds `maxdigits' */
00268 char float_copy(floatnum dest, cfloatnum source, int digits);
00269 
00270 /* transfers the contents of source to dest. source is assigned NaN
00271    afterwards.
00272    In contrast to float_copy, float_move does not create a copy of
00273    the significand (which employs memory allocation and copying),
00274    but transfers simply the data from the source to the destination.
00275    This function has been designed to implement, for example, swapping
00276    of variables in a fast way.
00277    If dest == source, nothing happens.
00278    This function never reports an error */
00279 void float_move(floatnum dest, floatnum source);
00280 
00281 /* changes the value of `f' to -`f'. Has no effect on zero or NaN.
00282    A return value of 0 indicates an error.
00283    errors: NaNOperand  */
00284 char float_neg(floatnum f);
00285 
00286 /* changes the sign of `f', if `f' is negative. Has no effect on a NaN.
00287    A return value of 0 indicates an error.
00288    errors: NaNOperand */
00289 char float_abs(floatnum f);
00290 
00291 /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2
00292    and -1 if val1 < val2.
00293    This function is not intended to be used with NaN's. If you
00294    pass it as an argument, UNORDERED is returned to indicate an error.
00295    errors: NaNOperand */
00296 signed char float_cmp(cfloatnum val1, cfloatnum val2);
00297 
00298 /* rounds `f' to `digits' digits according to the submitted mode.
00299    If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN.
00300    The same holds should the rounding operation overflow.
00301    mode == TONEAREST: checks whether the first cut off digit
00302                       is a '5' or greater. In this case, the
00303                       absolute value of the significand is rounded up,
00304                       otherwise rounded down. If the part cut off
00305                       is a single digit '5', the significand is
00306                       rounded such that its last digit is even.
00307    mode == TOZERO: cuts off all digits after the `digits'th digit.
00308                    This mode never overflows.
00309    mode = TOINFINITY: rounds positive numbers up, negative numbers down
00310                       (towards greater magnitude).
00311    mode == TOPLUSINFINITY: always rounds up. So, negative values
00312                            are effectively truncated.
00313    mode == TOMINUSINFINITY: always rounds down. So, negative values
00314                             usually increase in magnitude.
00315    A return value of 0 indicates an error.
00316    errors: NaNOperand
00317            InvalidParam
00318            InvalidPrecision
00319            Overflow */
00320 char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode);
00321 
00322 /* cuts off the fractional part of `f'. The result is always less
00323    or equal in magnitude to the passed argument.
00324    A NaN yields a NaN.
00325    A return value of 0 indicates an error.
00326    errors: NaNOperand */
00327 char float_int(floatnum f);
00328 
00329 /* cuts off the integer part of `f'. If the result is not equal to 0,
00330    it has the same sign as the argument.
00331    NaN yields NaN.
00332    A return value of 0 indicates an error.
00333    errors: NaNOperand */
00334 char float_frac(floatnum f);
00335 
00336 /* adds the values in `summand1' and `summand2' and stores the result in
00337    `dest'. `dest' may coincide with either summand (or even both).
00338    The result is evaluated to `digits' or `digits'+1 digits. If `digits'
00339    is EXACT, the sum is evaluated to full scale (if possible).
00340    NaN is returned, if
00341    - (at least) one operand is NaN;
00342    - the result overflows or underflows;
00343    - `digits' is invalid, or the resulting digits exceed `maxdigits'.
00344    A return value of 0 indicates an error.
00345    errors: NaNOperand
00346            InvalidPrecision
00347            Overflow
00348            Underflow */
00349 char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2,
00350   int digits);
00351 
00352 /* subtracts `subtrahend' from `minuend' and stores the result in
00353    `dest'. `dest' may coincide with either operand (or even both).
00354    The result is evaluated to `digits' or `digits'+1 digits. If `digits'
00355    is EXACT, the difference is evaluated to full scale (if possible).
00356    NaN is returned, if
00357    - (at least) one operand is NaN;
00358    - the result overflows or underflows;
00359    - `digits' is invalid, or the resulting digits exceed `maxdigits'.
00360    A return value of 0 indicates an error.
00361    errors: NaNOperand
00362            InvalidPrecision
00363            Overflow
00364            Underflow */
00365 char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend,
00366   int digits);
00367 
00368 /* multiplies both factors and stores the result in `dest'. `dest' may
00369    coincide with either factor (or even both). The result is
00370    evaluated to `digits' or `digits'+1 digits, or, if `digits' ==
00371    EXACT, to full scale (if possible).
00372    NaN is returned, if
00373    - (at least) one operand is NaN;
00374    - the result overflows or underflows;
00375    - `digits' is invalid, or the resulting scale exceeds `maxdigits'.
00376    A return value of 0 indicates an error.
00377    errors: NaNOperand
00378            InvalidPrecision
00379            Overflow
00380            Underflow */
00381 char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2,
00382   int digits);
00383 
00384 /* divides `dividend' by `divisor' and stores the result in `dest'. `dest'
00385    may coincide with either operand (or even both). The result is
00386    evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT,
00387    to the size of the integer part of the quotient.
00388    EXACT is not allowed, even in cases where the dividend is divisible
00389    by the divisor.
00390    NaN is returned, if
00391    - (at least) one operand is NaN;
00392    - the result overflows or underflows;
00393    - the divisor is zero;
00394    - `digits' is invalid, or the effective scale exceeds `maxdigits'.
00395    A return value of 0 indicates an error.
00396    errors: NaNOperand
00397            InvalidPrecision
00398            Overflow
00399            Underflow
00400            ZeroDivide */
00401 char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor,
00402   int digits);
00403 
00404 /* evaluates the quotient, using `digits' steps of the schoolbook
00405    division algorithm. The quotient, thus, has `digits' or `digits'-1 digits,
00406    and is always truncated towards zero.
00407    The remainder fulfills the equation:
00408      remainder = dividend - quotient * divisor.
00409    `digits' may assume the special value INTQUOT, in which case the integer
00410    part of the quotient is calculated.
00411    This function is an exact operation anyway, so EXACT is not allowed
00412    here.
00413    `digits' is subject to the `maxdigits' limit.
00414    `remainder' and `quotient' have to be different variables, but apart from
00415    this, there are no other restrictions on the passed variables.
00416    If this function fails, both result variables are set to NaN.
00417    A return value of 0 indicates an error.
00418    errors: NaNOperand
00419            InvalidParam
00420            InvalidPrecision
00421            TooExpensive
00422            Overflow
00423            Underflow
00424            ZeroDivide */
00425 char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend,
00426   cfloatnum divisor, int digits);
00427 
00428 /* computes the sqare root of `value' to `digits' or `digits'+1 digits.
00429    `digits' == EXACT is not allowed, even if the argument is a square.
00430    NaN is returned, if
00431    - the operand is NaN,
00432    - `digits' exceeds `maxdigits'
00433    - the operand is negative.
00434    A return value 0 indicates an error.
00435    errors: NaNOperand
00436            InvalidPrecision
00437            OutOfDomain */
00438 char float_sqrt(floatnum value, int digits);
00439 
00440 /* a few convenience functions used everywhere */
00441 
00442 char _setnan(floatnum result);
00443 char _seterror(floatnum result, Error code);
00444 char _checknan(cfloatnum f);
00445 char _setzero(floatnum x);
00446 
00447 #ifdef __cplusplus
00448 }
00449 #endif
00450 
00451 #endif /* FLOATNUM_H */