81 Commits
0.8.4 ... 0.9.2

Author SHA1 Message Date
3190f3011f changing version number to 0.9.2 release
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@320 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-23 20:52:20 +00:00
a34cf55155 added TTMATH_LOG to UInt::FromUInt(ulint n)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@319 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-23 19:51:55 +00:00
648de47400 fixed: Int::ToUInt(unsigned int & result)
wrong carry was returned


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@318 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-23 19:25:26 +00:00
362207e2f1 added some missing methods: ToUInt, ToInt, FromUInt, FromInt in Big<> class
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@317 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-23 18:56:55 +00:00
a40e951923 fixed: Big::ToDouble(double &) set always +INF (infinity)
when the value was too large (even for negative values)
       (it should set -INF in such a case)
added: some missing methods for converting
       for UInt<>, Int<> and Big<> classes:
       uint ToUInt()
       sint ToInt()
       ToUInt(uint32_t &)
       ToInt(uint32_t &)
       ToInt(int32_t &)
       ToUInt(uint64_t &)
       ToInt(uint64_t &)
       ToInt(int64_t &)
       FromUInt(uint32_t &)
       FromInt(uint32_t &)
       FromInt(int32_t &)
       FromUInt(uint64_t &)
       FromInt(uint64_t &)
       FromInt(int64_t &)
       and appropriate constructors and operators
       *** version for 64 bit platforms are not tested yet ***
added: double Big::ToDouble() /there was only Big::ToDouble(double &) /
       uint Big::ToFloat(float &)
       float Big::ToFloat()



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@316 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-22 19:43:12 +00:00
b028896118 added: some missing methods: ::FromUInt ::FromInt
now ::FromInt can be used in place of ::FromUint
       sample:
       UInt<1> a;
       a.FromInt(10); // previous was only: a.FromUInt(10)
changed: std::string Big::ToString(uint base = 10) const
         std::wstring Big::ToWString(uint base = 10) const
         can take optional parameter (base)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@315 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-21 22:31:07 +00:00
a67a088e3a removed: macro TTMATH_REFERENCE_ASSERT from all methods from public interface
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@314 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-21 15:52:48 +00:00
996fac15f1 in Big::ToString_CreateNewMantissaTryExponent():
ToString_BaseRound can be called only for non integer values



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@313 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-19 21:58:51 +00:00
1e268f1808 fixed: Big::ToString method
in some cases when in the output string the exponent should be equal zero
       the method changes the exponent to one so the last digit from the mantissa
       was lost
 
       sample:
       Big<1,1> a;
       a.info = 0;
       a.mantissa = 2147483649u; // (bin) 10000000000000000000000000000001
       // first and last bit in the mantissa is set
       a.exponent = 0;
       std::cout << a << std::endl;

       priovious result: 2147483640
       it was treated as 214748364e+1

       also the method has been a little improved




git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@312 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-19 21:54:46 +00:00
90674c9505 added: on 32bit platforms:
uint UInt::FromUInt(uint64_t n)
        uint Int::FromInt(int64_t n)
        void Big::FromUInt(uint64_t n)
        void Big::FromInt(int64_t n)        
        and appropriate constructors and operators
added:  TTMATH_FORCEASM macro
        asm version of the library is available by default only for:
        x86 and amd64 platforms and for Microsoft Visual and GCC compilers,
        but you can force using asm version (the same asm as for Microsoft Visual)
        by defining TTMATH_FORCEASM macro
        you have to be sure that your compiler accept such an asm format
                        


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@311 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-19 17:23:39 +00:00
b6fe168e3c added: Big::operator++()
Big::operator++(int)
         Big::operator--()
         Big::operator--(int)
         Big::AddOne()
         Big::SubOne()
changed: Big::SetOne()
         a little faster now



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@310 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-18 01:35:16 +00:00
ae61b302a8 fixed: TTMATH_DEBUG_LOG has generated different carry-flags in UInt<> (when TTMATH_NOASM was used)
fixed: some GCC warnings about uninitialized variables
added: macro TTMATH_BIG_DEFAULT_CLEAR
       when defined the default constructor from Big<> clears its mantissa and exponent
       Big<1, 2> var;
       var.mantissa and var.exponent will be set to zero
       (but var has the NaN flag set too - it is not zero value, this is mainly for debug purposes)
added: Big::SetZeroNan()
       this method sets NaN flag (Not a Number)
       also clears the mantissa and exponent (similarly as it would be a zero value)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@309 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-15 20:43:21 +00:00
a1c41c02db 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<value_size> & ss2)       
         void Big::Swap(UInt<value_size> & ss2)
         method for swapping this for an argument
changed: small optimization in Big::Sub()
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



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@304 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-05 18:21:58 +00:00
69f065245e fixed: Big::Add sometimes incorrectly rounded the last bit from mantissa
(when exp_offset == mantissa_size_in_bits ) the rounding_up was always false


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@303 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-08-18 23:31:58 +00:00
c65dac524a fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN
when the argument was negative (they only returned 2)
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



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@302 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-08-18 18:09:16 +00:00
b3c3dd8c3f 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 *) 


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@301 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-08-18 09:22:38 +00:00
1b7e13a9fd 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



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@294 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-03-01 13:08:50 +00:00
aeadb8a04a changed: version of the library: 0.9.1 now
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@286 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-07 18:17:24 +00:00
053861655d added: to samples: big2.cpp with TTMATH_BITS() macro
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@285 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-07 13:36:39 +00:00
35f2a8a28b the half-to-even rounding was turned off (some 'return' statement left)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@284 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-02 21:05:08 +00:00
d5a5ea1a7d removed: from Big::ToString() the feature with calculating how many valid digits there are
after the comma operator
         this was not correctly calculated - sometimes gives unexpected results,
         e.g. 0.5/2/2=0.125 (only one bit in the mantissa) gives 0.1 as the result
changed: cosmetic changes in Big::Add()




git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@283 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-02 21:02:10 +00:00
32b8c7a957 removed: from parser: SetSmallToZero(bool zero)
this was actually a bad feature


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@277 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-06 00:54:01 +00:00
e727eacce0 added: static sint UInt<value_size>::FindLowestBitInWord(uint x)
(asm_vc_32, asm_gcc_32, no_asm, and intrinsic for vc64)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@275 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-03 01:10:37 +00:00
39db6fc469 fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula:
new_exp_ = [log base (2^exponent)] + 1
       now the part '+ 1' is only made when the logarithm is positive and with fraction
       if the value is negative we can only skip the fraction, previously
       we lost some last digits from the new mantissa
       
       Consider this binary value (32 bit mantissa):
       (bin)1.0000000000000000000000000000011
       previously ToString() gave 1, now we have: 1.000000001



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@274 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-28 15:41:28 +00:00
0ada20b4cb fixed: added in the parser: operator's associativity
operator ^ (powering) is right-associative:
        sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24
        previously was: 2^3^4 = (2^3)^4 = 4096



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@273 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-25 22:06:49 +00:00
31563ce343 fixed: I have forgotten to remove rounding down from division (Big::div)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@264 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-14 15:54:23 +00:00
418db51f46 added: to Big::Add Big::Sub Big::Mul Big::Div
second parameter 'bool round = true'
         the rounding is made if it is true
changed: in Big::ToString_CreateNewMantissaAndExponent()
         we should use dividing without rounding
         consider this 32 bit binary value:
         1.1111111111111111111111111111111
         previous the result from converting (to the base 10) was equal 2
         now is 1.999999
      



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@263 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-14 12:16:32 +00:00
82711f4441 fixed: Big::Add() should make the half-to-even rounding
by analizing the old ss2 parameter,
        and when it does substraction too
added:  UInt::AreFirstBitsZero(uint bits)
        returning true if first bits are cleared


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@262 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-12 20:45:18 +00:00
e5fc7a52e8 fixed: base rounding in Big::ToString
if the result were integer we shoud not round the value
          3.0001 should be 3.0001 and
          2.9999 should be 2.9999



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@259 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-06 23:18:05 +00:00
357524ae13 added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
floating point algorithms:
         Big::Add
         Big::Sub
         Big::Mul
         Big::Div



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@258 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-06 01:09:55 +00:00
72052420dd fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
         (this bug was introduced in 0.9.0)
added:   to Big::ToString() - additional rounding when conv.base_round is used
         if the value is not an integer we calculate how many valid digits there are
         after the comma operator (in conv.base radix) and then we skipped the rest
         digits, after skipping the base-rounding is made
         this helps to print values which have some last clear bits in the mantissa
         consider this 32 bit value:
         (binary)0.00011100001010001111010111000000000
         which has mantissa equal: (binary)11100001010001111010111000000000 (32 bits)
         previous the ToString() method gave: (decimal)0.10999999[...] 
         now we have: (decimal)0.11
added:   Parser::SetSmallToZero(bool zero) (default true)
         if true then the parser changes small values into zero
         small value means:
         - if the mantissa of the value consists only of one, two or three set bits
         - and these bits are next to each other
         - and the exponent is smaller than about 2 times the number of bits from the mantissa
         this helps to correctly calculate expressions such as: "0.80-3*0.34+0.22"
         now the parser gives zero (previous there was a value very closed to zero)
added:   UInt::FindLowestBit(uint & table_id, uint & index)
         /temporary version - asm version is missing /



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@256 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-05 18:13:53 +00:00
321953e833 fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
       (this bug was introduced in 0.9.0)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@255 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-02 11:38:17 +00:00
125c051ea1 changed: version of the library: 0.9.0 now
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@251 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-25 13:49:38 +00:00
de150d00ec added: UInt::operator>>(int)
UInt::operator>>=(int)
       UInt::operator<<(int)
       UInt::operator<<=(int)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@250 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-25 12:57:06 +00:00
2d821bbad9 added: std::string UInt::ToString(uint b = 10)
std::wstring UInt::ToWString(uint b = 10)
        std::string  Int::ToString(uint b = 10)
        std::wstring Int::ToWString(uint b = 10)
        std::wstring Big::ToWString(const Conv & conv)
        std::wstring Big::ToWString()



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@248 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-24 20:39:36 +00:00
e083c5f889 added: const char * UInt::LibTypeStr()
const char * Big::LibTypeStr()
         LibTypeCode UInt::LibType()
         LibTypeCode Big::LibType()
         returning a string/enum represents the currect type of the library
         we have following types:
             asm_vc_32   - with asm code designed for Microsoft Visual C++ (32 bits)
             asm_gcc_32  - with asm code designed for GCC (32 bits)
             asm_vc_64   - with asm for VC (64 bit)
             asm_gcc_64  - with asm for GCC (64 bit)
             no_asm_32   - pure C++ version (32 bit) - without any asm code
             no_asm_64   - pure C++ version (64 bit) - without any asm code
changed: another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@247 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-24 20:15:46 +00:00
11b9f389b9 fixed: Int::DivInt() should take parameters as 'sint' and not 'int'
this has impact on 64 bit platforms
fixed: some warnings from Visual C++ (64 bit)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@245 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-24 06:12:46 +00:00
bac79e0bfa renamed: Conv::comma_digits to Conv::round
added:   bool Conv::base_round
         if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
         and the result value is not an integer then we make an additional rounding
         (after converting the last digit from the result is skipped)
changed: in Big::ToString() some additional rounding (base_round) is now made only 
         when the value is not an integer


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@244 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-24 05:14:54 +00:00
0d1a57bdb4 added: Int::DivInt(int divisor, int * remainder)
changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16
         the previous version was not accurate on some last digits (after the comma operator)
         consider this binary value (32 bit mantissa):
         base 2: 1.1111 1111 1111 1111 1111 1111 1110 101
         previous ToString() gave:
            base 4:  1.33333333333332
            base 8:  1.777777777
            base 16: 1.FFFFFF
         now we have:
            base 4:  1.3333333333333222
            base 8:  1.77777777724
            base 16: 1.FFFFFFEA



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@238 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-09 17:42:10 +00:00
4b4b30392a changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
they were not too much accurate for some integers
         e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@231 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-01 20:26:01 +00:00
4f1763d773 added: to the parser: function frac() - remains fraction
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@230 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-01 14:20:48 +00:00
cccf82797f added: Big::Sqrt()
global algorithm ttmath::Sqrt() moved to Big::Sqrt()


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@229 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-01 13:41:29 +00:00
e73ce2f8bc added: UInt::Sqrt() - a new algorithm for calculating the square root
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@228 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-01 13:26:19 +00:00
2feabc64e2 added: struct: Conv
consists of some parameters used
         in ToString() and FromString()
added:   Big::ToString() can group digits
         e.g. 1234567 -> 1`234`567
added:   Parser::SetGroup(int g)
         Parser::SetComma(int c, int c2 = 0)
         Parser::SetParamSep(int s)
added:   uint Big::ToString(std::string & result, const Conv & conv)
         uint Big::ToString(std::wstring & result, const Conv & conv)
         std::string Big::ToString(const Conv & conv) const
         std::string Big::ToString()
added:   uint FromString(const char * source, const Conv & conv, const char **, bool *)
         uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *)
         uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *)
         uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *)
removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
         the comma characters we have in Conv struct now



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@226 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-01 01:40:40 +00:00
413c83de45 updated: CHANGELOG and README
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@224 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-25 16:42:41 +00:00
bf520689fb added: to the parser: operator percentage
e.g. 1000-50%=1000-(1000*0,5)=500



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@217 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-18 12:37:14 +00:00
af4fbf3098 fixed: powering algorithm in:
UInt::Pow(UInt<value_size> pow)
       Big::Pow(UInt<pow_size> pow)
       Big::PowUInt(Big<exp, man> pow)
       when 'pow' was sufficient large the algorithm returned carry
       but the result could have been calculated correctly



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@213 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-16 16:56:49 +00:00
462ff7cc65 fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
changed: small optimization in ToInt(Int<int_size> & result)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@210 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-15 01:34:13 +00:00
02da809583 added: bool Parser::Calculated()
this method returns true is something was calculated
       (at least one mathematical operator was used or a function or variable)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@207 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-13 22:38:08 +00:00
32ebbbfd9e removed: Big::AboutEqualWithoutSign()
it was broken (it lacks the case when either 'this' or 'ss2' is zero)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@206 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-12 23:27:14 +00:00
e765fba8a1 changed: Big::AboutEqual()
it lacks the case when either 'this' or 'ss2' is zero


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@205 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-12 23:25:35 +00:00
a8eb29e57d fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
equal 1 (should be set 2)
       this affected only no-asm parts - when macro TTMATH_NOASM was defined
