File indexing completed on 2024-05-12 17:22:36
0001 /* floatnum.h: Arbitrary precision floating point numbers header file. */ 0002 /* 0003 Copyright (C) 2007, 2008 Wolf Lammen. 0004 0005 This program is free software; you can redistribute it and/or modify 0006 it under the terms of the GNU General Public License as published by 0007 the Free Software Foundation; either version 2 of the License , or 0008 (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU General Public License for more details. 0014 0015 You should have received a copy of the GNU General Public License 0016 along with this program; see the file COPYING. If not, write to: 0017 0018 The Free Software Foundation, Inc. 0019 59 Temple Place, Suite 330 0020 Boston, MA 02111-1307 USA. 0021 0022 0023 You may contact the author by: 0024 e-mail: ookami1 <at> gmx <dot> de 0025 mail: Wolf Lammen 0026 Oertzweg 45 0027 22307 Hamburg 0028 Germany 0029 0030 *************************************************************************/ 0031 #ifndef FLOATNUM_H 0032 # define FLOATNUM_H 0033 0034 #include "number.h" 0035 #include "floatconfig.h" 0036 #include "floatio.h" 0037 0038 #define NULLTERMINATED (-20) 0039 #define UNORDERED (-2) 0040 0041 #define EXACT (-101) 0042 #define INTQUOT (-102) 0043 0044 #define float_free(f) float_setnan(f) 0045 0046 #ifdef __cplusplus 0047 extern "C" { 0048 #endif 0049 0050 extern int maxdigits; 0051 0052 typedef struct { 0053 bc_num significand; 0054 int exponent; 0055 #ifdef FLOATDEBUG 0056 char value[110]; 0057 #endif /* FLOATDEBUG */ 0058 } floatstruct; 0059 0060 typedef floatstruct* floatnum; 0061 typedef const floatstruct* cfloatnum; 0062 0063 typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode; 0064 0065 /* initializes this module. Has to be called prior to the first 0066 use of any of the following functions */ 0067 void floatnum_init(); 0068 0069 /* sets the error to `code' unless it is already set */ 0070 void float_seterror(Error code); 0071 0072 /* gets the last error and clears the error afterwards */ 0073 Error float_geterror(); 0074 0075 /* returns the current overflow limit. It is the maximum possible 0076 exponent. The smallest exponent is -`return value' - 1. 0077 This function never reports an error */ 0078 int float_getrange(); 0079 0080 /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents 0081 between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others 0082 trigger overflow/underflow errors. 0083 `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding 0084 arguments are replaced by the respective limit. 0085 The return value is the old overflow limit. 0086 This function affects future results only. Current stored values are 0087 not subject to overflow/underflow checking, even when they are used as 0088 parameters to an operation. 0089 This function never reports an error */ 0090 int float_setrange(int maxexp); 0091 0092 /* returns the current precision limit. Arithmetic results may be cut off 0093 after this number of decimal digits */ 0094 int float_getprecision(); 0095 0096 /* sets the current maximum precision (in decimal digits) that is used by basic 0097 arithmetic operations. The precision is at least 1 and at most MAXDIGITS. 0098 An exceeding argument is replaced by the respective limit. 0099 Setting a new precision affects future operations only; currently set 0100 variables are kept unmodified. 0101 The return value is the old precision limit. 0102 This function never reports an error */ 0103 int float_setprecision(int digits); 0104 0105 /* checks whether the submitted exponent is within the current overflow and 0106 underflow limits. 0107 This function never reports an error */ 0108 char float_isvalidexp(int exp); 0109 0110 /* initializes a new floatnum to NaN. Call this before 0111 the first use of a floatnum variable. 0112 The destructing function is float_setnan or its alias, float_free. 0113 This function never reports an error. */ 0114 void float_create(floatnum f); 0115 0116 /* finalizes a variable. To avoid memory leaks, call this before a floatnum 0117 is freed. A special value (NaN = not a number) is loaded into `f', so 0118 any subsequent arithmetic operation on this variable will fail. 0119 However, a variable such finalized can still be re-used without prior 0120 initialization, by making it the destination of an operation. 0121 If you wish to deliberately "empty" a variable, without detroying it, 0122 call this function. 0123 An alias "float_free" to this function is defined that you 0124 may use anywhere as a replacement for float_setnan. 0125 This function never reports an error. */ 0126 void float_setnan(floatnum f); 0127 0128 /* returns the base 10 exponent of the value in `f'. If `f' is zero or 0129 NaN, the returned exponent is 0. 0130 This function never reports an error. */ 0131 int float_getexponent(cfloatnum f); 0132 0133 /* fills the buffer `buf' of size `bufsz' with an ASCII string 0134 representing the significand of `f'. 0135 No zeros are padded to the right to fill the buffer in case 0136 of a short significand. 0137 If `bufsz' <= 0, the function returns immediately with result 0. 0138 If the significand does not fit completely into the buffer, 0139 the output is stopped when the last buffer byte is written to. 0140 A non-zero significand yields a sequence of digits, without 0141 a decimal point; zero yields "0" and NaN "N". 0142 On truncation, no trailing zeros are removed. 0143 Exponent and sign are ignored, and no decimal point is written. 0144 No '\0' character is appended to the right. 0145 The return value are the number of characters written to the buffer. 0146 This function never reports an error. */ 0147 int float_getsignificand(char* buf, int bufsz, cfloatnum f); 0148 0149 /* returns the number of digits in the significand, or 0 for NaN and zero. 0150 This function never reports an error. */ 0151 int float_getlength(cfloatnum f); 0152 0153 /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is 0154 zero or NaN. 0155 This function never reports an error. */ 0156 signed char float_getsign(cfloatnum f); 0157 0158 /* writes the value stored in `f' as an ASCIIZ string into a buffer of 0159 size `bufsz'. If the buffer is too small to hold the full value, 0160 the significand is truncated appropriately. If the buffer is too small 0161 to even store the most significant digit of the significand besides 0162 exponent and sign, nothing is stored at all, and -1 is returned. 0163 Else, the length of the output, but without the trailing \0 0164 character, is returned. 0165 The output format is the usual scientific format. On truncation, 0166 no trailing zeros are removed from the output of the significand. 0167 Examples of an output: 0168 0169 value output 0170 ----- ------ 0171 NaN NaN\0 0172 0 0\0 0173 1 1.e0\0 0174 1.2 1.2e0\0 0175 0.5 5.e-1\0 0176 -1 -1.e0\0 0177 1.009 1.00e0\0 (truncated to 3 digits) 0178 10^10 1.e10\0 0179 0180 This function does not touch the adjacent bytes of the final 0181 output. If no reasonable output is possible, the complete buffer 0182 is left unchanged, not even the final \0 character is written. 0183 This function never reports an error. */ 0184 int float_getscientific(char* buf, int bufsz, cfloatnum f); 0185 0186 /* gets the `ofs'-th digit from the decimal representation 0187 of the significand of `f'. If `ofs' is negative or greater 0188 equal to the length of the significand, 0 is returned. 0189 The return value is between 0 and 9 (not the ASCII representation 0190 of these digits (0x30 - 0x39)). 0191 This function never returns an error */ 0192 char float_getdigit(cfloatnum f, int ofs); 0193 0194 /* sets the significand according to the the ASCII text in buffer buf 0195 of size `bufsz'. 0196 The buffer must contain digits '0' -'9' only, with one possible 0197 exception: A single decimal point ('.') may be placed anywhere in 0198 the buffer. It is skipped while encoding the significand. 0199 The function searches the buffer for the first non-zero digit, 0200 and starts the encoding from there. 0201 `f' is set to NaN, if the buffer fails to fulfill the above conditions. 0202 If the resulting significand exceeds <maxdigits> digits, it is truncated. 0203 The exponent of `f' is set to 0, so the result is always NaN, 0 or a 0204 number between 1 and 9.99... 0205 If you want to set both the significand and the exponent of f, 0206 set the significand first. 0207 If `leadingzeros' is not NULL, and the result in `f' is neither zero nor 0208 NaN, the number of leading (and skipped) zeros are stored here. 0209 In case of NaN or zero, this value is 0. 0210 All trailing zeros in the significand of `f' are removed. 0211 The result is the position of the decimal point in `buf', or -1 0212 if either none was found, or if it is not relevant (NaN or 0.0). 0213 This function never reports an error. */ 0214 int float_setsignificand(floatnum f, int* leadingzeros, const char* buf, 0215 int bufsz); 0216 0217 /* sets the base 10 exponent of f to exponent. The significand is 0218 only changed when this operation fails. 0219 Integers greater than EXPMAX or smaller than EXPMIN are not accepted as 0220 exponent and let the operation fail, setting `f' to NaN. 0221 You cannot change the exponent of 0 or NaN, this is ignored. 0222 If you want to set both the significand and the exponent of `f', 0223 set the significand first. 0224 This function never reports an error. */ 0225 void float_setexponent(floatnum f, int exponent); 0226 0227 /* converts an ASCII string of length `bufsz' in `buf' to `f'. 0228 `bufsz' may assume the special value NULLTERMINATED, in which case 0229 the first found \0 character terminates the input. 0230 The input format is 0231 [+|-][digit...][.[digit...][(e|E)[+|-]digit...]] 0232 At least one digit of the significand has to be present. 0233 Any non-valid input is converted into a NaN. 0234 This function never reports an error. */ 0235 void float_setscientific(floatnum f, const char* buf, int bufsz); 0236 0237 /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if 0238 `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1. 0239 This function never reports an error. */ 0240 void float_setsign(floatnum f, signed char s); 0241 0242 /* sets dest to the value in `value'. 0243 This function never reports an error. */ 0244 void float_setinteger(floatnum dest, int value); 0245 0246 /* sets a variable to the numerical value zero. 0247 This function never reports an error. */ 0248 void float_setzero (floatnum f); 0249 0250 /* returns 1, if f contains the special NaN value, 0 otherwise. 0251 This function never reports an error. */ 0252 char float_isnan(cfloatnum f); 0253 0254 /* returns 1, if f contains the value zero, 0 otherwise. 0255 This function never reports an error. */ 0256 char float_iszero(cfloatnum f); 0257 0258 /* copies source to dest, limiting the significand to at most `digits' digits. 0259 The parameter `digits' may assume the value EXACT, in which case a full 0260 copy is made. 0261 If source and dest coincide, float_copy tries to re-use the significand. 0262 This prevents unnecessary copying. 0263 If a copy has to be made, the allocated space is just big enough to hold 0264 the significand, so no memory is wasted. 0265 A return value of 0 indicates an error. 0266 errors: InvalidPrecision, if `digits', or the length of the copy, 0267 exceeds `maxdigits' */ 0268 char float_copy(floatnum dest, cfloatnum source, int digits); 0269 0270 /* transfers the contents of source to dest. source is assigned NaN 0271 afterwards. 0272 In contrast to float_copy, float_move does not create a copy of 0273 the significand (which employs memory allocation and copying), 0274 but transfers simply the data from the source to the destination. 0275 This function has been designed to implement, for example, swapping 0276 of variables in a fast way. 0277 If dest == source, nothing happens. 0278 This function never reports an error */ 0279 void float_move(floatnum dest, floatnum source); 0280 0281 /* changes the value of `f' to -`f'. Has no effect on zero or NaN. 0282 A return value of 0 indicates an error. 0283 errors: NaNOperand */ 0284 char float_neg(floatnum f); 0285 0286 /* changes the sign of `f', if `f' is negative. Has no effect on a NaN. 0287 A return value of 0 indicates an error. 0288 errors: NaNOperand */ 0289 char float_abs(floatnum f); 0290 0291 /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2 0292 and -1 if val1 < val2. 0293 This function is not intended to be used with NaN's. If you 0294 pass it as an argument, UNORDERED is returned to indicate an error. 0295 errors: NaNOperand */ 0296 signed char float_cmp(cfloatnum val1, cfloatnum val2); 0297 0298 /* rounds `f' to `digits' digits according to the submitted mode. 0299 If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN. 0300 The same holds should the rounding operation overflow. 0301 mode == TONEAREST: checks whether the first cut off digit 0302 is a '5' or greater. In this case, the 0303 absolute value of the significand is rounded up, 0304 otherwise rounded down. If the part cut off 0305 is a single digit '5', the significand is 0306 rounded such that its last digit is even. 0307 mode == TOZERO: cuts off all digits after the `digits'th digit. 0308 This mode never overflows. 0309 mode = TOINFINITY: rounds positive numbers up, negative numbers down 0310 (towards greater magnitude). 0311 mode == TOPLUSINFINITY: always rounds up. So, negative values 0312 are effectively truncated. 0313 mode == TOMINUSINFINITY: always rounds down. So, negative values 0314 usually increase in magnitude. 0315 A return value of 0 indicates an error. 0316 errors: NaNOperand 0317 InvalidParam 0318 InvalidPrecision 0319 Overflow */ 0320 char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode); 0321 0322 /* cuts off the fractional part of `f'. The result is always less 0323 or equal in magnitude to the passed argument. 0324 A NaN yields a NaN. 0325 A return value of 0 indicates an error. 0326 errors: NaNOperand */ 0327 char float_int(floatnum f); 0328 0329 /* cuts off the integer part of `f'. If the result is not equal to 0, 0330 it has the same sign as the argument. 0331 NaN yields NaN. 0332 A return value of 0 indicates an error. 0333 errors: NaNOperand */ 0334 char float_frac(floatnum f); 0335 0336 /* adds the values in `summand1' and `summand2' and stores the result in 0337 `dest'. `dest' may coincide with either summand (or even both). 0338 The result is evaluated to `digits' or `digits'+1 digits. If `digits' 0339 is EXACT, the sum is evaluated to full scale (if possible). 0340 NaN is returned, if 0341 - (at least) one operand is NaN; 0342 - the result overflows or underflows; 0343 - `digits' is invalid, or the resulting digits exceed `maxdigits'. 0344 A return value of 0 indicates an error. 0345 errors: NaNOperand 0346 InvalidPrecision 0347 Overflow 0348 Underflow */ 0349 char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2, 0350 int digits); 0351 0352 /* subtracts `subtrahend' from `minuend' and stores the result in 0353 `dest'. `dest' may coincide with either operand (or even both). 0354 The result is evaluated to `digits' or `digits'+1 digits. If `digits' 0355 is EXACT, the difference is evaluated to full scale (if possible). 0356 NaN is returned, if 0357 - (at least) one operand is NaN; 0358 - the result overflows or underflows; 0359 - `digits' is invalid, or the resulting digits exceed `maxdigits'. 0360 A return value of 0 indicates an error. 0361 errors: NaNOperand 0362 InvalidPrecision 0363 Overflow 0364 Underflow */ 0365 char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend, 0366 int digits); 0367 0368 /* multiplies both factors and stores the result in `dest'. `dest' may 0369 coincide with either factor (or even both). The result is 0370 evaluated to `digits' or `digits'+1 digits, or, if `digits' == 0371 EXACT, to full scale (if possible). 0372 NaN is returned, if 0373 - (at least) one operand is NaN; 0374 - the result overflows or underflows; 0375 - `digits' is invalid, or the resulting scale exceeds `maxdigits'. 0376 A return value of 0 indicates an error. 0377 errors: NaNOperand 0378 InvalidPrecision 0379 Overflow 0380 Underflow */ 0381 char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2, 0382 int digits); 0383 0384 /* divides `dividend' by `divisor' and stores the result in `dest'. `dest' 0385 may coincide with either operand (or even both). The result is 0386 evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT, 0387 to the size of the integer part of the quotient. 0388 EXACT is not allowed, even in cases where the dividend is divisible 0389 by the divisor. 0390 NaN is returned, if 0391 - (at least) one operand is NaN; 0392 - the result overflows or underflows; 0393 - the divisor is zero; 0394 - `digits' is invalid, or the effective scale exceeds `maxdigits'. 0395 A return value of 0 indicates an error. 0396 errors: NaNOperand 0397 InvalidPrecision 0398 Overflow 0399 Underflow 0400 ZeroDivide */ 0401 char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor, 0402 int digits); 0403 0404 /* evaluates the quotient, using `digits' steps of the schoolbook 0405 division algorithm. The quotient, thus, has `digits' or `digits'-1 digits, 0406 and is always truncated towards zero. 0407 The remainder fulfills the equation: 0408 remainder = dividend - quotient * divisor. 0409 `digits' may assume the special value INTQUOT, in which case the integer 0410 part of the quotient is calculated. 0411 This function is an exact operation anyway, so EXACT is not allowed 0412 here. 0413 `digits' is subject to the `maxdigits' limit. 0414 `remainder' and `quotient' have to be different variables, but apart from 0415 this, there are no other restrictions on the passed variables. 0416 If this function fails, both result variables are set to NaN. 0417 A return value of 0 indicates an error. 0418 errors: NaNOperand 0419 InvalidParam 0420 InvalidPrecision 0421 TooExpensive 0422 Overflow 0423 Underflow 0424 ZeroDivide */ 0425 char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend, 0426 cfloatnum divisor, int digits); 0427 0428 /* computes the sqare root of `value' to `digits' or `digits'+1 digits. 0429 `digits' == EXACT is not allowed, even if the argument is a square. 0430 NaN is returned, if 0431 - the operand is NaN, 0432 - `digits' exceeds `maxdigits' 0433 - the operand is negative. 0434 A return value 0 indicates an error. 0435 errors: NaNOperand 0436 InvalidPrecision 0437 OutOfDomain */ 0438 char float_sqrt(floatnum value, int digits); 0439 0440 /* a few convenience functions used everywhere */ 0441 0442 char _setnan(floatnum result); 0443 char _seterror(floatnum result, Error code); 0444 char _checknan(cfloatnum f); 0445 char _setzero(floatnum x); 0446 0447 #ifdef __cplusplus 0448 } 0449 #endif 0450 0451 #endif /* FLOATNUM_H */