Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
51e938eaa7 | ||
|
e102086f80 | ||
53547cfab5 | |||
d3a64b79ca | |||
|
51b2c974a1 | ||
|
5597373093 | ||
|
de58378488 | ||
|
de64608eba | ||
c70a947c07 | |||
8972fdfdb3 | |||
019a902fed | |||
74553109a5 | |||
9e42a5a9fd | |||
1b6858616d | |||
d789ac5396 | |||
|
be8913866a | ||
|
b31d34ebdd | ||
|
be821b59dd | ||
bb2583649e | |||
|
de1e7ac957 | ||
|
fdc292e91a | ||
5e5a106605 | |||
eaa19dd46a | |||
|
9b576ddbe2 | ||
|
a8c3a506ea | ||
|
3ba94dca90 | ||
|
cae50cd425 | ||
939d0f7519 | |||
05b67e7103 | |||
|
00e39d3608 | ||
|
37379d2f1f | ||
|
d7b67e4d47 | ||
|
c91bd24e98 | ||
|
cbc12db22f | ||
3e9bd5b093 |
83
CHANGELOG
83
CHANGELOG
@@ -1,3 +1,86 @@
|
|||||||
|
Version 0.9.0 prerelease (2009.07.16):
|
||||||
|
* 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)
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
1147
ttmath/ttmath.h
1147
ttmath/ttmath.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
110
ttmath/ttmathconfig.h
Normal file
110
ttmath/ttmathconfig.h
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the PNG licence.
|
||||||
|
* Author: Christian Kaiser <chk@online.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009 Christian Kaiser
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfilettmathconfig
|
||||||
|
#define headerfilettmathconfig
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#if defined(_MT)
|
||||||
|
class clsCrit
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
mutable CRITICAL_SECTION _Crit;
|
||||||
|
|
||||||
|
clsCrit(const clsCrit&) // inhibit copy (easy mistake to do; use clsCritObj instead!!!)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
clsCrit& operator=(const clsCrit& rhs); // inhibit assignment
|
||||||
|
public:
|
||||||
|
clsCrit(void)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&_Crit);
|
||||||
|
}
|
||||||
|
virtual ~clsCrit(void)
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&_Crit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enter(void) const
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&_Crit);
|
||||||
|
}
|
||||||
|
void Leave(void) const
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&_Crit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class clsCritObj
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const clsCrit& _Crit;
|
||||||
|
|
||||||
|
clsCritObj& operator=(const clsCritObj& rhs); // not applicable
|
||||||
|
public:
|
||||||
|
clsCritObj(const clsCrit& Sync)
|
||||||
|
: _Crit(Sync)
|
||||||
|
{
|
||||||
|
_Crit.Enter();
|
||||||
|
}
|
||||||
|
~clsCritObj(void)
|
||||||
|
{
|
||||||
|
_Crit.Leave();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ \
|
||||||
|
private: \
|
||||||
|
clsCrit CritSect; \
|
||||||
|
public: \
|
||||||
|
operator clsCrit&() \
|
||||||
|
{ \
|
||||||
|
return(CritSect); \
|
||||||
|
}
|
||||||
|
#define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c)
|
||||||
|
#endif
|
||||||
|
#else // defined(WIN32)
|
||||||
|
// not Windows world: no threading synchronization for now
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(TTMATH_IMPLEMENT_THREADSAFE_OBJ)
|
||||||
|
// if we don't know about serialization, make it a no-op
|
||||||
|
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ /* */
|
||||||
|
#define TTMATH_USE_THREADSAFE_OBJ(c) /* */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // headerfilettmathconfig
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -47,6 +47,10 @@
|
|||||||
|
|
||||||
#include "ttmathuint.h"
|
#include "ttmathuint.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(disable:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -641,8 +645,14 @@ public:
|
|||||||
|
|
||||||
// there can be a carry here when the size of this value is equal one word
|
// there can be a carry here when the size of this value is equal one word
|
||||||
// and the 'value' has the highest bit set
|
// and the 'value' has the highest bit set
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(disable:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
|
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
|
||||||
return 1;
|
return 1;
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(default:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -821,7 +831,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
a constructor for converting string to this class (with the base=10)
|
a constructor for converting string to this class (with the base=10)
|
||||||
*/
|
*/
|
||||||
Int(const char * s)
|
Int(const tt_char * s)
|
||||||
{
|
{
|
||||||
FromString(s);
|
FromString(s);
|
||||||
}
|
}
|
||||||
@@ -830,7 +840,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
a constructor for converting a string to this class (with the base=10)
|
a constructor for converting a string to this class (with the base=10)
|
||||||
*/
|
*/
|
||||||
Int(const std::string & s)
|
Int(const tt_string & s)
|
||||||
{
|
{
|
||||||
FromString( s.c_str() );
|
FromString( s.c_str() );
|
||||||
}
|
}
|
||||||
@@ -869,7 +879,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method converts the value to a string with a base equal 'b'
|
this method converts the value to a string with a base equal 'b'
|
||||||
*/
|
*/
|
||||||
void ToString(std::string & result, uint b = 10) const
|
void ToString(tt_string & result, uint b = 10) const
|
||||||
{
|
{
|
||||||
if( IsSign() )
|
if( IsSign() )
|
||||||
{
|
{
|
||||||
@@ -890,12 +900,14 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts a string into its value
|
this method converts a string into its value
|
||||||
|
string is given either as 'const char *' or 'const wchar_t *'
|
||||||
|
|
||||||
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
|
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
|
||||||
|
|
||||||
string is ended with a non-digit value, for example:
|
string is ended with a non-digit value, for example:
|
||||||
"-12" will be translated to -12
|
"-12" will be translated to -12
|
||||||
as well as:
|
as well as:
|
||||||
"- 12foo" will be translated to 12 too
|
"- 12foo" will be translated to -12 too
|
||||||
|
|
||||||
existing first white characters will be ommited
|
existing first white characters will be ommited
|
||||||
(between '-' and a first digit can be white characters too)
|
(between '-' and a first digit can be white characters too)
|
||||||
@@ -904,7 +916,7 @@ public:
|
|||||||
|
|
||||||
value_read (if exists) tells whether something has actually been read (at least one digit)
|
value_read (if exists) tells whether something has actually been read (at least one digit)
|
||||||
*/
|
*/
|
||||||
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
|
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
|
||||||
{
|
{
|
||||||
bool is_sign = false;
|
bool is_sign = false;
|
||||||
|
|
||||||
@@ -961,16 +973,16 @@ public:
|
|||||||
this method converts a string into its value
|
this method converts a string into its value
|
||||||
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
|
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
|
||||||
*/
|
*/
|
||||||
uint FromString(const std::string & s, uint b = 10)
|
uint FromString(const tt_string & s, uint b = 10)
|
||||||
{
|
{
|
||||||
return FromString( s.c_str() );
|
return FromString( s.c_str(), b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this operator converts a string into its value (with base = 10)
|
this operator converts a string into its value (with base = 10)
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(const char * s)
|
Int<value_size> & operator=(const tt_char * s)
|
||||||
{
|
{
|
||||||
FromString(s);
|
FromString(s);
|
||||||
|
|
||||||
@@ -981,7 +993,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this operator converts a string into its value (with base = 10)
|
this operator converts a string into its value (with base = 10)
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(const std::string & s)
|
Int<value_size> & operator=(const tt_string & s)
|
||||||
{
|
{
|
||||||
FromString( s.c_str() );
|
FromString( s.c_str() );
|
||||||
|
|
||||||
@@ -1268,9 +1280,14 @@ public:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
|
/*!
|
||||||
|
output for standard streams
|
||||||
|
|
||||||
|
tt_ostream is either std::ostream or std::wostream
|
||||||
|
*/
|
||||||
|
friend tt_ostream & operator<<(tt_ostream & s, const Int<value_size> & l)
|
||||||
{
|
{
|
||||||
std::string ss;
|
tt_string ss;
|
||||||
|
|
||||||
l.ToString(ss);
|
l.ToString(ss);
|
||||||
s << ss;
|
s << ss;
|
||||||
@@ -1279,13 +1296,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
input from standard streams
|
||||||
|
|
||||||
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
|
tt_istream is either std::istream or std::wistream
|
||||||
|
*/
|
||||||
|
friend tt_istream & operator>>(tt_istream & s, Int<value_size> & l)
|
||||||
{
|
{
|
||||||
std::string ss;
|
tt_string ss;
|
||||||
|
|
||||||
// char for operator>>
|
// tt_char for operator>>
|
||||||
unsigned char z;
|
tt_char z;
|
||||||
|
|
||||||
// operator>> omits white characters if they're set for ommiting
|
// operator>> omits white characters if they're set for ommiting
|
||||||
s >> z;
|
s >> z;
|
||||||
@@ -1300,7 +1321,7 @@ public:
|
|||||||
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
|
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
|
||||||
{
|
{
|
||||||
ss += z;
|
ss += z;
|
||||||
z = s.get();
|
z = static_cast<tt_char>(s.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're leaving the last readed character
|
// we're leaving the last readed character
|
||||||
@@ -1316,5 +1337,9 @@ public:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(default:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "ttmathtypes.h"
|
#include "ttmathtypes.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -73,18 +74,19 @@ public:
|
|||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
// name of a variable of a function
|
// name of a variable of a function
|
||||||
std::string value;
|
// (either std::string or std::wstring)
|
||||||
|
tt_string value;
|
||||||
|
|
||||||
// number of parameters required by the function
|
// number of parameters required by the function
|
||||||
// (if there's a variable this 'param' is ignored)
|
// (if there's a variable this 'param' is ignored)
|
||||||
int param;
|
int param;
|
||||||
|
|
||||||
Item() {}
|
Item() {}
|
||||||
Item(const std::string & v, int p) : value(v), param(p) {}
|
Item(const tt_string & v, int p) : value(v), param(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 'Table' is the type of our table
|
// 'Table' is the type of our table
|
||||||
typedef std::map<std::string, Item> Table;
|
typedef std::map<tt_string, Item> Table;
|
||||||
typedef Table::iterator Iterator;
|
typedef Table::iterator Iterator;
|
||||||
typedef Table::const_iterator CIterator;
|
typedef Table::const_iterator CIterator;
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ 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)
|
static bool IsNameCorrect(const tt_string & name)
|
||||||
{
|
{
|
||||||
if( name.empty() )
|
if( name.empty() )
|
||||||
return false;
|
return false;
|
||||||
@@ -120,7 +122,7 @@ public:
|
|||||||
if( !CorrectCharacter(name[0], false) )
|
if( !CorrectCharacter(name[0], false) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string::const_iterator i=name.begin();
|
tt_string::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) )
|
||||||
@@ -133,7 +135,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method returns true if such an object is defined (name exists)
|
this method returns true if such an object is defined (name exists)
|
||||||
*/
|
*/
|
||||||
bool IsDefined(const std::string & name)
|
bool IsDefined(const tt_string & name)
|
||||||
{
|
{
|
||||||
Iterator i = table.find(name);
|
Iterator i = table.find(name);
|
||||||
|
|
||||||
@@ -148,7 +150,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method adds one object (variable of function) into the table
|
this method adds one object (variable of function) into the table
|
||||||
*/
|
*/
|
||||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -205,7 +207,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method changes the value and the number of parameters for a specific object
|
this method changes the value and the number of parameters for a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
|
ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -225,7 +227,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method changes the name of a specific object
|
this method changes the name of a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
|
ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -256,7 +258,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method deletes an object
|
this method deletes an object
|
||||||
*/
|
*/
|
||||||
ErrorCode Delete(const std::string & name)
|
ErrorCode Delete(const tt_string & name)
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -275,7 +277,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method gets the value of a specific object
|
this method gets the value of a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
ErrorCode GetValue(const tt_string & name, tt_string & value) const
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -298,7 +300,7 @@ public:
|
|||||||
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)
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -321,7 +323,7 @@ public:
|
|||||||
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
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -347,7 +349,7 @@ public:
|
|||||||
of a specific object
|
of a specific object
|
||||||
(this version is used for not copying the whole string)
|
(this version is used for not copying the whole string)
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
|
ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
|
||||||
{
|
{
|
||||||
if( !IsNameCorrect(name) )
|
if( !IsNameCorrect(name) )
|
||||||
return err_incorrect_name;
|
return err_incorrect_name;
|
||||||
@@ -430,7 +432,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
History()
|
History()
|
||||||
{
|
{
|
||||||
buffer_max_size = 10;
|
buffer_max_size = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -487,10 +489,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 of the coefficients is a little time-consuming operation,
|
||||||
|
(especially when the mantissa is large) and first called 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
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
\brief A mathematical parser
|
\brief A mathematical parser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fstream>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -137,7 +137,6 @@ namespace ttmath
|
|||||||
template<class ValueType>
|
template<class ValueType>
|
||||||
class Parser
|
class Parser
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -256,7 +255,7 @@ public:
|
|||||||
bool function;
|
bool function;
|
||||||
|
|
||||||
// if function is true
|
// if function is true
|
||||||
std::string function_name;
|
tt_string function_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
the sign of value
|
the sign of value
|
||||||
@@ -311,10 +310,11 @@ ErrorCode error;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
pointer to the currently reading char
|
pointer to the currently reading char
|
||||||
|
it's either char* or wchar_t*
|
||||||
|
|
||||||
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 tt_char * pstring;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -351,7 +351,7 @@ const Objects * puser_variables;
|
|||||||
const Objects * puser_functions;
|
const Objects * puser_functions;
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<std::string, ValueType> FunctionLocalVariables;
|
typedef std::map<tt_string, ValueType> FunctionLocalVariables;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a pointer to the local variables of a function
|
a pointer to the local variables of a function
|
||||||
@@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
|
|||||||
/*!
|
/*!
|
||||||
a temporary set using during parsing user defined variables
|
a temporary set using during parsing user defined variables
|
||||||
*/
|
*/
|
||||||
std::set<std::string> visited_variables;
|
std::set<tt_string> visited_variables;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a temporary set using during parsing user defined functions
|
a temporary set using during parsing user defined functions
|
||||||
*/
|
*/
|
||||||
std::set<std::string> visited_functions;
|
std::set<tt_string> visited_functions;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
|
|||||||
table of mathematic functions
|
table of mathematic functions
|
||||||
|
|
||||||
this map consists of:
|
this map consists of:
|
||||||
std::string - function's name
|
tt_string - function's name
|
||||||
pfunction - pointer to specific function
|
pfunction - pointer to specific function
|
||||||
*/
|
*/
|
||||||
typedef std::map<std::string, pfunction> FunctionsTable;
|
typedef std::map<tt_string, pfunction> FunctionsTable;
|
||||||
FunctionsTable functions_table;
|
FunctionsTable functions_table;
|
||||||
|
|
||||||
|
|
||||||
@@ -407,10 +407,10 @@ FunctionsTable functions_table;
|
|||||||
table of mathematic operators
|
table of mathematic operators
|
||||||
|
|
||||||
this map consists of:
|
this map consists of:
|
||||||
std::string - operators's name
|
tt_string - operators's name
|
||||||
MatOperator::Type - type of the operator
|
MatOperator::Type - type of the operator
|
||||||
*/
|
*/
|
||||||
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
|
typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
|
||||||
OperatorsTable operators_table;
|
OperatorsTable operators_table;
|
||||||
|
|
||||||
|
|
||||||
@@ -418,18 +418,17 @@ OperatorsTable operators_table;
|
|||||||
table of mathematic variables
|
table of mathematic variables
|
||||||
|
|
||||||
this map consists of:
|
this map consists of:
|
||||||
std::string - variable's name
|
tt_string - variable's name
|
||||||
pfunction_var - pointer to specific function which returns value of variable
|
pfunction_var - pointer to specific function which returns value of variable
|
||||||
*/
|
*/
|
||||||
typedef std::map<std::string, pfunction_var> VariablesTable;
|
typedef std::map<tt_string, pfunction_var> VariablesTable;
|
||||||
VariablesTable variables_table;
|
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;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -456,7 +455,7 @@ void SkipWhiteCharacters()
|
|||||||
/*!
|
/*!
|
||||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
|
||||||
{
|
{
|
||||||
if( variable )
|
if( variable )
|
||||||
{
|
{
|
||||||
@@ -474,7 +473,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
|
|||||||
/*!
|
/*!
|
||||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
|
||||||
{
|
{
|
||||||
if( variable )
|
if( variable )
|
||||||
visited_variables.insert( name );
|
visited_variables.insert( name );
|
||||||
@@ -486,7 +485,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
|
|||||||
/*!
|
/*!
|
||||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
|
||||||
{
|
{
|
||||||
if( variable )
|
if( variable )
|
||||||
visited_variables.erase( name );
|
visited_variables.erase( name );
|
||||||
@@ -505,7 +504,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 tt_string & name, const tt_char * new_string,
|
||||||
|
FunctionLocalVariables * local_variables = 0)
|
||||||
{
|
{
|
||||||
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
|
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
|
||||||
RecurrenceParsingVariablesOrFunction_AddName(variable, name);
|
RecurrenceParsingVariablesOrFunction_AddName(variable, name);
|
||||||
@@ -548,12 +548,12 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method returns the user-defined value of a variable
|
this method returns the user-defined value of a variable
|
||||||
*/
|
*/
|
||||||
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
|
bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
|
||||||
{
|
{
|
||||||
if( !puser_variables )
|
if( !puser_variables )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char * string_value;
|
const tt_char * string_value;
|
||||||
|
|
||||||
if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
|
if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
|
||||||
return false;
|
return false;
|
||||||
@@ -567,7 +567,7 @@ return true;
|
|||||||
/*!
|
/*!
|
||||||
this method returns the value of a local variable of a function
|
this method returns the value of a local variable of a function
|
||||||
*/
|
*/
|
||||||
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
|
bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
|
||||||
{
|
{
|
||||||
if( !pfunction_local_variables )
|
if( !pfunction_local_variables )
|
||||||
return false;
|
return false;
|
||||||
@@ -589,7 +589,7 @@ return true;
|
|||||||
we make an object of type ValueType then call a method which
|
we make an object of type ValueType then call a method which
|
||||||
sets the correct value in it and finally we'll return the object
|
sets the correct value in it and finally we'll return the object
|
||||||
*/
|
*/
|
||||||
ValueType GetValueOfVariable(const std::string & variable_name)
|
ValueType GetValueOfVariable(const tt_string & variable_name)
|
||||||
{
|
{
|
||||||
ValueType result;
|
ValueType result;
|
||||||
|
|
||||||
@@ -600,7 +600,7 @@ ValueType result;
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
||||||
typename std::map<std::string, pfunction_var>::iterator i =
|
typename std::map<tt_string, pfunction_var>::iterator i =
|
||||||
variables_table.find(variable_name);
|
variables_table.find(variable_name);
|
||||||
|
|
||||||
if( i == variables_table.end() )
|
if( i == variables_table.end() )
|
||||||
@@ -674,6 +674,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 +699,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 +719,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 +731,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 +776,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 +995,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 +1074,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,17 +1355,34 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
we use such a method because 'wvsprintf' is not everywhere defined
|
||||||
|
*/
|
||||||
|
void Sprintf(tt_char * buffer, int par)
|
||||||
|
{
|
||||||
|
char buf[30]; // char, not tt_char
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sprintf(buf, "%d", par);
|
||||||
|
for(i=0 ; buf[i] != 0 ; ++i)
|
||||||
|
buffer[i] = buf[i];
|
||||||
|
|
||||||
|
buffer[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns the value from a user-defined function
|
this method returns the value from a user-defined function
|
||||||
|
|
||||||
(look at the description in 'CallFunction(...)')
|
(look at the description in 'CallFunction(...)')
|
||||||
*/
|
*/
|
||||||
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
|
bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||||
{
|
{
|
||||||
if( !puser_functions )
|
if( !puser_functions )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char * string_value;
|
const tt_char * string_value;
|
||||||
int param;
|
int param;
|
||||||
|
|
||||||
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok )
|
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok )
|
||||||
@@ -1357,15 +1396,17 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
|
|||||||
|
|
||||||
if( amount_of_args > 0 )
|
if( amount_of_args > 0 )
|
||||||
{
|
{
|
||||||
char buffer[20];
|
tt_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) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1389,7 +1430,7 @@ return true;
|
|||||||
result will be stored in 'stack[sindex-1].value'
|
result will be stored in 'stack[sindex-1].value'
|
||||||
(we don't have to set the correct type of this element, it'll be set later)
|
(we don't have to set the correct type of this element, it'll be set later)
|
||||||
*/
|
*/
|
||||||
void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
|
void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||||
{
|
{
|
||||||
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
|
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
|
||||||
return;
|
return;
|
||||||
@@ -1415,9 +1456,9 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
|
|||||||
function_name - name of the function
|
function_name - name of the function
|
||||||
pf - pointer to the function (to the wrapper)
|
pf - pointer to the function (to the wrapper)
|
||||||
*/
|
*/
|
||||||
void InsertFunctionToTable(const char * function_name, pfunction pf)
|
void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
|
||||||
{
|
{
|
||||||
functions_table.insert( std::make_pair(std::string(function_name), pf));
|
functions_table.insert( std::make_pair(tt_string(function_name), pf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1428,9 +1469,9 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
|
|||||||
variable_name - name of the function
|
variable_name - name of the function
|
||||||
pf - pointer to the function
|
pf - pointer to the function
|
||||||
*/
|
*/
|
||||||
void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
|
||||||
{
|
{
|
||||||
variables_table.insert( std::make_pair(std::string(variable_name), pf));
|
variables_table.insert( std::make_pair(tt_string(variable_name), pf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1439,67 +1480,65 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
|||||||
*/
|
*/
|
||||||
void CreateFunctionsTable()
|
void CreateFunctionsTable()
|
||||||
{
|
{
|
||||||
/*
|
InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
|
||||||
names of functions should consist of small letters
|
InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
|
||||||
*/
|
InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
|
||||||
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
|
InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
|
||||||
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
|
InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
|
||||||
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
|
InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
|
||||||
InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
|
InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
|
||||||
InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
|
InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
|
||||||
InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
|
InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
|
||||||
InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
|
InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
|
||||||
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
|
InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
|
||||||
InsertFunctionToTable("int", &Parser<ValueType>::Int);
|
InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
|
||||||
InsertFunctionToTable("round", &Parser<ValueType>::Round);
|
InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
|
||||||
InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
|
InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
|
||||||
InsertFunctionToTable("log", &Parser<ValueType>::Log);
|
InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
|
||||||
InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
|
InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
|
||||||
InsertFunctionToTable("max", &Parser<ValueType>::Max);
|
InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
|
||||||
InsertFunctionToTable("min", &Parser<ValueType>::Min);
|
InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
|
||||||
InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
|
InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
|
||||||
InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
|
InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
|
||||||
InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
|
InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
|
||||||
InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
|
InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
|
||||||
InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
|
InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
|
||||||
InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
|
InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
|
||||||
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
|
InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
|
||||||
InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
|
InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
|
||||||
InsertFunctionToTable("if", &Parser<ValueType>::If);
|
InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
|
||||||
InsertFunctionToTable("or", &Parser<ValueType>::Or);
|
InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
|
||||||
InsertFunctionToTable("and", &Parser<ValueType>::And);
|
InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
|
||||||
InsertFunctionToTable("not", &Parser<ValueType>::Not);
|
InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
|
||||||
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
|
InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
|
||||||
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
|
InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
|
||||||
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
|
InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
|
||||||
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
|
InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
|
||||||
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
|
InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
|
||||||
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
|
InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
|
||||||
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
|
InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
|
||||||
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
|
InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
|
||||||
InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
|
InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
|
||||||
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
|
InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
|
||||||
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
|
InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
|
||||||
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
|
InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
|
||||||
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
|
InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
|
||||||
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
|
InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
|
||||||
InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
|
InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
|
||||||
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
|
InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
|
||||||
InsertFunctionToTable("root", &Parser<ValueType>::Root);
|
InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
|
||||||
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
|
InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
|
||||||
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
|
InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
|
||||||
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
|
InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
|
||||||
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
|
InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
|
||||||
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
|
InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
|
||||||
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
|
InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
|
||||||
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
|
InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
|
||||||
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
|
InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
|
||||||
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
|
InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
|
||||||
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd);
|
InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
|
||||||
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr);
|
InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
|
||||||
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
|
InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
|
||||||
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
|
|
||||||
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1508,11 +1547,8 @@ void CreateFunctionsTable()
|
|||||||
*/
|
*/
|
||||||
void CreateVariablesTable()
|
void CreateVariablesTable()
|
||||||
{
|
{
|
||||||
/*
|
InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
|
||||||
names of variables should consist of small letters
|
InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
|
||||||
*/
|
|
||||||
InsertVariableToTable("pi", &ValueType::SetPi);
|
|
||||||
InsertVariableToTable("e", &ValueType::SetE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1538,7 +1574,7 @@ return c;
|
|||||||
what should be returned is tested just by a '(' character that means if there's
|
what should be returned is tested just by a '(' character that means if there's
|
||||||
a '(' character after a name that function returns 'true'
|
a '(' character after a name that function returns 'true'
|
||||||
*/
|
*/
|
||||||
bool ReadName(std::string & result)
|
bool ReadName(tt_string & result)
|
||||||
{
|
{
|
||||||
int character;
|
int character;
|
||||||
|
|
||||||
@@ -1555,7 +1591,7 @@ int character;
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
result += character;
|
result += static_cast<tt_char>( character );
|
||||||
character = * ++pstring;
|
character = * ++pstring;
|
||||||
}
|
}
|
||||||
while( (character>='a' && character<='z') ||
|
while( (character>='a' && character<='z') ||
|
||||||
@@ -1610,7 +1646,7 @@ return false;
|
|||||||
*/
|
*/
|
||||||
bool ReadVariableOrFunction(Item & result)
|
bool ReadVariableOrFunction(Item & result)
|
||||||
{
|
{
|
||||||
std::string name;
|
tt_string name;
|
||||||
bool is_it_name_of_function = ReadName(name);
|
bool is_it_name_of_function = ReadName(name);
|
||||||
|
|
||||||
if( is_it_name_of_function )
|
if( is_it_name_of_function )
|
||||||
@@ -1639,7 +1675,7 @@ return is_it_name_of_function;
|
|||||||
*/
|
*/
|
||||||
void ReadValue(Item & result, int reading_base)
|
void ReadValue(Item & result, int reading_base)
|
||||||
{
|
{
|
||||||
const char * new_stack_pointer;
|
const tt_char * new_stack_pointer;
|
||||||
bool value_read;
|
bool value_read;
|
||||||
|
|
||||||
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
||||||
@@ -1812,9 +1848,9 @@ return 0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type)
|
void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
|
||||||
{
|
{
|
||||||
operators_table.insert( std::make_pair(name, type) );
|
operators_table.insert( std::make_pair(tt_string(name), type) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1823,19 +1859,19 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type
|
|||||||
*/
|
*/
|
||||||
void CreateMathematicalOperatorsTable()
|
void CreateMathematicalOperatorsTable()
|
||||||
{
|
{
|
||||||
InsertOperatorToTable(std::string("||"), MatOperator::lor);
|
InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
|
||||||
InsertOperatorToTable(std::string("&&"), MatOperator::land);
|
InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
|
||||||
InsertOperatorToTable(std::string("!="), MatOperator::neq);
|
InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
|
||||||
InsertOperatorToTable(std::string("=="), MatOperator::eq);
|
InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
|
||||||
InsertOperatorToTable(std::string(">="), MatOperator::get);
|
InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
|
||||||
InsertOperatorToTable(std::string("<="), MatOperator::let);
|
InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
|
||||||
InsertOperatorToTable(std::string(">"), MatOperator::gt);
|
InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
|
||||||
InsertOperatorToTable(std::string("<"), MatOperator::lt);
|
InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
|
||||||
InsertOperatorToTable(std::string("-"), MatOperator::sub);
|
InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
|
||||||
InsertOperatorToTable(std::string("+"), MatOperator::add);
|
InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
|
||||||
InsertOperatorToTable(std::string("/"), MatOperator::div);
|
InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
|
||||||
InsertOperatorToTable(std::string("*"), MatOperator::mul);
|
InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
|
||||||
InsertOperatorToTable(std::string("^"), MatOperator::pow);
|
InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1845,12 +1881,12 @@ void CreateMathematicalOperatorsTable()
|
|||||||
e.g.
|
e.g.
|
||||||
true when str1="test" and str2="te"
|
true when str1="test" and str2="te"
|
||||||
*/
|
*/
|
||||||
bool IsSubstring(const std::string & str1, const std::string & str2)
|
bool IsSubstring(const tt_string & str1, const tt_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(tt_string::size_type i=0 ; i<str2.length() ; ++i)
|
||||||
if( str1[i] != str2[i] )
|
if( str1[i] != str2[i] )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1863,7 +1899,7 @@ return true;
|
|||||||
*/
|
*/
|
||||||
void ReadMathematicalOperator(Item & result)
|
void ReadMathematicalOperator(Item & result)
|
||||||
{
|
{
|
||||||
std::string oper;
|
tt_string oper;
|
||||||
typename OperatorsTable::iterator iter_old, iter_new;
|
typename OperatorsTable::iterator iter_old, iter_new;
|
||||||
|
|
||||||
iter_old = operators_table.end();
|
iter_old = operators_table.end();
|
||||||
@@ -2393,7 +2429,6 @@ 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();
|
|
||||||
|
|
||||||
CreateFunctionsTable();
|
CreateFunctionsTable();
|
||||||
CreateVariablesTable();
|
CreateVariablesTable();
|
||||||
@@ -2413,7 +2448,6 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
|
|||||||
base = p.base;
|
base = p.base;
|
||||||
deg_rad_grad = p.deg_rad_grad;
|
deg_rad_grad = p.deg_rad_grad;
|
||||||
error = err_ok;
|
error = err_ok;
|
||||||
factorial_max = p.factorial_max;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
we don't have to call 'CreateFunctionsTable()' etc.
|
we don't have to call 'CreateFunctionsTable()' etc.
|
||||||
@@ -2495,22 +2529,11 @@ void SetFunctions(const Objects * pf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
you will not be allowed to calculate the factorial
|
|
||||||
if its argument is greater than 'm'
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
factorial_max = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the main method using for parsing string
|
the main method using for parsing string
|
||||||
*/
|
*/
|
||||||
ErrorCode Parse(const char * str)
|
ErrorCode Parse(const tt_char * str)
|
||||||
{
|
{
|
||||||
stack_index = 0;
|
stack_index = 0;
|
||||||
pstring = str;
|
pstring = str;
|
||||||
@@ -2533,11 +2556,11 @@ return error;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the version of the library
|
the version of the library
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
if zero that means this is the release version of the library
|
if zero that means this is the release version of the library
|
||||||
*/
|
*/
|
||||||
#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 0
|
||||||
#define TTMATH_PRERELEASE_VER 0
|
#define TTMATH_PRERELEASE_VER 1
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -120,6 +120,7 @@ namespace ttmath
|
|||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
typedef signed int sint;
|
typedef signed int sint;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this type is twice bigger than uint
|
this type is twice bigger than uint
|
||||||
(64bit on a 32bit platforms)
|
(64bit on a 32bit platforms)
|
||||||
@@ -128,43 +129,39 @@ namespace ttmath
|
|||||||
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
|
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
|
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
|
|
||||||
typedef unsigned long long int ulint;
|
typedef unsigned long long int ulint;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*!
|
|
||||||
how many bits there are in the uint type
|
|
||||||
*/
|
|
||||||
#define TTMATH_BITS_PER_UINT 32u
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the max value of the unsigned 32bit word (2^32 - 1)
|
the max value of the unsigned 32bit word (2^32 - 1)
|
||||||
(all bits equal one)
|
(all bits equal one)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the number of words (32bit words on 32bit platform)
|
the number of words (32bit words on 32bit platform)
|
||||||
which are kept in built-in variables for a Big<> type
|
which are kept in built-in variables for a Big<> type
|
||||||
(these variables are defined in ttmathbig.h)
|
(these variables are defined in ttmathbig.h)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 256u;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||||
*/
|
*/
|
||||||
typedef unsigned long uint;
|
#if defined(_MSC_VER)
|
||||||
typedef signed long sint;
|
typedef unsigned __int64 uint;
|
||||||
|
typedef signed __int64 sint;
|
||||||
|
#else
|
||||||
|
typedef unsigned long long uint;
|
||||||
|
typedef signed long long sint;
|
||||||
|
#endif
|
||||||
/*!
|
/*!
|
||||||
on 64bit platform we do not define ulint
|
on 64bit platform we do not define ulint
|
||||||
sizeof(long long) is 8 (64bit) but we need 128bit
|
sizeof(long long) is 8 (64bit) but we need 128bit
|
||||||
@@ -174,33 +171,61 @@ namespace ttmath
|
|||||||
*/
|
*/
|
||||||
//typedef unsigned long long int ulint;
|
//typedef unsigned long long int ulint;
|
||||||
|
|
||||||
/*!
|
|
||||||
how many bits there are in the uint type
|
|
||||||
*/
|
|
||||||
#define TTMATH_BITS_PER_UINT 64ul
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the mask for the highest bit in the unsigned 64bit word (2^63)
|
the mask for the highest bit in the unsigned 64bit word (2^63)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
const uint TTMATH_UINT_HIGHEST_BIT = 0x8000000000000000ul;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the max value of the unsigned 64bit word (2^64 - 1)
|
the max value of the unsigned 64bit word (2^64 - 1)
|
||||||
(all bits equal one)
|
(all bits equal one)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffffffffffful;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the number of words (64bit words on 64bit platforms)
|
the number of words (64bit words on 64bit platforms)
|
||||||
which are kept in built-in variables for a Big<> type
|
which are kept in built-in variables for a Big<> type
|
||||||
(these variables are defined in ttmathbig.h)
|
(these variables are defined in ttmathbig.h)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 128ul;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const uint TTMATH_BITS_PER_UINT = (sizeof(uint)*8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||||||
|
#define TTMATH_USE_WCHAR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_USE_WCHAR
|
||||||
|
|
||||||
|
typedef wchar_t tt_char;
|
||||||
|
typedef std::wstring tt_string;
|
||||||
|
typedef std::wostringstream tt_ostringstream;
|
||||||
|
typedef std::wostream tt_ostream;
|
||||||
|
typedef std::wistream tt_istream;
|
||||||
|
#define TTMATH_TEXT_HELPER(txt) L##txt
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef char tt_char;
|
||||||
|
typedef std::string tt_string;
|
||||||
|
typedef std::ostringstream tt_ostringstream;
|
||||||
|
typedef std::ostream tt_ostream;
|
||||||
|
typedef std::istream tt_istream;
|
||||||
|
#define TTMATH_TEXT_HELPER(txt) txt
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TTMATH_TEXT(txt) TTMATH_TEXT_HELPER(txt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
characters which represent the comma operator
|
characters which represent the comma operator
|
||||||
@@ -237,6 +262,29 @@ 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 __GNUC__
|
||||||
|
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||||
|
#else
|
||||||
|
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||||
|
#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
|
||||||
{
|
{
|
||||||
@@ -271,7 +319,6 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -302,20 +349,20 @@ namespace ttmath
|
|||||||
*/
|
*/
|
||||||
class ExceptionInfo
|
class ExceptionInfo
|
||||||
{
|
{
|
||||||
const char * file;
|
const tt_char * file;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExceptionInfo() : file(0), line(0) {}
|
ExceptionInfo() : file(0), line(0) {}
|
||||||
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
|
ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
|
||||||
|
|
||||||
std::string Where() const
|
tt_string Where() const
|
||||||
{
|
{
|
||||||
if( !file )
|
if( !file )
|
||||||
return "unknown";
|
return TTMATH_TEXT("unknown");
|
||||||
|
|
||||||
std::ostringstream result;
|
tt_ostringstream result;
|
||||||
result << file << ":" << line;
|
result << file << TTMATH_TEXT(":") << line;
|
||||||
|
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
@@ -329,7 +376,7 @@ namespace ttmath
|
|||||||
can throw an exception of this type
|
can throw an exception 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 (or std::wstring) 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)
|
||||||
|
|
||||||
@@ -349,7 +396,7 @@ namespace ttmath
|
|||||||
foo.Add(foo);
|
foo.Add(foo);
|
||||||
but there are only few methods which can do that
|
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:
|
||||||
|
|
||||||
@@ -357,12 +404,12 @@ namespace ttmath
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ReferenceError(const char * f, int l) :
|
ReferenceError(const tt_char * f, int l) :
|
||||||
std::logic_error ("reference error"), ExceptionInfo(f,l)
|
std::logic_error ("reference error"), ExceptionInfo(f,l)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Where() const
|
tt_string Where() const
|
||||||
{
|
{
|
||||||
return ExceptionInfo::Where();
|
return ExceptionInfo::Where();
|
||||||
}
|
}
|
||||||
@@ -377,11 +424,11 @@ 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 (or std::wstring) 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:
|
||||||
|
|
||||||
@@ -389,12 +436,12 @@ namespace ttmath
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeError(const char * f, int l) :
|
RuntimeError(const tt_char * f, int l) :
|
||||||
std::runtime_error ("internal error"), ExceptionInfo(f,l)
|
std::runtime_error ("internal error"), ExceptionInfo(f,l)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Where() const
|
tt_string Where() const
|
||||||
{
|
{
|
||||||
return ExceptionInfo::Where();
|
return ExceptionInfo::Where();
|
||||||
}
|
}
|
||||||
@@ -409,11 +456,22 @@ namespace ttmath
|
|||||||
|
|
||||||
#if defined(__FILE__) && defined(__LINE__)
|
#if defined(__FILE__) && defined(__LINE__)
|
||||||
|
|
||||||
|
#ifdef TTMATH_USE_WCHAR
|
||||||
|
#define TTMATH_FILE_HELPER2(arg) L##arg
|
||||||
|
#define TTMATH_FILE_HELPER(x) TTMATH_FILE_HELPER2(x)
|
||||||
|
#define TTMATH_FILE TTMATH_FILE_HELPER(__FILE__)
|
||||||
|
#else
|
||||||
|
#define TTMATH_FILE __FILE__
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
|
||||||
|
|
||||||
#define TTMATH_ASSERT(expression) \
|
#define TTMATH_ASSERT(expression) \
|
||||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
|
||||||
|
|
||||||
|
#define TTMATH_VERIFY(expression) \
|
||||||
|
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -422,19 +480,32 @@ namespace ttmath
|
|||||||
|
|
||||||
#define TTMATH_ASSERT(expression) \
|
#define TTMATH_ASSERT(expression) \
|
||||||
if( !(expression) ) throw RuntimeError();
|
if( !(expression) ) throw RuntimeError();
|
||||||
|
|
||||||
|
#define TTMATH_VERIFY(expression) \
|
||||||
|
if( !(expression) ) throw RuntimeError();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||||
#define TTMATH_ASSERT(expression)
|
#define TTMATH_ASSERT(expression)
|
||||||
|
#define TTMATH_VERIFY(expression) (void)(expression);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LOG_PRINTF)
|
||||||
|
#define LOG_PRINTF printf
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TTMATH_DEBUG_LOG
|
#ifdef TTMATH_DEBUG_LOG
|
||||||
|
|
||||||
#define TTMATH_LOG(msg) \
|
#ifdef TTMATH_USE_WCHAR
|
||||||
|
#define TTMATH_LOG_HELPER(msg) \
|
||||||
|
PrintLog(L##msg, std::wcout);
|
||||||
|
#else
|
||||||
|
#define TTMATH_LOG_HELPER(msg) \
|
||||||
PrintLog(msg, std::cout);
|
PrintLog(msg, std::cout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -443,7 +514,9 @@ namespace ttmath
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#ifndef headerfilettmathuint
|
#ifndef headerfilettmathuint
|
||||||
#define headerfilettmathuint
|
#define headerfilettmathuint
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file ttmathuint.h
|
\file ttmathuint.h
|
||||||
\brief template class UInt<uint>
|
\brief template class UInt<uint>
|
||||||
@@ -48,9 +49,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
|
||||||
#include "ttmathtypes.h"
|
#include "ttmathtypes.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(disable:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief a namespace for the TTMath library
|
\brief a namespace for the TTMath library
|
||||||
@@ -84,7 +88,10 @@ public:
|
|||||||
|
|
||||||
it prints the table in a nice form of several columns
|
it prints the table in a nice form of several columns
|
||||||
*/
|
*/
|
||||||
void PrintTable(std::ostream & output) const
|
#ifndef TTMATH_USE_WCHAR
|
||||||
|
// gcc has a problem with std::setfill when wchar_t is used
|
||||||
|
|
||||||
|
void PrintTable(tt_ostream & output) const
|
||||||
{
|
{
|
||||||
// how many columns there'll be
|
// how many columns there'll be
|
||||||
const int columns = 8;
|
const int columns = 8;
|
||||||
@@ -92,7 +99,7 @@ public:
|
|||||||
int c = 1;
|
int c = 1;
|
||||||
for(int i=value_size-1 ; i>=0 ; --i)
|
for(int i=value_size-1 ; i>=0 ; --i)
|
||||||
{
|
{
|
||||||
output << "0x" << std::setfill('0');
|
output << TTMATH_TEXT("0x") << std::setfill('0');
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM32
|
#ifdef TTMATH_PLATFORM32
|
||||||
output << std::setw(8);
|
output << std::setw(8);
|
||||||
@@ -104,7 +111,7 @@ public:
|
|||||||
|
|
||||||
if( i>0 )
|
if( i>0 )
|
||||||
{
|
{
|
||||||
output << ", ";
|
output << TTMATH_TEXT(", ");
|
||||||
|
|
||||||
if( ++c > columns )
|
if( ++c > columns )
|
||||||
{
|
{
|
||||||
@@ -116,14 +123,14 @@ public:
|
|||||||
|
|
||||||
output << std::dec << std::endl;
|
output << std::dec << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void PrintLog(const tt_char * msg, tt_ostream & output) const
|
||||||
void PrintLog(const char * msg, std::ostream & output) const
|
|
||||||
{
|
{
|
||||||
output << msg << std::endl;
|
output << msg << std::endl;
|
||||||
|
|
||||||
for(uint i=0 ; i<value_size ; ++i)
|
for(uint i=0 ; i<value_size ; ++i)
|
||||||
output << " table[" << i << "]: " << table[i] << std::endl;
|
output << TTMATH_TEXT(" table[") << i << TTMATH_TEXT("]: ") << table[i] << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -840,8 +847,10 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
the multiplication 'this' = 'this' * ss2
|
the multiplication 'this' = 'this' * ss2
|
||||||
|
|
||||||
|
algorithm: 100 - means automatically choose the fastest algorithm
|
||||||
*/
|
*/
|
||||||
uint Mul(const UInt<value_size> & ss2, uint algorithm = 2)
|
uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
|
||||||
{
|
{
|
||||||
switch( algorithm )
|
switch( algorithm )
|
||||||
{
|
{
|
||||||
@@ -849,8 +858,14 @@ public:
|
|||||||
return Mul1(ss2);
|
return Mul1(ss2);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
default:
|
|
||||||
return Mul2(ss2);
|
return Mul2(ss2);
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return Mul3(ss2);
|
||||||
|
|
||||||
|
case 100:
|
||||||
|
default:
|
||||||
|
return MulFastest(ss2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,10 +875,12 @@ public:
|
|||||||
|
|
||||||
since the 'result' is twice bigger than 'this' and 'ss2'
|
since the 'result' is twice bigger than 'this' and 'ss2'
|
||||||
this method never returns a carry
|
this method never returns a carry
|
||||||
|
|
||||||
|
algorithm: 100 - means automatically choose the fastest algorithm
|
||||||
*/
|
*/
|
||||||
void MulBig(const UInt<value_size> & ss2,
|
void MulBig(const UInt<value_size> & ss2,
|
||||||
UInt<value_size*2> & result,
|
UInt<value_size*2> & result,
|
||||||
uint algorithm = 2)
|
uint algorithm = 100)
|
||||||
{
|
{
|
||||||
switch( algorithm )
|
switch( algorithm )
|
||||||
{
|
{
|
||||||
@@ -871,8 +888,14 @@ public:
|
|||||||
return Mul1Big(ss2, result);
|
return Mul1Big(ss2, result);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
default:
|
|
||||||
return Mul2Big(ss2, result);
|
return Mul2Big(ss2, result);
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return Mul3Big(ss2, result);
|
||||||
|
|
||||||
|
case 100:
|
||||||
|
default:
|
||||||
|
return MulFastestBig(ss2, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -964,7 +987,7 @@ public:
|
|||||||
uint Mul2(const UInt<value_size> & ss2)
|
uint Mul2(const UInt<value_size> & ss2)
|
||||||
{
|
{
|
||||||
UInt<value_size*2> result;
|
UInt<value_size*2> result;
|
||||||
uint i;
|
uint i, c = 0;
|
||||||
|
|
||||||
Mul2Big(ss2, result);
|
Mul2Big(ss2, result);
|
||||||
|
|
||||||
@@ -975,11 +998,14 @@ public:
|
|||||||
// testing carry
|
// testing carry
|
||||||
for( ; i<value_size*2 ; ++i)
|
for( ; i<value_size*2 ; ++i)
|
||||||
if( result.table[i] != 0 )
|
if( result.table[i] != 0 )
|
||||||
return 1;
|
{
|
||||||
|
c = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TTMATH_LOG("UInt::Mul2")
|
TTMATH_LOG("UInt::Mul2")
|
||||||
|
|
||||||
return 0;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -991,44 +1017,385 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||||
{
|
{
|
||||||
uint r2,r1;
|
Mul2Big2<value_size>(table, ss2.table, result);
|
||||||
uint x1size=value_size, x2size=value_size;
|
|
||||||
uint x1start=0, x2start=0;
|
TTMATH_LOG("UInt::Mul2Big")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for calculating the multiplication
|
||||||
|
|
||||||
|
arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding
|
||||||
|
unnecessary copying objects), the result should be taken as a pointer too,
|
||||||
|
but at the moment there is no method AddTwoInts() which can operate on pointers
|
||||||
|
*/
|
||||||
|
template<uint ss_size>
|
||||||
|
void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result)
|
||||||
|
{
|
||||||
|
uint x1size = ss_size, x2size = ss_size;
|
||||||
|
uint x1start = 0, x2start = 0;
|
||||||
|
|
||||||
|
if( ss_size > 2 )
|
||||||
|
{
|
||||||
|
// if the ss_size is smaller than or equal to 2
|
||||||
|
// there is no sense to set x1size (and others) to another values
|
||||||
|
|
||||||
|
for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size);
|
||||||
|
for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size);
|
||||||
|
|
||||||
|
for(x1start=0 ; x1start<x1size && ss1[x1start]==0 ; ++x1start);
|
||||||
|
for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for calculating the multiplication
|
||||||
|
*/
|
||||||
|
template<uint ss_size>
|
||||||
|
void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result, uint x1start, uint x1size, uint x2start, uint x2size)
|
||||||
|
{
|
||||||
|
uint r2, r1;
|
||||||
|
|
||||||
result.SetZero();
|
result.SetZero();
|
||||||
|
|
||||||
if( value_size > 2 )
|
if( x1size==0 || x2size==0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(uint x1=x1start ; x1<x1size ; ++x1)
|
||||||
{
|
{
|
||||||
// if the value_size is smaller than or equal to 2
|
for(uint x2=x2start ; x2<x2size ; ++x2)
|
||||||
// there is no sense to set x1size (and others) to another values
|
{
|
||||||
|
MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
|
||||||
|
result.AddTwoInts(r2, r1, x2+x1);
|
||||||
|
// here will never be a carry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: this = this * ss2
|
||||||
|
|
||||||
|
This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
|
||||||
|
or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
|
||||||
|
If value_size is smaller then we're using Mul2Big() instead.
|
||||||
|
|
||||||
|
Karatsuba multiplication:
|
||||||
|
Assume we have:
|
||||||
|
this = x = x1*B^m + x0
|
||||||
|
ss2 = y = y1*B^m + y0
|
||||||
|
where x0 and y0 are less than B^m
|
||||||
|
the product from multiplication we can show as:
|
||||||
|
x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
|
||||||
|
where
|
||||||
|
z2 = x1*y1
|
||||||
|
z1 = x1*y0 + x0*y1
|
||||||
|
z0 = x0*y0
|
||||||
|
this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
|
||||||
|
z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
|
||||||
|
and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
|
||||||
|
|
||||||
|
Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
|
||||||
|
Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
|
||||||
|
*/
|
||||||
|
uint Mul3(const UInt<value_size> & ss2)
|
||||||
|
{
|
||||||
|
UInt<value_size*2> result;
|
||||||
|
uint i, c = 0;
|
||||||
|
|
||||||
|
Mul3Big(ss2, result);
|
||||||
|
|
||||||
|
// copying result
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
table[i] = result.table[i];
|
||||||
|
|
||||||
|
// testing carry
|
||||||
|
for( ; i<value_size*2 ; ++i)
|
||||||
|
if( result.table[i] != 0 )
|
||||||
|
{
|
||||||
|
c = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::Mul3")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result = this * ss2
|
||||||
|
|
||||||
|
result is twice bigger than this and ss2,
|
||||||
|
this method never returns carry,
|
||||||
|
(Karatsuba multiplication)
|
||||||
|
*/
|
||||||
|
void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||||
|
{
|
||||||
|
Mul3Big2<value_size>(table, ss2.table, result.table);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::Mul3Big")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for calculating the Karatsuba multiplication
|
||||||
|
|
||||||
|
result_size is equal ss_size*2
|
||||||
|
*/
|
||||||
|
template<uint ss_size>
|
||||||
|
void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
|
||||||
|
{
|
||||||
|
const uint * x1, * x0, * y1, * y0;
|
||||||
|
|
||||||
|
|
||||||
|
if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
|
||||||
|
{
|
||||||
|
UInt<ss_size*2> res;
|
||||||
|
Mul2Big2<ss_size>(ss1, ss2, res);
|
||||||
|
|
||||||
|
for(uint i=0 ; i<ss_size*2 ; ++i)
|
||||||
|
result[i] = res.table[i];
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( ss_size == 1 )
|
||||||
|
{
|
||||||
|
return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( (ss_size & 1) == 1 )
|
||||||
|
{
|
||||||
|
// ss_size is odd
|
||||||
|
x0 = ss1;
|
||||||
|
y0 = ss2;
|
||||||
|
x1 = ss1 + ss_size / 2 + 1;
|
||||||
|
y1 = ss2 + ss_size / 2 + 1;
|
||||||
|
|
||||||
|
// the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
|
||||||
|
Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ss_size is even
|
||||||
|
x0 = ss1;
|
||||||
|
y0 = ss2;
|
||||||
|
x1 = ss1 + ss_size / 2;
|
||||||
|
y1 = ss2 + ss_size / 2;
|
||||||
|
|
||||||
|
// all four vectors (x0 x1 y0 y1) are equal in size
|
||||||
|
Mul3Big3<ss_size/2, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable : 4717)
|
||||||
|
//warning C4717: recursive on all control paths, function will cause runtime stack overflow
|
||||||
|
//we have the stop point in Mul3Big2() method
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for calculating the Karatsuba multiplication
|
||||||
|
|
||||||
|
x = x1*B^m + x0
|
||||||
|
y = y1*B^m + y0
|
||||||
|
|
||||||
|
first_size - is the size of vectors: x0 and y0
|
||||||
|
second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size)
|
||||||
|
|
||||||
|
x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
|
||||||
|
where
|
||||||
|
z0 = x0*y0
|
||||||
|
z2 = x1*y1
|
||||||
|
z1 = (x1 + x0)*(y1 + y0) - z2 - z0
|
||||||
|
*/
|
||||||
|
template<uint first_size, uint second_size, uint result_size>
|
||||||
|
void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
|
||||||
|
{
|
||||||
|
uint i, c, xc, yc;
|
||||||
|
|
||||||
|
UInt<first_size> temp, temp2;
|
||||||
|
UInt<first_size*3> z1;
|
||||||
|
|
||||||
|
// z0 and z2 we store directly in the result (we don't use any temporary variables)
|
||||||
|
Mul3Big2<first_size>(x0, y0, result); // z0
|
||||||
|
Mul3Big2<second_size>(x1, y1, result+first_size*2); // z2
|
||||||
|
|
||||||
|
// now we calculate z1
|
||||||
|
// temp = (x0 + x1)
|
||||||
|
// temp2 = (y0 + y1)
|
||||||
|
// we're using temp and temp2 with UInt<first_size>, although there can be a carry but
|
||||||
|
// we simple remember it in xc and yc (xc and yc can be either 0 or 1),
|
||||||
|
// and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm):
|
||||||
|
//
|
||||||
|
// xc | temp
|
||||||
|
// yc | temp2
|
||||||
|
// --------------------
|
||||||
|
// (temp * temp2)
|
||||||
|
// xc*temp2 |
|
||||||
|
// yc*temp |
|
||||||
|
// xc*yc |
|
||||||
|
// ---------- z1 --------
|
||||||
|
//
|
||||||
|
// and the result is never larger in size than 3*first_size
|
||||||
|
|
||||||
|
xc = AddVector(x0, x1, first_size, second_size, temp.table);
|
||||||
|
yc = AddVector(y0, y1, first_size, second_size, temp2.table);
|
||||||
|
|
||||||
|
Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
|
||||||
|
|
||||||
|
// clearing the rest of z1
|
||||||
|
for(i=first_size*2 ; i<first_size*3 ; ++i)
|
||||||
|
z1.table[i] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if( xc )
|
||||||
|
{
|
||||||
|
c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
|
||||||
|
TTMATH_ASSERT( c==0 )
|
||||||
|
}
|
||||||
|
|
||||||
|
if( yc )
|
||||||
|
{
|
||||||
|
c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
|
||||||
|
TTMATH_ASSERT( c==0 )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( xc && yc )
|
||||||
|
{
|
||||||
|
for( i=first_size*2 ; i<first_size*3 ; ++i )
|
||||||
|
if( ++z1.table[i] != 0 )
|
||||||
|
break; // break if there was no carry
|
||||||
|
}
|
||||||
|
|
||||||
|
// z1 = z1 - z2
|
||||||
|
c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
|
||||||
|
TTMATH_ASSERT(c==0)
|
||||||
|
|
||||||
|
// z1 = z1 - z0
|
||||||
|
c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
|
||||||
|
TTMATH_ASSERT(c==0)
|
||||||
|
|
||||||
|
// here we've calculated the z1
|
||||||
|
// now we're adding it to the result
|
||||||
|
|
||||||
|
if( first_size > second_size )
|
||||||
|
{
|
||||||
|
uint z1_size = result_size - first_size;
|
||||||
|
TTMATH_ASSERT( z1_size <= first_size*3 )
|
||||||
|
|
||||||
|
for(i=z1_size ; i<first_size*3 ; ++i)
|
||||||
|
TTMATH_ASSERT( z1.table[i] == 0 )
|
||||||
|
;
|
||||||
|
|
||||||
|
c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
|
||||||
|
TTMATH_ASSERT(c==0)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
|
||||||
|
TTMATH_ASSERT(c==0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (default : 4717)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication this = this * ss2
|
||||||
|
*/
|
||||||
|
uint MulFastest(const UInt<value_size> & ss2)
|
||||||
|
{
|
||||||
|
UInt<value_size*2> result;
|
||||||
|
uint i, c = 0;
|
||||||
|
|
||||||
|
MulFastestBig(ss2, result);
|
||||||
|
|
||||||
|
// copying result
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
table[i] = result.table[i];
|
||||||
|
|
||||||
|
// testing carry
|
||||||
|
for( ; i<value_size*2 ; ++i)
|
||||||
|
if( result.table[i] != 0 )
|
||||||
|
{
|
||||||
|
c = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::MulFastest")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication result = this * ss2
|
||||||
|
|
||||||
|
this method is trying to select the fastest algorithm
|
||||||
|
(in the future this method can be improved)
|
||||||
|
*/
|
||||||
|
void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||||
|
{
|
||||||
|
if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
|
||||||
|
return Mul2Big(ss2, result);
|
||||||
|
|
||||||
|
uint x1size = value_size, x2size = value_size;
|
||||||
|
uint x1start = 0, x2start = 0;
|
||||||
|
|
||||||
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||||
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
|
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
|
||||||
|
|
||||||
if( x1size==0 || x2size==0 )
|
if( x1size==0 || x2size==0 )
|
||||||
{
|
{
|
||||||
TTMATH_LOG("UInt::Mul2Big")
|
// either 'this' or 'ss2' is equal zero - the result is zero too
|
||||||
|
result.SetZero();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||||
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
|
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
|
||||||
}
|
|
||||||
|
|
||||||
for(uint x1=x1start ; x1<x1size ; ++x1)
|
uint distancex1 = x1size - x1start;
|
||||||
{
|
uint distancex2 = x2size - x2start;
|
||||||
for(uint x2=x2start ; x2<x2size ; ++x2)
|
|
||||||
{
|
|
||||||
MulTwoWords(table[x1], ss2.table[x2], &r2, &r1);
|
|
||||||
result.AddTwoInts(r2,r1,x2+x1);
|
|
||||||
// here will never be a carry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TTMATH_LOG("UInt::Mul2Big")
|
if( distancex1 < 3 || distancex2 < 3 )
|
||||||
}
|
// either 'this' or 'ss2' have only 2 (or 1) item different from zero (side by side)
|
||||||
|
// (this condition in the future can be improved)
|
||||||
|
return Mul2Big3<value_size>(table, ss2.table, result, x1start, x1size, x2start, x2size);
|
||||||
|
|
||||||
|
|
||||||
|
// Karatsuba multiplication
|
||||||
|
Mul3Big(ss2, result);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::MulFastestBig")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1453,7 +1820,7 @@ private:
|
|||||||
|
|
||||||
if( Div2_DivisorGreaterOrEqual( divisor, remainder,
|
if( Div2_DivisorGreaterOrEqual( divisor, remainder,
|
||||||
table_id, index,
|
table_id, index,
|
||||||
divisor_table_id, divisor_index) )
|
divisor_index) )
|
||||||
{
|
{
|
||||||
TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
|
TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1473,7 +1840,7 @@ private:
|
|||||||
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
|
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
|
||||||
UInt<value_size> * remainder,
|
UInt<value_size> * remainder,
|
||||||
uint table_id, uint index,
|
uint table_id, uint index,
|
||||||
uint divisor_table_id, uint divisor_index )
|
uint divisor_index )
|
||||||
{
|
{
|
||||||
if( divisor_index > index )
|
if( divisor_index > index )
|
||||||
{
|
{
|
||||||
@@ -1604,7 +1971,7 @@ private:
|
|||||||
for(uint i = j+1 ; i<value_size ; ++i)
|
for(uint i = j+1 ; i<value_size ; ++i)
|
||||||
q.table[i] = 0;
|
q.table[i] = 0;
|
||||||
|
|
||||||
while( true )
|
for (;;)
|
||||||
{
|
{
|
||||||
u1 = table[j+n-1];
|
u1 = table[j+n-1];
|
||||||
u0 = table[j+n-2];
|
u0 = table[j+n-2];
|
||||||
@@ -1921,7 +2288,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool IsTheLowestBitSet() const
|
bool IsTheLowestBitSet() const
|
||||||
{
|
{
|
||||||
return (*table & 1) != 0;
|
return (table[0] & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2005,7 +2372,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts a digit into a char
|
this method converts a digit into a tt_char
|
||||||
digit should be from <0,F>
|
digit should be from <0,F>
|
||||||
(we don't have to get a base)
|
(we don't have to get a base)
|
||||||
|
|
||||||
@@ -2015,12 +2382,12 @@ public:
|
|||||||
10 -> A
|
10 -> A
|
||||||
15 -> F
|
15 -> F
|
||||||
*/
|
*/
|
||||||
static uint DigitToChar(uint digit)
|
static tt_char DigitToChar(uint digit)
|
||||||
{
|
{
|
||||||
if( digit < 10 )
|
if( digit < 10 )
|
||||||
return digit + '0';
|
return (tt_char)(digit + '0');
|
||||||
|
|
||||||
return digit - 10 + 'A';
|
return((tt_char)(digit - 10 + 'A'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2141,7 +2508,7 @@ public:
|
|||||||
this constant 10 has the int type (signed int), if we don't give such
|
this constant 10 has the int type (signed int), if we don't give such
|
||||||
operators and constructors the compiler will not compile the program,
|
operators and constructors the compiler will not compile the program,
|
||||||
because it has to make a conversion and doesn't know into which type
|
because it has to make a conversion and doesn't know into which type
|
||||||
(the UInt class has operator=(const char*), operator=(uint) etc.)
|
(the UInt class has operator=(const tt_char*), operator=(uint) etc.)
|
||||||
*/
|
*/
|
||||||
UInt<value_size> & operator=(sint i)
|
UInt<value_size> & operator=(sint i)
|
||||||
{
|
{
|
||||||
@@ -2256,18 +2623,18 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
a constructor for converting a string to this class (with the base=10)
|
a constructor for converting a string to this class (with the base=10)
|
||||||
*/
|
*/
|
||||||
UInt(const char * s)
|
UInt(const tt_char * s)
|
||||||
{
|
{
|
||||||
FromString(s);
|
FromString(s);
|
||||||
|
|
||||||
TTMATH_LOG("UInt::UInt(const char *)")
|
TTMATH_LOG("UInt::UInt(const tt_char *)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a constructor for converting a string to this class (with the base=10)
|
a constructor for converting a string to this class (with the base=10)
|
||||||
*/
|
*/
|
||||||
UInt(const std::string & s)
|
UInt(const tt_string & s)
|
||||||
{
|
{
|
||||||
FromString( s.c_str() );
|
FromString( s.c_str() );
|
||||||
}
|
}
|
||||||
@@ -2282,6 +2649,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a copy constructor
|
a copy constructor
|
||||||
*/
|
*/
|
||||||
@@ -2332,10 +2700,10 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method converts the value to a string with a base equal 'b'
|
this method converts the value to a string with a base equal 'b'
|
||||||
*/
|
*/
|
||||||
void ToString(std::string & result, uint b = 10) const
|
void ToString(tt_string & result, uint b = 10) const
|
||||||
{
|
{
|
||||||
UInt<value_size> temp( *this );
|
UInt<value_size> temp( *this );
|
||||||
char character;
|
tt_char character;
|
||||||
uint rem;
|
uint rem;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
@@ -2346,7 +2714,7 @@ public:
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
temp.DivInt(b, &rem);
|
temp.DivInt(b, &rem);
|
||||||
character = DigitToChar( rem );
|
character = static_cast<tt_char>( DigitToChar(rem) );
|
||||||
result.insert(result.begin(), character);
|
result.insert(result.begin(), character);
|
||||||
}
|
}
|
||||||
while( !temp.IsZero() );
|
while( !temp.IsZero() );
|
||||||
@@ -2360,7 +2728,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
this method's ommiting any white characters from the string
|
this method's ommiting any white characters from the string
|
||||||
*/
|
*/
|
||||||
static void SkipWhiteCharacters(const char * & c)
|
static void SkipWhiteCharacters(const tt_char * & c)
|
||||||
{
|
{
|
||||||
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
||||||
++c;
|
++c;
|
||||||
@@ -2384,7 +2752,7 @@ public:
|
|||||||
|
|
||||||
value_read (if exists) tells whether something has actually been read (at least one digit)
|
value_read (if exists) tells whether something has actually been read (at least one digit)
|
||||||
*/
|
*/
|
||||||
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
|
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
|
||||||
{
|
{
|
||||||
UInt<value_size> base( b );
|
UInt<value_size> base( b );
|
||||||
UInt<value_size> temp;
|
UInt<value_size> temp;
|
||||||
@@ -2434,7 +2802,7 @@ public:
|
|||||||
|
|
||||||
(it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
|
(it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
|
||||||
*/
|
*/
|
||||||
uint FromString(const std::string & s, uint b = 10)
|
uint FromString(const tt_string & s, uint b = 10)
|
||||||
{
|
{
|
||||||
return FromString( s.c_str(), b );
|
return FromString( s.c_str(), b );
|
||||||
}
|
}
|
||||||
@@ -2444,11 +2812,11 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this operator converts a string into its value (with base = 10)
|
this operator converts a string into its value (with base = 10)
|
||||||
*/
|
*/
|
||||||
UInt<value_size> & operator=(const char * s)
|
UInt<value_size> & operator=(const tt_char * s)
|
||||||
{
|
{
|
||||||
FromString(s);
|
FromString(s);
|
||||||
|
|
||||||
TTMATH_LOG("UInt::operator=(const char *)")
|
TTMATH_LOG("UInt::operator=(const tt_char *)")
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -2457,7 +2825,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this operator converts a string into its value (with base = 10)
|
this operator converts a string into its value (with base = 10)
|
||||||
*/
|
*/
|
||||||
UInt<value_size> & operator=(const std::string & s)
|
UInt<value_size> & operator=(const tt_string & s)
|
||||||
{
|
{
|
||||||
FromString( s.c_str() );
|
FromString( s.c_str() );
|
||||||
|
|
||||||
@@ -2825,9 +3193,15 @@ public:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
|
|
||||||
|
/*!
|
||||||
|
output for standard streams
|
||||||
|
|
||||||
|
tt_ostream is either std::ostream or std::wostream
|
||||||
|
*/
|
||||||
|
friend tt_ostream & operator<<(tt_ostream & s, const UInt<value_size> & l)
|
||||||
{
|
{
|
||||||
std::string ss;
|
tt_string ss;
|
||||||
|
|
||||||
l.ToString(ss);
|
l.ToString(ss);
|
||||||
s << ss;
|
s << ss;
|
||||||
@@ -2837,12 +3211,17 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
|
/*!
|
||||||
{
|
input from standard streams
|
||||||
std::string ss;
|
|
||||||
|
|
||||||
// char for operator>>
|
tt_istream is either std::istream or std::wistream
|
||||||
unsigned char z;
|
*/
|
||||||
|
friend tt_istream & operator>>(tt_istream & s, UInt<value_size> & l)
|
||||||
|
{
|
||||||
|
tt_string ss;
|
||||||
|
|
||||||
|
// tt_char for operator>>
|
||||||
|
tt_char z;
|
||||||
|
|
||||||
// operator>> omits white characters if they're set for ommiting
|
// operator>> omits white characters if they're set for ommiting
|
||||||
s >> z;
|
s >> z;
|
||||||
@@ -2851,10 +3230,10 @@ public:
|
|||||||
while( s.good() && CharToDigit(z, 10)>=0 )
|
while( s.good() && CharToDigit(z, 10)>=0 )
|
||||||
{
|
{
|
||||||
ss += z;
|
ss += z;
|
||||||
z = s.get();
|
z = static_cast<tt_char>(s.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're leaving the last readed character
|
// we're leaving the last read character
|
||||||
// (it's not belonging to the value)
|
// (it's not belonging to the value)
|
||||||
s.unget();
|
s.unget();
|
||||||
|
|
||||||
@@ -2874,7 +3253,6 @@ public:
|
|||||||
ttmathuint_noasm.h
|
ttmathuint_noasm.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef TTMATH_NOASM
|
|
||||||
static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
|
static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
|
||||||
static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
|
static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
|
||||||
|
|
||||||
@@ -2899,8 +3277,6 @@ public:
|
|||||||
static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
|
static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
|
||||||
|
|
||||||
#endif // TTMATH_PLATFORM64
|
#endif // TTMATH_PLATFORM64
|
||||||
#endif // TTMATH_NOASM
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint Rcl2_one(uint c);
|
uint Rcl2_one(uint c);
|
||||||
@@ -2909,12 +3285,13 @@ private:
|
|||||||
uint Rcr2(uint bits, uint c);
|
uint Rcr2(uint bits, uint c);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
uint Add(const UInt<value_size> & ss2, uint c=0);
|
uint Add(const UInt<value_size> & ss2, uint c=0);
|
||||||
uint AddInt(uint value, uint index = 0);
|
uint AddInt(uint value, uint index = 0);
|
||||||
uint AddTwoInts(uint x2, uint x1, uint index);
|
uint AddTwoInts(uint x2, uint x1, uint index);
|
||||||
|
static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
|
||||||
uint Sub(const UInt<value_size> & ss2, uint c=0);
|
uint Sub(const UInt<value_size> & ss2, uint c=0);
|
||||||
uint SubInt(uint value, uint index = 0);
|
uint SubInt(uint value, uint index = 0);
|
||||||
|
static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
|
||||||
static sint FindLeadingBitInWord(uint x);
|
static sint FindLeadingBitInWord(uint x);
|
||||||
static uint SetBitInWord(uint & value, uint bit);
|
static uint SetBitInWord(uint & value, uint bit);
|
||||||
static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
|
static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
|
||||||
@@ -2922,8 +3299,29 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array"
|
||||||
|
when compiling Mul3Big2() method
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
class UInt<0>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint table[1];
|
||||||
|
|
||||||
|
void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) };
|
||||||
|
void SetZero() { TTMATH_ASSERT(false) };
|
||||||
|
uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(default:4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "ttmathuint_x86.h"
|
#include "ttmathuint_x86.h"
|
||||||
#include "ttmathuint_x86_64.h"
|
#include "ttmathuint_x86_64.h"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#ifdef TTMATH_NOASM
|
#ifdef TTMATH_NOASM
|
||||||
|
|
||||||
|
#pragma message("TTMATH_NOASM")
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file ttmathuint_noasm.h
|
\file ttmathuint_noasm.h
|
||||||
\brief template class UInt<uint> with methods without any assembler code
|
\brief template class UInt<uint> with methods without any assembler code
|
||||||
@@ -95,7 +97,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_LOG("UInt::Add")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -131,7 +133,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_LOG("UInt::AddInt")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -184,13 +186,54 @@ 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_LOG("UInt::AddTwoInts")
|
||||||
|
|
||||||
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_LOG("UInt::AddVector")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 +275,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_LOG("UInt::Sub")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -270,12 +313,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_LOG("UInt::SubInt")
|
||||||
|
|
||||||
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_LOG("UInt::SubVector")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -305,7 +387,7 @@ namespace ttmath
|
|||||||
c = new_c;
|
c = new_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Rcl2_one")
|
TTMATH_LOG("UInt::Rcl2_one")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -344,7 +426,7 @@ namespace ttmath
|
|||||||
c = new_c;
|
c = new_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Rcr2_one")
|
TTMATH_LOG("UInt::Rcr2_one")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -421,7 +503,7 @@ namespace ttmath
|
|||||||
c = new_c;
|
c = new_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Rcr2")
|
TTMATH_LOG("UInt::Rcr2")
|
||||||
|
|
||||||
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -39,11 +39,10 @@
|
|||||||
#ifndef headerfilettmathuint_x86_64
|
#ifndef headerfilettmathuint_x86_64
|
||||||
#define headerfilettmathuint_x86_64
|
#define headerfilettmathuint_x86_64
|
||||||
|
|
||||||
|
|
||||||
#ifndef TTMATH_NOASM
|
#ifndef TTMATH_NOASM
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
#pragma message("TTMATH_ASM64")
|
||||||
/*!
|
/*!
|
||||||
\file ttmathuint_x86_64.h
|
\file ttmathuint_x86_64.h
|
||||||
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
|
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
|
||||||
@@ -51,10 +50,31 @@
|
|||||||
this file is included at the end of ttmathuint.h
|
this file is included at the end of ttmathuint.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined(_M_X64)
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||||
|
uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||||
|
uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
|
||||||
|
uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||||
|
uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||||
|
uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||||
|
uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||||
|
uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
|
||||||
|
uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||||
|
uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* basic mathematic functions
|
* basic mathematic functions
|
||||||
@@ -78,23 +98,27 @@ 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__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = adc_x64(p1,p2,b,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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 +136,7 @@ namespace ttmath
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Add")
|
TTMATH_LOG("UInt::Add")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -145,15 +169,19 @@ 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__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = addindexed_x64(p1,b,index,value);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
uint dummy, dummy2;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
@@ -173,12 +201,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_LOG("UInt::AddInt")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -219,19 +247,55 @@ namespace ttmath
|
|||||||
*/
|
*/
|
||||||
template<uint value_size>
|
template<uint value_size>
|
||||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size )
|
||||||
|
|
||||||
|
printf("add %Id + %Id\n",x1,x2);
|
||||||
|
for(int i=index ; i<value_size ; ++i)
|
||||||
|
printf("%d: %Id\n",i,table[i]);
|
||||||
|
|
||||||
|
c = AddTwoWords(table[index], x1, 0, &table[index]);
|
||||||
|
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
|
||||||
|
|
||||||
|
for(i=index+2 ; i<value_size && c ; ++i)
|
||||||
|
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||||
|
for(i=index ; i<value_size ; ++i)
|
||||||
|
printf("%d: %Id\n",i,table[i]);
|
||||||
|
printf(" -> %d\n",c);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::AddTwoInts")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#else
|
||||||
{
|
{
|
||||||
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__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
//printf("add %Id + %Id\n",x1,x2);
|
||||||
|
//for(int i=index ; i<value_size ; ++i)
|
||||||
|
// printf("%d: %Id\n",i,table[i]);
|
||||||
|
//if (table[0] == 1265784741359897913) DebugBreak();
|
||||||
|
c = addindexed2_x64(p1,b,index,x1,x2);
|
||||||
|
//for(int i=index ; i<value_size ; ++i)
|
||||||
|
// printf("%d: %Id\n",i,table[i]);
|
||||||
|
//printf(" -> %d\n",c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
uint dummy, dummy2;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
"subq %%rdx, %%rcx \n"
|
||||||
@@ -254,15 +318,16 @@ 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_LOG("UInt::AddTwoInts")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -284,20 +349,25 @@ 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__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = sbb_x64(p1,p2,b,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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"
|
||||||
@@ -316,7 +386,7 @@ namespace ttmath
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Sub")
|
TTMATH_LOG("UInt::Sub")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -347,15 +417,20 @@ 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__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = subindexed_x64(p1,b,index,value);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
uint dummy, dummy2;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
"subq %%rdx, %%rcx \n"
|
||||||
@@ -374,7 +449,7 @@ 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
|
||||||
@@ -404,17 +479,22 @@ namespace ttmath
|
|||||||
{
|
{
|
||||||
sint b = value_size;
|
sint b = value_size;
|
||||||
uint * p1 = table;
|
uint * p1 = table;
|
||||||
uint dummy, dummy2;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = rcl_x64(p1,b,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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 +506,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_LOG("UInt::Rcl2_one")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -456,16 +536,21 @@ namespace ttmath
|
|||||||
{
|
{
|
||||||
sint b = value_size;
|
sint b = value_size;
|
||||||
uint * p1 = table;
|
uint * p1 = table;
|
||||||
uint dummy;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = rcr_x64(p1,b,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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 +561,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_LOG("UInt::Rcr2_one")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -509,13 +594,18 @@ namespace ttmath
|
|||||||
|
|
||||||
uint b = value_size;
|
uint b = value_size;
|
||||||
uint * p1 = table;
|
uint * p1 = table;
|
||||||
uint dummy, dummy2, dummy3;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = rcl2_x64(p1,b,bits,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
uint dummy, dummy2, dummy3;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
"movq %%rcx, %%rsi \n"
|
"movq %%rcx, %%rsi \n"
|
||||||
@@ -553,7 +643,7 @@ namespace ttmath
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Rcl2")
|
TTMATH_LOG("UInt::Rcl2")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -580,14 +670,19 @@ namespace ttmath
|
|||||||
|
|
||||||
sint b = value_size;
|
sint b = value_size;
|
||||||
uint * p1 = table;
|
uint * p1 = table;
|
||||||
uint dummy, dummy2, dummy3;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_M_X64)
|
||||||
|
c = rcr2_x64(p1,b,bits,c);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
uint dummy, dummy2, dummy3;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
"movq %%rcx, %%rsi \n"
|
"movq %%rcx, %%rsi \n"
|
||||||
@@ -628,7 +723,7 @@ namespace ttmath
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TTMATH_LOG("UInt64::Rcr2")
|
TTMATH_LOG("UInt::Rcr2")
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -646,19 +741,29 @@ namespace ttmath
|
|||||||
register sint result;
|
register sint result;
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
unsigned long nIndex(0);
|
||||||
|
|
||||||
|
if (_BitScanReverse64(&nIndex,x) == 0)
|
||||||
|
result = -1;
|
||||||
|
else
|
||||||
|
result = nIndex;
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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" );
|
: "cc" );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -691,14 +796,22 @@ namespace ttmath
|
|||||||
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#if defined(TTMATH_PLATFORM64)
|
||||||
|
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
|
||||||
|
#else
|
||||||
|
old_bit = _bittestandset((long*)&value,bit) != 0;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#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 +855,20 @@ 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__
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
result1_ = _umul128(a,b,&result2_);
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ (
|
||||||
|
|
||||||
"mulq %%rdx \n"
|
"mulq %%rdx \n"
|
||||||
|
|
||||||
@@ -776,6 +893,7 @@ namespace ttmath
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||||
@@ -793,8 +911,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
|
||||||
@@ -803,12 +921,18 @@ namespace ttmath
|
|||||||
TTMATH_ASSERT( c != 0 )
|
TTMATH_ASSERT( c != 0 )
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
div_x64(&a,&b,c);
|
||||||
|
r_ = a;
|
||||||
|
rest_ = b;
|
||||||
|
#else
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ (
|
||||||
|
|
||||||
"divq %%rcx \n"
|
"divq %%rcx \n"
|
||||||
|
|
||||||
@@ -823,6 +947,132 @@ namespace ttmath
|
|||||||
*rest = rest_;
|
*rest = rest_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
|
||||||
|
{
|
||||||
|
uint temp;
|
||||||
|
|
||||||
|
if( carry == 0 )
|
||||||
|
{
|
||||||
|
temp = a + b;
|
||||||
|
|
||||||
|
if( temp < a )
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carry = 1;
|
||||||
|
temp = a + b + carry;
|
||||||
|
|
||||||
|
if( temp > a ) // !(temp<=a)
|
||||||
|
carry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = temp;
|
||||||
|
|
||||||
|
return carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
|
||||||
|
{
|
||||||
|
if( carry == 0 )
|
||||||
|
{
|
||||||
|
*result = a - b;
|
||||||
|
|
||||||
|
if( a < b )
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carry = 1;
|
||||||
|
*result = a - b - carry;
|
||||||
|
|
||||||
|
if( a > b ) // !(a <= b )
|
||||||
|
carry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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_LOG("UInt::AddVector")
|
||||||
|
|
||||||
|
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_LOG("UInt::SubVector")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef __GNUC__
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
|
386
ttmath/ttmathuint_x86_amd64_msvc.asm
Normal file
386
ttmath/ttmathuint_x86_amd64_msvc.asm
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
PUBLIC adc_x64
|
||||||
|
PUBLIC addindexed_x64
|
||||||
|
PUBLIC addindexed2_x64
|
||||||
|
|
||||||
|
PUBLIC sbb_x64
|
||||||
|
PUBLIC subindexed_x64
|
||||||
|
|
||||||
|
PUBLIC rcl_x64
|
||||||
|
PUBLIC rcr_x64
|
||||||
|
|
||||||
|
PUBLIC rcl2_x64
|
||||||
|
PUBLIC rcr2_x64
|
||||||
|
|
||||||
|
PUBLIC div_x64
|
||||||
|
|
||||||
|
;
|
||||||
|
; "rax, rcx, rdx, r8-r11 are volatile."
|
||||||
|
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
|
||||||
|
;
|
||||||
|
|
||||||
|
.CODE
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
adc_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
addindexed_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
addindexed2_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
sbb_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
jc return_1 ; most of the times, there will be NO carry (I hope)
|
||||||
|
|
||||||
|
done:
|
||||||
|
xor rax, rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
return_1:
|
||||||
|
mov rax, 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
subindexed_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
rcl_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
rcr_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
div_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
rcl2_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
rcr2_x64 ENDP
|
||||||
|
|
||||||
|
END
|
Reference in New Issue
Block a user