fixed: UInt<value_size>::MulInt(uint ss2)
       there was a buffer overflow when value_size was equal 1
fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
       when macro TTMATH_NOASM was defined
added: macros:
       TTMATH_LOGC(msg, carry)
       TTMATH_VECTOR_LOG(msg, vector, len)
       TTMATH_VECTOR_LOGC(msg, carry, vector, len)
added: UInt::PrintVectorLog() for debugging purposes
changed: UInt<> class uses new log macros



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@203 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-03 01:10:08 +00:00
31b8c242bd changed: if TTMATH_DEBUG_LOG is defined then TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE is always 3
(regardless of the compiler)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@202 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-20 20:41:11 +00:00
4c0d8c26ff changed: small optimization in ttmath_subindexed_x64()
(asm for x86_64 on MS VC)
changed: removed some MS VC warnings
changed: if TTMATH_DEBUG_LOG is defined then UInt::UInt()
         constructor fills the table with special values
added:   macro: TTMATH_BITS(min_bits)
         which returns the number of machine words
         capable to hold min_bits bits


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@201 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-20 20:10:29 +00:00
01a86e40d9 changed: small changes in UInt::Div_CalculatingSize()
some warnings were raported by GCC
         (uninitialized variable)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@200 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-20 12:47:44 +00:00
f19078f9f1 fixed: Factorial(const ValueType & x, ErrorCode * err = 0)
didn't want to compile
moved: UInt<>::SkipWhiteCharacters() to Misc::SkipWhiteCharacters()
       UInt<>::CharToDigit() to Misc::CharToDigit()
       UInt<>::DigitToChar() to Misc::DigitToChar()
removed: Parser::CharToDigit() - was duplicated (it's the same as Misc::CharToDigit())



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@198 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-17 23:18:11 +00:00
adc5015ad9 small optimization in Parser::Parse(const wchar_t *)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@194 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-13 19:29:29 +00:00
da730d1c70 fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
added:   wide characters can be used simultaneously with ascii characters
         now we have two kind of methods: one for ascii characters and the other for wide characters
         e.g.
           void UInt::ToString(std::string & result)
           void UInt::ToString(std::wstring & result)
         previous was only one:
           void UInt::ToString(tt_string & result)
         and the 'tt_string' was a typedef to either std::string or std::wstring
         and it was a little misleading to a user (he has to know what the tt_string is)
added:   file: ttmathmisc.h some useful functions
changed: classes: ExceptionInfo, ReferenceError and RuntimeError are used only with ascii characters
removed: macros: TTMATH_USE_WCHAR,  TTMATH_TEXT()
removed: typedefs: tt_char, tt_string, tt_ostringstream, tt_ostream, tt_istream


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@193 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-13 19:16:42 +00:00
9ccacd8817 added: uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
       asm code for AddVector() and SubVector() for MS VC x86_64
changed: added prefixes "ttmath_" to all public procedures from ttmathuint_x86_64_msvc.asm


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@192 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-11 23:55:44 +00:00
b3d27979d0 changed: removing some MS VC warnings when compiling x86_64 target
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@191 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-11 20:48:52 +00:00
e13e5eb329 added: flag TTMATH_BIG_ZERO to Big<> class
if this flag is set then there is a value zero
added:   Big::ClearInfoBit(unsigned char)
         Big::SetInfoBit(unsigned char)
         Big::IsInfoBit(unsigned char)
         some methods for manipulating the info flags
changed: IsZero() is using TTMATH_BIG_ZERO flag
         now it has O(1) complexity
         previously was O(n)
changed: optimized some methods
         they are using IsZero() for testing at the beginning
         because this method is much faster now
changed: Big::Div(ss2)
         Big::Mod(ss2)
         they return 2 when ss2 is zero
         previously returned 1



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@190 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-11 04:24:42 +00:00
74b31b1f54 fixed/optimized: Big::AboutEqual() didn't compile on GCC
(there was used ttmath::Abs() function which is unknown in Big<> class)
         AboutEqual() returned true for: "2345.5" and "-2345.5" (the sign was not checked)
renamed: Big::AboutEqual() to Big::AboutEqualWithoutSign()
added:   Big::AboutEqual()



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@189 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-10 16:28:05 +00:00
28964d30f7 merged: x86_64 asm code for Microsoft Visual compiler
file: ttmathuint_x86_64_msvc.asm from chk branch (original was: ttmathuint_x86_amd64_msvc.asm)
        (this file should be compiled first because MS VC doesn't support inline assembler in x86_64 mode) 



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@187 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-07 02:03:00 +00:00
0d71b0cec2 merged: AboutEqual() from chk branch
deleted: properties svn:mime-type from ttmath.h
         (it was for testing viewvc)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@186 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-09-05 16:43:38 +00:00
3544a1df3c setting svn:mime-type to text/plain for ttmath.h
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@185 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-08-24 05:08:13 +00:00
00519ff26d added/fixed: special version of ToString_LogBase() method
in single thread environment
             the previous version of the method didn't store
             the calculated logarithms


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@184 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-08-04 18:55:18 +00:00
799e2c32a7 added: multithread support for Big<> class
you should compile with TTMATH_MULTITHREADS
        and use TTMATH_MULTITHREADS_HELPER macro somewhere in your *.cpp file
        added file: ttmaththreads.h (look there for more info)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@183 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-08-04 18:23:35 +00:00
53547cfab5 * added: global Gamma() function
* added:   gamma() function to the parser
* added:   Big::IsInteger() method
           returns true if the value is integer
* added:   CGamma<ValueType> class
           is used with Gamma() and Factorial() in multithreaded environment
* changed: Factorial() is using the Gamma() function now
* removed: Parser<>::SetFactorialMax() method
           the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@178 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-16 03:22:29 +00:00
d3a64b79ca added: support for wide characters (wchar_t)
wide characters are used when macro TTMATH_USE_WCHAR is defined
       this macro is defined automatically when there is macro UNICODE or _UNICODE defined
       some types have been changed
        char               -> tt_char
        std::string        -> tt_string
        std::ostringstream -> tt_ostringstream
        std::ostream       -> tt_ostream
        std::istream       -> tt_istream
       normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on)
       (all typedef's are in ttmathtypes.h)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@177 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-02 01:04:25 +00:00
c70a947c07 updated changelog to previous commit
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@164 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-16 18:33:20 +00:00
8972fdfdb3 fixed: Sqrt(), Root() and Factorial() didn't correctly treat the NaN flag
fixed: some methods should set 'err_improper_argument' when the argument is a NaN object
       (was: err_overflow)
changed: version of the library: 0.8.5 now



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@163 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-16 18:31:39 +00:00
019a902fed changed: small optimization in Big::ExpSurrounding0() and Big::LnSurrounding1()
the remainder from a division '%' was changed with a bitwise And operation '&'
         ((i % 5) == 0) was changed to: ((i & 3) == 0) - it means ((i % 4) == 0)
         now the test if performed after 4 iterations (early were after 5 iterations)
         we can do that when the divisor is a power of 2
changed: optimization in Factorial()
         we're testing WasStopSignal() only after a few iterations
         it's faster now about 4 times on GCC 4.3.3 (when stop object is provided to the factorial)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@161 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-14 19:55:15 +00:00
74553109a5 fixed: (performance) in Big::LnSurrounding1() and Big::ExpSurrounding0()
we can copy 'old_value = *this' only when 'testing' is true


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@160 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-14 18:45:36 +00:00
9e42a5a9fd fixed: Big::FromDouble() on a 32 bit platform:
SetNaN() should be SetNan() /*compilation error*/


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@158 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 15:03:22 +00:00
1b6858616d fixed: in Big::FromDouble(): SetNaN() should be SetNan();
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@157 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 10:04:50 +00:00
d789ac5396 added: using NaN flag in method Big::ToDouble() and Big::FromDouble()
changed: some cosmetic changes to get rid of warnings generated by 
         MS Visual 2008 when warning level is 4
changed: names of labels in asm code: p to ttmath_loop, end to ttmath_end
         p2 to ttmath_loop2
         Robert Muir reported that there was a confict with boost::end


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@156 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 02:31:41 +00:00
bb2583649e added: to Big<> class: support for NaN flag (Not a Number)
bool Big::IsNan() - returns true if the NaN flag is set
       void Big::SetNan() - sets the NaN flag
       The NaN flag is set by default after creating an object:
         Big<1, 2> a;    // NaN is set (it means the object has not a valid number)
         std::cout << a; // cout gives "NaN"
         a = 123;        // now NaN is not set
         std::cout << a; // cout gives "123"
       The NaN is set if there was a carry during calculations
         a.Mul(very_big_value); // a will have a NaN set
	   The NaN is set if an argument is NaN too
	     b.SetNan();
	     a.Add(b);  // a will have NaN because b has NaN too
       If you try to do something on a NaN object, the result is a NaN too
         a.SetNan();
         a.Add(2);  // a is still a NaN 
       The NaN is set if you use incorrect arguments
         a.Ln(-10); // a will have the NaN flag
       The only way to clear the NaN flag is to assign a correct value or other correct object
         supposing 'a' has NaN flag, to remove the flag you can either:
         a = 10;
         a.FromInt(30);
         a.SetOne(); 
         a.FromBig(other_object_without_nan);
         etc.
changed: renamed macro CONSTANTSGENERATOR to TTMATH_CONSTANTSGENERATOR



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@152 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-26 23:13:22 +00:00
5e5a106605 changed: a little changes in all asm code
it should be a little faster


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@149 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-17 00:04:42 +00:00
eaa19dd46a added: uint UInt::Mul3(const UInt<value_size> & ss2)
void UInt::Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
         a new multiplication algorithm: Karatsuba multiplication,
         on a vector UInt<100> with all items different from zero this algorithm is faster
         about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from
         zero this algorithm is faster more than 5 times than Mul2Big()
         (measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE)
added:   uint MulFastest(const UInt<value_size> & ss2)
         void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
         those methods are trying to select the fastest multiplication algorithm
changed: uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
         void MulBig(const UInt<value_size> & ss2, UInt<value_size*2> & result, uint algorithm = 100)
         those methods by default use MulFastest() and MulFastestBig()
changed: changed a little Mul2Big() to cooperate with Mul3Big()
changed: names of methods in macros TTMATH_LOG()
added:   uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
         uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
         three forms: asm x86, asm x86_64, no-asm
         those methods are used by the Karatsuba multiplication algorithm



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@148 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-15 22:27:04 +00:00
939d0f7519 fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x)
fixed:   global function Mod(x) didn't set an ErrorCode object
fixed:   global function Round() didn't test a carry
         now it sets ErrorCode object
changed: function Sin(x) to Sin(x, ErrorCode * err=0)
         when x was very big the function returns zero
         now it sets ErrorCode object to err_overflow
         and the result is undefined
         the same is to Cos() function
changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
         should be a little accurate especially on a very big 'x'



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@143 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-11 01:50:00 +00:00
05b67e7103 changed: corrected spaces in changelog
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@142 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-09 01:34:45 +00:00
23 changed files with 9726 additions and 2135 deletions

294
CHANGELOG
View File

@@ -1,3 +1,297 @@
Version 0.9.2 (2010.09.23):
* 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 *)
* fixed: Big::ToString method
in some cases when in the output string the exponent should be equal zero
the method changes the exponent to one so the last digit from the mantissa
was lost
* fixed: Big::ToDouble(double &) set always +INF (infinity)
when the value was too large (even for negative values)
(it should set -INF in such a case)
* 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
Big::operator++()
Big::operator++(int)
Big::operator--()
Big::operator--(int)
* 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<value_size> & ss2)
void Big::Swap(UInt<value_size> & ss2)
method for swapping this for an argument
* added: macro TTMATH_BIG_DEFAULT_CLEAR
when defined the default constructor from Big<> clears its mantissa and exponent
Big<1, 2> var;
var.mantissa and var.exponent will be set to zero
(but var has the NaN flag set too - it is not zero value, this is mainly for debug purposes)
* added: only on 32bit platforms:
uint UInt::FromUInt(uint64_t n)
uint Int::FromInt(int64_t n)
void Big::FromUInt(uint64_t n)
void Big::FromInt(int64_t n)
and appropriate constructors and operators
* added: TTMATH_FORCEASM macro
asm version of the library is available by default only for:
x86 and amd64 platforms and for Microsoft Visual and GCC compilers,
but you can force using asm version (the same asm as for Microsoft Visual)
by defining TTMATH_FORCEASM macro
you have to be sure that your compiler accept such an asm format
* added: some missing methods for converting
for UInt<>, Int<> and Big<> classes:
uint ToUInt()
sint ToInt()
ToUInt(uint32_t &)
ToInt(uint32_t &)
ToInt(int32_t &)
ToUInt(uint64_t &)
ToInt(uint64_t &)
ToInt(int64_t &)
FromUInt(uint32_t &)
FromInt(uint32_t &)
FromInt(int32_t &)
FromUInt(uint64_t &)
FromInt(uint64_t &)
FromInt(int64_t &)
and appropriate constructors and operators
* added: double Big::ToDouble() /there was only Big::ToDouble(double &) /
uint Big::ToFloat(float &)
float Big::ToFloat()
* changed: now asm version is available only on x86 and amd64
(and only for GCC and MS VC compilers)
* removed: macro TTMATH_RELEASE (now the 'release' version is default)
for debug version define TTMATH_DEBUG macro
TTMATH_DEBUG is also automatically defined when DEBUG or _DEBUG is set
* removed: macro TTMATH_REFERENCE_ASSERT from all methods in public interface
Version 0.9.1 (2010.02.07):
* fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
(this bug was introduced in 0.9.0)
* fixed: added in the parser: operator's associativity
operator ^ (powering) is right-associative:
sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24
previously was: 2^3^4 = (2^3)^4 = 4096
* fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula:
new_exp_ = [log base (2^exponent)] + 1
now the part '+ 1' is only made when the logarithm is positive and with fraction
if the value is negative we can only skip the fraction, previously
we lost some last digits from the new mantissa
Consider this binary value (32 bit mantissa):
(bin)1.0000000000000000000000000000011
previously ToString() gave 1, now we have: 1.000000001
* changed: in Big::ToString() the base rounding is made only if the result value
would not be an integer, e.g. if the value is 1.999999999999 then
the base rounding will not be done - because as the result would be 2
* added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
floating point algorithms: Big::Add, Big::Sub, Big::Mul, Big::Div
* added: static sint UInt<value_size>::FindLowestBitInWord(uint x)
this method is looking for the lowest set bit in a word
* added: UInt::FindLowestBit(uint & table_id, uint & index)
this method is looking for the lowest set bit
Version 0.9.0 (2009.11.25):
* added: support for wide characters (wchar_t, std::wstring)
* added: Big::IsInteger()
returns true if the value is integer (without fraction)
(NaN flag is not checked)
* added: global Gamma() function
* added: gamma() function to the parser
* added: CGamma<ValueType> class
is used with Gamma() and Factorial() in multithreaded environment
* added: multithread support for Big<> class
you should compile with TTMATH_MULTITHREADS
and use TTMATH_MULTITHREADS_HELPER macro somewhere in your *.cpp file
* added: x86_64 asm code for Microsoft Visual compiler
file: ttmathuint_x86_64_msvc.asm
(this file should be compiled first because MS VC doesn't support inline assembler in x86_64 mode)
* added: flag TTMATH_BIG_ZERO to Big<> class
if this flag is set then there is a value zero
Big::IsZero() is faster now
* added: Big::ClearInfoBit(unsigned char)
Big::SetInfoBit(unsigned char)
Big::IsInfoBit(unsigned char)
some methods for manipulating the info flags
* added: macro: TTMATH_BITS(min_bits)
which returns the number of machine words
capable to hold min_bits bits
* added: bool Parser::Calculated()
this method returns true is something was calculated
(at least one mathematical operator was used or a function or variable)
* added: to the parser: operator percentage
e.g. 1000-50%=1000-(1000*0,5)=500
* added: struct: Conv
consists of some parameters used
in ToString() and FromString()
* added: Big::ToString() can group digits
e.g. 1234567 -> 1`234`567
* added: Parser::SetGroup(int g)
Parser::SetComma(int c, int c2 = 0)
Parser::SetParamSep(int s)
* added: std::string UInt::ToString(uint b = 10)
std::wstring UInt::ToWString(uint b = 10)
std::string Int::ToString(uint b = 10)
std::wstring Int::ToWString(uint b = 10)
uint Big::ToString(std::string & result, const Conv & conv)
uint Big::ToString(std::wstring & result, const Conv & conv)
std::string Big::ToString(const Conv & conv)
std::string Big::ToString()
std::wstring Big::ToWString(const Conv & conv)
std::wstring Big::ToWString()
* added: uint FromString(const char * source, const Conv & conv, const char **, bool *)
uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *)
uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *)
uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *)
* added: UInt::Sqrt() - a new algorithm for calculating the square root
* added: to the parser: function frac() - returns a value without the integer part
(only fraction remains)
* added: Int::DivInt(sint divisor, sint * remainder)
* added: const char * UInt::LibTypeStr()
const char * Big::LibTypeStr()
LibTypeCode UInt::LibType()
LibTypeCode Big::LibType()
returning a string/enum represents the currect type of the library
we have following types:
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
asm_gcc_32 - with asm code designed for GCC (32 bits)
asm_vc_64 - with asm for VC (64 bit)
asm_gcc_64 - with asm for GCC (64 bit)
no_asm_32 - pure C++ version (32 bit) - without any asm code
no_asm_64 - pure C++ version (64 bit) - without any asm code
* added: UInt::operator>>(int)
UInt::operator>>=(int)
UInt::operator<<(int)
UInt::operator<<=(int)
* changed: Factorial() is using the Gamma() function now
* changed: Big::Div(ss2)
Big::Mod(ss2)
they return 2 when ss2 is zero
previously returned 1
* changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
they were not too much accurate for some integers
e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)
* changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16
the previous version was not accurate on some last digits (after the comma operator)
consider this binary value (32 bit mantissa):
base 2: 1.1111 1111 1111 1111 1111 1111 1110 101
previous ToString() gave:
base 4: 1.33333333333332
base 8: 1.777777777
base 16: 1.FFFFFF
now we have:
base 4: 1.3333333333333222
base 8: 1.77777777724
base 16: 1.FFFFFFEA
* changed: in Big::ToString() some additional rounding (base_round) is now made only
when the value is not an integer
* changed: another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
* removed: Parser<>::SetFactorialMax() method
the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial
* removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
the comma characters we have in Conv struct now
Version 0.8.6 (2009.10.25):
* fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
equal 1 (should be set 2)
this affected only no-asm parts - when macro TTMATH_NOASM was defined
* fixed: UInt<value_size>::MulInt(uint ss2)
there was a buffer overflow when value_size was equal 1
* fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
when macro TTMATH_NOASM was defined
* fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
* fixed: Int::FromString(const tt_string & s, uint b = 10)
didn't use 'b' (always was '10')
* fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
* fixed: powering algorithm in:
UInt::Pow(UInt<value_size> pow)
Big::Pow(UInt<pow_size> pow)
Big::PowUInt(Big<exp, man> pow)
when 'pow' was sufficient large the algorithm returned carry
but the result could have been calculated correctly
Version 0.8.5 (2009.06.16):
* fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x)
* fixed: global function Mod(x) didn't set an ErrorCode object
* fixed: global function Round() didn't test a carry
now it sets ErrorCode object
* changed: function Sin(x) to Sin(x, ErrorCode * err=0)
when x was very big the function returns zero
now it sets ErrorCode object to err_overflow
and the result has a NaN flag set
the same is to Cos() function
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
should be a little accurate especially on a very big 'x'
* changed: uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
void MulBig(const UInt<value_size> & ss2, UInt<value_size*2> & result, uint algorithm = 100)
those methods by default use MulFastest() and MulFastestBig()
* changed: changed a little Mul2Big() to cooperate with Mul3Big()
* added: uint UInt::Mul3(const UInt<value_size> & ss2)
void UInt::Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
a new multiplication algorithm: Karatsuba multiplication,
on a vector UInt<100> with all items different from zero this algorithm is faster
about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from
zero this algorithm is faster more than 5 times than Mul2Big()
(measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE)
* added: uint MulFastest(const UInt<value_size> & ss2)
void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
those methods are trying to select the fastest multiplication algorithm
* added: uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
three forms: asm x86, asm x86_64, no-asm
those methods are used by the Karatsuba multiplication algorithm
* added: to Big<> class: support for NaN flag (Not a Number)
bool Big::IsNan() - returns true if the NaN flag is set
void Big::SetNan() - sets the NaN flag
The NaN flag is set by default after creating an object:
Big<1, 2> a; // NaN is set (it means the object has not a valid number)
std::cout << a; // cout gives "NaN"
a = 123; // now NaN is not set
std::cout << a; // cout gives "123"
The NaN is set if there was a carry during calculations
a.Mul(very_big_value); // a will have a NaN set
The NaN is set if an argument is NaN too
b.SetNan();
a.Add(b); // a will have NaN because b has NaN too
If you try to do something on a NaN object, the result is a NaN too
a.SetNan();
a.Add(2); // a is still a NaN
The NaN is set if you use incorrect arguments
a.Ln(-10); // a will have the NaN flag
The only way to clear the NaN flag is to assign a correct value or other correct object,
supposing 'a' has NaN flag, to remove the flag you can either:
a = 10;
a.FromInt(30);
a.SetOne();
a.FromBig(other_object_without_nan);
etc.
Version 0.8.4 (2009.05.08): Version 0.8.4 (2009.05.08):
* fixed: UInt::DivInt() didn't check whether the divisor is zero * fixed: UInt::DivInt() didn't check whether the divisor is zero
there was a hardware interruption when the divisor was zero there was a hardware interruption when the divisor was zero

