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