diff --git a/CHANGELOG b/CHANGELOG index c47a2ad..3b1f9f4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,39 @@ -Version 0.9.2 prerelease (2009.03.01): +Version 0.9.2 prerelease (2010.09.05): + * fixed: Big::Add() sometimes incorrectly rounded the last bit from its mantissa + * fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN + when the argument was negative (they only returned 2) + * fixed: recurrence calling in Big::FromString(const std::string &, uint, const wchar_t **, bool *) + it should have the signature: Big::FromString(const std::string &, uint, const char **, bool *) + * added: some missing operators + UInt::operator~() /* bitwise neg */ + UInt::operator&() /* bitwise and */ + UInt::operator&=() + UInt::operator|() /* bitwise or */ + UInt::operator|=() + UInt::operator^() /* bitwise xor */ + UInt::operator^=() + Big::operator&() + Big::operator&=() + Big::operator|() + Big::operator|=() + Big::operator^() + Big::operator^=() + for Big<> we do not define bitwise neg * added: macro TTMATH_DONT_USE_WCHAR if defined then the library does not use wide characters (wchar_t, std::wstring, ...) this is a workaround for some compilers + * added: bool UInt::IsOnlyTheHighestBitSet() + bool UInt::IsOnlyTheLowestBitSet() + returning true if only the highest/lowest bit is set + * added: uint Int::MulInt(sint ss2) + * added: void UInt::Swap(UInt & ss2) + void Big::Swap(UInt & ss2) + method for swapping this for an argument + * changed: now asm version is available only on x86 and amd64 + (and only for GCC and MS VC compilers) + * removed: macro TTMATH_RELEASE + for debug version define TTMATH_DEBUG macro + TTMATH_DEBUG is also automatically defined when DEBUG or _DEBUG is set Version 0.9.1 (2010.02.07): diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index be1e376..48f5f48 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -294,6 +294,20 @@ public: } + /*! + this method swappes this for an argument + */ + void Swap(Big & ss2) + { + unsigned char info_temp = info; + info = ss2.info; + ss2.info = info_temp; + + exponent.Swap(ss2.exponent); + mantissa.Swap(ss2.mantissa); + } + + private: /*! @@ -862,7 +876,7 @@ public: it returns carry if the sum is too big */ - uint Add(Big ss2, bool round = true) + uint Add(Big ss2, bool round = true, bool adding = true) { bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up; Int exp_offset( exponent ); @@ -871,18 +885,15 @@ public: if( IsNan() || ss2.IsNan() ) return CheckCarry(1); + if( !adding ) + ss2.ChangeSign(); // subtracting + exp_offset.Sub( ss2.exponent ); exp_offset.Abs(); // (1) abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) - { - // !! use Swap here (not implemented yet) - Big temp(ss2); - - ss2 = *this; - *this = temp; - } + Swap(ss2); if( ss2.IsZero() ) return 0; @@ -908,17 +919,14 @@ public: } - /*! Subtraction this = this - ss2 it returns carry if the result is too big */ - uint Sub(Big ss2, bool round = true) + uint Sub(const Big & ss2, bool round = true) { - ss2.ChangeSign(); - - return Add(ss2, round); + return Add(ss2, round, false); } @@ -961,12 +969,7 @@ public: // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) - { - Big temp(ss2); - - ss2 = *this; - *this = temp; - } + Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) { @@ -1024,12 +1027,7 @@ public: // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) - { - Big temp(ss2); - - ss2 = *this; - *this = temp; - } + Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) // the second value is too small @@ -1084,12 +1082,7 @@ public: // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) - { - Big temp(ss2); - - ss2 = *this; - *this = temp; - } + Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) // the second value is too small diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index a8af569..4b630fd 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -104,13 +104,10 @@ public: */ uint ChangeSign() { - Int temp; - - temp.SetMin(); - /* if the value is equal that one which has been returned from SetMin - that means we can't change sign because the value is too big (bigger about one) + (only the highest bit is set) that means we can't change sign + because the value is too big (bigger about one) e.g. when value_size = 1 and value is -2147483648 we can't change it to the 2147483648 because the max value which can be held is 2147483647 @@ -119,13 +116,12 @@ public: (if we look on our value without the sign we get the correct value eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) */ - if( operator==(temp) ) + if( UInt::IsOnlyTheHighestBitSet() ) return 1; - temp.SetZero(); - temp.UInt::Sub(*this); - - operator=(temp); + UInt temp(*this); + UInt::SetZero(); + UInt::Sub(temp); return 0; } @@ -350,33 +346,11 @@ public: } +private: - /*! - multiplication this = this * ss2 - it returns carry if the result is too big - (we're using the method from the base class but we have to make - one correction in account of signs) - */ - uint Mul(Int ss2) + uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign) { - bool ss1_is_sign, ss2_is_sign; - - ss1_is_sign = IsSign(); - ss2_is_sign = ss2.IsSign(); - - /* - we don't have to check the carry from Abs (values will be correct - because next we're using the method Mul from the base class UInt - which is without a sign) - */ - Abs(); - ss2.Abs(); - - if( UInt::Mul(ss2) ) - return 1; - - /* we have to examine the sign of the result now but if the result is with the sign then: @@ -391,36 +365,100 @@ public: */ if( IsSign() ) { - /* - there can be one case where signs are different and - the result will be equal the value from SetMin() - (this situation is ok) - */ if( ss1_is_sign != ss2_is_sign ) { - Int temp; - temp.SetMin(); - - if( operator!=(temp) ) - /* - the result is too big - */ + /* + there can be one case where signs are different and + the result will be equal the value from SetMin() (only the highest bit is set) + (this situation is ok) + */ + if( !UInt::IsOnlyTheHighestBitSet() ) return 1; } else { - /* - the result is too big - */ + // signs were the same return 1; } } + return 0; + } + + +public: + + + /*! + multiplication: this = this * ss2 + + it can return a carry + */ + uint MulInt(sint ss2) + { + bool ss1_is_sign, ss2_is_sign; + uint c; + + ss1_is_sign = IsSign(); + + /* + we don't have to check the carry from Abs (values will be correct + because next we're using the method MulInt from the base class UInt + which is without a sign) + */ + Abs(); + + if( ss2 < 0 ) + { + ss2 = -ss2; + ss2_is_sign = true; + } + else + { + ss2_is_sign = false; + } + + c = UInt::MulInt((uint)ss2); + c += CheckMinCarry(ss1_is_sign, ss2_is_sign); + if( ss1_is_sign != ss2_is_sign ) SetSign(); + return c; + } - return 0; + + + /*! + multiplication this = this * ss2 + + it returns carry if the result is too big + (we're using the method from the base class but we have to make + one correction in account of signs) + */ + uint Mul(Int ss2) + { + bool ss1_is_sign, ss2_is_sign; + uint c; + + ss1_is_sign = IsSign(); + ss2_is_sign = ss2.IsSign(); + + /* + we don't have to check the carry from Abs (values will be correct + because next we're using the method Mul from the base class UInt + which is without a sign) + */ + Abs(); + ss2.Abs(); + + c = UInt::Mul(ss2); + c += CheckMinCarry(ss1_is_sign, ss2_is_sign); + + if( ss1_is_sign != ss2_is_sign ) + SetSign(); + + return c; } diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index 3742a88..72222e2 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -56,11 +56,13 @@ #include #include + /*! the version of the library TTMATH_PRERELEASE_VER is either zero or one if zero that means this is the release version of the library + (one means something like beta) */ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 9 @@ -68,58 +70,66 @@ #define TTMATH_PRERELEASE_VER 1 -/*! - 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 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) - TTMATH_RELEASE - if you are confident that your code is perfect 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 !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64 + + #if !defined _M_X64 && !defined __x86_64__ + + /* + other platforms than x86 and amd64 are not recognized at the moment + so you should set TTMATH_PLATFORMxx manually + */ + + /*! + we're using a 32bit platform + */ + #define TTMATH_PLATFORM32 + + #else + + /*! + we're using a 64bit platform + */ + #define TTMATH_PLATFORM64 + + #endif - if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically -*/ -#ifndef TTMATH_RELEASE - #define TTMATH_DEBUG #endif +#if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64 + /*! + x86 architecture: + __i386__ defined by GNU C + _X86_ defined by MinGW32 + _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++ + + amd64 architecture: + __x86_64__ defined by GNU C and Sun Studio + _M_X64 defined by Visual Studio + + asm version is available only for x86 or amd64 platforms + */ + #define TTMATH_NOASM +#endif + + + +#if !defined _MSC_VER && !defined __GNUC__ + /*! + another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM) + */ + #define TTMATH_NOASM +#endif + + + + namespace ttmath { -#if !defined _M_X64 && !defined __x86_64__ - - /*! - we're using a 32bit platform - */ - #define TTMATH_PLATFORM32 - -#else - - /*! - we're using a 64bit platform - */ - #define TTMATH_PLATFORM64 - -#endif - - - -/*! - another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM) -*/ -#if !defined _MSC_VER && !defined __GNUC__ - #define TTMATH_NOASM -#endif - - #ifdef TTMATH_PLATFORM32 @@ -596,8 +606,21 @@ namespace ttmath /*! - look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG + 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 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) + + TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined */ + #if defined DEBUG || defined _DEBUG + #define TTMATH_DEBUG + #endif + + #ifdef TTMATH_DEBUG #if defined(__FILE__) && defined(__LINE__) diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index fa2ab87..9b55bcb 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -233,6 +233,19 @@ public: } + /*! + this method swappes this for an argument + */ + void Swap(UInt & ss2) + { + for(uint i=0 ; i