View File

@@ -1,4 +1,4 @@
Copyright (c) 2006-2009, Tomasz Sowa Copyright (c) 2006-2010, Tomasz Sowa
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

35
README
View File

@@ -1,26 +1,23 @@
TTMath - a bignum library for C++ A bignum library for C++
TTMath is a small library which allows one to perform arithmetic operations TTMath is a small library which allows one to perform arithmetic operations
with big unsigned integer, big signed integer and big floating point with big unsigned integer, big signed integer and big floating point numbers.
numbers. It provides standard mathematical operations like adding, It provides standard mathematical operations like adding, subtracting,
subtracting, multiplying, dividing etc. With the library also goes multiplying, dividing. With the library also goes a mathematical parser to
a mathematical parser which helps you solving input formulas read directly help you solving mathematical expressions.
from a user.
TTMath is developed under the BSD licence which means that it is free TTMath is developed under the BSD licence which means that it is free for
for both personal and commercial use. both personal and commercial use.
The library has some technical limitations:
* there are only two platforms that are supported: x86 and x86_64,
* you can use this library only with the C++ programming language.
The main goal of the library is to allow one to use big values in the same The main goal of the library is to allow one to use big values in the same
way as the standard types like int, float, etc. It does not need to be way as the standard types like int or float. It does not need to be compiled
compiled first because the whole library is written as the C++ templates. first because the whole library is written as the C++ templates. This means
This means only C++ developers can use this library and one thing they have only C++ developers can use this library and one thing they have to do is
to do is to use 'include' directive of the preprocessor. How big the to use 'include' directive of the preprocessor. How big the values can be
values can be is set directly in the source code by the programmer. is set at compile time.
Author: Tomasz Sowa <t.sowa@ttmath.org> Author: Tomasz Sowa <t.sowa@ttmath.org>
Project pages: http://www.ttmath.org WWW: http://www.ttmath.org
http://sourceforge.net/projects/ttmath
Contributors:
Christian Kaiser <chk@online.de>

View File

@@ -1,6 +1,6 @@
o = main.o o = main.o
CC = g++ CC = g++
CFLAGS = -s -O2 -DCONSTANTSGENERATOR CFLAGS = -s -O2 -DTTMATH_CONSTANTSGENERATOR
name = gen name = gen

View File

@@ -91,7 +91,7 @@ void CalcE()
ttmath::Big<1,400> e; ttmath::Big<1,400> e;
ttmath::uint steps; ttmath::uint steps;
// macro CONSTANTSGENERATOR has to be defined // macro TTMATH_CONSTANTSGENERATOR has to be defined
e.ExpSurrounding0(1, &steps); e.ExpSurrounding0(1, &steps);
std::cout << "---------------- e ----------------" << std::endl; std::cout << "---------------- e ----------------" << std::endl;
e.mantissa.PrintTable(std::cout); e.mantissa.PrintTable(std::cout);
@@ -105,7 +105,7 @@ void CalcLn(int x)
ttmath::Big<1,400> ln; ttmath::Big<1,400> ln;
ttmath::uint steps; ttmath::uint steps;
// macro CONSTANTSGENERATOR has to be defined // macro TTMATH_CONSTANTSGENERATOR has to be defined
ln.LnSurrounding1(x, &steps); ln.LnSurrounding1(x, &steps);
std::cout << "---------------- ln(" << x << ") ----------------" << std::endl; std::cout << "---------------- ln(" << x << ") ----------------" << std::endl;
ln.mantissa.PrintTable(std::cout); ln.mantissa.PrintTable(std::cout);

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = TTMath
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # if some version control system is used.
PROJECT_NUMBER = 0.8.2 PROJECT_NUMBER = 0.9.2
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put. # base path where the generated documentation will be put.

View File

@@ -1,5 +1,5 @@
CC = g++ CC = g++
CFLAGS = -Wall -pedantic -s -O2 -I.. CFLAGS = -Wall -pedantic -s -O2 -I.. -DTTMATH_DONT_USE_WCHAR
.SUFFIXES: .cpp .o .SUFFIXES: .cpp .o
@@ -8,7 +8,7 @@ CFLAGS = -Wall -pedantic -s -O2 -I..
$(CC) -c $(CFLAGS) $< $(CC) -c $(CFLAGS) $<
all: uint int big parser all: uint int big big2 parser
uint: uint.o uint: uint.o
@@ -20,6 +20,9 @@ int: int.o
big: big.o big: big.o
$(CC) -o big $(CFLAGS) big.o $(CC) -o big $(CFLAGS) big.o
big2: big2.o
$(CC) -o big2 $(CFLAGS) big2.o
parser: parser.o parser: parser.o
$(CC) -o parser $(CFLAGS) parser.o $(CC) -o parser $(CFLAGS) parser.o
@@ -27,6 +30,7 @@ parser: parser.o
uint.o: uint.cpp uint.o: uint.cpp
int.o: int.cpp int.o: int.cpp
big.o: big.cpp big.o: big.cpp
big2.o: big2.cpp
parser.o: parser.cpp parser.o: parser.cpp
@@ -36,6 +40,7 @@ clean:
rm -f uint rm -f uint
rm -f int rm -f int
rm -f big rm -f big
rm -f big2
rm -f parser rm -f parser
# on MS Windows can automatically be added suffixes .exe to the names of output programs # on MS Windows can automatically be added suffixes .exe to the names of output programs
rm -f *.exe rm -f *.exe

View File

