1 /* floatnum.h: Arbitrary precision floating point numbers header file. */
2 /*
3     Copyright (C) 2007, 2008 Wolf Lammen.
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License , or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; see the file COPYING.  If not, write to:
17 
18       The Free Software Foundation, Inc.
19       59 Temple Place, Suite 330
20       Boston, MA 02111-1307 USA.
21 
22 
23     You may contact the author by:
24        e-mail:  ookami1 <at> gmx <dot> de
25        mail:  Wolf Lammen
26               Oertzweg 45
27               22307 Hamburg
28               Germany
29 
30 *************************************************************************/
31 #ifndef FLOATNUM_H
32 # define FLOATNUM_H
33 
34 #include "number.h"
35 #include "floatconfig.h"
36 #include "floatio.h"
37 
38 #define NULLTERMINATED (-20)
39 #define UNORDERED (-2)
40 
41 #define EXACT (-101)
42 #define INTQUOT (-102)
43 
44 #define float_free(f) float_setnan(f)
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 extern int maxdigits;
51 
52 typedef struct {
53   bc_num significand;
54   int exponent;
55 #ifdef FLOATDEBUG
56   char value[110];
57 #endif /* FLOATDEBUG */
58 } floatstruct;
59 
60 typedef floatstruct* floatnum;
61 typedef const floatstruct* cfloatnum;
62 
63 typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode;
64 
65 /* initializes this module. Has to be called prior to the first
66    use of any of the following functions */
67 void floatnum_init();
68 
69 /* sets the error to `code' unless it is already set */
70 void float_seterror(Error code);
71 
72 /* gets the last error and clears the error afterwards */
73 Error float_geterror();
74 
75 /* returns the current overflow limit. It is the maximum possible
76    exponent. The smallest exponent is -`return value' - 1.
77    This function never reports an error */
78 int float_getrange();
79 
80 /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents
81    between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others
82    trigger overflow/underflow errors.
83    `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding
84    arguments are replaced by the respective limit.
85    The return value is the old overflow limit.
86    This function affects future results only. Current stored values are
87    not subject to overflow/underflow checking, even when they are used as
88    parameters to an operation.
89    This function never reports an error */
90 int float_setrange(int maxexp);
91 
92 /* returns the current precision limit. Arithmetic results may be cut off
93    after this number of decimal digits */
94 int float_getprecision();
95 
96 /* sets the current maximum precision (in decimal digits) that is used by basic
97    arithmetic operations. The precision is at least 1 and at most MAXDIGITS.
98    An exceeding argument is replaced by the respective limit.
99    Setting a new precision affects future operations only; currently set
100    variables are kept unmodified.
101    The return value is the old precision limit.
102    This function never reports an error */
103 int float_setprecision(int digits);
104 
105 /* checks whether the submitted exponent is within the current overflow and
106    underflow limits.
107    This function never reports an error */
108 char float_isvalidexp(int exp);
109 
110 /* initializes a new floatnum to NaN. Call this before
111    the first use of a floatnum variable.
112    The destructing function is float_setnan or its alias, float_free.
113    This function never reports an error. */
114 void float_create(floatnum f);
115 
116 /* finalizes a variable. To avoid memory leaks, call this before a floatnum
117    is freed. A special value (NaN = not a number) is loaded into `f', so
118    any subsequent arithmetic operation on this variable will fail.
119    However, a variable such finalized can still be re-used without prior
120    initialization, by making it the destination of an operation.
121    If you wish to deliberately "empty" a variable, without detroying it,
122    call this function.
123    An alias "float_free" to this function is defined that you
124    may use anywhere as a replacement for float_setnan.
125    This function never reports an error. */
126 void float_setnan(floatnum f);
127 
128 /* returns the base 10 exponent of the value in `f'. If `f' is zero or
129    NaN, the returned exponent is 0.
130    This function never reports an error. */
131 int float_getexponent(cfloatnum f);
132 
133 /* fills the buffer `buf' of size `bufsz' with an ASCII string
134    representing the significand of `f'.
135    No zeros are padded to the right to fill the buffer in case
136    of a short significand.
137    If `bufsz' <= 0, the function returns immediately with result 0.
138    If the significand does not fit completely into the buffer,
139    the output is stopped when the last buffer byte is written to.
140    A non-zero significand yields a sequence of digits, without
141    a decimal point; zero yields "0" and NaN "N".
142    On truncation, no trailing zeros are removed.
143    Exponent and sign are ignored, and no decimal point is written.
144    No '\0' character is appended to the right.
145    The return value are the number of characters written to the buffer.
146    This function never reports an error. */
147 int float_getsignificand(char* buf, int bufsz, cfloatnum f);
148 
149 /* returns the number of digits in the significand, or 0 for NaN and zero.
150    This function never reports an error. */
151 int float_getlength(cfloatnum f);
152 
153 /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is
154    zero or NaN.
155    This function never reports an error. */
156 signed char float_getsign(cfloatnum f);
157 
158 /* writes the value stored in `f' as an ASCIIZ string into a buffer of
159    size `bufsz'. If the buffer is too small to hold the full value,
160    the significand is truncated appropriately. If the buffer is too small
161    to even store the most significant digit of the significand besides
162    exponent and sign, nothing is stored at all, and -1 is returned.
163    Else, the length of the output, but without the trailing \0
164    character, is returned.
165    The output format is the usual scientific format. On truncation,
166    no trailing zeros are removed from the output of the significand.
167    Examples of an output:
168 
169    value  output
170    -----  ------
171    NaN    NaN\0
172    0      0\0
173    1      1.e0\0
174    1.2    1.2e0\0
175    0.5    5.e-1\0
176    -1     -1.e0\0
177    1.009  1.00e0\0 (truncated to 3 digits)
178    10^10  1.e10\0
179 
180    This function does not touch the adjacent bytes of the final
181    output. If no reasonable output is possible, the complete buffer
182    is left unchanged, not even the final \0 character is written.
183    This function never reports an error. */
184 int float_getscientific(char* buf, int bufsz, cfloatnum f);
185 
186 /* gets the `ofs'-th digit from the decimal representation
187    of the significand of `f'. If `ofs' is negative or greater
188    equal to the length of the significand, 0 is returned.
189    The return value is between 0 and 9 (not the ASCII representation
190    of these digits (0x30 - 0x39)).
191    This function never returns an error */
192 char float_getdigit(cfloatnum f, int ofs);
193 
194 /* sets the significand according to the the ASCII text in buffer buf
195    of size `bufsz'.
196    The buffer must contain digits '0' -'9' only, with one possible
197    exception: A single decimal point ('.') may be placed anywhere in
198    the buffer. It is skipped while encoding the significand.
199    The function searches the buffer for the first non-zero digit,
200    and starts the encoding from there.
201    `f' is set to NaN, if the buffer fails to fulfill the above conditions.
202    If the resulting significand exceeds <maxdigits> digits, it is truncated.
203    The exponent of `f' is set to 0, so the result is always NaN, 0 or a
204    number between 1 and 9.99...
205    If you want to set both the significand and the exponent of f,
206    set the significand first.
207    If `leadingzeros' is not NULL, and the result in `f' is neither zero nor
208    NaN, the number of leading (and skipped) zeros are stored here.
209    In case of NaN or zero, this value is 0.
210    All trailing zeros in the significand of `f' are removed.
211    The result is the position of the decimal point in `buf', or -1
212    if either none was found, or if it is not relevant (NaN or 0.0).
213    This function never reports an error. */
214 int float_setsignificand(floatnum f, int* leadingzeros, const char* buf,
215                          int bufsz);
216 
217 /* sets the base 10 exponent of f to exponent. The significand is
218    only changed when this operation fails.
219    Integers greater than EXPMAX or smaller than EXPMIN are not accepted as
220    exponent and let the operation fail, setting `f' to NaN.
221    You cannot change the exponent of 0 or NaN, this is ignored.
222    If you want to set both the significand and the exponent of `f',
223    set the significand first.
224    This function never reports an error. */
225 void float_setexponent(floatnum f, int exponent);
226 
227 /* converts an ASCII string of length `bufsz' in `buf' to `f'.
228    `bufsz' may assume the special value NULLTERMINATED, in which case
229    the first found \0 character terminates the input.
230    The input format is
231    [+|-][digit...][.[digit...][(e|E)[+|-]digit...]]
232    At least one digit of the significand has to be present.
233    Any non-valid input is converted into a NaN.
234    This function never reports an error. */
235 void float_setscientific(floatnum f, const char* buf, int bufsz);
236 
237 /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if
238    `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1.
239    This function never reports an error. */
240 void float_setsign(floatnum f, signed char s);
241 
242 /* sets dest to the value in `value'.
243    This function never reports an error. */
244 void float_setinteger(floatnum dest, int value);
245 
246 /* sets a variable to the numerical value zero.
247    This function never reports an error. */
248 void float_setzero (floatnum f);
249 
250 /* returns 1, if f contains the special NaN value, 0 otherwise.
251    This function never reports an error. */
252 char float_isnan(cfloatnum f);
253 
254 /* returns 1, if f contains the value zero, 0 otherwise.
255    This function never reports an error. */
256 char float_iszero(cfloatnum f);
257 
258 /* copies source to dest, limiting the significand to at most `digits' digits.
259    The parameter `digits' may assume the value EXACT, in which case a full
260    copy is made.
261    If source and dest coincide, float_copy tries to re-use the significand.
262    This prevents unnecessary copying.
263    If a copy has to be made, the allocated space is just big enough to hold
264    the significand, so no memory is wasted.
265    A return value of 0 indicates an error.
266    errors: InvalidPrecision,   if `digits', or the length of the copy,
267                                exceeds `maxdigits' */
268 char float_copy(floatnum dest, cfloatnum source, int digits);
269 
270 /* transfers the contents of source to dest. source is assigned NaN
271    afterwards.
272    In contrast to float_copy, float_move does not create a copy of
273    the significand (which employs memory allocation and copying),
274    but transfers simply the data from the source to the destination.
275    This function has been designed to implement, for example, swapping
276    of variables in a fast way.
277    If dest == source, nothing happens.
278    This function never reports an error */
279 void float_move(floatnum dest, floatnum source);
280 
281 /* changes the value of `f' to -`f'. Has no effect on zero or NaN.
282    A return value of 0 indicates an error.
283    errors: NaNOperand  */
284 char float_neg(floatnum f);
285 
286 /* changes the sign of `f', if `f' is negative. Has no effect on a NaN.
287    A return value of 0 indicates an error.
288    errors: NaNOperand */
289 char float_abs(floatnum f);
290 
291 /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2
292    and -1 if val1 < val2.
293    This function is not intended to be used with NaN's. If you
294    pass it as an argument, UNORDERED is returned to indicate an error.
295    errors: NaNOperand */
296 signed char float_cmp(cfloatnum val1, cfloatnum val2);
297 
298 /* rounds `f' to `digits' digits according to the submitted mode.
299    If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN.
300    The same holds should the rounding operation overflow.
301    mode == TONEAREST: checks whether the first cut off digit
302                       is a '5' or greater. In this case, the
303                       absolute value of the significand is rounded up,
304                       otherwise rounded down. If the part cut off
305                       is a single digit '5', the significand is
306                       rounded such that its last digit is even.
307    mode == TOZERO: cuts off all digits after the `digits'th digit.
308                    This mode never overflows.
309    mode = TOINFINITY: rounds positive numbers up, negative numbers down
310                       (towards greater magnitude).
311    mode == TOPLUSINFINITY: always rounds up. So, negative values
312                            are effectively truncated.
313    mode == TOMINUSINFINITY: always rounds down. So, negative values
314                             usually increase in magnitude.
315    A return value of 0 indicates an error.
316    errors: NaNOperand
317            InvalidParam
318            InvalidPrecision
319            Overflow */
320 char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode);
321 
322 /* cuts off the fractional part of `f'. The result is always less
323    or equal in magnitude to the passed argument.
324    A NaN yields a NaN.
325    A return value of 0 indicates an error.
326    errors: NaNOperand */
327 char float_int(floatnum f);
328 
329 /* cuts off the integer part of `f'. If the result is not equal to 0,
330    it has the same sign as the argument.
331    NaN yields NaN.
332    A return value of 0 indicates an error.
333    errors: NaNOperand */
334 char float_frac(floatnum f);
335 
336 /* adds the values in `summand1' and `summand2' and stores the result in
337    `dest'. `dest' may coincide with either summand (or even both).
338    The result is evaluated to `digits' or `digits'+1 digits. If `digits'
339    is EXACT, the sum is evaluated to full scale (if possible).
340    NaN is returned, if
341    - (at least) one operand is NaN;
342    - the result overflows or underflows;
343    - `digits' is invalid, or the resulting digits exceed `maxdigits'.
344    A return value of 0 indicates an error.
345    errors: NaNOperand
346            InvalidPrecision
347            Overflow
348            Underflow */
349 char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2,
350   int digits);
351 
352 /* subtracts `subtrahend' from `minuend' and stores the result in
353    `dest'. `dest' may coincide with either operand (or even both).
354    The result is evaluated to `digits' or `digits'+1 digits. If `digits'
355    is EXACT, the difference is evaluated to full scale (if possible).
356    NaN is returned, if
357    - (at least) one operand is NaN;
358    - the result overflows or underflows;
359    - `digits' is invalid, or the resulting digits exceed `maxdigits'.
360    A return value of 0 indicates an error.
361    errors: NaNOperand
362            InvalidPrecision
363            Overflow
364            Underflow */
365 char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend,
366   int digits);
367 
368 /* multiplies both factors and stores the result in `dest'. `dest' may
369    coincide with either factor (or even both). The result is
370    evaluated to `digits' or `digits'+1 digits, or, if `digits' ==
371    EXACT, to full scale (if possible).
372    NaN is returned, if
373    - (at least) one operand is NaN;
374    - the result overflows or underflows;
375    - `digits' is invalid, or the resulting scale exceeds `maxdigits'.
376    A return value of 0 indicates an error.
377    errors: NaNOperand
378            InvalidPrecision
379            Overflow
380            Underflow */
381 char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2,
382   int digits);
383 
384 /* divides `dividend' by `divisor' and stores the result in `dest'. `dest'
385    may coincide with either operand (or even both). The result is
386    evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT,
387    to the size of the integer part of the quotient.
388    EXACT is not allowed, even in cases where the dividend is divisible
389    by the divisor.
390    NaN is returned, if
391    - (at least) one operand is NaN;
392    - the result overflows or underflows;
393    - the divisor is zero;
394    - `digits' is invalid, or the effective scale exceeds `maxdigits'.
395    A return value of 0 indicates an error.
396    errors: NaNOperand
397            InvalidPrecision
398            Overflow
399            Underflow
400            ZeroDivide */
401 char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor,
402   int digits);
403 
404 /* evaluates the quotient, using `digits' steps of the schoolbook
405    division algorithm. The quotient, thus, has `digits' or `digits'-1 digits,
406    and is always truncated towards zero.
407    The remainder fulfills the equation:
408      remainder = dividend - quotient * divisor.
409    `digits' may assume the special value INTQUOT, in which case the integer
410    part of the quotient is calculated.
411    This function is an exact operation anyway, so EXACT is not allowed
412    here.
413    `digits' is subject to the `maxdigits' limit.
414    `remainder' and `quotient' have to be different variables, but apart from
415    this, there are no other restrictions on the passed variables.
416    If this function fails, both result variables are set to NaN.
417    A return value of 0 indicates an error.
418    errors: NaNOperand
419            InvalidParam
420            InvalidPrecision
421            TooExpensive
422            Overflow
423            Underflow
424            ZeroDivide */
425 char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend,
426   cfloatnum divisor, int digits);
427 
428 /* computes the sqare root of `value' to `digits' or `digits'+1 digits.
429    `digits' == EXACT is not allowed, even if the argument is a square.
430    NaN is returned, if
431    - the operand is NaN,
432    - `digits' exceeds `maxdigits'
433    - the operand is negative.
434    A return value 0 indicates an error.
435    errors: NaNOperand
436            InvalidPrecision
437            OutOfDomain */
438 char float_sqrt(floatnum value, int digits);
439 
440 /* a few convenience functions used everywhere */
441 
442 char _setnan(floatnum result);
443 char _seterror(floatnum result, Error code);
444 char _checknan(cfloatnum f);
445 char _setzero(floatnum x);
446 
447 #ifdef __cplusplus
448 }
449 #endif
450 
451 #endif /* FLOATNUM_H */
452