SpeedCrunch
0.11
|
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 */