@@ -5,6 +5,8 @@
// this type has 2 words for its mantissa and 1 word for its exponent // this type has 2 words for its mantissa and 1 word for its exponent
// (on a 32bit platform one word means a word of 32 bits, // (on a 32bit platform one word means a word of 32 bits,
// and on a 64bit platform one word means a word of 64 bits) // and on a 64bit platform one word means a word of 64 bits)
// Big<exponent, mantissa>
typedef ttmath::Big<1,2> MyBig; typedef ttmath::Big<1,2> MyBig;
@@ -56,6 +58,7 @@ MyBig atemp;
} }
int main() int main()
{ {
MyBig a,b; MyBig a,b;
@@ -85,13 +88,13 @@ a = 123456.543456
b = 98767878.124322 b = 98767878.124322
a + b = 98891334.667778 a + b = 98891334.667778
a - b = -98644421.580866 a - b = -98644421.580866
a * b = 12193540837712.2708 a * b = 12193540837712.27076
a / b = 0.0012499665458095765 a / b = 0.00124996654580957646
Calculating with a carry Calculating with a carry
a = 1.624801256070839555e+646457012 a = 1.6248012560666408782e+646457012
b = 456.31999999999999 b = 456.319999999999993
a + b = 1.624801256070839555e+646457012 a + b = 1.6248012560666408782e+646457012
a - b = 1.624801256070839555e+646457012 a - b = 1.6248012560666408782e+646457012
a * b = (carry) a * b = (carry)
a / b = 3.56066193914542334e+646457009 a / b = 3.560661939136222174e+646457009
*/ */

113
samples/big2.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include <ttmath/ttmath.h>
#include <iostream>
// this is a similar example to big.cpp
// but now we're using TTMATH_BITS() macro
// this macro returns how many words we need to store
// the given number of bits
// TTMATH_BITS(64)
// on a 32bit platform the macro returns 2 (2*32=64)
// on a 64bit platform the macro returns 1
// TTMATH_BITS(128)
// on a 32bit platform the macro returns 4 (4*32=128)
// on a 64bit platform the macro returns 2 (2*64=128)
// Big<exponent, mantissa>
typedef ttmath::Big<TTMATH_BITS(64), TTMATH_BITS(128)> MyBig;
// consequently on a 32bit platform we define: Big<2, 4>
// and on a 64bit platform: Big<1, 2>
// and the calculations will be the same on both platforms
void SimpleCalculating(const MyBig & a, const MyBig & b)
{
std::cout << "Simple calculating" << std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
std::cout << "a + b = " << a+b << std::endl;
std::cout << "a - b = " << a-b << std::endl;
std::cout << "a * b = " << a*b << std::endl;
std::cout << "a / b = " << a/b << std::endl;
}
void CalculatingWithCarry(const MyBig & a, const MyBig & b)
{
MyBig atemp;
std::cout << "Calculating with a carry" << std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
atemp = a;
if( !atemp.Add(b) )
std::cout << "a + b = " << atemp << std::endl;
else
std::cout << "a + b = (carry)" << std::endl;
// it have no sense to print 'atemp' (it's undefined)
atemp = a;
if( !atemp.Sub(b) )
std::cout << "a - b = " << atemp << std::endl;
else
std::cout << "a - b = (carry)" << std::endl;
atemp = a;
if( !atemp.Mul(b) )
std::cout << "a * b = " << atemp << std::endl;
else
std::cout << "a * b = (carry)" << std::endl;
atemp = a;
if( !atemp.Div(b) )
std::cout << "a / b = " << atemp << std::endl;
else
std::cout << "a / b = (carry or division by zero) " << std::endl;
}
int main()
{
MyBig a,b;
// conversion from 'const char *'
a = "123456.543456";
b = "98767878.124322";
SimpleCalculating(a,b);
// 'a' will have the max value which can be held in this type
a.SetMax();
// conversion from double
b = 456.32;
// Look at the value 'a' and the product from a+b and a-b
// Don't worry this is the nature of floating point numbers
CalculatingWithCarry(a,b);
}
/*
the result (the same on a 32 or 64bit platform):
Simple calculating
a = 123456.543456
b = 98767878.124322
a + b = 98891334.667778
a - b = -98644421.580866
a * b = 12193540837712.270763536832
a / b = 0.0012499665458095764605964485261668609133
Calculating with a carry
a = 2.34953455457111777368832820909595050034e+2776511644261678604
b = 456.3199999999999931787897367030382156
a + b = 2.34953455457111777368832820909595050034e+2776511644261678604
a - b = 2.34953455457111777368832820909595050034e+2776511644261678604
a * b = (carry)
a / b = 5.1488748127873374141170361292780486452e+2776511644261678601
*/

View File

@@ -29,6 +29,11 @@ const char equation[] = " (34 + 24) * 123 - 34.32 ^ 6 * sin(2.56) - atan(10)";
/* /*
the result (on 32 bit platform): the result (on 32 bit platform):
-897705014.525731067
-897705014.52573107 */
/*
the result (on 64 bit platform):
-897705014.5257310676097719585259773124
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

250
ttmath/ttmathmisc.h Normal file
View File

@@ -0,0 +1,250 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmathmisc
#define headerfilettmathmisc
/*!
\file ttmathmisc.h
\brief some helpful functions
*/
#include <string>
namespace ttmath
{
/*!
some helpful functions
*/
class Misc
{
public:
/*
*
* AssignString(result, str)
* result = str
*
*/
/*!
result = str
*/
static void AssignString(std::string & result, const char * str)
{
result = str;
}
#ifndef TTMATH_DONT_USE_WCHAR
/*!
result = str
*/
static void AssignString(std::wstring & result, const char * str)
{
result.clear();
for( ; *str ; ++str )
result += *str;
}
/*!
result = str
*/
static void AssignString(std::wstring & result, const std::string & str)
{
return AssignString(result, str.c_str());
}
/*!
result = str
*/
static void AssignString(std::string & result, const wchar_t * str)
{
result.clear();
for( ; *str ; ++str )
result += static_cast<char>(*str);
}
/*!
result = str
*/
static void AssignString(std::string & result, const std::wstring & str)
{
return AssignString(result, str.c_str());
}
#endif
/*
*
* AddString(result, str)
* result += str
*
*/
/*!
result += str
*/
static void AddString(std::string & result, const char * str)
{
result += str;
}
#ifndef TTMATH_DONT_USE_WCHAR
/*!
result += str
*/
static void AddString(std::wstring & result, const char * str)
{
for( ; *str ; ++str )
result += *str;
}
#endif
/*
this method omits any white characters from the string
char_type is char or wchar_t
*/
template<class char_type>
static void SkipWhiteCharacters(const char_type * & c)
{
// 13 is at the end in a DOS text file (\r\n)
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
++c;
}
/*!
this static method converts one character into its value
for example:
1 -> 1
8 -> 8
A -> 10
f -> 15
this method don't check whether c is correct or not
*/
static uint CharToDigit(uint c)
{
if(c>='0' && c<='9')
return c-'0';
if(c>='a' && c<='z')
return c-'a'+10;
return c-'A'+10;
}
/*!
this method changes a character 'c' into its value
(if there can't be a correct value it returns -1)
for example:
c=2, base=10 -> function returns 2
c=A, base=10 -> function returns -1
c=A, base=16 -> function returns 10
*/
static sint CharToDigit(uint c, uint base)
{
if( c>='0' && c<='9' )
c=c-'0';
else
if( c>='a' && c<='z' )
c=c-'a'+10;
else
if( c>='A' && c<='Z' )
c=c-'A'+10;
else
return -1;
if( c >= base )
return -1;
return sint(c);
}
/*!
this method converts a digit into a char
digit should be from <0,F>
(we don't have to get a base)
for example:
1 -> 1
8 -> 8
10 -> A
15 -> F
*/
static uint DigitToChar(uint digit)
{
if( digit < 10 )
return digit + '0';
return digit - 10 + 'A';
}
}; // struct Misc
}
#endif

View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of TTMath Mathematical Library * This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2006-2009, Tomasz Sowa * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -44,12 +44,13 @@
\brief Mathematic functions. \brief Mathematic functions.
*/ */
#include "ttmathtypes.h"
#include <string> #include <string>
#include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include "ttmathtypes.h"
#include "ttmathmisc.h"
namespace ttmath namespace ttmath
@@ -73,6 +74,7 @@ public:
struct Item struct Item
{ {
// name of a variable of a function // name of a variable of a function
// internally we store variables and funcions as std::string (not std::wstring even when wide characters are used)
std::string value; std::string value;
// number of parameters required by the function // number of parameters required by the function
@@ -112,7 +114,8 @@ public:
/*! /*!
this method returns true if the name can be as a name of an object this method returns true if the name can be as a name of an object
*/ */
static bool IsNameCorrect(const std::string & name) template<class string_type>
static bool IsNameCorrect(const string_type & name)
{ {
if( name.empty() ) if( name.empty() )
return false; return false;
@@ -120,7 +123,7 @@ public:
if( !CorrectCharacter(name[0], false) ) if( !CorrectCharacter(name[0], false) )
return false; return false;
std::string::const_iterator i=name.begin(); typename string_type::const_iterator i = name.begin();
for(++i ; i!=name.end() ; ++i) for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) ) if( !CorrectCharacter(*i, true) )
@@ -145,6 +148,27 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method returns true if such an object is defined (name exists)
*/
bool IsDefined(const std::wstring & name)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return false;
Misc::AssignString(str_tmp1, name);
return IsDefined(str_tmp1);
}
#endif
/*! /*!
this method adds one object (variable of function) into the table this method adds one object (variable of function) into the table
*/ */
@@ -165,6 +189,27 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method adds one object (variable of function) into the table
*/
ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
Misc::AssignString(str_tmp2, value);
return Add(str_tmp1, str_tmp2, param);
}
#endif
/*! /*!
this method returns 'true' if the table is empty this method returns 'true' if the table is empty
*/ */
@@ -222,6 +267,28 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method changes the value and the number of parameters for a specific object
*/
ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
Misc::AssignString(str_tmp2, value);
return EditValue(str_tmp1, str_tmp2, param);
}
#endif
/*! /*!
this method changes the name of a specific object this method changes the name of a specific object
*/ */
@@ -253,6 +320,29 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method changes the name of a specific object
*/
ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, old_name);
Misc::AssignString(str_tmp2, new_name);
return EditName(str_tmp1, str_tmp2);
}
#endif
/*! /*!
this method deletes an object this method deletes an object
*/ */
@@ -272,6 +362,27 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method deletes an object
*/
ErrorCode Delete(const std::wstring & name)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
return Delete(str_tmp1);
}
#endif
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
*/ */
@@ -294,6 +405,28 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method gets the value of a specific object
*/
ErrorCode GetValue(const std::wstring & name, std::wstring & value)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
ErrorCode err = GetValue(str_tmp1, str_tmp2);
Misc::AssignString(value, str_tmp2);
return err;
}
#endif
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
@@ -317,6 +450,27 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method gets the value of a specific object
(this version is used for not copying the whole string)
*/
ErrorCode GetValue(const std::wstring & name, const char ** value)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
return GetValue(str_tmp1, value);
}
#endif
/*! /*!
this method gets the value and the number of parameters this method gets the value and the number of parameters
of a specific object of a specific object
@@ -342,6 +496,29 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method gets the value and the number of parameters
of a specific object
*/
ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param);
Misc::AssignString(value, str_tmp2);
return err;
}
#endif
/*! /*!
this method sets the value and the number of parameters this method sets the value and the number of parameters
of a specific object of a specific object
@@ -368,6 +545,31 @@ public:
} }
#ifndef TTMATH_DONT_USE_WCHAR
/*!
this method sets the value and the number of parameters
of a specific object
(this version is used for not copying the whole string
but in fact we make one copying during AssignString())
*/
ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param)
{
// we should check whether the name (in wide characters) are correct
// before calling AssignString() function
if( !IsNameCorrect(name) )
return err_incorrect_name;
Misc::AssignString(str_tmp1, name);
return GetValueAndParam(str_tmp1, value, param);
}
#endif
/*! /*!
this method returns a pointer into the table this method returns a pointer into the table
*/ */
@@ -380,6 +582,7 @@ public:
private: private:
Table table; Table table;
std::string str_tmp1, str_tmp2;
}; // end of class Objects }; // end of class Objects
@@ -426,11 +629,11 @@ public:
/*! /*!
default constructor default constructor
default max size of the History's container is 10 items default max size of the History's container is 15 items
*/ */
History() History()
{ {
buffer_max_size = 10; buffer_max_size = 15;
} }
@@ -487,10 +690,118 @@ public:
return false; return false;
} }
/*!
this methods deletes an item
we assume that there is only one item with the 'key'
(this methods removes the first one)
*/
bool Remove(const ValueType & key)
{
typename buffer_type::iterator i = buffer.begin();
for( ; i != buffer.end() ; ++i )
{
if( i->key == key )
{
buffer.erase(i);
return true;
}
}
return false;
}
}; // end of class History }; // end of class History
/*!
this is an auxiliary class used when calculating Gamma() or Factorial()
in multithreaded environment you can provide an object of this class to
the Gamma() or Factorial() function, e.g;
typedef Big<1, 3> MyBig;
MyBig x = 123456;
CGamma<MyBig> cgamma;
std::cout << Gamma(x, cgamma);
each thread should have its own CGamma<> object
in a single-thread environment a CGamma<> object is a static variable
in a second version of Gamma() and you don't have to explicitly use it, e.g.
typedef Big<1, 3> MyBig;
MyBig x = 123456;
std::cout << Gamma(x);
*/
template<class ValueType>
struct CGamma
{
/*!
this table holds factorials
1
1
2
6
24
120
720
.......
*/
std::vector<ValueType> fact;
/*!
this table holds Bernoulli numbers
1
-0.5
0.166666666666666666666666667
0
-0.0333333333333333333333333333
0
0.0238095238095238095238095238
0
-0.0333333333333333333333333333
0
0.075757575757575757575757576
.....
*/
std::vector<ValueType> bern;
/*!
here we store some calculated values
(this is for speeding up, if the next argument of Gamma() or Factorial()
is in the 'history' then the result we are not calculating but simply
return from the 'history' object)
*/
History<ValueType> history;
/*!
this method prepares some coefficients: factorials and Bernoulli numbers
stored in 'fact' and 'bern' objects
how many values should be depends on the size of the mantissa - if
the mantissa is larger then we must calculate more values
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
we have to calculate about 30 values (the size of fact and bern will be 30),
and for a 2048 bits mantissa we have to calculate 306 coefficients
you don't have to call this method, these coefficients will be automatically calculated
when they are needed
you must note that calculating these coefficients is a little time-consuming operation,
(especially when the mantissa is large) and first call to Gamma() or Factorial()
can take more time than next calls, and in the end this is the point when InitAll()
comes in handy: you can call this method somewhere at the beginning of your program
*/
void InitAll();
// definition is in ttmath.h
};
} // namespace } // namespace

