diff --git a/CHANGELOG b/CHANGELOG index a224f32..66ec304 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,10 @@ +Version 0.6.3 (2007.01.22): + * position of arguments (x and base) in logarithm functions are swapped + * it's possible to use any multiplication algorithms in the same time + (macros UINT_MUL_VERSION_'X' have gone) + * added ExceptionInfo, ReferenceError and RuntimeError classes + * the mess in macros has been cleaned up + * added TTMATH_RELEASE macro + Version 0.6.2 (2007.01.10): * New division algorithm (radix b) where b is 2^32 - - diff --git a/TODO b/TODO index 5ce5641..62a1eb5 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,5 @@ TODO TTMath Library =================== - - - +* add the method Mod (a remainder from a division) for the Big type diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 960cd64..7f7f296 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -59,10 +59,10 @@ namespace ttmath e.g. Factorial(4) = 4! = 1*2*3*4 */ - template - Big Factorial(const Big & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) + template + ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) { - Big result; + ValueType result; result.SetOne(); @@ -76,17 +76,17 @@ namespace ttmath if( !x.exponent.IsSign() && !x.exponent.IsZero() ) { - // when x>0 there's no sense to calculate the formula + // when x.exponent>0 there's no sense to calculate the formula // (we can't add one into the x bacause - // we don't have enough bits in our mantissa) + // we don't have enough bits in the mantissa) if( err ) *err = err_overflow; return result; } - Big multipler; - Big one; + ValueType multipler; + ValueType one; uint carry = 0; one = result; // =1 @@ -124,10 +124,10 @@ namespace ttmath e.g. -2 = 2 2 = 2 */ - template - Big Abs(const Big & x) + template + ValueType Abs(const ValueType & x) { - Big result( x ); + ValueType result( x ); result.Abs(); return result; @@ -141,10 +141,10 @@ namespace ttmath -2.2 = 2 -2.7 = 2 */ - template - Big SkipFraction(const Big & x) + template + ValueType SkipFraction(const ValueType & x) { - Big result( x ); + ValueType result( x ); result.SkipFraction(); return result; @@ -158,10 +158,10 @@ namespace ttmath -2.2 = -2 -2.7 = -3 */ - template - Big Round(const Big & x) + template + ValueType Round(const ValueType & x) { - Big result( x ); + ValueType result( x ); result.Round(); return result; @@ -171,10 +171,10 @@ namespace ttmath /*! this method calculates the natural logarithm (logarithm with the base 'e') */ - template - Big Ln(const Big & x, ErrorCode * err = 0) + template + ValueType Ln(const ValueType & x, ErrorCode * err = 0) { - Big result; + ValueType result; uint state = result.Ln(x); @@ -205,12 +205,12 @@ namespace ttmath /*! this method calculates the logarithm */ - template - Big Log(const Big & base, const Big & x, ErrorCode * err = 0) + template + ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) { - Big result; + ValueType result; - uint state = result.Log(base,x); + uint state = result.Log(x, base); if( err ) { @@ -239,10 +239,10 @@ namespace ttmath /*! this method calculates the expression e^x */ - template - Big Exp(const Big & x, ErrorCode * err = 0) + template + ValueType Exp(const ValueType & x, ErrorCode * err = 0) { - Big result; + ValueType result; uint state = result.Exp(x); @@ -267,10 +267,10 @@ namespace ttmath an auxiliary function for calculating the Sin (you don't have to call this function) */ - template - void PrepareSin(Big & x, bool & change_sign) + template + void PrepareSin(ValueType & x, bool & change_sign) { - Big temp; + ValueType temp; change_sign = false; @@ -332,13 +332,13 @@ namespace ttmath and when a=PI/2: sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... */ - template - Big Sin0pi05(const Big & x) + template + ValueType Sin0pi05(const ValueType & x) { - Big result; - Big numerator, denominator; - Big d_numerator, d_denominator; - Big one, temp, old_result; + ValueType result; + ValueType numerator, denominator; + ValueType d_numerator, d_denominator; + ValueType one, temp, old_result; // temp = pi/4 temp.Set05Pi(); @@ -367,7 +367,7 @@ namespace ttmath denominator = one; // d_numerator = (x-pi/2)^2 - Big pi05; + ValueType pi05; pi05.Set05Pi(); temp = x; @@ -382,7 +382,7 @@ namespace ttmath bool addition = false; old_result = result; - for(int i=1 ; i<5000 ; ++i) + for(int i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { // we're starting from a second part of the formula c += numerator. Mul( d_numerator ); @@ -424,21 +424,24 @@ namespace ttmath /*! this function calulates the Sin */ - template - Big Sin(Big x) + template + ValueType Sin(ValueType x) { - Big one; + ValueType one; bool change_sign; PrepareSin( x, change_sign ); - Big result = Sin0pi05( x ); + ValueType result = Sin0pi05( x ); one.SetOne(); + // after calculations there can be small distortions in the result if( result > one ) result = one; else if( result.IsSign() ) + // we've calculated the sin from <0, pi/2> and the result + // should be positive result.SetZero(); if( change_sign ) @@ -452,10 +455,10 @@ namespace ttmath this function calulates the Cos we're using the formula cos(x) = sin(x + PI/2) */ - template - Big Cos(Big x) + template + ValueType Cos(ValueType x) { - Big pi05; + ValueType pi05; pi05.Set05Pi(); x.Add( pi05 ); @@ -469,15 +472,15 @@ namespace ttmath we're using the formula tan(x) = sin(x) / cos(x) it takes more time than calculating the Tan directly - from for example Taylor series but should be a bit precise + from for example Taylor series but should be a bit preciser because Tan receives its values from -infinity to +infinity and when we calculate it from any series then we can make a small mistake than calculating 'sin/cos' */ - template - Big Tan(const Big & x, ErrorCode * err = 0) + template + ValueType Tan(const ValueType & x, ErrorCode * err = 0) { - Big result = Cos(x); + ValueType result = Cos(x); if( result.IsZero() ) { @@ -499,12 +502,12 @@ namespace ttmath we're using the formula tan(x) = cos(x) / sin(x) (why do we make it in this way? - look at the info in Tan() function) + look at information in Tan() function) */ - template - Big CTan(const Big & x, ErrorCode * err = 0) + template + ValueType CTan(const ValueType & x, ErrorCode * err = 0) { - Big result = Sin(x); + ValueType result = Sin(x); if( result.IsZero() ) { diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 3995fe1..470e5b1 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -204,7 +204,7 @@ public: // (first is the highest word) mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint)); - exponent = -int(man)*int(BITS_PER_UINT) + 2; + exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2; info = 0; } @@ -215,7 +215,7 @@ public: void Set05Pi() { SetPi(); - exponent = -int(man)*int(BITS_PER_UINT) + 1; + exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 1; } @@ -225,7 +225,7 @@ public: void Set2Pi() { SetPi(); - exponent = -int(man)*int(BITS_PER_UINT) + 3; + exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 3; } @@ -249,7 +249,7 @@ public: }; mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint)); - exponent = -int(man)*int(BITS_PER_UINT) + 2; + exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2; info = 0; } @@ -274,7 +274,7 @@ public: }; mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint)); - exponent = -int(man)*int(BITS_PER_UINT); + exponent = -int(man)*int(TTMATH_BITS_PER_UINT); info = 0; } @@ -394,7 +394,7 @@ public: uint Add(Big ss2) { Int exp_offset( exponent ); - Int mantissa_size_in_bits( man * BITS_PER_UINT ); + Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); int c = 0; exp_offset.Sub( ss2.exponent ); @@ -472,22 +472,22 @@ public: */ uint Mul(const Big & ss2) { - MATHTT_THIS_ASSERT( ss2 ) + TTMATH_REFERENCE_ASSERT( ss2 ) UInt man_result; int i,c; // man_result = mantissa * ss2.mantissa - mantissa.Mul(ss2.mantissa, man_result); + mantissa.MulBig(ss2.mantissa, man_result); - // 'i' will be from 0 to man*BITS_PER_UINT + // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT // because mantissa and ss2.mantissa are standardized // (the highest bit in man_result is set to 1 or // if there is a zero value in man_result the method CompensationToLeft() // returns 0 but we'll correct this at the end in Standardizing() method) i = man_result.CompensationToLeft(); - c = exponent.Add( man * BITS_PER_UINT - i ); + c = exponent.Add( man * TTMATH_BITS_PER_UINT - i ); c += exponent.Add( ss2.exponent ); for(i=0 ; i & ss2) { - MATHTT_THIS_ASSERT( ss2 ) + TTMATH_REFERENCE_ASSERT( ss2 ) UInt man1; UInt man2; @@ -635,15 +635,15 @@ public: */ bool Mod2() const { - if( exponent>int(0) || exponent<=-int(man*BITS_PER_UINT) ) + if( exponent>int(0) || exponent<=-int(man*TTMATH_BITS_PER_UINT) ) return false; int exp_int = exponent.ToInt(); // 'exp_int' is negative (or zero), we set its as positive exp_int = -exp_int; - int value = mantissa.table[ exp_int / BITS_PER_UINT ]; - value >>= (exp_int % BITS_PER_UINT); + int value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ]; + value >>= (exp_int % TTMATH_BITS_PER_UINT); return bool(value & 1); } @@ -696,7 +696,7 @@ public: */ uint PowBInt(const Big & pow) { - MATHTT_THIS_ASSERT( pow ) + TTMATH_REFERENCE_ASSERT( pow ) if( !pow.IsSign() ) return PowBUInt(pow); @@ -745,7 +745,7 @@ public: int Pow(const Big pow) #endif { - MATHTT_THIS_ASSERT( pow ) + TTMATH_REFERENCE_ASSERT( pow ) if( IsZero() ) { @@ -789,7 +789,7 @@ private: */ void ExpSurrounding0(const Big & x) { - MATHTT_THIS_ASSERT( x ) + TTMATH_REFERENCE_ASSERT( x ) Big denominator, denominator_i; Big one, old_value, next_part; @@ -800,13 +800,12 @@ private: denominator.SetOne(); denominator_i.SetOne(); - // we assume only 'max_loop' iterations of our loop + // every 'step_test' times we make a test - const uint max_loop = 2000; const uint step_test = 5; // we begin from 1 in order to not testing at the start - for(uint i=1 ; i<=max_loop ; ++i) + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { bool testing = ((i % step_test) == 0); @@ -870,18 +869,18 @@ public: // m will be the value of the mantissa in range (-1,1) Big m(x); - m.exponent = -int(man*BITS_PER_UINT); + m.exponent = -int(man*TTMATH_BITS_PER_UINT); // 'e_' will be the value of '2^exponent' - // e_.mantissa.table[man-1] = uint_the_highest_bit; and + // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and // e_.exponent.Add(1) mean: // e_.mantissa.table[0] = 1; // e_.Standardizing(); - // e_.exponent.Add(man*BITS_PER_UINT) - // (we must add 'man*BITS_PER_UINT' because we've taken it from the mantissa) + // e_.exponent.Add(man*TTMATH_BITS_PER_UINT) + // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa) Big e_(x); e_.mantissa.SetZero(); - e_.mantissa.table[man-1] = uint_the_highest_bit; + e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; c += e_.exponent.Add(1); e_.Abs(); @@ -957,13 +956,12 @@ private: denominator.SetOne(); SetZero(); - // we assume only 'max_loop' iterations of our loop // every 'step_test' times we make a test - const uint max_loop = 2000; + const uint step_test = 5; // we begin from 1 in order to not testing at the beginning - for(uint i=1 ; i< max_loop+1 ; ++i) + for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { bool testing = ((i % step_test) == 0); @@ -1026,21 +1024,21 @@ public: */ uint Ln(const Big & x) { - MATHTT_THIS_ASSERT( x ) + TTMATH_REFERENCE_ASSERT( x ) if( x.IsSign() || x.IsZero() ) return 2; // m will be the value of the mantissa in range <1,2) Big m(x); - m.exponent = -int(man*BITS_PER_UINT - 1); + m.exponent = -int(man*TTMATH_BITS_PER_UINT - 1); LnSurrounding1(m); Big exponent_temp; exponent_temp.FromInt( x.exponent ); - // we must add 'man*BITS_PER_UINT-1' because we've taken it from the mantissa - uint c = exponent_temp.Add(man*BITS_PER_UINT-1); + // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa + uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1); Big ln2; ln2.SetLn2(); @@ -1071,10 +1069,10 @@ public: because if we passed 'parts' into 'ln(base)' as well then the error (after dividing) would be too great */ - uint Log(const Big & base, const Big & x) + uint Log(const Big & x, const Big & base) { - MATHTT_THIS_ASSERT( base ) - MATHTT_THIS_ASSERT( x ) + TTMATH_REFERENCE_ASSERT( base ) + TTMATH_REFERENCE_ASSERT( x ) if( x.IsSign() || x.IsZero() ) return 2; @@ -1125,10 +1123,10 @@ public: if( IsZero() ) return 0; - int maxbit = -int(man*BITS_PER_UINT); + int maxbit = -int(man*TTMATH_BITS_PER_UINT); - if( exponent > maxbit + int(BITS_PER_UINT) ) - // if exponent > (maxbit + int(BITS_PER_UINT)) the value can't be passed + if( exponent > maxbit + int(TTMATH_BITS_PER_UINT) ) + // if exponent > (maxbit + int(TTMATH_BITS_PER_UINT)) the value can't be passed // into the 'int' type (it's too big) return 1; @@ -1144,14 +1142,14 @@ public: how_many_bits = -how_many_bits; // we're taking into an account only the last word in a mantissa table - mantissa_temp.Rcr( how_many_bits % BITS_PER_UINT, 0 ); + mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); result = mantissa_temp.table[ man-1 ]; // the exception for the minimal value - if( IsSign() && result == uint_the_highest_bit ) + if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT ) return 0; - if( (result & uint_the_highest_bit) != 0 ) + if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 ) // the value is too big return 1; @@ -1175,10 +1173,10 @@ public: if( IsZero() ) return 0; - int maxbit = -int(man*BITS_PER_UINT); + int maxbit = -int(man*TTMATH_BITS_PER_UINT); - if( exponent > maxbit + int(int_size*BITS_PER_UINT) ) - // if exponent > (maxbit + int(int_size*BITS_PER_UINT)) the value can't be passed + if( exponent > maxbit + int(int_size*TTMATH_BITS_PER_UINT) ) + // if exponent > (maxbit + int(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed // into the 'Int' type (it's too big) return 1; @@ -1192,20 +1190,20 @@ public: if( how_many_bits < 0 ) { how_many_bits = -how_many_bits; - uint index = how_many_bits / BITS_PER_UINT; - mantissa_temp.Rcr( how_many_bits % BITS_PER_UINT, 0 ); + uint index = how_many_bits / TTMATH_BITS_PER_UINT; + mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); for(uint i=index, a=0 ; i new_exp_; - c += new_exp_.ToString_Log(base, temp); // this logarithm isn't very complicated + c += new_exp_.ToString_Log(temp, base); // this logarithm isn't very complicated new_exp_.SkipFraction(); temp.SetOne(); c += new_exp_.Add( temp ); @@ -1628,9 +1626,9 @@ private: x is greater than 0 base is in <2,16> range */ - uint ToString_Log(uint base, const Big & x) + uint ToString_Log(const Big & x, uint base) { - MATHTT_THIS_ASSERT( x ) + TTMATH_REFERENCE_ASSERT( x ) Big temp; temp.SetOne(); @@ -1691,13 +1689,13 @@ private: if( !exponent.IsSign() ) return 1; - if( exponent <= -int(man*BITS_PER_UINT) ) - // if 'exponent' is <= than '-int(man*BITS_PER_UINT)' + if( exponent <= -int(man*TTMATH_BITS_PER_UINT) ) + // if 'exponent' is <= than '-int(man*TTMATH_BITS_PER_UINT)' // it means that we must cut the whole mantissa // (there'll not be any of the valid bits) return 1; - // e will be from (-man*BITS_PER_UINT, 0> + // e will be from (-man*TTMATH_BITS_PER_UINT, 0> int e = -( exponent.ToInt() ); mantissa.Rcr(e,0); @@ -1723,9 +1721,9 @@ private: { uint value = mantissa.table[i]; - for( unsigned int bit=0 ; bit0 && new_man[i]==MATHTT_COMMA_CHARACTER_1 ) + if( i>0 && new_man[i]==TTMATH_COMMA_CHARACTER_1 ) --i; new_man.erase(i+1, new_man.length()-i-1); @@ -2010,7 +2008,7 @@ private: int max_digit_after_comma) const { // first we're looking for the comma operator - std::string::size_type index = new_man.find(MATHTT_COMMA_CHARACTER_1, 0); + std::string::size_type index = new_man.find(TTMATH_COMMA_CHARACTER_1, 0); if( index == std::string::npos ) // nothing was found (actually there can't be this situation) @@ -2154,8 +2152,8 @@ private: */ bool FromString_TestCommaOperator(const char * & source) { - if( (*source == MATHTT_COMMA_CHARACTER_1) || - (*source == MATHTT_COMMA_CHARACTER_2 && MATHTT_COMMA_CHARACTER_2 != 0 ) ) + if( (*source == TTMATH_COMMA_CHARACTER_1) || + (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) { ++source; @@ -2662,14 +2660,14 @@ public: // exponent >=0 -- the value don't have any fractions return; - if( exponent <= -int(man*BITS_PER_UINT) ) + if( exponent <= -int(man*TTMATH_BITS_PER_UINT) ) { // the value is from (-1,1), we return zero SetZero(); return; } - // exponent is in range (-man*BITS_PER_UINT, 0) + // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) int e = exponent.ToInt(); mantissa.ClearFirstBits( -e ); @@ -2700,17 +2698,17 @@ public: return; } - if( exponent <= -int(man*BITS_PER_UINT) ) + if( exponent <= -int(man*TTMATH_BITS_PER_UINT) ) { // the value is from (-1,1) // we don't make anything with the value return; } - // e will be from (-man*BITS_PER_UINT, 0) + // e will be from (-man*TTMATH_BITS_PER_UINT, 0) int e = exponent.ToInt(); - int how_many_bits_leave = man*BITS_PER_UINT + e; // there'll be a subtraction -- e is negative + int how_many_bits_leave = man*TTMATH_BITS_PER_UINT + e; // there'll be a subtraction -- e is negative mantissa.Rcl( how_many_bits_leave, 0); // there'll not be a carry because the exponent is too small @@ -2797,10 +2795,10 @@ public: // we're reading only digits (base=10) and only one comma operator while( s.good() && - ( UInt::CharToDigit(z, 10)>=0 || (!was_comma && z==MATHTT_COMMA_CHARACTER_1) ) + ( UInt::CharToDigit(z, 10)>=0 || (!was_comma && z==TTMATH_COMMA_CHARACTER_1) ) ) { - if( z == MATHTT_COMMA_CHARACTER_1 ) + if( z == TTMATH_COMMA_CHARACTER_1 ) was_comma = true; ss += z; diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index 4b2553b..d0586b0 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -69,7 +69,7 @@ public: void SetMaxValue() { UInt::SetMaxValue(); - UInt::table[value_size-1] = ~uint_the_highest_bit; + UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; } @@ -80,7 +80,7 @@ public: void SetMinValue() { UInt::SetZero(); - UInt::table[value_size-1] = uint_the_highest_bit; + UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; } @@ -421,14 +421,14 @@ public: if( i < value_size ) { - uint fill = (p.table[argument_size-1] & uint_the_highest_bit)? uint_max_value : 0; + uint fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0; for( ; i::table[i] = fill; } else { - uint test = (UInt::table[value_size-1] & uint_the_highest_bit)? uint_max_value : 0; + uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0; for( ; i */ diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index 8ba62f8..ebf2cce 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -81,7 +81,7 @@ namespace ttmath "1" "2.1234" "2,1234" (they are the same, we can either use a comma or a dot in values) - (look at the macro MATHTT_COMMA_CHARACTER_2) + (look at the macro TTMATH_COMMA_CHARACTER_2) "1 + 2" "(1 + 2) * 3" "pi" diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index af84c27..24b3a9f 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -36,24 +36,24 @@ */ - #ifndef headerfilettmathtypes #define headerfilettmathtypes /*! \file ttmathtypes.h - \brief A Documented file. + \brief constants which are used in the library - Details. + As our library is written in header files (templates) we cannot use + constants like 'const int' etc. because we should have some source files + *.cpp to define this variables. Only what we can have are constants + defined by #define preprocessor macro. + + All macros are preceded TTMATH_ part */ -#include -#include -#include -#include - - +#include +#include /*! @@ -61,95 +61,92 @@ */ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 6 -#define TTMATH_REVISION_VER 2 - - - - - - +#define TTMATH_REVISION_VER 3 /*! + TTMATH_DEBUG this macro enables further testing during writing your code you don't have to define it in a release mode - if this macro is set then macro MATHTT_ASSERT is set as well - and MATHTT_ASSERT can throw an exception if a condition is not fulfilled - (look at the definition of MATHTT_ASSERT) + if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT + are set as well and these macros can throw an exception if a condition in it + is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) - if you don't want any further testing put two characters '//' before this macro - e.g. - // #define MATHTT_DEBUG + TTMATH_RELEASE + if you are confident that your code is without bugs you can define TTMATH_RELEASE + macro for example by using -D option in gcc + gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp + or by defining this macro in your code before using any header files of this library + + if TTMATH_RELEASE is not set then TTMATH_DEBUG is set */ -#define MATHTT_DEBUG +#ifndef TTMATH_RELEASE + #define TTMATH_DEBUG +#endif -/*! - 32 bit integer value without a sign - (the same on 64 bits platform (amd)) -*/ -typedef unsigned int uint; +namespace ttmath +{ + /*! + 32 bit integer value without a sign + (on 64bit platforms will be 32bit as well) + */ + typedef unsigned int uint; +} /*! how many bits there are in the uint type */ -#define BITS_PER_UINT 32u +#define TTMATH_BITS_PER_UINT 32u /*! - the mask for the highest bit in the unsigned 32bits word (2^31) + the mask for the highest bit in the unsigned 32bit word (2^31) */ -#define uint_the_highest_bit 2147483648u +#define TTMATH_UINT_HIGHEST_BIT 2147483648u /*! - the max value of the unsigned 32bits word (2^32 - 1) + the max value of the unsigned 32bit word (2^32 - 1) (all bits equal one) */ -#define uint_max_value 4294967295u - - -/*! - if you define this macro that means the version one of the multiplication algorithm - will be used in the UInt class -*/ -//#define UINT_MUL_VERSION_1 - - - -/*! - if you define this macro that means the version two of the multiplication algorithm - will be used in the UInt class - - this algorithm is much faster than previous - - you can't use both these macros together, you must use either UINT_MUL_VERSION_1 - or UINT_MUL_VERSION_2 -*/ -#define UINT_MUL_VERSION_2 - +#define TTMATH_UINT_MAX_VALUE 4294967295u /*! characters which represent the comma operator - MATHTT_COMMA_CHARACTER_1 is used in reading (parsing) and in writing - MATHTT_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character + TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing + TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character that means you can input values for example 1.2345 and 1,2345 as well if you don't want it just put 0 there eg. - #define MATHTT_COMMA_CHARACTER_2 0 - then only MATHTT_COMMA_CHARACTER_1 will be used + #define TTMATH_COMMA_CHARACTER_2 0 + then only TTMATH_COMMA_CHARACTER_1 will be used don't put here any special character which is used by the parser (for example a semicolon ';' shouldn't be here) */ -#define MATHTT_COMMA_CHARACTER_1 '.' -#define MATHTT_COMMA_CHARACTER_2 ',' -////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -//// odwrocic nazwy ma byc TTMATH +#define TTMATH_COMMA_CHARACTER_1 '.' +#define TTMATH_COMMA_CHARACTER_2 ',' + + +/*! + this variable defines how many iterations are performed + during some kind of calculating when we're making any long formulas + (for example Taylor series) + + it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. + + note! there'll not be so many iterations, iterations are stopped when + there is no sense to continue calculating (for example when the result + still remains unchanged after adding next series and we know that the next + series are smaller than previous) +*/ +#define TTMATH_ARITHMETIC_MAX_LOOP 5000 + @@ -162,37 +159,34 @@ namespace ttmath enum ErrorCode { err_ok = 0, - err_nothing_has_read = 1, - err_unknown_character = 2, - err_unexpected_final_bracket = 4, - err_stack_not_clear = 6, - err_unknown_variable = 8, - err_division_by_zero = 9, - err_interrupt = 10, - err_overflow = 11, - err_unknown_function = 12, - err_unexpected_semicolon_operator = 18, - err_improper_amount_of_arguments = 19, - err_improper_argument = 20, - err_unexpected_end = 21, - err_internal_error = 100, - + err_nothing_has_read, + err_unknown_character, + err_unexpected_final_bracket, + err_stack_not_clear, + err_unknown_variable, + err_division_by_zero, + err_interrupt, + err_overflow, + err_unknown_function, + err_unexpected_semicolon_operator, + err_improper_amount_of_arguments, + err_improper_argument, + err_unexpected_end, + err_internal_error, err_incorrect_name, err_incorrect_value, err_variable_exists, err_variable_loop, err_functions_loop, err_must_be_only_one_value, - err_object_exists, - err_unknown_object, - - - err_this_cant_be_used = 200 + err_unknown_object }; + /*! + */ class StopCalculating { public: @@ -201,84 +195,135 @@ namespace ttmath }; + /*! + a small class which is useful when compiling with gcc - - - - -// moze tutaj z runtime dziedziczyc? - //zmienic nazwe na TTMathError - class MathTTError : public std::exception + object of this type holds the name and the line of a file + in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used + */ + class ExceptionInfo { - ErrorCode code; + const char * file; + int line; public: - MathTTError(ErrorCode c) : code(c) {} - const char* what() const throw() - { - switch( code ) - { - case err_this_cant_be_used: - return "You've used 'this' somewhere in your code but you can't use it there"; - // dac tu jakis lepszy komunikat w stylu - // 'uzyles referencji do samego siebie ale w tym miejscu nie mozesz tego zrobic' - default: - return ":)"; // temporary - } + ExceptionInfo() : file(0), line(0) {} + ExceptionInfo(const char * f, int l) : file(f), line(l) {} - return "Unnamed"; + std::string Where() const + { + if( !file ) + return "unknown"; + + std::ostringstream result; + result << file << ":" << line; + + return result.str(); } }; - #ifdef MATHTT_DEBUG - #define MATHTT_ASSERT(expression, c) \ - if( !(expression) ) throw MathTTError(c); + + /*! + A small class used for reporting 'reference' errors + + In the library is used macro TTMATH_REFERENCE_ASSERT which + can throw an exception of this type + + If you compile with gcc you can get a small benefit + from using method Where() (it returns std::string with + the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT + was used) + + What is it the 'reference' error? + Some kind of methods use a reference as their argument to another object, + and the another object not always can be the same which is calling, e.g. + Big<1,2> foo(10); + foo.Mul(foo); // this is incorrect + above method Mul is making something more with 'this' object and + 'this' cannot be passed as the argument because the result will be undefined + + macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem + + note! some methods can use 'this' object as the argument + for example this code is correct: + UInt<2> foo(10); + foo.Add(foo); + but there are only few methods which can do that + */ + class ReferenceError : public std::logic_error, ExceptionInfo + { + public: + + ReferenceError() : std::logic_error ("reference error") + { + } + + ReferenceError(const char * f, int l) : + std::logic_error ("reference error"), ExceptionInfo(f,l) + { + } + + std::string Where() const + { + return ExceptionInfo::Where(); + } + }; + + + /*! + a small class used for reporting errors + + in the library is used macro TTMATH_ASSERT which + (if the condition in it is false) throw an exception + of this type + + if you compile with gcc you can get a small benefit + from using method Where() (it returns std::string with + the name and the line of a file where the macro TTMATH_ASSERT + was used) + */ + class RuntimeError : public std::runtime_error, ExceptionInfo + { + public: + + RuntimeError() : std::runtime_error ("internal error") + { + } + + RuntimeError(const char * f, int l) : + std::runtime_error ("internal error"), ExceptionInfo(f,l) + { + } + + std::string Where() const + { + return ExceptionInfo::Where(); + } + }; + + + + #ifdef TTMATH_DEBUG + #ifdef __GNUC__ + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ReferenceError(__FILE__, __LINE__); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw RuntimeError(__FILE__, __LINE__); + #else + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ReferenceError(); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw RuntimeError(); + #endif #else - #define MATHTT_ASSERT(expression, c) + #define TTMATH_REFERENCE_ASSERT(expression) + #define TTMATH_ASSERT(expression) #endif - #define MATHTT_THIS_ASSERT(expression) \ - MATHTT_ASSERT( &expression != this, err_this_cant_be_used) - - - -/* - template - class ValuesHistory - { - typedef std::map buffer_type; - buffer_type buffer; - - public: - - void AddValue(const ValueType & key, const ValueType & result) - { - buffer.insert( std::make_pair(key, result) ); - } - - bool GetValue(const ValueType & key, ValueType & result) const - { - buffer_type::iterator i = buffer.find( key ); - - if( i == buffer.end() ) - return false; - - result = *i; - - return true; - } - - uint Size() const - { - return static_cast( buffer.size() ); - } - }; -*/ } // namespace - - - #endif diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index a3f72e0..aee561c 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -1,5 +1,5 @@ /* - * This file is part of TTMath Mathematical Library + * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -50,8 +50,6 @@ #define TTMATH_UINT_GUARD 1234567891 -// !!! -extern bool bylocos; namespace ttmath { @@ -113,7 +111,7 @@ public: void SetMaxValue() { for(uint i=0 ; i + bits is from a range of <0, man * TTMATH_BITS_PER_UINT> or it can be even bigger then all bits will be set to 'c' the value c will be set into the lowest bits @@ -811,10 +809,10 @@ public: int second; int last_c = 0; - if( bits > value_size*BITS_PER_UINT ) - bits = value_size*BITS_PER_UINT; + if( bits > value_size*TTMATH_BITS_PER_UINT ) + bits = value_size*TTMATH_BITS_PER_UINT; - int all_words = int(bits) / int(BITS_PER_UINT); + int all_words = int(bits) / int(TTMATH_BITS_PER_UINT); if( all_words > 0 ) { @@ -826,12 +824,12 @@ public: } // sets the rest bits of value into 'c' - uint mask = (c!=0)? uint_max_value : 0; + uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0; for( ; first>=0 ; --first ) table[first] = mask; } - int rest_bits = int(bits) % int(BITS_PER_UINT); + int rest_bits = int(bits) % int(TTMATH_BITS_PER_UINT); for( ; rest_bits > 0 ; --rest_bits ) last_c = Rcl(c); @@ -843,7 +841,7 @@ public: this method moving all bits into the right side 'bits' times c -> this -> return value - bits is from a range of <0, man * BITS_PER_UINT> + bits is from a range of <0, man * TTMATH_BITS_PER_UINT> or it can be even bigger then all bits will be set to 'c' the value c will be set into the highest bits @@ -855,17 +853,17 @@ public: int second; int last_c = 0; - if( bits > value_size*BITS_PER_UINT ) - bits = value_size*BITS_PER_UINT; + if( bits > value_size*TTMATH_BITS_PER_UINT ) + bits = value_size*TTMATH_BITS_PER_UINT; - int all_words = int(bits) / int(BITS_PER_UINT); + int all_words = int(bits) / int(TTMATH_BITS_PER_UINT); if( all_words > 0 ) { // copying the first part of the value for(first=0, second=all_words ; second 0 ; --rest_bits ) last_c = Rcr(c); @@ -906,7 +904,7 @@ public: if( a != value_size-1 ) { - moving += ( value_size-1 - a ) * BITS_PER_UINT; + moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; // moving all words int i; @@ -918,7 +916,7 @@ public: table[i] = 0; } - // moving the rest bits (max BITS_PER_UINT -- only one word) + // moving the rest bits (max TTMATH_BITS_PER_UINT -- only one word) while( !IsTheHighestBitSet() ) { Rcl(); @@ -1011,11 +1009,11 @@ public: */ void SetBit(uint bit_index) { - uint index = bit_index / BITS_PER_UINT; + uint index = bit_index / TTMATH_BITS_PER_UINT; if( index >= value_size ) return; - bit_index %= BITS_PER_UINT; + bit_index %= TTMATH_BITS_PER_UINT; uint result = 1; if( bit_index > 0 ) @@ -1025,75 +1023,14 @@ public: } + /*! + * + * Multiplication + * + * + */ - #ifdef UINT_MUL_VERSION_1 - - /*! - the first version of the multiplication algorithm - */ - - /*! - multiplication: this = this * ss2 - - it returns carry if it has been - - we can't use a reference to the ss2 because someone can use this - method in this way: mul(*this) - */ - uint Mul(const UInt & ss2) - { - MATHTT_THIS_ASSERT( ss2 ) - - UInt ss1( *this ); - SetZero(); - - for(uint i=0; i < value_size*BITS_PER_UINT ; ++i) - { - if( Add(*this) ) - return 1; - - if( ss1.Rcl() ) - if( Add(ss2) ) - return 1; - } - - return 0; - } - - - /*! - multiplication: result = this * ss2 - - result is twice bigger than 'this' and 'ss2' - this method never returns carry - */ - void Mul(const UInt & ss2_, UInt & result) - { - UInt ss2; - uint i; - - // copying *this into result and ss2_ into ss2 - for(i=0 ; i u( *this ); + SetZero(); - - - #ifdef UINT_MUL_VERSION_2 - - /*! - the second version of the multiplication algorithm - - this algorithm is similar to the 'schoolbook method' which is done by hand - */ - - /*! - multiplication: this = this * ss2 - - it returns carry if it has been - */ - uint Mul(const UInt & ss2) + for(uint x1=0 ; x1 result; - uint i; + Mul64(u.table[x1], ss2, &r2, &r1 ); + + if( x1 <= value_size - 2 ) + { + if( AddTwoUints(x1,r2,r1) ) + return 1; + } + else + { + // last iteration: + // x1 = value_size - 1; - Mul(ss2, result); - - // copying result - for(i=0 ; i u( *this ); - SetZero(); - - for(uint x1=0 ; x1 & ss2, UInt & result) - { - uint r2,r1; - - result.SetZero(); - - for(uint x1=0 ; x1 & ss2, uint algorithm = 2) + { + switch( algorithm ) + { + case 1: + return Mul1(ss2); + + default: + return Mul2(ss2); + } + } + + + /*! + + */ + void MulBig(const UInt & ss2, + UInt & result, + uint algorithm = 2) + { + switch( algorithm ) + { + case 1: + return Mul1Big(ss2, result); + + default: + return Mul2Big(ss2, result); + } + } + + + + /*! + the first version of the multiplication algorithm + */ + + /*! + multiplication: this = this * ss2 + + it returns carry if it has been + + we can't use a reference to the ss2 because someone can use this + method in this way: mul(*this) + */ + uint Mul1(const UInt & ss2) + { + TTMATH_REFERENCE_ASSERT( ss2 ) + + UInt ss1( *this ); + SetZero(); + + for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) + { + if( Add(*this) ) + return 1; + + if( ss1.Rcl() ) + if( Add(ss2) ) + return 1; + } + + return 0; + } + + + /*! + multiplication: result = this * ss2 + + result is twice bigger than 'this' and 'ss2' + this method never returns carry + */ + void Mul1Big(const UInt & ss2_, UInt & result) + { + UInt ss2; + uint i; + + // copying *this into result and ss2_ into ss2 + for(i=0 ; i & ss2) + { + UInt result; + uint i; + + Mul2Big(ss2, result); + + // copying result + for(i=0 ; i & ss2, UInt & result) + { + uint r2,r1,x1size,x2size,x1start,x2start; + + result.SetZero(); + + for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); + for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); + + if( x1size==0 || x2size==0 ) + return; + + for(x1start=0 ; x1start & divisor, UInt & rest) { - MATHTT_THIS_ASSERT( divisor ) + TTMATH_REFERENCE_ASSERT( divisor ) int loop; int c; rest.SetZero(); - loop = value_size * BITS_PER_UINT; + loop = value_size * TTMATH_BITS_PER_UINT; c = 0; @@ -1593,7 +1641,7 @@ public: */ uint Div2(const UInt & divisor, UInt * remainder = 0) { - MATHTT_THIS_ASSERT( divisor ) + TTMATH_REFERENCE_ASSERT( divisor ) uint bits_diff; uint status = Div2_Calculate(divisor, remainder, bits_diff); @@ -1692,8 +1740,8 @@ private: return 0; } - divisor_index += divisor_table_id * BITS_PER_UINT; - index += table_id * BITS_PER_UINT; + divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; + index += table_id * TTMATH_BITS_PER_UINT; if( divisor_table_id == 0 ) { @@ -1790,7 +1838,7 @@ public: */ uint Div3(const UInt & v, UInt * remainder = 0) { - MATHTT_THIS_ASSERT( v ) + TTMATH_REFERENCE_ASSERT( v ) uint m,n, test; @@ -1830,7 +1878,7 @@ private: void Div3_Division(UInt v, UInt * remainder, uint m, uint n) { - MATHTT_ASSERT( n>=2, ttmath::err_internal_error ) + TTMATH_ASSERT( n>=2 ) UInt uu, vv; UInt q; @@ -1931,7 +1979,7 @@ private: { uint c = 0; - for( d = 0 ; (v.table[n-1] & uint_the_highest_bit) == 0 ; ++d ) + for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) { // we can move the bits only to the 'n-1' index but at the moment // we don't have such method @@ -1969,7 +2017,7 @@ private: u_temp.table[0] = u1; u_temp.DivInt(v1, &rp); - MATHTT_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1, ttmath::err_internal_error); + TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) do { @@ -2048,7 +2096,7 @@ public: */ void ClearFirstBits(uint n) { - if( n >= value_size*BITS_PER_UINT ) + if( n >= value_size*TTMATH_BITS_PER_UINT ) { SetZero(); return; @@ -2057,10 +2105,10 @@ public: uint * p = table; // first we're clearing the whole words - while( n >= BITS_PER_UINT ) + while( n >= TTMATH_BITS_PER_UINT ) { *p++ = 0; - n -= BITS_PER_UINT; + n -= TTMATH_BITS_PER_UINT; } if( n == 0 ) @@ -2068,7 +2116,7 @@ public: // and then we're clearing one word which has left // mask -- all bits are set to one - uint mask = uint_max_value; + uint mask = TTMATH_UINT_MAX_VALUE; mask = mask << n; @@ -2081,7 +2129,7 @@ public: */ bool IsTheHighestBitSet() const { - return (table[value_size-1] & uint_the_highest_bit) == uint_the_highest_bit; + return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) == TTMATH_UINT_HIGHEST_BIT; } @@ -2211,8 +2259,10 @@ public: table[i] = p.table[i]; - if( i < value_size ) + if( value_size > argument_size ) { + // 'this' is longer than 'p' + for( ; i