diff --git a/providers/calculator/floatconfig.h b/providers/calculator/floatconfig.h index 01f605a..94475ca 100644 --- a/providers/calculator/floatconfig.h +++ b/providers/calculator/floatconfig.h @@ -1,174 +1,174 @@ /* floatdefines.h: basic settings in floatnum. */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /* this file contains the basic settings, that control the overall behaviour of floatnum and derivates. Uncomment or set any of the following defines according to your needs. */ #ifndef _FLOATCONFIG_H #define _FLOATCONFIG_H /* FLOATDEBUG introduces some extensions to floatnum, so you can easily follow operations of floatnum in a debugger like ddd. Uncomment this, if you develop code based on floatnum, and if you want to look into floatnum variables during a debugger session. */ // #define FLOATDEBUG /* enables a pre-defined set of macros so that a regression test suite of floatnum can be executed. These settings are such that corner cases can easily be triggered. The settings are not useful in a real application of floatnum. Uncomment this if you want to run the standard regression test suite of floatnum */ // #define _FLOATNUMTEST /* floatnum uses bc's bc_num format to store and operate on data. Since bc_num is an arbitrary precision format, operands may grow to extreme sizes, where complex operations take considerable time to execute, up to an hour or more. floatconfig defines a guard value to avoid extreme long operands. Any request to produce a result of more than MAXDIGITS digits is considered an error and yields a NaN result. When setting this value, bear in mind, this is a global value that effects internal operations as well as 'user' requests. When using the routines for transcendent mathematical functions, you should allow extra 14 digits, so that operations like float_exp do not fail when they compute something near maximum precision. */ #define MAXDIGITS 250 /* the number of bits into which an exponent of a floatnum is encoded. In order to avoid integer overflow, this should be at least two bits less than the bits in the integer type chosen for the exponent. The default is two bit less than the size of an int */ // #define BITS_IN_EXP 30 /* floatnum puts an upper limit on the base 10 exponent of its numbers that is based on the size of an integer, but even for 16 bit integers this limit is as big as 4095. Real applications usually do not need such big numbers. If you want to limit the range of possible numbers, set this value accordingly. An operation result exceeding this limit is converted into a NaN, and an overflow/underflow is reported. The default is the maximum positive value that can be encoded in BITS_IN_EXP bits. If you change EXPMAX, you might want to reduce BITS_IN_EXP as well. */ /* #define EXPMAX 5000 */ /* The precision of basic operations like + or * is limited by MAXDIGITS. In addition, some higher mathematical functions involve constants, that, of course, are stored to a limited precision only. This puts another bound on floatnum, described by the value MATHPRECISION. Since procedures for higher mathematical functions employ basic operations to determine their result, MATHPRECISION is <= MAXDIGITS. The current math library version of floatnum limits higher mathematical functions to 100 digits precision. One can say, MATHPRECISION describes the granularity of the number space, because higher functions do not (reliably) produce different results for values closer to each other than this granularity. You may re-define granularity by setting DECPRECISION. This will never bypass MATHPRECISION, being always the limit for the math library, but basic operations may benefit from finer granularity, up to the overall limit MAXDIGITS. If you lower granularity, that saves some memory and evaluation time in a few places. Granularity means that integers with more than DECPRECISION digits might not be saved without loss of digits. So DECPRECISION defines the integer range of floatnum. Because base convertion and logic operations are integer based, both are limited by DECPRECISION as well. By default, DECPRECISION is set to MATHPRECISION */ #define DECPRECISION 78 /* The integer domain of logical functions is a true subset of the integer range, because, according to their nature, they operate modulo a power of two, so the limit on their input is best chosen to be a power of 2. If you do not declare a limit here, an appropriate value is derived from DECPRECISION. If you change this value, make sure 2^LOGICRANGE is less than 10^DECPRECISION */ #define LOGICRANGE 256 /*************************************************************************** END OF USER SETABLE DEFINES ***************************************************************************/ /* the limit of the math library */ #define MATHPRECISION 100 #if defined(_FLOATNUMTEST) # undef MAXDIGITS # undef MATHPRECISION # undef DECPRECISION # undef LOGICRANGE # define MAXDIGITS 130 # define MATHPRECISION 130 # define LOGICRANGE 96 #endif #define MAXBITS_IN_EXP (sizeof(int)*8-2) #define MAXEXP ((1 << MAXBITS_IN_EXP) - 1) #ifndef BITS_IN_EXP /* we need 2 extra bits during conversion, so that the exponent does not overflow while computing a base 2 expression */ # define BITS_IN_EXP MAXBITS_IN_EXP #endif /* necessary width of an integer to hold all possible exponents after a conversion to another base */ #define BITS_IN_HEXEXP BITS_IN_EXP #define BITS_IN_OCTEXP (BITS_IN_EXP + 1) #define BITS_IN_BINEXP (BITS_IN_EXP + 2) #ifndef MAXDIGITS # define MAXDIGITS 500 #endif /* MAXDIGITS */ #ifndef EXPMAX # define EXPMAX ((1 << (BITS_IN_EXP-1)) - 1) #endif /* EXPMAX */ #define EXPMIN (-EXPMAX - 1) -#define EXPZERO ((int)((-1) << (sizeof(int)*8-1))) +#define EXPZERO ((int)((unsigned)(-1) << (sizeof(int)*8-1))) #define EXPNAN ((int)(~EXPZERO)) #ifndef DECPRECISION #define DECPRECISION MATHPRECISION #endif #define BINPRECISION ((33219*DECPRECISION)/10000 + 1) #define OCTPRECISION ((11073*DECPRECISION)/10000 + 1) #define HEXPRECISION ((8305*DECPRECISION)/10000 + 1) #ifndef LOGICRANGE # define LOGICRANGE (16*((BINPRECISION-2)/16)) #endif #endif /* _FLOATCONFIG_H */ diff --git a/providers/calculator/floatlogic.c b/providers/calculator/floatlogic.c index bfd5d42..0605aba 100644 --- a/providers/calculator/floatlogic.c +++ b/providers/calculator/floatlogic.c @@ -1,238 +1,238 @@ /* floatlogic.c: logic functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlogic.h" #include "floatconst.h" #define MAXIDX ((LOGICRANGE-1) / BITS_IN_UNSIGNED) #define SIGNBIT (LOGICRANGE - 1 - MAXIDX * BITS_IN_UNSIGNED) static void _zeroextend( t_longint* longint) { int idx; idx = longint->length - 1; for (; ++idx <= (int)MAXIDX;) longint->value[idx] = 0; } signed char _signof( t_longint* longint) { return (longint->value[MAXIDX] & (1 << SIGNBIT)) != 0? -1:1; } static char _signextend( t_longint* longint) { unsigned mask; signed char sign; sign = _signof(longint); - mask = (~0) << SIGNBIT; + mask = (unsigned)(~0) << SIGNBIT; if (sign < 0) longint->value[MAXIDX] |= mask; else longint->value[MAXIDX] &= ~mask; return sign; } static void _neg( t_longint* longint) { int idx = -1; const int maxidx = MAXIDX; while (++idx <= maxidx && longint->value[idx] == 0); if (idx <= maxidx) longint->value[idx] = - longint->value[idx]; while (++idx <= maxidx) longint->value[idx] = ~longint->value[idx]; } char _floatnum2logic( t_longint* longint, cfloatnum x) { floatstruct tmp; int digits; digits = float_getexponent(x)+1; if (float_iszero(x) || digits <= 0) { longint->length = 1; longint->value[0] = 0; } else { if (digits > MATHPRECISION) return 0; float_create(&tmp); /* floatnum2longint rounds, we have to truncate first */ float_copy(&tmp, x, digits); if (float_getsign(x) < 0) float_add(&tmp, &tmp, &c1, EXACT); _floatnum2longint(longint, &tmp); float_free(&tmp); if (_bitlength(longint) > LOGICRANGE) return 0; } _zeroextend(longint); if (float_getsign(x) < 0) _not(longint); return 1; } void _logic2floatnum( floatnum f, t_longint* longint) { int idx; signed char sign; sign = _signextend(longint); if (sign < 0) _neg(longint); idx = MAXIDX; while (idx >= 0 && longint->value[idx] == 0) --idx; if (idx < 0) longint->length = 0; else longint->length = idx + 1; _longint2floatnum(f, longint); float_setsign(f, sign); } void _not( t_longint* longint) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) longint->value[idx] = ~(longint->value[idx]); } void _and( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] & x2->value[idx]; } void _or( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] | x2->value[idx]; } void _xor( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] ^ x2->value[idx]; } void _shr( t_longint* x, unsigned shift) { int idx; const unsigned sign = _signof(x) < 0? ~0 : 0; const int moves = shift/BITS_IN_UNSIGNED; const int maxidx = MAXIDX; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = moves-1; ++idx <= maxidx;) x->value[idx-moves] = x->value[idx]; idx = MAXIDX - moves + 1; if (idx < 0) idx = 0; for (; idx <= maxidx; ++idx) x->value[idx] = sign; } if (shift > 0) { for (idx = -1; ++idx < maxidx;) x->value[idx] = _longshr(x->value[idx], x->value[idx+1], shift); x->value[MAXIDX] = _longshr(x->value[MAXIDX], sign, shift); } } void _shl( t_longint* x, unsigned shift) { int moves, idx; moves = shift/BITS_IN_UNSIGNED; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = MAXIDX; idx >= moves; --idx) x->value[idx] = x->value[idx-moves]; if (moves > (int)MAXIDX) moves = MAXIDX+1; for (idx = -1; ++idx < moves;) x->value[idx] = 0; } if (shift > 0) { for (idx = MAXIDX; idx > 0; --idx) x->value[idx] = _longshl(x->value[idx-1], x->value[idx], shift); x->value[0] <<= shift; } }