View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of TTMath Mathematical Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2006-2009, Tomasz Sowa * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,13 +45,14 @@
\brief A mathematical parser \brief A mathematical parser
*/ */
#include <fstream> #include <cstdio>
#include <vector> #include <vector>
#include <map> #include <map>
#include <set> #include <set>
#include "ttmath.h" #include "ttmath.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"
#include "ttmathmisc.h"
@@ -109,8 +110,7 @@ namespace ttmath
for example a correct input string can be: for example a correct input string can be:
"1" "1"
"2.1234" "2.1234"
"2,1234" (they are the same, we can either use a comma or a dot in values) "2,1234" (they are the same, by default we can either use a comma or a dot)
(look at the macro TTMATH_COMMA_CHARACTER_2)
"1 + 2" "1 + 2"
"(1 + 2) * 3" "(1 + 2) * 3"
"pi" "pi"
@@ -131,13 +131,12 @@ namespace ttmath
for example: for example:
"1+2;4+5" "1+2;4+5"
the result will be on the stack as follows: the result will be on the stack as follows:
"3" stack[0].value=3
"9" stack[1].value=9
*/ */
template<class ValueType> template<class ValueType>
class Parser class Parser
{ {
private: private:
/*! /*!
@@ -160,14 +159,20 @@ private:
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
}; };
enum Assoc
{
right, // right-associative
non_right // associative or left-associative
};
Type GetType() const { return type; } Type GetType() const { return type; }
int GetPriority() const { return priority; } int GetPriority() const { return priority; }
Assoc GetAssoc() const { return assoc; }
void SetType(Type t) void SetType(Type t)
{ {
type = t; type = t;
assoc = non_right;
switch( type ) switch( type )
{ {
@@ -201,6 +206,7 @@ private:
case pow: case pow:
priority = 14; priority = 14;
assoc = right;
break; break;
default: default:
@@ -209,7 +215,7 @@ private:
} }
} }
MatOperator(): type(none), priority(0) MatOperator(): type(none), priority(0), assoc(non_right)
{ {
} }
@@ -217,7 +223,7 @@ private:
Type type; Type type;
int priority; int priority;
Assoc assoc;
}; // end of MatOperator class }; // end of MatOperator class
@@ -276,9 +282,16 @@ public:
/*! /*!
stack on which we're keeping the Items stack on which we're keeping the Items
at the end of parsing we'll have the result on its at the end of parsing we'll have the result here
the result don't have to be one value, it can be a list the result don't have to be one value, it can be
of values separated by the 'semicolon item' more than one if we have used a semicolon in the global space
e.g. such input string "1+2;3+4" will generate a result:
stack[0].value=3
stack[1].value=7
you should check if the stack is not empty, because if there was
a syntax error in the input string then we do not have any results
on the stack
*/ */
std::vector<Item> stack; std::vector<Item> stack;
@@ -311,7 +324,6 @@ ErrorCode error;
/*! /*!
pointer to the currently reading char pointer to the currently reading char
when an error has occured it may be used to count the index of the wrong character when an error has occured it may be used to count the index of the wrong character
*/ */
const char * pstring; const char * pstring;
@@ -426,10 +438,44 @@ VariablesTable variables_table;
/*! /*!
you can't calculate the factorial if the argument is greater than 'factorial_max' some coefficients used when calculating the gamma (or factorial) function
default value is zero which means there are not any limitations
*/ */
ValueType factorial_max; CGamma<ValueType> cgamma;
/*!
temporary object for a whole string when Parse(std::wstring) is used
*/
std::string wide_to_ansi;
/*!
group character (used when parsing)
default zero (not used)
*/
int group;
/*!
characters used as a comma
default: '.' and ','
comma2 can be zero (it means it is not used)
*/
int comma, comma2;
/*!
an additional character used as a separator between function parameters
(semicolon is used always)
*/
int param_sep;
/*!
true if something was calculated (at least one mathematical operator was used or a function or a variable)
*/
bool calculated;
/*! /*!
@@ -505,7 +551,8 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
(there can be a recurrence here therefore we're using 'visited_variables' (there can be a recurrence here therefore we're using 'visited_variables'
and 'visited_functions' sets to make a stop condition) and 'visited_functions' sets to make a stop condition)
*/ */
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0) ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string,
FunctionLocalVariables * local_variables = 0)
{ {
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
RecurrenceParsingVariablesOrFunction_AddName(variable, name); RecurrenceParsingVariablesOrFunction_AddName(variable, name);
@@ -559,6 +606,7 @@ bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType &
return false; return false;
result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value); result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
calculated = true;
return true; return true;
} }
@@ -607,6 +655,7 @@ ValueType result;
Error( err_unknown_variable ); Error( err_unknown_variable );
(result.*(i->second))(); (result.*(i->second))();
calculated = true;
return result; return result;
} }
@@ -674,6 +723,20 @@ return result;
} }
void Gamma(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
ErrorCode err;
result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok)
Error( err );
}
/*! /*!
factorial factorial
result = 1 * 2 * 3 * 4 * .... * x result = 1 * 2 * 3 * 4 * .... * x
@@ -685,10 +748,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
ErrorCode err; ErrorCode err;
if( !factorial_max.IsZero() && stack[sindex].value > factorial_max ) result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
Error( err_too_big_factorial );
result = ttmath::Factorial(stack[sindex].value, &err, pstop_calculating);
if(err != err_ok) if(err != err_ok)
Error( err ); Error( err );
@@ -708,7 +768,11 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) ); ErrorCode err;
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
} }
void Cos(int sindex, int amount_of_args, ValueType & result) void Cos(int sindex, int amount_of_args, ValueType & result)
@@ -716,7 +780,11 @@ void Cos(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) ); ErrorCode err;
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
} }
void Tan(int sindex, int amount_of_args, ValueType & result) void Tan(int sindex, int amount_of_args, ValueType & result)
@@ -757,7 +825,10 @@ void Round(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Round(stack[sindex].value); result = stack[sindex].value;
if( result.Round() )
Error( err_overflow );
} }
@@ -973,7 +1044,7 @@ void Not(int sindex, int amount_of_args, ValueType & result)
void DegToRad(int sindex, int amount_of_args, ValueType & result) void DegToRad(int sindex, int amount_of_args, ValueType & result)
{ {
ErrorCode err; ErrorCode err = err_ok;
if( amount_of_args == 1 ) if( amount_of_args == 1 )
{ {
@@ -1052,7 +1123,7 @@ void RadToGrad(int sindex, int amount_of_args, ValueType & result)
void DegToGrad(int sindex, int amount_of_args, ValueType & result) void DegToGrad(int sindex, int amount_of_args, ValueType & result)
{ {
ErrorCode err; ErrorCode err = err_ok;
if( amount_of_args == 1 ) if( amount_of_args == 1 )
{ {
@@ -1333,6 +1404,45 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
} }
void Frac(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = stack[sindex].value;
result.RemainFraction();
}
/*!
we use such a method because 'wvsprintf' is not everywhere defined
*/
void Sprintf(char * buffer, int par)
{
char buf[30]; // char, not wchar_t
int i;
#ifdef _MSC_VER
#pragma warning( disable: 4996 )
//warning C4996: 'sprintf': This function or variable may be unsafe.
#endif
sprintf(buf, "%d", par);
for(i=0 ; buf[i] != 0 ; ++i)
buffer[i] = buf[i];
buffer[i] = 0;
#ifdef _MSC_VER
#pragma warning( default: 4996 )
#endif
}
/*! /*!
this method returns the value from a user-defined function this method returns the value from a user-defined function
@@ -1357,20 +1467,23 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
if( amount_of_args > 0 ) if( amount_of_args > 0 )
{ {
char buffer[20]; char buffer[30];
// x = x1 // x = x1
sprintf(buffer,"x"); buffer[0] = 'x';
buffer[1] = 0;
local_variables.insert( std::make_pair(buffer, stack[sindex].value) ); local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
for(int i=0 ; i<amount_of_args ; ++i) for(int i=0 ; i<amount_of_args ; ++i)
{ {
sprintf(buffer,"x%d",i+1); buffer[0] = 'x';
Sprintf(buffer+1, i+1);
local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) ); local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
} }
} }
stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables); stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
calculated = true;
return true; return true;
} }
@@ -1403,6 +1516,7 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
calling the specify function calling the specify function
*/ */
(this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value); (this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value);
calculated = true;
} }
@@ -1417,10 +1531,14 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
*/ */
void InsertFunctionToTable(const char * function_name, pfunction pf) void InsertFunctionToTable(const char * function_name, pfunction pf)
{ {
functions_table.insert( std::make_pair(std::string(function_name), pf)); std::string str;
Misc::AssignString(str, function_name);
functions_table.insert( std::make_pair(str, pf) );
} }
/*! /*!
inserting a function to the variables' table inserting a function to the variables' table
(this function returns value of variable) (this function returns value of variable)
@@ -1430,7 +1548,10 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
*/ */
void InsertVariableToTable(const char * variable_name, pfunction_var pf) void InsertVariableToTable(const char * variable_name, pfunction_var pf)
{ {
variables_table.insert( std::make_pair(std::string(variable_name), pf)); std::string str;
Misc::AssignString(str, variable_name);
variables_table.insert( std::make_pair(str, pf) );
} }
@@ -1439,9 +1560,7 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
*/ */
void CreateFunctionsTable() void CreateFunctionsTable()
{ {
/* InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma);
names of functions should consist of small letters
*/
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial); InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
InsertFunctionToTable("abs", &Parser<ValueType>::Abs); InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
InsertFunctionToTable("sin", &Parser<ValueType>::Sin); InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
@@ -1500,6 +1619,7 @@ void CreateFunctionsTable()
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor); InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
InsertFunctionToTable("sum", &Parser<ValueType>::Sum); InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
InsertFunctionToTable("avg", &Parser<ValueType>::Avg); InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
InsertFunctionToTable("frac", &Parser<ValueType>::Frac);
} }
@@ -1508,9 +1628,6 @@ void CreateFunctionsTable()
*/ */
void CreateVariablesTable() void CreateVariablesTable()
{ {
/*
names of variables should consist of small letters
*/
InsertVariableToTable("pi", &ValueType::SetPi); InsertVariableToTable("pi", &ValueType::SetPi);
InsertVariableToTable("e", &ValueType::SetE); InsertVariableToTable("e", &ValueType::SetE);
} }
@@ -1555,7 +1672,7 @@ int character;
do do
{ {
result += character; result += static_cast<char>( character );
character = * ++pstring; character = * ++pstring;
} }
while( (character>='a' && character<='z') || while( (character>='a' && character<='z') ||
@@ -1634,6 +1751,8 @@ return is_it_name_of_function;
} }
/*! /*!
we're reading a numerical value directly from the string we're reading a numerical value directly from the string
*/ */
@@ -1641,8 +1760,14 @@ void ReadValue(Item & result, int reading_base)
{ {
const char * new_stack_pointer; const char * new_stack_pointer;
bool value_read; bool value_read;
Conv conv;
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read); conv.base = reading_base;
conv.comma = comma;
conv.comma2 = comma2;
conv.group = group;
uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
pstring = new_stack_pointer; pstring = new_stack_pointer;
if( carry ) if( carry )
@@ -1653,43 +1778,18 @@ bool value_read;
} }
/*!
this method converts the character ascii c into the value in range <0;base-1>
if the character is incorrect for this base the funcion will return -1
*/
int CharToDigit(int c, int base)
{
if( c>='0' && c<='9' )
c=c-'0';
else
if( c>='a' && c<='z' )
c=c-'a'+10;
else
if( c>='A' && c<='Z' )
c=c-'A'+10;
else
return -1;
if( c >= base )
return -1;
return c;
}
/*! /*!
this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too) this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too)
*/ */
bool ValueStarts(int character, int base) bool ValueStarts(int character, int base)
{ {
if( character == TTMATH_COMMA_CHARACTER_1 ) if( character == comma )
return true; return true;
if( TTMATH_COMMA_CHARACTER_2 != 0 && character == TTMATH_COMMA_CHARACTER_2 ) if( comma2!=0 && character==comma2 )
return true; return true;
if( CharToDigit(character, base) != -1 ) if( Misc::CharToDigit(character, base) != -1 )
return true; return true;
return false; return false;
@@ -1812,9 +1912,9 @@ return 0;
} }
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type) void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
{ {
operators_table.insert( std::make_pair(name, type) ); operators_table.insert( std::make_pair(std::string(name), type) );
} }
@@ -1823,19 +1923,19 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type
*/ */
void CreateMathematicalOperatorsTable() void CreateMathematicalOperatorsTable()
{ {
InsertOperatorToTable(std::string("||"), MatOperator::lor); InsertOperatorToTable("||", MatOperator::lor);
InsertOperatorToTable(std::string("&&"), MatOperator::land); InsertOperatorToTable("&&", MatOperator::land);
InsertOperatorToTable(std::string("!="), MatOperator::neq); InsertOperatorToTable("!=", MatOperator::neq);
InsertOperatorToTable(std::string("=="), MatOperator::eq); InsertOperatorToTable("==", MatOperator::eq);
InsertOperatorToTable(std::string(">="), MatOperator::get); InsertOperatorToTable(">=", MatOperator::get);
InsertOperatorToTable(std::string("<="), MatOperator::let); InsertOperatorToTable("<=", MatOperator::let);
InsertOperatorToTable(std::string(">"), MatOperator::gt); InsertOperatorToTable(">", MatOperator::gt);
InsertOperatorToTable(std::string("<"), MatOperator::lt); InsertOperatorToTable("<", MatOperator::lt);
InsertOperatorToTable(std::string("-"), MatOperator::sub); InsertOperatorToTable("-", MatOperator::sub);
InsertOperatorToTable(std::string("+"), MatOperator::add); InsertOperatorToTable("+", MatOperator::add);
InsertOperatorToTable(std::string("/"), MatOperator::div); InsertOperatorToTable("/", MatOperator::div);
InsertOperatorToTable(std::string("*"), MatOperator::mul); InsertOperatorToTable("*", MatOperator::mul);
InsertOperatorToTable(std::string("^"), MatOperator::pow); InsertOperatorToTable("^", MatOperator::pow);
} }
@@ -1850,7 +1950,7 @@ bool IsSubstring(const std::string & str1, const std::string & str2)
if( str2.length() > str1.length() ) if( str2.length() > str1.length() )
return false; return false;
for(std::string::size_type i=0 ; i<str2.length() ; ++i) for(typename std::string::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] ) if( str1[i] != str2[i] )
return false; return false;
@@ -1892,6 +1992,31 @@ typename OperatorsTable::iterator iter_old, iter_new;
} }
/*!
this method makes a calculation for the percentage operator
e.g.
1000-50% = 1000-(1000*0,5) = 500
*/
void OperatorPercentage()
{
if( stack_index < 3 ||
stack[stack_index-1].type != Item::numerical_value ||
stack[stack_index-2].type != Item::mat_operator ||
stack[stack_index-3].type != Item::numerical_value )
Error(err_percent_from);
++pstring;
SkipWhiteCharacters();
uint c = 0;
c += stack[stack_index-1].value.Div(100);
c += stack[stack_index-1].value.Mul(stack[stack_index-3].value);
if( c )
Error(err_overflow);
}
/*! /*!
this method reads a mathematic operators this method reads a mathematic operators
or the final bracket or the semicolon operator or the final bracket or the semicolon operator
@@ -1904,6 +2029,10 @@ int ReadOperator(Item & result)
{ {
SkipWhiteCharacters(); SkipWhiteCharacters();
if( *pstring == '%' )
OperatorPercentage();
if( *pstring == 0 ) if( *pstring == 0 )
return 1; return 1;
else else
@@ -1913,7 +2042,7 @@ int ReadOperator(Item & result)
++pstring; ++pstring;
} }
else else
if( *pstring == ';' ) if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
{ {
result.type = Item::semicolon; result.type = Item::semicolon;
++pstring; ++pstring;
@@ -1943,7 +2072,9 @@ return 0;
void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator, void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator,
const ValueType & value2) const ValueType & value2)
{ {
int res; uint res;
calculated = true;
switch( mat_operator ) switch( mat_operator )
{ {
@@ -2006,7 +2137,6 @@ int res;
break; break;
default: default:
/* /*
on the stack left an unknown operator but we had to recognize its before on the stack left an unknown operator but we had to recognize its before
@@ -2038,7 +2168,17 @@ void TryRollingUpStackWithOperatorPriority()
stack[stack_index-3].type == Item::mat_operator && stack[stack_index-3].type == Item::mat_operator &&
stack[stack_index-2].type == Item::numerical_value && stack[stack_index-2].type == Item::numerical_value &&
stack[stack_index-1].type == Item::mat_operator && stack[stack_index-1].type == Item::mat_operator &&
stack[stack_index-3].moperator.GetPriority() >= stack[stack_index-1].moperator.GetPriority() (
(
// the first operator has greater priority
stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority()
) ||
(
// or both operators have the same priority and the first operator is not right associative
stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() &&
stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right
)
)
) )
{ {
MakeStandardMathematicOperation(stack[stack_index-4].value, MakeStandardMathematicOperation(stack[stack_index-4].value,
@@ -2393,7 +2533,10 @@ Parser(): default_stack_size(100)
base = 10; base = 10;
deg_rad_grad = 1; deg_rad_grad = 1;
error = err_ok; error = err_ok;
factorial_max.SetZero(); group = 0;
comma = '.';
comma2 = ',';
param_sep = 0;
CreateFunctionsTable(); CreateFunctionsTable();
CreateVariablesTable(); CreateVariablesTable();
@@ -2412,8 +2555,11 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
pfunction_local_variables = 0; pfunction_local_variables = 0;
base = p.base; base = p.base;
deg_rad_grad = p.deg_rad_grad; deg_rad_grad = p.deg_rad_grad;
error = err_ok; error = p.error;
factorial_max = p.factorial_max; group = p.group;
comma = p.comma;
comma2 = p.comma2;
param_sep = p.param_sep;
/* /*
we don't have to call 'CreateFunctionsTable()' etc. we don't have to call 'CreateFunctionsTable()' etc.
@@ -2441,6 +2587,7 @@ Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
/*! /*!
the new base of mathematic system the new base of mathematic system
default is 10
*/ */
void SetBase(int b) void SetBase(int b)
{ {
@@ -2496,14 +2643,36 @@ void SetFunctions(const Objects * pf)
/*! /*!
you will not be allowed to calculate the factorial setting the group character
if its argument is greater than 'm' default zero (not used)
there'll be: ErrorCode::err_too_big_factorial
default 'factorial_max' is zero which means you can calculate what you want to
*/ */
void SetFactorialMax(const ValueType & m) void SetGroup(int g)
{ {
factorial_max = m; group = g;
}
/*!
setting the main comma operator and the additional comma operator
the additional operator can be zero (which means it is not used)
default are: '.' and ','
*/
void SetComma(int c, int c2 = 0)
{
comma = c;
comma2 = c2;
}
/*!
setting an additional character which is used as a parameters separator
the main parameters separator is a semicolon (is used always)
this character is used also as a global separator
*/
void SetParamSep(int s)
{
param_sep = s;
} }
@@ -2515,6 +2684,7 @@ ErrorCode Parse(const char * str)
stack_index = 0; stack_index = 0;
pstring = str; pstring = str;
error = err_ok; error = err_ok;
calculated = false;
stack.resize( default_stack_size ); stack.resize( default_stack_size );
@@ -2525,6 +2695,7 @@ ErrorCode Parse(const char * str)
catch(ErrorCode c) catch(ErrorCode c)
{ {
error = c; error = c;
calculated = false;
} }
NormalizeStack(); NormalizeStack();
@@ -2533,11 +2704,61 @@ return error;
} }
/*!
the main method using for parsing string
*/
ErrorCode Parse(const std::string & str)
{
return Parse(str.c_str());
}
#ifndef TTMATH_DONT_USE_WCHAR
/*!
the main method using for parsing string
*/
ErrorCode Parse(const wchar_t * str)
{
Misc::AssignString(wide_to_ansi, str);
return Parse(wide_to_ansi.c_str());
// !! wide_to_ansi clearing can be added here
}
/*!
the main method using for parsing string
*/
ErrorCode Parse(const std::wstring & str)
{
return Parse(str.c_str());
}
#endif
/*!
this method returns true is something was calculated
(at least one mathematical operator was used or a function or variable)
e.g. true if the string to Parse() looked like this:
"1+1"
"2*3"
"sin(5)"
if the string was e.g. "678" the result is false
*/
bool Calculated()
{
return calculated;
}
}; };
} // namespace } // namespace

250
ttmath/ttmaththreads.h Normal file
View File

@@ -0,0 +1,250 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmaththreads
#define headerfilettmaththreads
#include "ttmathtypes.h"
#ifdef TTMATH_WIN32_THREADS
#include <windows.h>
#include <cstdio>
#endif
#ifdef TTMATH_POSIX_THREADS
#include <pthread.h>
#endif
/*!
\file ttmaththreads.h
\brief Some objects used in multithreads environment
*/
/*
this is a simple skeleton of a program in multithreads environment:
#define TTMATH_MULTITHREADS
#include<ttmath/ttmath.h>
TTMATH_MULTITHREADS_HELPER
int main()
{
[...]
}
make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file)
use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope)
*/
namespace ttmath
{
#ifdef TTMATH_WIN32_THREADS
/*
we use win32 threads
*/
/*!
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
somewhere in *.cpp file
(at the moment in win32 this macro does nothing)
*/
#define TTMATH_MULTITHREADS_HELPER
/*!
objects of this class are used to synchronize
*/
class ThreadLock
{
HANDLE mutex_handle;
void CreateName(char * buffer) const
{
#ifdef _MSC_VER
#pragma warning (disable : 4996)
// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
#endif
sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId());
#ifdef _MSC_VER
#pragma warning (default : 4996)
#endif
}
public:
bool Lock()
{
char buffer[50];
CreateName(buffer);
mutex_handle = CreateMutexA(0, false, buffer);
if( mutex_handle == 0 )
return false;
WaitForSingleObject(mutex_handle, INFINITE);
return true;
}
ThreadLock()
{
mutex_handle = 0;
}
~ThreadLock()
{
if( mutex_handle != 0 )
{
ReleaseMutex(mutex_handle);
CloseHandle(mutex_handle);
}
}
};
#endif // #ifdef TTMATH_WIN32_THREADS
#ifdef TTMATH_POSIX_THREADS
/*
we use posix threads
*/
/*!
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
somewhere in *.cpp file
(this macro defines a pthread_mutex_t object used by TTMath library)
*/
#define TTMATH_MULTITHREADS_HELPER \
namespace ttmath \
{ \
pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \
}
/*!
ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro
*/
extern pthread_mutex_t ttmath_mutex;
/*!
objects of this class are used to synchronize
*/
class ThreadLock
{
public:
bool Lock()
{
if( pthread_mutex_lock(&ttmath_mutex) != 0 )
return false;
return true;
}
~ThreadLock()
{
pthread_mutex_unlock(&ttmath_mutex);
}
};
#endif // #ifdef TTMATH_POSIX_THREADS
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
/*!
we don't use win32 and pthreads
*/
/*!
*/
#define TTMATH_MULTITHREADS_HELPER
/*!
objects of this class are used to synchronize
actually we don't synchronize, the method Lock() returns always 'false'
*/
class ThreadLock
{
public:
bool Lock()
{
return false;
}
};
#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
} // namespace
#endif

View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2006-2009, Tomasz Sowa * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -54,63 +54,97 @@
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
#include <vector>
#ifndef _MSC_VER
#include <stdint.h>
// for uint64_t and int64_t on a 32 bit platform
#endif
/*! /*!
the version of the library the version of the library
TTMATH_PRERELEASE_VER is either zero or one TTMATH_PRERELEASE_VER is either zero or one
if zero that means this is the release version of the library zero means that this is the release version of the library
(one means something like beta)
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 9
#define TTMATH_REVISION_VER 4 #define TTMATH_REVISION_VER 2
#define TTMATH_PRERELEASE_VER 0 #define TTMATH_PRERELEASE_VER 0
/*! /*!
TTMATH_DEBUG you can define a platform explicitly by defining either
this macro enables further testing during writing your code TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro
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 TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
*/ */
#ifndef TTMATH_RELEASE #if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64
#define TTMATH_DEBUG
#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
#endif #endif
/*!
asm version of the library is available by default only for:
x86 and amd64 platforms and for Microsoft Visual and GCC compilers
but you can force using asm version (the same asm as for Microsoft Visual)
by defining TTMATH_FORCEASM macro
you have to be sure that your compiler accept such an asm format
*/
#ifndef TTMATH_FORCEASM
#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
*/
#define TTMATH_NOASM
#endif
#endif
namespace ttmath 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
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
@@ -121,17 +155,18 @@ namespace ttmath
typedef signed int sint; typedef signed int sint;
/*! /*!
this type is twice bigger than uint on 32 bit platform ulint and slint will be equal 64 bits
(64bit on a 32bit platforms)
although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long)
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
but only on a 32bit platform
*/ */
#ifdef TTMATH_NOASM #ifdef _MSC_VER
// long long on MS Windows (Visual and GCC mingw compilers) have 64 bits
// stdint.h is not available on Visual Studio prior to VS 2010 version
typedef unsigned long long int ulint; typedef unsigned long long int ulint;
typedef signed long long int slint;
#else
// we do not use 'long' here because there is a difference in unix and windows
// environments: in unix 'long' has 64 bits but in windows it has only 32 bits
typedef uint64_t ulint;
typedef int64_t slint;
#endif #endif
/*! /*!
@@ -157,22 +192,30 @@ namespace ttmath
*/ */
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u #define TTMATH_BUILTIN_VARIABLES_SIZE 256u
/*!
this macro returns the number of machine words
capable to hold min_bits bits
e.g. TTMATH_BITS(128) returns 4
*/
#define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1)
#else #else
/*! /*!
on 64bit platforms one word (uint, sint) will be equal 64bits on 64bit platforms one word (uint, sint) will be equal 64bits
*/ */
#ifdef _MSC_VER
/* in VC 'long' type has 32 bits, __int64 is VC extension */
typedef unsigned __int64 uint;
typedef signed __int64 sint;
#else
typedef unsigned long uint; typedef unsigned long uint;
typedef signed long sint; typedef signed long sint;
#endif
/*! /*!
on 64bit platform we do not define ulint on 64bit platforms we do not define ulint and slint
sizeof(long long) is 8 (64bit) but we need 128bit
on 64 bit platform (when there is defined TTMATH_NOASM macro)
methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit
*/ */
//typedef unsigned long long int ulint;
/*! /*!
how many bits there are in the uint type how many bits there are in the uint type
@@ -197,27 +240,28 @@ namespace ttmath
*/ */
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
/*!
this macro returns the number of machine words
capable to hold min_bits bits
e.g. TTMATH_BITS(128) returns 2
*/
#define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1)
#endif #endif
} }
#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC)
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
/*! #if defined(_WIN32)
characters which represent the comma operator #define TTMATH_WIN32_THREADS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#define TTMATH_POSIX_THREADS
#endif
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function) #endif
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character #endif
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 e.g.
#define TTMATH_COMMA_CHARACTER_2 0
then only TTMATH_COMMA_CHARACTER_1 will be used
don't put there any special character which is used by the parser
(for example a semicolon ';' shouldn't be there)
*/
#define TTMATH_COMMA_CHARACTER_1 '.'
#define TTMATH_COMMA_CHARACTER_2 ','
@@ -237,10 +281,59 @@ namespace ttmath
/*!
this is a limit when calculating Karatsuba multiplication
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
the Karatsuba algorithm will use standard schoolbook multiplication
*/
#ifdef TTMATH_DEBUG_LOG
// if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
#else
#ifdef __GNUC__
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
#else
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
#endif
#endif
/*!
this is a special value used when calculating the Gamma(x) function
if x is greater than this value then the Gamma(x) will be calculated using
some kind of series
don't use smaller values than about 100
*/
#define TTMATH_GAMMA_BOUNDARY 2000
namespace ttmath namespace ttmath
{ {
/*!
lib type codes:
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
asm_gcc_32 - with asm code designed for GCC (32 bits)
asm_vc_64 - with asm for VC (64 bit)
asm_gcc_64 - with asm for GCC (64 bit)
no_asm_32 - pure C++ version (32 bit) - without any asm code
no_asm_64 - pure C++ version (64 bit) - without any asm code
*/
enum LibTypeCode
{
asm_vc_32 = 0,
asm_gcc_32,
asm_vc_64,
asm_gcc_64,
no_asm_32,
no_asm_64
};
/*! /*!
error codes error codes
*/ */
@@ -271,11 +364,132 @@ namespace ttmath
err_object_exists, err_object_exists,
err_unknown_object, err_unknown_object,
err_still_calculating, err_still_calculating,
err_too_big_factorial, err_in_short_form_used_function,
err_in_short_form_used_function err_percent_from
}; };
/*!
this struct is used when converting to/from a string
/temporarily only in Big::ToString() and Big::FromString()/
*/
struct Conv
{
/*!
base (radix) on which the value will be shown (or read)
default: 10
*/
uint base;
/*!
used only in Big::ToString()
if true the value will be always shown in the scientific mode, e.g: 123e+30
default: false
*/
bool scient;
/*!
used only in Big::ToString()
if scient is false then the value will be printed in the scientific mode
only if the exponent is greater than scien_from
default: 15
*/
sint scient_from;
/*!
if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
and the result value is not an integer then we make an additional rounding
(after converting the last digit from the result is skipped)
default: true
e.g.
Conv c;
c.base_round = false;
Big<1, 1> a = "0.1"; // decimal input
std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999
*/
bool base_round;
/*!
used only in Big::ToString()
tells how many digits after comma are possible
default: -1 which means all digits are printed
set it to zero if you want integer value only
for example when the value is:
12.345678 and 'round' is 4
then the result will be
12.3457 (the last digit was rounded)
*/
sint round;
/*!
if true that not mattered digits in the mantissa will be cut off
(zero characters at the end -- after the comma operator)
e.g. 1234,78000 will be: 1234,78
default: true
*/
bool trim_zeroes;
/*!
the main comma operator (used when reading and writing)
default is a dot '.'
*/
uint comma;
/*!
additional comma operator (used only when reading)
if you don't want it just set it to zero
default is a comma ','
this allowes you to convert from a value:
123.45 as well as from 123,45
*/
uint comma2;
/*!
it sets the character which is used for grouping
if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
if you don't want grouping just set it to zero (which is default)
*/
uint group;
/*!
*/
uint group_exp; // not implemented yet
Conv()
{
// default values
base = 10;
scient = false;
scient_from = 15;
base_round = true;
round = -1;
trim_zeroes = true;
comma = '.';
comma2 = ',';
group = 0;
group_exp = 0;
}
};
/*! /*!
this simple class can be used in multithreading model this simple class can be used in multithreading model
(you can write your own class derived from this one) (you can write your own class derived from this one)
@@ -328,37 +542,24 @@ namespace ttmath
In the library is used macro TTMATH_REFERENCE_ASSERT which In the library is used macro TTMATH_REFERENCE_ASSERT which
can throw an exception of this type can throw an exception of this type
** from version 0.9.2 this macro is removed from all methods
in public interface so you don't have to worry about it **
If you compile with gcc you can get a small benefit If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with from using method Where() (it returns std::string) with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used) was used)
What is 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 class ReferenceError : public std::logic_error, public ExceptionInfo
{ {
public: public:
ReferenceError() : std::logic_error ("reference error") ReferenceError() : std::logic_error("reference error")
{ {
} }
ReferenceError(const char * f, int l) : ReferenceError(const char * f, int l) :
std::logic_error ("reference error"), ExceptionInfo(f,l) std::logic_error("reference error"), ExceptionInfo(f,l)
{ {
} }
@@ -377,20 +578,20 @@ namespace ttmath
of this type of this type
if you compile with gcc you can get a small benefit if you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with from using method Where() (it returns std::string) with
the name and the line of a file where the macro TTMATH_ASSERT the name and the line of a file where the macro TTMATH_ASSERT
was used) was used)
*/ */
class RuntimeError : public std::runtime_error, ExceptionInfo class RuntimeError : public std::runtime_error, public ExceptionInfo
{ {
public: public:
RuntimeError() : std::runtime_error ("internal error") RuntimeError() : std::runtime_error("internal error")
{ {
} }
RuntimeError(const char * f, int l) : RuntimeError(const char * f, int l) :
std::runtime_error ("internal error"), ExceptionInfo(f,l) std::runtime_error("internal error"), ExceptionInfo(f,l)
{ {
} }
@@ -403,8 +604,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 #ifdef TTMATH_DEBUG
#if defined(__FILE__) && defined(__LINE__) #if defined(__FILE__) && defined(__LINE__)
@@ -432,18 +646,22 @@ namespace ttmath
#ifdef TTMATH_DEBUG_LOG #ifdef TTMATH_DEBUG_LOG
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
#define TTMATH_LOG(msg) \ #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout);
PrintLog(msg, std::cout); #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len);
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len);
#else #else
#define TTMATH_LOG(msg) #define TTMATH_LOG(msg)
#define TTMATH_LOGC(msg, carry)
#define TTMATH_VECTOR_LOG(msg, vector, len)
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
#endif #endif
} // namespace } // namespace
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2006-2009, Tomasz Sowa * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,56 @@
namespace ttmath namespace ttmath
{ {
/*!
returning the string represents the currect type of the library
we have following types:
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
asm_gcc_32 - with asm code designed for GCC (32 bits)
asm_vc_64 - with asm for VC (64 bit)
asm_gcc_64 - with asm for GCC (64 bit)
no_asm_32 - pure C++ version (32 bit) - without any asm code
no_asm_64 - pure C++ version (64 bit) - without any asm code
*/
template<uint value_size>
const char * UInt<value_size>::LibTypeStr()
{
#ifdef TTMATH_PLATFORM32
static const char info[] = "no_asm_32";
#endif
#ifdef TTMATH_PLATFORM64
static const char info[] = "no_asm_64";
#endif
return info;
}
/*!
returning the currect type of the library
*/
template<uint value_size>
LibTypeCode UInt<value_size>::LibType()
{
#ifdef TTMATH_PLATFORM32
LibTypeCode info = no_asm_32;
#endif
#ifdef TTMATH_PLATFORM64
LibTypeCode info = no_asm_64;
#endif
return info;
}
/*!
this method adds two words together
returns carry
this method is created only when TTMATH_NOASM macro is defined
*/
template<uint value_size> template<uint value_size>
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result) uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
{ {
@@ -95,7 +145,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i) for(i=0 ; i<value_size ; ++i)
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]); c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOG("UInt_noasm::Add") TTMATH_LOGC("UInt::Add", c)
return c; return c;
} }
@@ -131,7 +181,7 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i) for(i=index+1 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]); c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt_noasm::AddInt") TTMATH_LOGC("UInt::AddInt", c)
return c; return c;
} }
@@ -184,13 +234,60 @@ namespace ttmath
for(i=index+2 ; i<value_size && c ; ++i) for(i=index+2 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]); c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt64::AddTwoInts") TTMATH_LOGC("UInt::AddTwoInts", c)
return c; return c;
} }
/*!
this static method addes one vector to the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5+1
4 3 4+3
2 7 2+7
6 6
9 9
of course the carry is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = AddTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
return c;
}
/*!
this method subtractes one word from the other
returns carry
this method is created only when TTMATH_NOASM macro is defined
*/
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result) uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
{ {
@@ -232,7 +329,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i) for(i=0 ; i<value_size ; ++i)
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]); c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOG("UInt_noasm::Sub") TTMATH_LOGC("UInt::Sub", c)
return c; return c;
} }
@@ -270,12 +367,51 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i) for(i=index+1 ; i<value_size && c ; ++i)
c = SubTwoWords(table[i], 0, c, &table[i]); c = SubTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt_noasm::SubInt") TTMATH_LOGC("UInt::SubInt", c)
return c; return c;
} }
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5-1
4 3 4-3
2 7 2-7
6 6-1 (the borrow from previous item)
9 9
return (carry): 0
of course the carry (borrow) is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = SubTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
return c;
}
/*! /*!
@@ -305,7 +441,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOG("UInt64::Rcl2_one") TTMATH_LOGC("UInt::Rcl2_one", c)
return c; return c;
} }
@@ -344,7 +480,9 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOG("UInt64::Rcr2_one") c = (c != 0)? 1 : 0;
TTMATH_LOGC("UInt::Rcr2_one", c)
return c; return c;
} }
@@ -382,7 +520,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOG("UInt::Rcl2") TTMATH_LOGC("UInt::Rcl2", (c & 1))
return (c & 1); return (c & 1);
} }
@@ -421,18 +559,19 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOG("UInt64::Rcr2") c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; TTMATH_LOGC("UInt::Rcr2", c)
return c;
} }
/* /*!
this method returns the number of the highest set bit in x this method returns the number of the highest set bit in x
if the 'x' is zero this method returns '-1' if the 'x' is zero this method returns '-1'
*/ */
template<uint value_size> template<uint value_size>
sint UInt<value_size>::FindLeadingBitInWord(uint x) sint UInt<value_size>::FindLeadingBitInWord(uint x)
@@ -453,13 +592,34 @@ namespace ttmath
/*!
this method returns the number of the highest set bit in x
if the 'x' is zero this method returns '-1'
*/
template<uint value_size>
sint UInt<value_size>::FindLowestBitInWord(uint x)
{
if( x == 0 )
return -1;
uint bit = 0;
while( (x & 1) == 0 )
{
x = x >> 1;
++bit;
}
return bit;
}
/*! /*!
this method sets a special bit in the 'value' this method sets a special bit in the 'value'
and returns the last state of the bit (zero or one) and returns the last state of the bit (zero or one)
bit is from <0,63> bit is from <0,TTMATH_BITS_PER_UINT-1>
e.g. e.g.
uint x = 100; uint x = 100;
@@ -473,7 +633,7 @@ namespace ttmath
uint mask = 1; uint mask = 1;
if( bit > 1 ) if( bit > 0 )
mask = mask << bit; mask = mask << bit;
uint last = value & mask; uint last = value & mask;
@@ -661,11 +821,11 @@ namespace ttmath
temp1.u_.high = a_.u_.low; temp1.u_.high = a_.u_.low;
temp1.u_.low = b_.u_.high; temp1.u_.low = b_.u_.high;
res_.u_.high = temp1.u / c; res_.u_.high = (unsigned int)(temp1.u / c);
temp2.u_.high = temp1.u % c; temp2.u_.high = (unsigned int)(temp1.u % c);
temp2.u_.low = b_.u_.low; temp2.u_.low = b_.u_.low;
res_.u_.low = temp2.u / c; res_.u_.low = (unsigned int)(temp2.u / c);
*rest = temp2.u % c; *rest = temp2.u % c;
*r = res_.u; *r = res_.u;

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2006-2009, Tomasz Sowa * Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -51,10 +51,77 @@
this file is included at the end of ttmathuint.h this file is included at the end of ttmathuint.h
*/ */
#ifndef __GNUC__
#include <intrin.h>
#endif
namespace ttmath namespace ttmath
{ {
#ifndef __GNUC__
extern "C"
{
uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
};
#endif
/*!
returning the string represents the currect type of the library
we have following types:
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
asm_gcc_32 - with asm code designed for GCC (32 bits)
asm_vc_64 - with asm for VC (64 bit)
asm_gcc_64 - with asm for GCC (64 bit)
no_asm_32 - pure C++ version (32 bit) - without any asm code
no_asm_64 - pure C++ version (64 bit) - without any asm code
*/
template<uint value_size>
const char * UInt<value_size>::LibTypeStr()
{
#ifndef __GNUC__
static const char info[] = "asm_vc_64";
#endif
#ifdef __GNUC__
static const char info[] = "asm_gcc_64";
#endif
return info;
}
/*!
returning the currect type of the library
*/
template<uint value_size>
LibTypeCode UInt<value_size>::LibType()
{
#ifndef __GNUC__
LibTypeCode info = asm_vc_64;
#endif
#ifdef __GNUC__
LibTypeCode info = asm_gcc_64;
#endif
return info;
}
/*! /*!
* *
* basic mathematic functions * basic mathematic functions
@@ -78,23 +145,24 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
const uint * p2 = ss2.table; const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_adc_x64(p1,p2,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
/* /*
this part should be compiled with gcc this part should be compiled with gcc
*/ */
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n" "movq (%%rsi,%%rdx,8), %%rax \n"
@@ -112,7 +180,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Add") TTMATH_LOGC("UInt::Add", c)
return c; return c;
} }
@@ -145,15 +213,16 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_addindexed_x64(p1,b,index,value);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
@@ -173,12 +242,12 @@ namespace ttmath
"movzx %%al, %%rdx \n" "movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2) : "=d" (c), "=a" (dummy), "=c" (dummy2)
: "a" (value), "c" (b), "0" (index), "b" (p1) : "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::AddInt") TTMATH_LOGC("UInt::AddInt", c)
return c; return c;
} }
@@ -223,15 +292,17 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size - 1 ) TTMATH_ASSERT( index < value_size - 1 )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"subq %%rdx, %%rcx \n" "subq %%rdx, %%rcx \n"
@@ -254,18 +325,99 @@ namespace ttmath
"movzx %%al, %%rax \n" "movzx %%al, %%rax \n"
: "=a" (c), "=c" (dummy), "=d" (dummy2) : "=a" (c), "=c" (dummy), "=d" (dummy2)
: "1" (b), "2" (index), "b" (p1), "S" (x1), "0" (x2) : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::AddTwoInts") TTMATH_LOGC("UInt::AddTwoInts", c)
return c; return c;
} }
/*!
this static method addes one vector to the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5+1
4 3 4+3
2 7 2+7
6 6
9 9
of course the carry is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint c;
#ifndef __GNUC__
c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
#ifdef __GNUC__
uint dummy1, dummy2, dummy3;
uint rest = ss1_size - ss2_size;
// this part should be compiled with gcc
__asm__ __volatile__(
"mov %%rdx, %%r8 \n"
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
"1: \n"
"mov (%%rsi,%%rdx,8), %%rax \n"
"adc (%%rbx,%%rdx,8), %%rax \n"
"mov %%rax, (%%rdi,%%rdx,8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 1b \n"
"adc %%rcx, %%rcx \n" // rcx has the cf state
"or %%r8, %%r8 \n"
"jz 3f \n"
"xor %%rbx, %%rbx \n" // ebx = 0
"neg %%rcx \n" // setting cf from rcx
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
"2: \n"
"mov (%%rsi, %%rdx, 8), %%rax \n"
"adc %%rbx, %%rax \n"
"mov %%rax, (%%rdi, %%rdx, 8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 2b \n"
"adc %%rcx, %%rcx \n"
"3: \n"
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
: "%r8", "cc", "memory" );
#endif
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
return c;
}
/*! /*!
@@ -284,20 +436,22 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
const uint * p2 = ss2.table; const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_sbb_x64(p1,p2,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n" "movq (%%rsi,%%rdx,8), %%rax \n"
@@ -313,15 +467,15 @@ namespace ttmath
: "0" (b), "1" (c), "b" (p1), "S" (p2) : "0" (b), "1" (c), "b" (p1), "S" (p2)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::Sub") TTMATH_LOGC("UInt::Sub", c)
return c; return c;
} }
/*! /*!
this method subtracts one word (at a specific position) this method subtracts one word (at a specific position)
and returns a carry (if it was) and returns a carry (if it was)
@@ -347,15 +501,17 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_subindexed_x64(p1,b,index,value);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"subq %%rdx, %%rcx \n" "subq %%rdx, %%rcx \n"
@@ -374,12 +530,97 @@ namespace ttmath
"movzx %%al, %%rdx \n" "movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2) : "=d" (c), "=a" (dummy), "=c" (dummy2)
: "1" (value), "2" (b), "0" (index), "b" (p1) : "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::SubInt") TTMATH_LOGC("UInt::SubInt", c)
return c;
}
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5-1
4 3 4-3
2 7 2-7
6 6-1 (the borrow from previous item)
9 9
return (carry): 0
of course the carry (borrow) is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint c;
#ifndef __GNUC__
c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
#ifdef __GNUC__
// the asm code is nearly the same as in AddVector
// only two instructions 'adc' are changed to 'sbb'
uint dummy1, dummy2, dummy3;
uint rest = ss1_size - ss2_size;
__asm__ __volatile__(
"mov %%rdx, %%r8 \n"
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
"1: \n"
"mov (%%rsi,%%rdx,8), %%rax \n"
"sbb (%%rbx,%%rdx,8), %%rax \n"
"mov %%rax, (%%rdi,%%rdx,8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 1b \n"
"adc %%rcx, %%rcx \n" // rcx has the cf state
"or %%r8, %%r8 \n"
"jz 3f \n"
"xor %%rbx, %%rbx \n" // ebx = 0
"neg %%rcx \n" // setting cf from rcx
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
"2: \n"
"mov (%%rsi, %%rdx, 8), %%rax \n"
"sbb %%rbx, %%rax \n"
"mov %%rax, (%%rdi, %%rdx, 8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 2b \n"
"adc %%rcx, %%rcx \n"
"3: \n"
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
: "%r8", "cc", "memory" );
#endif
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
return c; return c;
} }
@@ -404,17 +645,20 @@ namespace ttmath
{ {
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_rcl_x64(p1,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" // rdx=0 "xorq %%rdx, %%rdx \n" // rdx=0
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rclq $1, (%%rbx, %%rdx, 8) \n" "rclq $1, (%%rbx, %%rdx, 8) \n"
@@ -426,12 +670,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n" "adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy), "=d" (dummy2) : "=c" (c), "=a" (dummy), "=d" (dummy2)
: "1" (c), "0" (b), "b" (p1) : "0" (b), "1" (c), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::Rcl2_one") TTMATH_LOGC("UInt::Rcl2_one", c)
return c; return c;
} }
@@ -456,16 +700,19 @@ namespace ttmath
{ {
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_rcr_x64(p1,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy;
__asm__ __volatile__( __asm__ __volatile__(
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rcrq $1, -8(%%rbx, %%rcx, 8) \n" "rcrq $1, -8(%%rbx, %%rcx, 8) \n"
@@ -476,12 +723,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n" "adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy) : "=c" (c), "=a" (dummy)
: "1" (c), "0" (b), "b" (p1) : "0" (b), "1" (c), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::Rcr2_one") TTMATH_LOGC("UInt::Rcr2_one", c)
return c; return c;
} }
@@ -509,13 +756,16 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_rcl2_x64(p1,b,bits,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__( __asm__ __volatile__(
"movq %%rcx, %%rsi \n" "movq %%rcx, %%rsi \n"
@@ -528,7 +778,6 @@ namespace ttmath
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"movq %%rdx, %%rsi \n" "movq %%rdx, %%rsi \n"
"orq %%rax, %%rax \n" "orq %%rax, %%rax \n"
"cmovnz %%r8, %%rsi \n" "cmovnz %%r8, %%rsi \n"
@@ -553,7 +802,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Rcl2") TTMATH_LOGC("UInt::Rcl2", c)
return c; return c;
} }
@@ -580,14 +829,16 @@ namespace ttmath
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" c = ttmath_rcr2_x64(p1,b,bits,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__( __asm__ __volatile__(
"movq %%rcx, %%rsi \n" "movq %%rcx, %%rsi \n"
@@ -602,7 +853,6 @@ namespace ttmath
"movq %%rdx, %%rsi \n" "movq %%rdx, %%rsi \n"
"addq %%rdi, %%rdx \n" "addq %%rdi, %%rdx \n"
"decq %%rdx \n" "decq %%rdx \n"
"orq %%rax, %%rax \n" "orq %%rax, %%rax \n"
"cmovnz %%R8, %%rsi \n" "cmovnz %%R8, %%rsi \n"
@@ -628,7 +878,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Rcr2") TTMATH_LOGC("UInt::Rcr2", c)
return c; return c;
} }
@@ -643,22 +893,76 @@ namespace ttmath
template<uint value_size> template<uint value_size>
sint UInt<value_size>::FindLeadingBitInWord(uint x) sint UInt<value_size>::FindLeadingBitInWord(uint x)
{ {
register sint result; sint result;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode"
unsigned long nIndex = 0;
if( _BitScanReverse64(&nIndex,x) == 0 )
result = -1;
else
result = nIndex;
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( uint dummy;
"bsrq %1, %0 \n" __asm__ (
"jnz 1f \n"
"movq $-1, %0 \n"
"1: \n"
: "=R" (result) "movq $-1, %1 \n"
: "R" (x) "bsrq %2, %0 \n"
"cmovz %1, %0 \n"
: "=r" (result), "=&r" (dummy)
: "r" (x)
: "cc" );
#endif
return result;
}
/*
this method returns the number of the highest set bit in one 64-bit word
if the 'x' is zero this method returns '-1'
***this method is created only on a 64bit platform***
*/
template<uint value_size>
sint UInt<value_size>::FindLowestBitInWord(uint x)
{
sint result;
#ifndef __GNUC__
unsigned long nIndex = 0;
if( _BitScanForward64(&nIndex,x) == 0 )
result = -1;
else
result = nIndex;
#endif
#ifdef __GNUC__
uint dummy;
__asm__ (
"movq $-1, %1 \n"
"bsfq %2, %0 \n"
"cmovz %1, %0 \n"
: "=r" (result), "=&r" (dummy)
: "r" (x)
: "cc" ); : "cc" );
#endif #endif
@@ -691,14 +995,15 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" old_bit = _bittestandset64((__int64*)&value,bit) != 0;
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__(
__asm__ (
"btsq %%rbx, %%rax \n" "btsq %%rbx, %%rax \n"
"setc %%bl \n" "setc %%bl \n"
"movzx %%bl, %%rbx \n" "movzx %%bl, %%rbx \n"
@@ -742,16 +1047,18 @@ namespace ttmath
this has no effect in visual studio but it's usefull when this has no effect in visual studio but it's usefull when
using gcc and options like -O using gcc and options like -O
*/ */
register uint result1_; uint result1_;
register uint result2_; uint result2_;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" result1_ = _umul128(a,b,&result2_);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ (
"mulq %%rdx \n" "mulq %%rdx \n"
@@ -793,8 +1100,8 @@ namespace ttmath
template<uint value_size> template<uint value_size>
void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
{ {
register uint r_; uint r_;
register uint rest_; uint rest_;
/* /*
these variables have similar meaning like those in these variables have similar meaning like those in
the multiplication algorithm MulTwoWords the multiplication algorithm MulTwoWords
@@ -802,13 +1109,19 @@ namespace ttmath
TTMATH_ASSERT( c != 0 ) TTMATH_ASSERT( c != 0 )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode"
ttmath_div_x64(&a,&b,c);
r_ = a;
rest_ = b;
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ (
"divq %%rcx \n" "divq %%rcx \n"
@@ -823,7 +1136,6 @@ namespace ttmath
*rest = rest_; *rest = rest_;
} }
} //namespace } //namespace

View File

@@ -0,0 +1,548 @@
;
; This file is a part of TTMath Bignum Library
; and is distributed under the (new) BSD licence.
; Author: Christian Kaiser <chk@online.de>
;
;
; Copyright (c) 2009, Christian Kaiser
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;
; * Redistributions of source code must retain the above copyright notice,
; this list of conditions and the following disclaimer.
;
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; * Neither the name Christian Kaiser nor the names of contributors to this
; project may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
; THE POSSIBILITY OF SUCH DAMAGE.
;
;
; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm
; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm
; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program
;
PUBLIC ttmath_adc_x64
PUBLIC ttmath_addindexed_x64
PUBLIC ttmath_addindexed2_x64
PUBLIC ttmath_addvector_x64
PUBLIC ttmath_sbb_x64
PUBLIC ttmath_subindexed_x64
PUBLIC ttmath_subvector_x64
PUBLIC ttmath_rcl_x64
PUBLIC ttmath_rcr_x64
PUBLIC ttmath_rcl2_x64
PUBLIC ttmath_rcr2_x64
PUBLIC ttmath_div_x64
;
; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx
;
; "rax, rcx, rdx, r8-r11 are volatile."
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
;
.CODE
ALIGN 8
;----------------------------------------
ttmath_adc_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nSize
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
adc qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
ttmath_adc_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_addindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
xor rax, rax ; rax = result
sub rdx, r8 ; rdx = remaining count of uints
add qword ptr [rcx + r8 * 8], r9
jc next1
ret
next1:
mov r9, 1
ALIGN 16
loop1:
dec rdx
jz done_with_cy
lea r8, [r8+1]
add qword ptr [rcx + r8 * 8], r9
jc loop1
ret
done_with_cy:
lea rax, [rax+1] ; rax = 1
ret
ttmath_addindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_addindexed2_x64 PROC
; rcx = p1 (pointer)
; rdx = b (value size)
; r8 = nPos
; r9 = nValue1
; [esp+0x28] = nValue2
xor rax, rax ; return value
mov r11, rcx ; table
sub rdx, r8 ; rdx = remaining count of uints
mov r10, [esp+028h] ; r10 = nValue2
add qword ptr [r11 + r8 * 8], r9
lea r8, [r8+1]
lea rdx, [rdx-1]
adc qword ptr [r11 + r8 * 8], r10
jc next
ret
ALIGN 16
loop1:
lea r8, [r8+1]
add qword ptr [r11 + r8 * 8], 1
jc next
ret
next:
dec rdx ; does not modify CY too...
jnz loop1
lea rax, [rax+1]
ret
ttmath_addindexed2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_addvector_x64 PROC
; rcx = ss1
; rdx = ss2
; r8 = ss1_size
; r9 = ss2_size
; [esp+0x28] = result
mov r10, [esp+028h]
sub r8, r9
xor r11, r11 ; r11=0, cf=0
ALIGN 16
loop1:
mov rax, qword ptr [rcx + r11 * 8]
adc rax, qword ptr [rdx + r11 * 8]
mov qword ptr [r10 + r11 * 8], rax
inc r11
dec r9
jnz loop1
adc r9, r9 ; r9 has the cf state
or r8, r8
jz done
neg r9 ; setting cf from r9
mov r9, 0 ; don't use xor here (cf is used)
loop2:
mov rax, qword ptr [rcx + r11 * 8]
adc rax, r9
mov qword ptr [r10 + r11 * 8], rax
inc r11
dec r8
jnz loop2
adc r8, r8
mov rax, r8
ret
done:
mov rax, r9
ret
ttmath_addvector_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_sbb_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nCount
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
sbb qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
ttmath_sbb_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_subindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
sub rdx, r8 ; rdx = remaining count of uints
ALIGN 16
loop1:
sub qword ptr [rcx + r8 * 8], r9
jnc done
lea r8, [r8+1]
mov r9, 1
dec rdx
jnz loop1
mov rax, 1
ret
done:
xor rax, rax
ret
ttmath_subindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb'
ttmath_subvector_x64 PROC
; rcx = ss1
; rdx = ss2
; r8 = ss1_size
; r9 = ss2_size
; [esp+0x28] = result
mov r10, [esp+028h]
sub r8, r9
xor r11, r11 ; r11=0, cf=0
ALIGN 16
loop1:
mov rax, qword ptr [rcx + r11 * 8]
sbb rax, qword ptr [rdx + r11 * 8]
mov qword ptr [r10 + r11 * 8], rax
inc r11
dec r9
jnz loop1
adc r9, r9 ; r9 has the cf state
or r8, r8
jz done
neg r9 ; setting cf from r9
mov r9, 0 ; don't use xor here (cf is used)
loop2:
mov rax, qword ptr [rcx + r11 * 8]
sbb rax, r9
mov qword ptr [r10 + r11 * 8], rax
inc r11
dec r8
jnz loop2
adc r8, r8
mov rax, r8
ret
done:
mov rax, r9
ret
ttmath_subvector_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcl_x64 PROC
; rcx = p1
; rdx = b
; r8 = nLowestBit
mov r11, rcx ; table
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcl qword ptr [r11 + r10 * 8], 1
lea r10, [r10+1]
dec rdx
jnz loop1
setc al
movzx rax, al
ret
ttmath_rcl_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcr_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nLowestBit
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcr qword ptr -8[rcx + rdx * 8], 1
dec rdx
jnz loop1
setc al
movzx rax, al
ret
ttmath_rcr_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_div_x64 PROC
; rcx = &Hi
; rdx = &Lo
; r8 = nDiv
mov r11, rcx
mov r10, rdx
mov rdx, qword ptr [r11]
mov rax, qword ptr [r10]
div r8
mov qword ptr [r10], rdx ; remainder
mov qword ptr [r11], rax ; value
ret
ttmath_div_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcl2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shr r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rax ; r9 = index (0..nSize-1)
ALIGN 16
loop1:
rol qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9+1]
dec rdx
jnz loop1
and rax, 1
pop rbx
ret
ttmath_rcl2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcr2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shl r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rdx ; r9 = index (0..nSize-1)
lea r9, [r9-1]
ALIGN 16
loop1:
ror qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9-1]
dec rdx
jnz loop1
rol rax, 1
and rax, 1
pop rbx
ret
ttmath_rcr2_x64 ENDP
END