Compare commits
102 Commits
Author | SHA1 | Date | |
---|---|---|---|
125c051ea1 | |||
de150d00ec | |||
2d821bbad9 | |||
e083c5f889 | |||
11b9f389b9 | |||
bac79e0bfa | |||
0d1a57bdb4 | |||
4b4b30392a | |||
4f1763d773 | |||
cccf82797f | |||
e73ce2f8bc | |||
2feabc64e2 | |||
413c83de45 | |||
bf520689fb | |||
af4fbf3098 | |||
462ff7cc65 | |||
02da809583 | |||
32ebbbfd9e | |||
e765fba8a1 | |||
a8eb29e57d | |||
31b8c242bd | |||
4c0d8c26ff | |||
01a86e40d9 | |||
f19078f9f1 | |||
adc5015ad9 | |||
da730d1c70 | |||
9ccacd8817 | |||
b3d27979d0 | |||
e13e5eb329 | |||
74b31b1f54 | |||
28964d30f7 | |||
0d71b0cec2 | |||
3544a1df3c | |||
00519ff26d | |||
799e2c32a7 | |||
53547cfab5 | |||
d3a64b79ca | |||
c70a947c07 | |||
8972fdfdb3 | |||
019a902fed | |||
74553109a5 | |||
9e42a5a9fd | |||
1b6858616d | |||
d789ac5396 | |||
bb2583649e | |||
5e5a106605 | |||
eaa19dd46a | |||
939d0f7519 | |||
05b67e7103 | |||
3231780a85 | |||
1bae0d6cb8 | |||
277dd72fb6 | |||
a7a7eb7808 | |||
e665f91682 | |||
85945b2bb0 | |||
1efe39686b | |||
d8b829f4c5 | |||
fca1bc1a33 | |||
c65857297b | |||
f530635262 | |||
9327b4ebd4 | |||
d695785cbb | |||
85d1b87ac0 | |||
bfdc6d3df3 | |||
5668fbecf5 | |||
3899b8631c | |||
460608859c | |||
978815f12d | |||
404727f3de | |||
4aebe9aa18 | |||
e18201ba35 | |||
5b24101a83 | |||
6da0386a2d | |||
c7c859fc76 | |||
1d81dc75ff | |||
712bfc9c3b | |||
91e7badb62 | |||
cfd719cca2 | |||
f1115a2ce9 | |||
ca51020fe6 | |||
f8f324f98f | |||
cdd95f602c | |||
98c2379182 | |||
2933213a02 | |||
4d0241c9c9 | |||
4f3f05fa9d | |||
f139e6457c | |||
29bb4fb3f7 | |||
5002f435ae | |||
61886fc829 | |||
25f876762a | |||
692ff5406e | |||
669698c6d7 | |||
93ba8ce17d | |||
d27cabec93 | |||
bc9d528a75 | |||
bb16c871c9 | |||
2116418f08 | |||
062881900a | |||
0170572f84 | |||
e40ed603c6 | |||
c97ebf282f |
443
CHANGELOG
443
CHANGELOG
@@ -1,11 +1,392 @@
|
|||||||
|
Version 0.9.0 (2009.11.25):
|
||||||
|
* added: support for wide characters (wchar_t, std::wstring)
|
||||||
|
* added: Big::IsInteger()
|
||||||
|
returns true if the value is integer (without fraction)
|
||||||
|
(NaN flag is not checked)
|
||||||
|
* added: global Gamma() function
|
||||||
|
* added: gamma() function to the parser
|
||||||
|
* added: CGamma<ValueType> class
|
||||||
|
is used with Gamma() and Factorial() in multithreaded environment
|
||||||
|
* added: multithread support for Big<> class
|
||||||
|
you should compile with TTMATH_MULTITHREADS
|
||||||
|
and use TTMATH_MULTITHREADS_HELPER macro somewhere in your *.cpp file
|
||||||
|
* added: x86_64 asm code for Microsoft Visual compiler
|
||||||
|
file: ttmathuint_x86_64_msvc.asm
|
||||||
|
(this file should be compiled first because MS VC doesn't support inline assembler in x86_64 mode)
|
||||||
|
* added: flag TTMATH_BIG_ZERO to Big<> class
|
||||||
|
if this flag is set then there is a value zero
|
||||||
|
Big::IsZero() is faster now
|
||||||
|
* added: Big::ClearInfoBit(unsigned char)
|
||||||
|
Big::SetInfoBit(unsigned char)
|
||||||
|
Big::IsInfoBit(unsigned char)
|
||||||
|
some methods for manipulating the info flags
|
||||||
|
* added: macro: TTMATH_BITS(min_bits)
|
||||||
|
which returns the number of machine words
|
||||||
|
capable to hold min_bits bits
|
||||||
|
* added: bool Parser::Calculated()
|
||||||
|
this method returns true is something was calculated
|
||||||
|
(at least one mathematical operator was used or a function or variable)
|
||||||
|
* added: to the parser: operator percentage
|
||||||
|
e.g. 1000-50%=1000-(1000*0,5)=500
|
||||||
|
* added: struct: Conv
|
||||||
|
consists of some parameters used
|
||||||
|
in ToString() and FromString()
|
||||||
|
* added: Big::ToString() can group digits
|
||||||
|
e.g. 1234567 -> 1`234`567
|
||||||
|
* added: Parser::SetGroup(int g)
|
||||||
|
Parser::SetComma(int c, int c2 = 0)
|
||||||
|
Parser::SetParamSep(int s)
|
||||||
|
* added: std::string UInt::ToString(uint b = 10)
|
||||||
|
std::wstring UInt::ToWString(uint b = 10)
|
||||||
|
std::string Int::ToString(uint b = 10)
|
||||||
|
std::wstring Int::ToWString(uint b = 10)
|
||||||
|
uint Big::ToString(std::string & result, const Conv & conv)
|
||||||
|
uint Big::ToString(std::wstring & result, const Conv & conv)
|
||||||
|
std::string Big::ToString(const Conv & conv)
|
||||||
|
std::string Big::ToString()
|
||||||
|
std::wstring Big::ToWString(const Conv & conv)
|
||||||
|
std::wstring Big::ToWString()
|
||||||
|
* added: uint FromString(const char * source, const Conv & conv, const char **, bool *)
|
||||||
|
uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *)
|
||||||
|
uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *)
|
||||||
|
uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *)
|
||||||
|
* added: UInt::Sqrt() - a new algorithm for calculating the square root
|
||||||
|
* added: to the parser: function frac() - returns a value without the integer part
|
||||||
|
(only fraction remains)
|
||||||
|
* added: Int::DivInt(sint divisor, sint * remainder)
|
||||||
|
* added: const char * UInt::LibTypeStr()
|
||||||
|
const char * Big::LibTypeStr()
|
||||||
|
LibTypeCode UInt::LibType()
|
||||||
|
LibTypeCode Big::LibType()
|
||||||
|
returning a string/enum represents the currect type of the library
|
||||||
|
we have following types:
|
||||||
|
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||||
|
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||||
|
asm_vc_64 - with asm for VC (64 bit)
|
||||||
|
asm_gcc_64 - with asm for GCC (64 bit)
|
||||||
|
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||||
|
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||||
|
* added: UInt::operator>>(int)
|
||||||
|
UInt::operator>>=(int)
|
||||||
|
UInt::operator<<(int)
|
||||||
|
UInt::operator<<=(int)
|
||||||
|
* changed: Factorial() is using the Gamma() function now
|
||||||
|
* changed: Big::Div(ss2)
|
||||||
|
Big::Mod(ss2)
|
||||||
|
they return 2 when ss2 is zero
|
||||||
|
previously returned 1
|
||||||
|
* changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
|
||||||
|
they were not too much accurate for some integers
|
||||||
|
e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)
|
||||||
|
* changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16
|
||||||
|
the previous version was not accurate on some last digits (after the comma operator)
|
||||||
|
consider this binary value (32 bit mantissa):
|
||||||
|
base 2: 1.1111 1111 1111 1111 1111 1111 1110 101
|
||||||
|
previous ToString() gave:
|
||||||
|
base 4: 1.33333333333332
|
||||||
|
base 8: 1.777777777
|
||||||
|
base 16: 1.FFFFFF
|
||||||
|
now we have:
|
||||||
|
base 4: 1.3333333333333222
|
||||||
|
base 8: 1.77777777724
|
||||||
|
base 16: 1.FFFFFFEA
|
||||||
|
* changed: in Big::ToString() some additional rounding (base_round) is now made only
|
||||||
|
when the value is not an integer
|
||||||
|
* changed: another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
|
||||||
|
* removed: Parser<>::SetFactorialMax() method
|
||||||
|
the factorial() is such a fast now that we don't need the method longer
|
||||||
|
* removed: ErrorCode::err_too_big_factorial
|
||||||
|
* removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
|
||||||
|
the comma characters we have in Conv struct now
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.6 (2009.10.25):
|
||||||
|
* fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
|
||||||
|
equal 1 (should be set 2)
|
||||||
|
this affected only no-asm parts - when macro TTMATH_NOASM was defined
|
||||||
|
* fixed: UInt<value_size>::MulInt(uint ss2)
|
||||||
|
there was a buffer overflow when value_size was equal 1
|
||||||
|
* fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
|
||||||
|
when macro TTMATH_NOASM was defined
|
||||||
|
* fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
|
||||||
|
* fixed: Int::FromString(const tt_string & s, uint b = 10)
|
||||||
|
didn't use 'b' (always was '10')
|
||||||
|
* fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
|
||||||
|
* fixed: powering algorithm in:
|
||||||
|
UInt::Pow(UInt<value_size> pow)
|
||||||
|
Big::Pow(UInt<pow_size> pow)
|
||||||
|
Big::PowUInt(Big<exp, man> pow)
|
||||||
|
when 'pow' was sufficient large the algorithm returned carry
|
||||||
|
but the result could have been calculated correctly
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.5 (2009.06.16):
|
||||||
|
* fixed: Big::Mod(x) didn't correctly return a carry
|
||||||
|
and the result was sometimes very big (even greater than x)
|
||||||
|
* fixed: global function Mod(x) didn't set an ErrorCode object
|
||||||
|
* fixed: global function Round() didn't test a carry
|
||||||
|
now it sets ErrorCode object
|
||||||
|
* changed: function Sin(x) to Sin(x, ErrorCode * err=0)
|
||||||
|
when x was very big the function returns zero
|
||||||
|
now it sets ErrorCode object to err_overflow
|
||||||
|
and the result has a NaN flag set
|
||||||
|
the same is to Cos() function
|
||||||
|
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
|
||||||
|
should be a little accurate especially on a very big 'x'
|
||||||
|
* changed: uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
|
||||||
|
void MulBig(const UInt<value_size> & ss2, UInt<value_size*2> & result, uint algorithm = 100)
|
||||||
|
those methods by default use MulFastest() and MulFastestBig()
|
||||||
|
* changed: changed a little Mul2Big() to cooperate with Mul3Big()
|
||||||
|
* added: uint UInt::Mul3(const UInt<value_size> & ss2)
|
||||||
|
void UInt::Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||||
|
a new multiplication algorithm: Karatsuba multiplication,
|
||||||
|
on a vector UInt<100> with all items different from zero this algorithm is faster
|
||||||
|
about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from
|
||||||
|
zero this algorithm is faster more than 5 times than Mul2Big()
|
||||||
|
(measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE)
|
||||||
|
* added: uint MulFastest(const UInt<value_size> & ss2)
|
||||||
|
void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||||
|
those methods are trying to select the fastest multiplication algorithm
|
||||||
|
* added: uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||||
|
uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||||
|
three forms: asm x86, asm x86_64, no-asm
|
||||||
|
those methods are used by the Karatsuba multiplication algorithm
|
||||||
|
* added: to Big<> class: support for NaN flag (Not a Number)
|
||||||
|
bool Big::IsNan() - returns true if the NaN flag is set
|
||||||
|
void Big::SetNan() - sets the NaN flag
|
||||||
|
The NaN flag is set by default after creating an object:
|
||||||
|
Big<1, 2> a; // NaN is set (it means the object has not a valid number)
|
||||||
|
std::cout << a; // cout gives "NaN"
|
||||||
|
a = 123; // now NaN is not set
|
||||||
|
std::cout << a; // cout gives "123"
|
||||||
|
The NaN is set if there was a carry during calculations
|
||||||
|
a.Mul(very_big_value); // a will have a NaN set
|
||||||
|
The NaN is set if an argument is NaN too
|
||||||
|
b.SetNan();
|
||||||
|
a.Add(b); // a will have NaN because b has NaN too
|
||||||
|
If you try to do something on a NaN object, the result is a NaN too
|
||||||
|
a.SetNan();
|
||||||
|
a.Add(2); // a is still a NaN
|
||||||
|
The NaN is set if you use incorrect arguments
|
||||||
|
a.Ln(-10); // a will have the NaN flag
|
||||||
|
The only way to clear the NaN flag is to assign a correct value or other correct object,
|
||||||
|
supposing 'a' has NaN flag, to remove the flag you can either:
|
||||||
|
a = 10;
|
||||||
|
a.FromInt(30);
|
||||||
|
a.SetOne();
|
||||||
|
a.FromBig(other_object_without_nan);
|
||||||
|
etc.
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.4 (2009.05.08):
|
||||||
|
* fixed: UInt::DivInt() didn't check whether the divisor is zero
|
||||||
|
there was a hardware interruption when the divisor was zero
|
||||||
|
(now the method returns one)
|
||||||
|
* fixed: the problem with GCC optimization on x86_64
|
||||||
|
sometimes when using -O2 or -O3 GCC doesn't set correctly
|
||||||
|
the stack pointer (actually the stack is used for other things)
|
||||||
|
and you can't use instructions like push/pop in assembler code.
|
||||||
|
All the asm code in x86_64 have been rewritten, now instructions
|
||||||
|
push/pop are not used, other thing which have access to stack
|
||||||
|
(like "m" (mask) constraints in Rcl2 and Rcr2) have also gone away,
|
||||||
|
now the library works well with -O2 and -O3 and the asm code
|
||||||
|
is a little faster
|
||||||
|
* added: UInt::PrintLog(const char * msg, std::ostream & output)
|
||||||
|
used (for debugging purposes) by macro TTMATH_LOG(msg)
|
||||||
|
(it is used in nearly all methods in UInt class)
|
||||||
|
* added: macro TTMATH_DEBUG_LOG: when defined then TTMATH_LOG()
|
||||||
|
put some debug information (to std::cout)
|
||||||
|
* added: ttmathuint_x86.h, ttmathuint_x86_64.h, ttmathuint_noasm.h,
|
||||||
|
all the methods which are using assembler code have been
|
||||||
|
rewritten to no-asm forms, now we have:
|
||||||
|
1. asm for x86 file: ttmathuint_x86.h
|
||||||
|
2. asm for x86_64 file: ttmathuint_x86_64.h
|
||||||
|
3. no asm file: ttmathuint_noasm.h
|
||||||
|
(it's used when macro TTMATH_NOASM is defined)
|
||||||
|
The third form can be used on x86 and x86_64 as well and
|
||||||
|
on other platforms with a little effort.
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.3 (2009.04.06):
|
||||||
|
* fixed: RclMoveAllWords() and RcrMoveAllWords() sometimes didn't return
|
||||||
|
the proper carry, (when 'bits' was greater than or equal to 'value_size')
|
||||||
|
this had impact on Rcl() and Rcr(), they also returned the wrong carry
|
||||||
|
* fixed: UInt::Div() didn't return a correct result when the divisor was equal 1
|
||||||
|
there was an error in UInt::DivInt() - when the divisor was 1 it returned
|
||||||
|
zero and the carry was set
|
||||||
|
* fixed: there was a TTMATH_REREFENCE_ASSERT error in Big::PowUInt() caused by: start.Mul(start)
|
||||||
|
* fixed: Big::Add incorrectly rounded 'this' when both exponents were equal
|
||||||
|
it caused that sometimes when adding a zero the result has changed
|
||||||
|
this had impact among other things on FromString() method
|
||||||
|
"0,8" had different binary representation from "0,80"
|
||||||
|
* fixed: template Big::FromBig(const Big<another_exp, another_man> & another)
|
||||||
|
didn't correctly set the exponent (when the mantisses had different size -
|
||||||
|
when 'man' was different from 'another_man')
|
||||||
|
this had impact on operator= too
|
||||||
|
sample:
|
||||||
|
Big<2,3> a = 100;
|
||||||
|
Big<3,5> b;
|
||||||
|
b = a; // b had a wrong value
|
||||||
|
* fixed: Big::Pow(const Big<exp, man> & pow)
|
||||||
|
it's using PowInt() only when pow.exponent is in range (-man*TTMATH_BITS_PER_UINT; 0]
|
||||||
|
previously the powering 'hung' on an input like this: "(1+ 1e-10000) ^ 10e100000000"
|
||||||
|
(there was 10e100000000 iterations in PowInt())
|
||||||
|
* fixed: in function DegToRad(const ValueType & x, ErrorCode * err = 0) it is better
|
||||||
|
to make division first and then mutliplication -- the result is more
|
||||||
|
accurate especially when x is: 90,180,270 or 360
|
||||||
|
* fixed: the parser didn't correctly treat operators for changing the base
|
||||||
|
(radix) -- operators '#' and '&', e.g.:
|
||||||
|
'#sin(1)' was equal '0' -- there was a zero from '#' and then
|
||||||
|
it was multipied by 'sin(1)'
|
||||||
|
the parser didn't check whether Big::FromString() has actually
|
||||||
|
read a proper value -- the method Big::FromString() didn't have
|
||||||
|
something to report such a situation
|
||||||
|
* fixed: Big::FromString() when the base is 10, the method reads the scientific
|
||||||
|
part only if such a part it correctly supplied, e.g:
|
||||||
|
'1234e10', '1234e+10', '1234e-5'
|
||||||
|
previous '1234e' was treated as: '1234e0' (now parsing stops on 'e' and
|
||||||
|
the 'e' can be parsed by other parsers, e.g. the mathematical
|
||||||
|
parser -- now in the parser would be: '1234e' = '1234 * e' = '3354,3597...' )
|
||||||
|
* changed: renamed: Big::PowUInt(UInt<pow_size> pow) -> Big::Pow(UInt<pow_size> pow)
|
||||||
|
it returns 2 when there is: 0^0
|
||||||
|
* changed: renamed: Big::PowInt(Int<pow_size> pow) -> Big::Pow(Int<pow_size> pow)
|
||||||
|
it returns 2 when there is: 0^0 or 0^(-something)
|
||||||
|
* changed: renamed: Big::PowBUInt() -> PowUInt(), Big::PowBInt() -> Big::PowInt()
|
||||||
|
they return 2 when the arguments are incorrect (like above)
|
||||||
|
* changed: UInt::SetBitInWord(uint & value, uint bit) is taking the first argument by a reference now,
|
||||||
|
the specific bit is set in the 'value' and the method returns the last state of the bit (zero or one)
|
||||||
|
* changed: UInt::SetBit(uint bit_index) - it's using TTMATH_ASSERT now
|
||||||
|
* changed: the size of built-in variables (constants) in ttmathbig.h
|
||||||
|
now they consist of 256 32bit words
|
||||||
|
macro TTMATH_BUILTIN_VARIABLES_SIZE is equal: 256u on a 32bit platform and 128ul on a 64bit platform
|
||||||
|
* changed: the asm code in ttmathuint.h and ttmathuint64.h has been completely rewritten
|
||||||
|
now UInt<> is faster about 15-30% than UInt<> from 0.8.2
|
||||||
|
this has impact on Big<> too - it's faster about 10% now
|
||||||
|
* changed: in the parser: the form with operators '#' and '&' is as follows:
|
||||||
|
[-|+][#|&]numeric_value
|
||||||
|
previous was: [-|+][#|&][-|+]numeric_value
|
||||||
|
* changed: in the parser: the short form of multiplication has the same
|
||||||
|
priority as the normal multiplication, e.g.:
|
||||||
|
'2x^3' = 2 * (x^3)
|
||||||
|
previous the priority was greater than powering priority
|
||||||
|
previous: '2x^3' = (2*x) ^ 3
|
||||||
|
* added: UInt::GetBit(uint bit_index) - returning the state of the specific bit
|
||||||
|
* added: Big::operator=(double) and Big::Big(double)
|
||||||
|
* added: UInt::Pow(UInt<value_size> pow) and Int::Pow(Int<value_size> pow)
|
||||||
|
* added: global template functions in ttmath.h:
|
||||||
|
ValueType GradToRad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType DegToGrad(const ValueType & d, const ValueType & m,
|
||||||
|
const ValueType & s, ErrorCode * err = 0)
|
||||||
|
ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
* added: Parser::SetDegRadGrad(int angle) - 0 deg, 1 rad (default), 2 grad
|
||||||
|
this affects following functions (in the parser only): sin, cos, tan, cot,
|
||||||
|
asin, acos, atan, acot
|
||||||
|
* added: functions to the parser: gradtorad(grad), radtograd(rad), degtograd(deg),
|
||||||
|
degtograd(d,m,s), gradtodeg(grad)
|
||||||
|
* added: UInt::FromString, added a parametr 'after_source'
|
||||||
|
which is pointing at the end of the parsed string
|
||||||
|
* added: Int::FromString(): parameter 'const char ** after_source = 0'
|
||||||
|
if exists it's pointing at the end of the parsed string
|
||||||
|
* added: to UInt::FromString(), Int::FromString(), Big::FromString():
|
||||||
|
parameter 'bool * value_read = 0' - (if exists) tells
|
||||||
|
whether something has actually been read (at least one digit)
|
||||||
|
* added: Objects::IsDefined(const std::string & name)
|
||||||
|
returning true if such an object is defined
|
||||||
|
* removed: Big::FromString() this method doesn't longer recognize operators
|
||||||
|
for changing the base ('#' and '&')
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.2 (2008.06.18):
|
||||||
|
* added: UInt::BitNot2() this method has been proposed by
|
||||||
|
Arek <kmicicc AnTispam users.sourceforge.net>
|
||||||
|
* changed: Int::FromInt(const Int<argument_size> & p),
|
||||||
|
Int::FromInt(sint value) (it returns zero now)
|
||||||
|
Int::operator=(uint i)
|
||||||
|
Int::Int(uint i)
|
||||||
|
* added: Int::FromUInt(const UInt<argument_size> & p),
|
||||||
|
Int::FromUInt(uint value)
|
||||||
|
and appropriate constructors and assignment
|
||||||
|
operators as well
|
||||||
|
* changed: Big::FromInt(Int<int_size> value),
|
||||||
|
* added: Big::FromUInt(UInt<int_size> value),
|
||||||
|
Big::operator=(const UInt<int_size> & value)
|
||||||
|
Big::Big(const UInt<int_size> & value)
|
||||||
|
* changed: the parser is allowed to recognize values which
|
||||||
|
begin with a dot, e.g '.5' is treated as '0.5'
|
||||||
|
* added: a method Big::FromDouble(double) which converts from
|
||||||
|
standard double into a Big
|
||||||
|
* added: uint Big::ToDouble(double&) - converting into double
|
||||||
|
* added: Big::FromBig() and an operator= and a contructor
|
||||||
|
for converting from another kind of a Big class
|
||||||
|
* added: to the parser: avg(), sum()
|
||||||
|
* added: 'decimal_point' parameter into Big::ToString(...)
|
||||||
|
* fixed: Big::operator>> didn't use TTMATH_COMMA_CHARACTER_2 macro
|
||||||
|
* added: a short form of multiplication (without the '*' character)
|
||||||
|
e.g. '5y', (it's used only if the second parameter
|
||||||
|
is a variable or function)
|
||||||
|
* changed: variables and functions are case-sensitive now
|
||||||
|
* added: variables and functions can have underline characters
|
||||||
|
in their names
|
||||||
|
* changed: 'max_digit_after_comma' in Big::ToString()
|
||||||
|
remove the -2 state
|
||||||
|
* added: 'remove_trailing_zeroes' in Big::ToString()
|
||||||
|
it's either true or false
|
||||||
|
* fixed/changed: the way of using Big::SetSign()
|
||||||
|
the method do not check whether there is a zero or not now
|
||||||
|
(even if there's a zero the method can set a sign bit)
|
||||||
|
I changed this due to some prior errors
|
||||||
|
(errors corrected in revision 17, 49 and 58)
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.1 (2007.04.17):
|
||||||
|
* fixed: Big::PowFrac(..) didn't return a correct error code
|
||||||
|
(when 'this' was negative)
|
||||||
|
* added: Root(x; index) (and to the parser as well)
|
||||||
|
* added: macro: TTMATH_PRERELEASE_VER (can be either zero or one)
|
||||||
|
* added: UInt::MulInt(int, UInt<int another_size>::&)
|
||||||
|
* added: Big::MulUInt(uint)
|
||||||
|
* changed: Big::MulInt(sint)
|
||||||
|
* added: Big::ToUInt(uint &)
|
||||||
|
* changed: Big::ToInt(sint&)
|
||||||
|
* changed: Factorial() it uses Big::MulUInt() at the beginning
|
||||||
|
(faster now especially more on a 32bit platform)
|
||||||
|
* added: doxygen.cfg for generating a documentation from the doxygen
|
||||||
|
* changed: UInt::Rcl(uint c=0) and UInt::Rcr(uint c=0) into
|
||||||
|
UInt::Rcl2(uint bits, uint c) and UInt::Rcr2(uint bits, uint c)
|
||||||
|
now they can move more than one bit and they are only private
|
||||||
|
* fixed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||||
|
didn't correctly return a carry if the 'bits' were equal
|
||||||
|
to 'value_size*TTMATH_BITS_PER_UINT'
|
||||||
|
* changed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||||
|
into UInt::Rcl(uint bits, uint c=0) and
|
||||||
|
UInt::Rcr(uint bits, uint c=0)
|
||||||
|
they are faster now when the bits is greater than a half of
|
||||||
|
the TTMATH_BITS_PER_UINT
|
||||||
|
* changed: UInt::CompensationToLeft() it's faster now
|
||||||
|
* changed: more small changes where there were UInt::Rcl(uint c=0) and
|
||||||
|
UInt::Rcr(uint c=0) used
|
||||||
|
* changed: as the Big type uses UInt::Rcl() and UInt::Rcr() a lot then
|
||||||
|
it is much faster now (about 5-25%)
|
||||||
|
* added: ASinh(), ACosh(), ATanh() /ATgh()/, ACoth() /ACtgh()/
|
||||||
|
and to the parser as well
|
||||||
|
* added: UInt::BitAnd(), UInt::BitOr(), UInt::BitXor(), UInt::BitNot(),
|
||||||
|
Big::BitAnd(), Big::BitOr(), Big::BitXor()
|
||||||
|
* added: to the parser: bitand(), bitor(), bitxor()
|
||||||
|
/band(), bor(), bxor()/
|
||||||
|
* changed: the way of parsing operators in the mathematical parser
|
||||||
|
(the parser is not too much greedy now)
|
||||||
|
|
||||||
|
|
||||||
Version 0.8.0 (2007.03.28):
|
Version 0.8.0 (2007.03.28):
|
||||||
* added: into the parser: SetFactorialMax()
|
* added: into the parser: SetFactorialMax()
|
||||||
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
||||||
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x),
|
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x),
|
||||||
Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/
|
Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/
|
||||||
* changed: class Objects in ttmathobjects.h has been completely rewritten,
|
* changed: class Objects in ttmathobjects.h has been completely rewritten,
|
||||||
we can change the names of user-defined variables or functions, and the
|
we can change the names of user-defined variables or functions,
|
||||||
names are case-sensitive now
|
and the names are case-sensitive now
|
||||||
* added: class History which is used in functions which take a lot of time
|
* added: class History which is used in functions which take a lot of time
|
||||||
during calculating e.g. Factorial(x)
|
during calculating e.g. Factorial(x)
|
||||||
* added: Tg(x) a wrapper for Tan(x)
|
* added: Tg(x) a wrapper for Tan(x)
|
||||||
@@ -16,14 +397,14 @@ Version 0.8.0 (2007.03.28):
|
|||||||
* added: ACtg(x) a wrapper for ACot(x)
|
* added: ACtg(x) a wrapper for ACot(x)
|
||||||
* added: UInt::PrintTable() (for debugging etc.)
|
* added: UInt::PrintTable() (for debugging etc.)
|
||||||
* changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have
|
* changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have
|
||||||
been rewritten, now they have 128 32bit words (it's about 1232 valid
|
been rewritten, now they have 128 32bit words (it's about
|
||||||
decimal digits)
|
1232 valid decimal digits)
|
||||||
* fixed: previous values from Big::SetPi() Big::SetE() and
|
* fixed: previous values from Big::SetPi() Big::SetE() and
|
||||||
Big::SetLn2() were not too much accurate (last 2-3 words were wrong)
|
Big::SetLn2() were not too much accurate (last 2-3 words were wrong)
|
||||||
* added: Big::SetLn10() (128 32bit words as well)
|
* added: Big::SetLn10() (128 32bit words as well)
|
||||||
* added: macro: TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on
|
* added: macro TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on
|
||||||
32bit platforms and 64ul on 64bit platforms (128/2=64)
|
32bit platforms and 64ul on 64bit platforms (128/2=64)
|
||||||
* added: macros: TTMATH_PLATFORM32 and TTMATH_PLATFORM64
|
* added: macros TTMATH_PLATFORM32 and TTMATH_PLATFORM64
|
||||||
* changed: a small optimisation in UInt::Mul2Big()
|
* changed: a small optimisation in UInt::Mul2Big()
|
||||||
* added: at the end of ttmath.h: #include "ttmathparser.h"
|
* added: at the end of ttmath.h: #include "ttmathparser.h"
|
||||||
this is for convenience for a programmer, he can only use #include
|
this is for convenience for a programmer, he can only use #include
|
||||||
@@ -31,13 +412,14 @@ Version 0.8.0 (2007.03.28):
|
|||||||
* added: to samples: big.cpp, parser.cpp
|
* added: to samples: big.cpp, parser.cpp
|
||||||
* added/changes/fixed: in copy-constructors and operators= in Int,
|
* added/changes/fixed: in copy-constructors and operators= in Int,
|
||||||
Uint and Big (more info in the commit log)
|
Uint and Big (more info in the commit log)
|
||||||
* renamed Big::SetDotOne() into Big::Set05()
|
* renamed: Big::SetDotOne() into Big::Set05()
|
||||||
* changes: a few small optimisations in Big
|
* changes: a few small optimisations in Big
|
||||||
* deleted: the word 'virtual' from destructors: UInt, Int, Big
|
* deleted: the word 'virtual' from destructors: UInt, Int, Big
|
||||||
(types in this library are not projected to be base-classes for
|
(types in this library are not projected to be base-classes for
|
||||||
another ones derived from them)
|
another ones derived from them)
|
||||||
* and more small changes (look at the commit log)
|
* and more small changes (look at the commit log)
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.2 (2007.03.09):
|
Version 0.7.2 (2007.03.09):
|
||||||
* added: Big::Mod - the remainder from a division
|
* added: Big::Mod - the remainder from a division
|
||||||
* added: Big::Sgn - the 'sign' from the value (-1,0,1)
|
* added: Big::Sgn - the 'sign' from the value (-1,0,1)
|
||||||
@@ -48,37 +430,42 @@ Version 0.7.2 (2007.03.09):
|
|||||||
* added: into the parser: logical functions: and() or() not() if()
|
* added: into the parser: logical functions: and() or() not() if()
|
||||||
* added: ErrorCode::err_unknown_operator when the parser couldn't read an operator
|
* added: ErrorCode::err_unknown_operator when the parser couldn't read an operator
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.1 (2007.02.27):
|
Version 0.7.1 (2007.02.27):
|
||||||
* fixed the error 'overflow during printing' which was caused
|
* fixed: the error 'overflow during printing' which was caused
|
||||||
by Big::FromInt(Int<int_size> value) (the sign has to be set at the end)
|
by Big::FromInt(Int<int_size> value) (the sign has to be set at the end)
|
||||||
* fixed many small errors
|
* fixed: many small errors
|
||||||
* added ATan (arctan), ACTan (arc ctan) functions
|
* added: ATan (arctan), ACTan (arc ctan) functions
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.0 (2007.02.24):
|
Version 0.7.0 (2007.02.24):
|
||||||
* finished support for 64bit platforms
|
* finished: support for 64bit platforms
|
||||||
* added ASin (arcsin), ACos (arccos) functions
|
* added: ASin (arcsin), ACos (arccos) functions
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.4 (2007.01.29):
|
Version 0.6.4 (2007.01.29):
|
||||||
* fixed the problem with a sign in the mathematical parser /-(1) was 1/
|
* fixed: the problem with a sign in the mathematical parser /-(1) was 1/
|
||||||
* added UInt::AddInt and UInt::SubInt
|
* added: UInt::AddInt and UInt::SubInt
|
||||||
* changed UInt::AddOne and UInt::SubOne (much faster now)
|
* changed: UInt::AddOne and UInt::SubOne (much faster now)
|
||||||
* added UInt::SetBitInWord
|
* added: UInt::SetBitInWord
|
||||||
* changed UInt::SetBit (much faster now)
|
* changed: UInt::SetBit (much faster now)
|
||||||
* UInt::AddTwoUints renamed to UInt::AddTwoInts
|
UInt::AddTwoUints renamed to UInt::AddTwoInts
|
||||||
* UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord
|
UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord
|
||||||
* added UInt::SetBitInWord
|
UInt::Mul64 renamed to UInt::MulTwoWords
|
||||||
* UInt::Mul64 renamed to UInt::MulTwoWords
|
UInt::Div64 renamed to UInt::DivTwoWords
|
||||||
* UInt::Div64 renamed to UInt::DivTwoWords
|
* added: UInt::SetBitInWord
|
||||||
* and more small changes in UInt type
|
* and more small changes in UInt type
|
||||||
* start adding support for Amd64 (not finished yet) (added ttmathuint64.h)
|
* start adding support for Amd64 (not finished yet) (added ttmathuint64.h)
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.3 (2007.01.22):
|
Version 0.6.3 (2007.01.22):
|
||||||
* position of arguments (x and base) in logarithm functions are swapped
|
* changed: position of arguments (x and base) in logarithm functions are swapped
|
||||||
* it's possible to use any multiplication algorithms in the same time
|
* changed: it's possible to use any multiplication algorithms in the same time
|
||||||
(macros UINT_MUL_VERSION_'X' have gone)
|
(macros UINT_MUL_VERSION_'X' have gone)
|
||||||
* added ExceptionInfo, ReferenceError and RuntimeError classes
|
* added: ExceptionInfo, ReferenceError and RuntimeError classes
|
||||||
* the mess in macros has been cleaned up
|
* changed: the mess in macros has been cleaned up
|
||||||
* added TTMATH_RELEASE macro
|
* added: TTMATH_RELEASE macro
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.2 (2007.01.10):
|
Version 0.6.2 (2007.01.10):
|
||||||
* New division algorithm (radix b) where b is 2^32
|
* added: New division algorithm (radix b) where b is 2^32
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2006-2007, Tomasz Sowa
|
Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
35
README
35
README
@@ -1,24 +1,23 @@
|
|||||||
TTMath - a bignum library for C++
|
A bignum library for C++
|
||||||
|
|
||||||
TTMath is a small library which allows one to perform arithmetic operations
|
TTMath is a small library which allows one to perform arithmetic operations
|
||||||
with big unsigned integer, big signed integer and big floating point
|
with big unsigned integer, big signed integer and big floating point numbers.
|
||||||
numbers. It provides standard mathematical operations like adding,
|
It provides standard mathematical operations like adding, subtracting,
|
||||||
subtracting, multiplying, dividing etc. With the library also goes
|
multiplying, dividing. With the library also goes a mathematical parser to
|
||||||
a mathematical parser which helps you solving input formulas read directly
|
help you solving mathematical expressions.
|
||||||
from a user.
|
|
||||||
|
|
||||||
TTMath is developed under the (new) BSD licence which means that it is free
|
TTMath is developed under the BSD licence which means that it is free for
|
||||||
for both personal and commercial use but the library has some technical
|
both personal and commercial use.
|
||||||
limitations: you can use it only on i386 and Amd64, another platforms are
|
|
||||||
not supported (Intel 64bit platforms were not tested but should work as
|
|
||||||
well), and you can use this library only with the C++ programming language.
|
|
||||||
|
|
||||||
The main goal of the library is to allow one to use big values in the same
|
The main goal of the library is to allow one to use big values in the same
|
||||||
way as the standard types like int, float, etc. It does not need to be
|
way as the standard types like int or float. It does not need to be compiled
|
||||||
compiled first because the whole library is written as the C++ templates.
|
first because the whole library is written as the C++ templates. This means
|
||||||
This means only C++ developers can use this library and one thing they have
|
only C++ developers can use this library and one thing they have to do is
|
||||||
to do is to use 'include' directive of the preprocessor. How big the
|
to use 'include' directive of the preprocessor. How big the values can be
|
||||||
values can be is set directly in the source code by the programmer.
|
is set at compile time.
|
||||||
|
|
||||||
Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl>
|
Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
Home page: http://sourceforge.net/projects/ttmath
|
WWW: http://www.ttmath.org
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Christian Kaiser <chk@online.de>
|
||||||
|
7
TODO
7
TODO
@@ -1,7 +0,0 @@
|
|||||||
TODO TTMath Library
|
|
||||||
===================
|
|
||||||
|
|
||||||
* Add bitwise operators (or functions) and, or, xor
|
|
||||||
* Add functions for generating random values
|
|
||||||
|
|
||||||
|
|
27
constgen/Makefile
Normal file
27
constgen/Makefile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
o = main.o
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -s -O2 -DTTMATH_CONSTANTSGENERATOR
|
||||||
|
name = gen
|
||||||
|
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
all: $(name)
|
||||||
|
|
||||||
|
$(name): $(o)
|
||||||
|
$(CC) -o $(name) $(CFLAGS) $(o)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main.o: main.cpp
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f *.s
|
||||||
|
rm -f $(name)
|
||||||
|
rm -f $(name).exe
|
126
constgen/main.cpp
Normal file
126
constgen/main.cpp
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
this simple program is used to make constants which then are put into ttmathbig.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../ttmath/ttmath.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
void CalcPi()
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> pi;
|
||||||
|
|
||||||
|
// 3100 digits after commna, taken from: http://zenwerx.com/pi.php
|
||||||
|
pi = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||||
|
"8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196"
|
||||||
|
"4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273"
|
||||||
|
"7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094"
|
||||||
|
"3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912"
|
||||||
|
"9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132"
|
||||||
|
"0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235"
|
||||||
|
"4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859"
|
||||||
|
"5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303"
|
||||||
|
"5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"
|
||||||
|
"3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151"
|
||||||
|
"5574857242454150695950829533116861727855889075098381754637464939319255060400927701671139009848824012"
|
||||||
|
"8583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912"
|
||||||
|
"9331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279"
|
||||||
|
"6782354781636009341721641219924586315030286182974555706749838505494588586926995690927210797509302955"
|
||||||
|
"3211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000"
|
||||||
|
"8164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333"
|
||||||
|
"4547762416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784383"
|
||||||
|
"8279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863"
|
||||||
|
"0674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009"
|
||||||
|
"9465764078951269468398352595709825822620522489407726719478268482601476990902640136394437455305068203"
|
||||||
|
"4962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382"
|
||||||
|
"6868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388"
|
||||||
|
"4390451244136549762780797715691435997700129616089441694868555848406353422072225828488648158456028506"
|
||||||
|
"0168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125"
|
||||||
|
"1507606947945109659609402522887971089314566913686722874894056010150330861792868092087476091782493858"
|
||||||
|
"9009714909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234364"
|
||||||
|
"5428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344"
|
||||||
|
"0374200731057853906219838744780847848968332144571386875194350643021845319104848100537061468067491927"
|
||||||
|
"8191197939952061419663428754440643745123718192179998391015919561814675142691239748940907186494231961"
|
||||||
|
"5679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215";
|
||||||
|
|
||||||
|
std::cout << "---------------- PI ----------------" << std::endl;
|
||||||
|
pi.mantissa.PrintTable(std::cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CalcE()
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> e;
|
||||||
|
ttmath::uint steps;
|
||||||
|
|
||||||
|
// macro TTMATH_CONSTANTSGENERATOR has to be defined
|
||||||
|
e.ExpSurrounding0(1, &steps);
|
||||||
|
std::cout << "---------------- e ----------------" << std::endl;
|
||||||
|
e.mantissa.PrintTable(std::cout);
|
||||||
|
|
||||||
|
std::cout << "ExpSurrounding0(1): " << steps << " iterations" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CalcLn(int x)
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> ln;
|
||||||
|
ttmath::uint steps;
|
||||||
|
|
||||||
|
// macro TTMATH_CONSTANTSGENERATOR has to be defined
|
||||||
|
ln.LnSurrounding1(x, &steps);
|
||||||
|
std::cout << "---------------- ln(" << x << ") ----------------" << std::endl;
|
||||||
|
ln.mantissa.PrintTable(std::cout);
|
||||||
|
|
||||||
|
std::cout << "LnSurrounding1(" << x << "): " << steps << " iterations" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CalcPi();
|
||||||
|
CalcE();
|
||||||
|
CalcLn(2);
|
||||||
|
CalcLn(10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
1257
doxygen.cfg
Normal file
1257
doxygen.cfg
Normal file
File diff suppressed because it is too large
Load Diff
@@ -32,20 +32,21 @@ MyBig atemp;
|
|||||||
if( !atemp.Add(b) )
|
if( !atemp.Add(b) )
|
||||||
std::cout << "a + b = " << atemp << std::endl;
|
std::cout << "a + b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a + b = (carry) " << atemp << std::endl;
|
std::cout << "a + b = (carry)" << std::endl;
|
||||||
|
// it have no sense to print 'atemp' (it's undefined)
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Sub(b) )
|
if( !atemp.Sub(b) )
|
||||||
std::cout << "a - b = " << atemp << std::endl;
|
std::cout << "a - b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a - b = (carry) " << atemp << std::endl;
|
std::cout << "a - b = (carry)" << std::endl;
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Mul(b) )
|
if( !atemp.Mul(b) )
|
||||||
std::cout << "a * b = " << atemp << std::endl;
|
std::cout << "a * b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a * b = (carry: the result is too big) " << std::endl;
|
std::cout << "a * b = (carry)" << std::endl;
|
||||||
// it have no sense to print 'atemp' (it's undefined)
|
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Div(b) )
|
if( !atemp.Div(b) )
|
||||||
@@ -68,9 +69,8 @@ MyBig a,b;
|
|||||||
// 'a' will have the max value which can be held in this type
|
// 'a' will have the max value which can be held in this type
|
||||||
a.SetMax();
|
a.SetMax();
|
||||||
|
|
||||||
// at the moment conversions from double (or float etc.) are not supported
|
// conversion from double
|
||||||
// you cannot do that: b = 456.32f
|
b = 456.32;
|
||||||
b = "456.32";
|
|
||||||
|
|
||||||
// Look at the value 'a' and the product from a+b and a-b
|
// Look at the value 'a' and the product from a+b and a-b
|
||||||
// Don't worry this is the nature of floating point numbers
|
// Don't worry this is the nature of floating point numbers
|
||||||
@@ -89,9 +89,9 @@ a * b = 12193540837712.2708
|
|||||||
a / b = 0.0012499665458095765
|
a / b = 0.0012499665458095765
|
||||||
Calculating with a carry
|
Calculating with a carry
|
||||||
a = 1.624801256070839555e+646457012
|
a = 1.624801256070839555e+646457012
|
||||||
b = 456.32
|
b = 456.31999999999999
|
||||||
a + b = 1.624801256070839555e+646457012
|
a + b = 1.624801256070839555e+646457012
|
||||||
a - b = 1.624801256070839555e+646457012
|
a - b = 1.624801256070839555e+646457012
|
||||||
a * b = (carry: the result is too big)
|
a * b = (carry)
|
||||||
a / b = 3.56066193914542329e+646457009
|
a / b = 3.56066193914542334e+646457009
|
||||||
*/
|
*/
|
||||||
|
31
tests/Makefile
Normal file
31
tests/Makefile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
CC = g++
|
||||||
|
o = main.o uinttest.o
|
||||||
|
CFLAGS = -Wall -O2 -s
|
||||||
|
ttmath = ..
|
||||||
|
name = tests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) -I$(ttmath) $<
|
||||||
|
|
||||||
|
|
||||||
|
all: $(name)
|
||||||
|
|
||||||
|
|
||||||
|
$(name): $(o)
|
||||||
|
$(CC) -o $(name) $(CFLAGS) -I$(ttmath) $(o)
|
||||||
|
|
||||||
|
|
||||||
|
main.o: main.cpp uinttest.h
|
||||||
|
uinttest.o: uinttest.cpp uinttest.h
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f $(name)
|
||||||
|
rm -f $(name).exe
|
||||||
|
|
||||||
|
|
68
tests/main.cpp
Normal file
68
tests/main.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ttmath/ttmath.h>
|
||||||
|
#include "uinttest.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char uint_tests_file[] = "tests.uint32";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void test_uint()
|
||||||
|
{
|
||||||
|
UIntTest test;
|
||||||
|
|
||||||
|
test.set_file_name(uint_tests_file);
|
||||||
|
test.go();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace ttmath;
|
||||||
|
|
||||||
|
|
||||||
|
test_uint();
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
92
tests/tests.uint32
Normal file
92
tests/tests.uint32
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Add
|
||||||
|
|
||||||
|
# min_bits max_bits a b result carry
|
||||||
|
add 32 0 0 0 0 0
|
||||||
|
add 32 0 1 1 2 0
|
||||||
|
add 32 0 2342234 3563456 5905690 0
|
||||||
|
add 32 0 254455 3453435 3707890 0
|
||||||
|
add 32 0 4294967295 0 4294967295 0
|
||||||
|
add 32 32 4294967295 1 0 1
|
||||||
|
add 32 32 4294967295 0 4294967295 0
|
||||||
|
add 64 64 18446744073709551615 1 0 1
|
||||||
|
add 64 64 18446744073709551615 0 18446744073709551615 0
|
||||||
|
add 96 96 79228162514264337593543950335 1 0 1
|
||||||
|
add 96 96 79228162514264337593543950335 0 79228162514264337593543950335 0
|
||||||
|
add 128 128 340282366920938463463374607431768211455 1 0 1
|
||||||
|
add 128 128 340282366920938463463374607431768211455 0 340282366920938463463374607431768211455 0
|
||||||
|
add 160 160 1461501637330902918203684832716283019655932542975 1 0 1
|
||||||
|
add 160 160 1461501637330902918203684832716283019655932542975 0 1461501637330902918203684832716283019655932542975 0
|
||||||
|
add 192 192 6277101735386680763835789423207666416102355444464034512895 1 0 1
|
||||||
|
add 192 192 6277101735386680763835789423207666416102355444464034512895 0 6277101735386680763835789423207666416102355444464034512895 0
|
||||||
|
|
||||||
|
|
||||||
|
# AddInt
|
||||||
|
|
||||||
|
# min_bits max_bits bits_per_int a b(int) index result carry
|
||||||
|
addint 32 0 32 0 0 0 0 0
|
||||||
|
addint 32 0 32 1000 2000 0 3000 0
|
||||||
|
addint 64 0 32 562342345 1423445 1 6113650284997065 0
|
||||||
|
addint 64 0 32 5342342455 3423553423 0 8765895878 0
|
||||||
|
addint 96 0 32 478895734 46756734 2 862509505820513898647477878 0
|
||||||
|
addint 128 0 32 27370506140054471803784984408165997441 24543 3 27372450636847059393422542757339093889 0
|
||||||
|
addint 128 128 32 340282366841711102552375003685868034945 2234543 3 177038656721750864719686733515479937 1
|
||||||
|
addint 160 160 32 1461501637330902918124457471805283415910032366465 3 3 158457126631793409034731674497 1
|
||||||
|
addint 192 0 32 6277101735386680763835789423128439055191355840718134336385 3354 1 6277101735386680763835789423128439055191355855123454647169 0
|
||||||
|
addint 192 192 32 6277101735386680763835789423128439055191355840718134336385 3354 5 4901876491607848387655079701569502248322251848964993 1
|
||||||
|
|
||||||
|
addint 64 0 64 0 0 0 0 0
|
||||||
|
addint 64 0 64 5342342 345534234 0 350876576 0
|
||||||
|
addint 64 0 64 5342342455 34235534234 0 39577876689 0
|
||||||
|
addint 64 64 64 18446744073709550615 2000 0 999 1
|
||||||
|
addint 128 0 64 42895062544824211012058135 3453234 0 42895062544824211015511369 0
|
||||||
|
addint 128 0 64 42895062544824211012058135 456234234 1 8458931214807741031021280279 0
|
||||||
|
addint 128 128 64 340282366920938426569886460012664978455 45623 1 804702316727431770143767 1
|
||||||
|
addint 192 192 64 6277101735386680763835789423207666379208867297044931279895 45623234 1 841563227924816702308613143 1
|
||||||
|
addint 192 192 64 6277101735386679588840776445207152040176347835149297122327 45623234 2 15523607057094857017675614218510090830281178135 1
|
||||||
|
addint 192 192 64 6277101735386680763835789423207666416102355444464034512895 1 0 0 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# AddTwoInts
|
||||||
|
# a the value
|
||||||
|
# c lower word
|
||||||
|
# b higher word
|
||||||
|
# index - index of the lower (c) word
|
||||||
|
# if there is a carry the result is skipped
|
||||||
|
|
||||||
|
# min_bits max_bits bits_per_int a b(int) c(int) index result carry
|
||||||
|
addtwoints 64 0 32 0 0 0 0 0 0
|
||||||
|
addtwoints 64 0 32 23542345 3453245 2356252356 0 14831576719870221 0
|
||||||
|
addtwoints 64 64 32 4563456879824345332 3453245255 3673623543 0 0 1
|
||||||
|
addtwoints 96 0 32 345345634564352344231 1231354534 345324551 1 22714482299528678798871855271 0
|
||||||
|
addtwoints 96 96 32 33333336690445123453645645123 4241542514 145235414 1 0 1
|
||||||
|
addtwoints 128 0 32 921345787234870984751756 2356245656 3423623455 2 186681013820253010515426931265335245452 0
|
||||||
|
addtwoints 128 128 32 259817508127340892734075234234345345346 3452345324 452354345 2 0 1
|
||||||
|
addtwoints 160 0 32 458674036702857083457018457034 435236456 1451234242 1 466702732224470435083940719562 0
|
||||||
|
addtwoints 160 0 32 258672084570198475012875019876674534523452543562 935245345 736765636 3 576919584276960743542382023227664277469907669578 0
|
||||||
|
addtwoints 192 0 32 2398670187501982374012837086745045 3253453245 234567536 4 4754927244626858434362642830810490464530603685767816794581 0
|
||||||
|
addtwoints 192 192 32 1734564564356435667546738087098769876387468736123143453646 3456345245 3256347435 4 0 1
|
||||||
|
|
||||||
|
|
||||||
|
addtwoints 128 0 64 0 0 0 0 0 0
|
||||||
|
addtwoints 128 0 64 14513452345 234512412345 8473567534 0 4325990452636459442359440119399 0
|
||||||
|
addtwoints 128 128 64 325434534534536347567567356714513452345 4324546234512412345 8473567534 0 0 1
|
||||||
|
addtwoints 192 0 64 8786356223462562562561234 4356879827345 34745638455 1 1482569380039046311960318103044992688410168990618834 0
|
||||||
|
addtwoints 192 0 64 875687458745872039847234234048572306857602 12341234356 3472568734534 1 4199505313073142510985676024483326499863441546882 0
|
||||||
|
addtwoints 192 192 64 6234554767823878635622346242564564564564564564562562561234 457644356879827345 34844576655 1 0 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
424
tests/uinttest.cpp
Normal file
424
tests/uinttest.cpp
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "uinttest.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::set_file_name(const std::string & f)
|
||||||
|
{
|
||||||
|
file_name = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::read_uint(uuint & result)
|
||||||
|
{
|
||||||
|
UInt<1> temp;
|
||||||
|
|
||||||
|
int c = temp.FromString(pline, 10, &pline);
|
||||||
|
|
||||||
|
result = temp.ToUInt();
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
std::cerr << " carry from reading uint" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::read_uint(UInt<type_size> & result)
|
||||||
|
{
|
||||||
|
int c = result.FromString(pline, 10, &pline);
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
std::cerr << " carry from UInt<>::FromString()" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_minmax_bits(int type_size)
|
||||||
|
{
|
||||||
|
uuint min_bits;
|
||||||
|
uuint max_bits;
|
||||||
|
|
||||||
|
read_uint(min_bits);
|
||||||
|
read_uint(max_bits);
|
||||||
|
|
||||||
|
if( min_bits != 0 && type_size * TTMATH_BITS_PER_UINT < (unsigned int)min_bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( max_bits != 0 && type_size * TTMATH_BITS_PER_UINT > (unsigned int)max_bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_minmax_bits_bitperint(int type_size)
|
||||||
|
{
|
||||||
|
if( !check_minmax_bits(type_size) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uuint bits;
|
||||||
|
|
||||||
|
read_uint(bits);
|
||||||
|
|
||||||
|
if( TTMATH_BITS_PER_UINT != bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_end()
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
|
||||||
|
if( *pline!='#' && *pline!= 0 )
|
||||||
|
{
|
||||||
|
std::cerr << "syntax error" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::check_result_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if( new_carry != carry )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect carry: " << new_carry << " (expected: " << carry << ")" << std::endl;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( new_result != result )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect result: " << new_result << " (expected: " << result << ")" << std::endl;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::check_result_or_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry)
|
||||||
|
{
|
||||||
|
if( new_carry != carry )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect carry: " << new_carry << " (expected: " << carry << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( new_carry == 1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( new_result != result )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect result: " << new_result << " (expected: " << result << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_add()
|
||||||
|
{
|
||||||
|
UInt<type_size> a,b,result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
uuint carry;
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] Add<" << type_size << ">: ";
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.Add(b);
|
||||||
|
|
||||||
|
if( check_result_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_addint()
|
||||||
|
{
|
||||||
|
UInt<type_size> a, result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits_bitperint(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
uuint b, index, carry;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(index);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] AddInt<" << type_size << ">: ";
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.AddInt(b, index);
|
||||||
|
|
||||||
|
if( check_result_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_addtwoints()
|
||||||
|
{
|
||||||
|
UInt<type_size> a, result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits_bitperint(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] AddTwoInts<" << type_size << ">: ";
|
||||||
|
|
||||||
|
uuint b, c, index, carry;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(c);
|
||||||
|
read_uint(index);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( index >= type_size - 1 )
|
||||||
|
{
|
||||||
|
std::cerr << "index too large" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.AddTwoInts(b, c, index);
|
||||||
|
|
||||||
|
if( check_result_or_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UIntTest::upper_char(int c)
|
||||||
|
{
|
||||||
|
if( c>='a' && c<='z' )
|
||||||
|
return c - 'a' + 'A';
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::is_white(int c)
|
||||||
|
{
|
||||||
|
if( c==' ' || c=='\t' || c==13 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::skip_white_characters()
|
||||||
|
{
|
||||||
|
while( is_white(*pline) )
|
||||||
|
++pline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::read_method()
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
|
||||||
|
if( *pline == '#' )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
method.clear();
|
||||||
|
|
||||||
|
for(int c = upper_char(*pline) ; c>='A'&& c<='Z' ; c = upper_char(*pline) )
|
||||||
|
{
|
||||||
|
method += c;
|
||||||
|
++pline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( method.empty() )
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
if( *pline == 0 )
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << '[' << row << "] ";
|
||||||
|
std::cerr << "syntax error" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::test_method()
|
||||||
|
{
|
||||||
|
const char * p = pline;
|
||||||
|
|
||||||
|
if( method == "ADD" )
|
||||||
|
{
|
||||||
|
pline = p; test_add<1>();
|
||||||
|
pline = p; test_add<2>();
|
||||||
|
pline = p; test_add<3>();
|
||||||
|
pline = p; test_add<4>();
|
||||||
|
pline = p; test_add<5>();
|
||||||
|
pline = p; test_add<6>();
|
||||||
|
pline = p; test_add<7>();
|
||||||
|
pline = p; test_add<8>();
|
||||||
|
pline = p; test_add<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( method == "ADDINT" )
|
||||||
|
{
|
||||||
|
pline = p; test_addint<1>();
|
||||||
|
pline = p; test_addint<2>();
|
||||||
|
pline = p; test_addint<3>();
|
||||||
|
pline = p; test_addint<4>();
|
||||||
|
pline = p; test_addint<5>();
|
||||||
|
pline = p; test_addint<6>();
|
||||||
|
pline = p; test_addint<7>();
|
||||||
|
pline = p; test_addint<8>();
|
||||||
|
pline = p; test_addint<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( method == "ADDTWOINTS" )
|
||||||
|
{
|
||||||
|
pline = p; test_addtwoints<1>();
|
||||||
|
pline = p; test_addtwoints<2>();
|
||||||
|
pline = p; test_addtwoints<3>();
|
||||||
|
pline = p; test_addtwoints<4>();
|
||||||
|
pline = p; test_addtwoints<5>();
|
||||||
|
pline = p; test_addtwoints<6>();
|
||||||
|
pline = p; test_addtwoints<7>();
|
||||||
|
pline = p; test_addtwoints<8>();
|
||||||
|
pline = p; test_addtwoints<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << '[' << row << "] ";
|
||||||
|
std::cerr << "method " << method << " is not supported" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_line()
|
||||||
|
{
|
||||||
|
std::getline(file, line);
|
||||||
|
|
||||||
|
pline = line.c_str();
|
||||||
|
|
||||||
|
if( read_method() )
|
||||||
|
test_method();
|
||||||
|
|
||||||
|
|
||||||
|
if( file.eof() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::go()
|
||||||
|
{
|
||||||
|
file.open(file_name.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
if( !file )
|
||||||
|
{
|
||||||
|
std::cerr << "I can't open the input file" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
row = 1;
|
||||||
|
|
||||||
|
while( check_line() )
|
||||||
|
++row;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
105
tests/uinttest.h
Normal file
105
tests/uinttest.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef headerfileuinttest
|
||||||
|
#define headerfileuinttest
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <ttmath/ttmath.h>
|
||||||
|
|
||||||
|
using namespace ttmath;
|
||||||
|
typedef ttmath::uint uuint;
|
||||||
|
|
||||||
|
|
||||||
|
class UIntTest
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string file_name;
|
||||||
|
|
||||||
|
// current line from the file
|
||||||
|
std::string line;
|
||||||
|
const char * pline;
|
||||||
|
|
||||||
|
std::ifstream file;
|
||||||
|
|
||||||
|
|
||||||
|
std::string method;
|
||||||
|
|
||||||
|
int row;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set_file_name(const std::string & f);
|
||||||
|
|
||||||
|
void go();
|
||||||
|
|
||||||
|
bool read_uint(uuint & result);
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool read_uint(UInt<type_size> & result);
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size> void test_add();
|
||||||
|
template<uuint type_size> void test_addint();
|
||||||
|
template<uuint type_size> void test_addtwoints();
|
||||||
|
|
||||||
|
template<uuint type_size> bool check_result_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry);
|
||||||
|
|
||||||
|
template<uuint type_size> bool check_result_or_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry);
|
||||||
|
|
||||||
|
int upper_char(int c);
|
||||||
|
bool is_white(int c);
|
||||||
|
void skip_white_characters();
|
||||||
|
bool read_method();
|
||||||
|
void test_method();
|
||||||
|
bool check_line();
|
||||||
|
|
||||||
|
bool check_minmax_bits(int type_size);
|
||||||
|
bool check_minmax_bits_bitperint(int type_size);
|
||||||
|
bool check_end();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1589
ttmath/ttmath.h
1589
ttmath/ttmath.h
File diff suppressed because it is too large
Load Diff
2970
ttmath/ttmathbig.h
2970
ttmath/ttmathbig.h
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* This file is a part of TTMath Mathematical Library
|
* This file is a part of TTMath Bignum Library
|
||||||
* and is distributed under the (new) BSD licence.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -208,7 +208,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds two value with a sign and returns carry
|
this method adds two value with a sign and returns a carry
|
||||||
|
|
||||||
we're using methods from the base class because values are stored with U2
|
we're using methods from the base class because values are stored with U2
|
||||||
we must only make the carry correction
|
we must only make the carry correction
|
||||||
@@ -468,6 +468,129 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
division this = this / ss2 (ss2 is int)
|
||||||
|
returned values:
|
||||||
|
0 - ok
|
||||||
|
1 - division by zero
|
||||||
|
|
||||||
|
for example: (result means 'this')
|
||||||
|
20 / 3 --> result: 6 remainder: 2
|
||||||
|
-20 / 3 --> result: -6 remainder: -2
|
||||||
|
20 / -3 --> result: -6 remainder: 2
|
||||||
|
-20 / -3 --> result: 6 remainder: -2
|
||||||
|
|
||||||
|
in other words: this(old) = ss2 * this(new)(result) + remainder
|
||||||
|
*/
|
||||||
|
uint DivInt(sint ss2, sint * remainder = 0)
|
||||||
|
{
|
||||||
|
bool ss1_is_sign, ss2_is_sign;
|
||||||
|
|
||||||
|
ss1_is_sign = IsSign();
|
||||||
|
|
||||||
|
/*
|
||||||
|
we don't have to test the carry from Abs as well as in Mul
|
||||||
|
*/
|
||||||
|
Abs();
|
||||||
|
|
||||||
|
if( ss2 < 0 )
|
||||||
|
{
|
||||||
|
ss2 = -ss2;
|
||||||
|
ss2_is_sign = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss2_is_sign = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint rem;
|
||||||
|
uint c = UInt<value_size>::DivInt((uint)ss2, &rem);
|
||||||
|
|
||||||
|
if( ss1_is_sign != ss2_is_sign )
|
||||||
|
SetSign();
|
||||||
|
|
||||||
|
if( remainder )
|
||||||
|
{
|
||||||
|
if( ss1_is_sign )
|
||||||
|
*remainder = -sint(rem);
|
||||||
|
else
|
||||||
|
*remainder = sint(rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint DivInt(sint ss2, sint & remainder)
|
||||||
|
{
|
||||||
|
return DivInt(ss2, &remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
power this = this ^ pow
|
||||||
|
this can be negative
|
||||||
|
pow is >= 0
|
||||||
|
*/
|
||||||
|
uint Pow2(const Int<value_size> & pow)
|
||||||
|
{
|
||||||
|
bool was_sign = IsSign();
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
if( was_sign )
|
||||||
|
c += Abs();
|
||||||
|
|
||||||
|
uint c_temp = UInt<value_size>::Pow(pow);
|
||||||
|
if( c_temp > 0 )
|
||||||
|
return c_temp; // c_temp can be: 0, 1 or 2
|
||||||
|
|
||||||
|
if( was_sign && (pow.table[0] & 1) == 1 )
|
||||||
|
// negative value to the power of odd number is negative
|
||||||
|
c += ChangeSign();
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
power this = this ^ pow
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments 0^0 or 0^(-something)
|
||||||
|
*/
|
||||||
|
uint Pow(Int<value_size> pow)
|
||||||
|
{
|
||||||
|
if( !pow.IsSign() )
|
||||||
|
return Pow2(pow);
|
||||||
|
|
||||||
|
if( UInt<value_size>::IsZero() )
|
||||||
|
// if 'pow' is negative then
|
||||||
|
// 'this' must be different from zero
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if( pow.ChangeSign() )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
Int<value_size> t(*this);
|
||||||
|
uint c_temp = t.Pow2(pow);
|
||||||
|
if( c_temp > 0 )
|
||||||
|
return c_temp;
|
||||||
|
|
||||||
|
UInt<value_size>::SetOne();
|
||||||
|
if( Div(t) )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -475,17 +598,14 @@ public:
|
|||||||
* convertion methods
|
* convertion methods
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method convert an UInt<another_size> type to this class
|
an auxiliary method for converting both from UInt and Int
|
||||||
|
|
||||||
this operation has mainly sense if the value from p
|
|
||||||
can be held in this type
|
|
||||||
|
|
||||||
it returns a carry if the value 'p' is too big
|
|
||||||
*/
|
*/
|
||||||
template<uint argument_size>
|
template<uint argument_size>
|
||||||
uint FromInt(const Int<argument_size> & p)
|
uint FromUIntOrInt(const UInt<argument_size> & p, bool UInt_type)
|
||||||
{
|
{
|
||||||
uint min_size = (value_size < argument_size)? value_size : argument_size;
|
uint min_size = (value_size < argument_size)? value_size : argument_size;
|
||||||
uint i;
|
uint i;
|
||||||
@@ -496,15 +616,25 @@ public:
|
|||||||
|
|
||||||
if( value_size > argument_size )
|
if( value_size > argument_size )
|
||||||
{
|
{
|
||||||
// 'this' is longer than 'p'
|
uint fill;
|
||||||
uint fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
|
|
||||||
|
|
||||||
|
if( UInt_type )
|
||||||
|
fill = 0;
|
||||||
|
else
|
||||||
|
fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)?
|
||||||
|
TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
|
// 'this' is longer than 'p'
|
||||||
for( ; i<value_size ; ++i)
|
for( ; i<value_size ; ++i)
|
||||||
UInt<value_size>::table[i] = fill;
|
UInt<value_size>::table[i] = fill;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
|
uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)?
|
||||||
|
TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
|
if( UInt_type && test!=0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
for( ; i<argument_size ; ++i)
|
for( ; i<argument_size ; ++i)
|
||||||
if( p.table[i] != test )
|
if( p.table[i] != test )
|
||||||
@@ -514,11 +644,27 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts an Int<another_size> type into this class
|
||||||
|
|
||||||
|
this operation has mainly sense if the value from p
|
||||||
|
can be held in this type
|
||||||
|
|
||||||
|
it returns a carry if the value 'p' is too big
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
uint FromInt(const Int<argument_size> & p)
|
||||||
|
{
|
||||||
|
return FromUIntOrInt(p, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the sint type into this class
|
this method converts the sint type into this class
|
||||||
*/
|
*/
|
||||||
void FromInt(sint value)
|
uint FromInt(sint value)
|
||||||
{
|
{
|
||||||
uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
|
uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
@@ -526,16 +672,46 @@ public:
|
|||||||
UInt<value_size>::table[i] = fill;
|
UInt<value_size>::table[i] = fill;
|
||||||
|
|
||||||
UInt<value_size>::table[0] = uint(value);
|
UInt<value_size>::table[0] = uint(value);
|
||||||
|
|
||||||
|
// there'll never be a carry here
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this operator converts an UInt<another_size> type to this class
|
this method converts UInt<another_size> into this class
|
||||||
|
|
||||||
it doesn't return a carry
|
|
||||||
*/
|
*/
|
||||||
template<uint argument_size>
|
template<uint argument_size>
|
||||||
Int<value_size> & operator=(const Int<argument_size> & p)
|
uint FromUInt(const UInt<argument_size> & p)
|
||||||
|
{
|
||||||
|
return FromUIntOrInt(p, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the uint type into this class
|
||||||
|
*/
|
||||||
|
uint FromUInt(uint value)
|
||||||
|
{
|
||||||
|
for(uint i=1 ; i<value_size ; ++i)
|
||||||
|
UInt<value_size>::table[i] = 0;
|
||||||
|
|
||||||
|
UInt<value_size>::table[0] = value;
|
||||||
|
|
||||||
|
// there can be a carry here when the size of this value is equal one word
|
||||||
|
// and the 'value' has the highest bit set
|
||||||
|
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the default assignment operator
|
||||||
|
*/
|
||||||
|
Int<value_size> & operator=(const Int<value_size> & p)
|
||||||
{
|
{
|
||||||
FromInt(p);
|
FromInt(p);
|
||||||
|
|
||||||
@@ -544,9 +720,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the default assignment operator
|
this operator converts an Int<another_size> type to this class
|
||||||
|
|
||||||
|
it doesn't return a carry
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(const Int<value_size> & p)
|
template<uint argument_size>
|
||||||
|
Int<value_size> & operator=(const Int<argument_size> & p)
|
||||||
{
|
{
|
||||||
FromInt(p);
|
FromInt(p);
|
||||||
|
|
||||||
@@ -575,11 +754,46 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the uint type to this class
|
a copy constructor
|
||||||
|
*/
|
||||||
|
Int(const Int<value_size> & u)
|
||||||
|
{
|
||||||
|
FromInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for copying from another types
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int(const Int<argument_size> & u)
|
||||||
|
{
|
||||||
|
// look that 'size' we still set as 'value_size' and not as u.value_size
|
||||||
|
FromInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this operator converts an UInt<another_size> type to this class
|
||||||
|
|
||||||
|
it doesn't return a carry
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int<value_size> & operator=(const UInt<argument_size> & p)
|
||||||
|
{
|
||||||
|
FromUInt(p);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the Uint type to this class
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(uint i)
|
Int<value_size> & operator=(uint i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(i);
|
FromUInt(i);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -590,10 +804,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int(uint i)
|
Int(uint i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(i);
|
FromUInt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for copying from another types
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int(const UInt<argument_size> & u)
|
||||||
|
{
|
||||||
|
// look that 'size' we still set as 'value_size' and not as u.value_size
|
||||||
|
FromUInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -630,7 +857,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(unsigned int i)
|
Int<value_size> & operator=(unsigned int i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(uint(i));
|
FromUInt(uint(i));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -644,7 +871,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int(unsigned int i)
|
Int(unsigned int i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(uint(i));
|
FromUInt(uint(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -659,6 +886,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for converting string to this class (with the base=10)
|
||||||
|
*/
|
||||||
|
Int(const wchar_t * s)
|
||||||
|
{
|
||||||
|
FromString(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
@@ -668,6 +904,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for converting a string to this class (with the base=10)
|
||||||
|
*/
|
||||||
|
Int(const std::wstring & s)
|
||||||
|
{
|
||||||
|
FromString( s.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a default constructor
|
a default constructor
|
||||||
|
|
||||||
@@ -678,18 +923,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
the copy constructor
|
|
||||||
*/
|
|
||||||
template<uint argument_size>
|
|
||||||
Int(const Int<argument_size> & u) : UInt<value_size>::size(value_size)
|
|
||||||
{
|
|
||||||
// look that 'size' we still set as 'value_size' and not as u.value_size
|
|
||||||
|
|
||||||
operator=(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the destructor
|
the destructor
|
||||||
*/
|
*/
|
||||||
@@ -697,6 +930,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns the lowest value from table with a sign
|
this method returns the lowest value from table with a sign
|
||||||
|
|
||||||
@@ -709,10 +943,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the value to a string with a base equal 'b'
|
an auxiliary method for converting to a string
|
||||||
*/
|
*/
|
||||||
void ToString(std::string & result, uint b = 10) const
|
template<class string_type>
|
||||||
|
void ToStringBase(string_type & result, uint b = 10) const
|
||||||
{
|
{
|
||||||
if( IsSign() )
|
if( IsSign() )
|
||||||
{
|
{
|
||||||
@@ -728,39 +965,74 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the value to a string with a base equal 'b'
|
||||||
|
*/
|
||||||
|
void ToString(std::string & result, uint b = 10) const
|
||||||
|
{
|
||||||
|
return ToStringBase(result, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts a string into its value
|
this method converts the value to a string with a base equal 'b'
|
||||||
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:
|
|
||||||
"-12" will be translated to -12
|
|
||||||
as well as:
|
|
||||||
"- 12foo" will be translated to 12 too
|
|
||||||
|
|
||||||
existing first white characters will be ommited
|
|
||||||
(between '-' and a first digit can be white characters too)
|
|
||||||
*/
|
*/
|
||||||
uint FromString(const char * s, uint b = 10)
|
void ToString(std::wstring & result, uint b = 10) const
|
||||||
|
{
|
||||||
|
return ToStringBase(result, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the value to a string with a base equal 'b'
|
||||||
|
*/
|
||||||
|
std::string ToString(uint b = 10) const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
ToStringBase(result, b);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the value to a string with a base equal 'b'
|
||||||
|
*/
|
||||||
|
std::wstring ToWString(uint b = 10) const
|
||||||
|
{
|
||||||
|
std::wstring result;
|
||||||
|
ToStringBase(result, b);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for converting from a string
|
||||||
|
*/
|
||||||
|
template<class char_type>
|
||||||
|
uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
|
||||||
{
|
{
|
||||||
bool is_sign = false;
|
bool is_sign = false;
|
||||||
|
|
||||||
UInt<value_size>::SkipWhiteCharacters(s);
|
Misc::SkipWhiteCharacters(s);
|
||||||
|
|
||||||
if( *s == '-' )
|
if( *s == '-' )
|
||||||
{
|
{
|
||||||
is_sign = true;
|
is_sign = true;
|
||||||
UInt<value_size>::SkipWhiteCharacters(++s);
|
Misc::SkipWhiteCharacters(++s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( *s == '+' )
|
if( *s == '+' )
|
||||||
{
|
{
|
||||||
UInt<value_size>::SkipWhiteCharacters(++s);
|
Misc::SkipWhiteCharacters(++s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( UInt<value_size>::FromString(s,b) )
|
if( UInt<value_size>::FromString(s,b,after_source,value_read) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( is_sign )
|
if( is_sign )
|
||||||
@@ -771,12 +1043,15 @@ public:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
the reference to mmin will be automatically converted to the reference
|
the reference to mmin will be automatically converted to the reference
|
||||||
to a UInt type
|
to UInt type
|
||||||
(this value can be equal mmin -- look at a description in ChangeSign())
|
(this value can be equal mmin -- look at a description in ChangeSign())
|
||||||
*/
|
*/
|
||||||
if( UInt<value_size>::operator>( mmin ) )
|
if( UInt<value_size>::operator>( mmin ) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it)
|
||||||
|
*/
|
||||||
ChangeSign();
|
ChangeSign();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -793,13 +1068,56 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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
|
||||||
|
|
||||||
|
string is ended with a non-digit value, for example:
|
||||||
|
"-12" will be translated to -12
|
||||||
|
as well as:
|
||||||
|
"- 12foo" will be translated to -12 too
|
||||||
|
|
||||||
|
existing first white characters will be ommited
|
||||||
|
(between '-' and a first digit can be white characters too)
|
||||||
|
|
||||||
|
after_source (if exists) is pointing at the end of the parsed string
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return FromStringBase(s, b, after_source, value_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts a string into its value
|
||||||
|
*/
|
||||||
|
uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
|
||||||
|
{
|
||||||
|
return FromStringBase(s, b, after_source, value_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
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 std::string & s, uint b = 10)
|
||||||
{
|
{
|
||||||
return FromString( s.c_str() );
|
return FromString( s.c_str(), b );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
uint FromString(const std::wstring & s, uint b = 10)
|
||||||
|
{
|
||||||
|
return FromString( s.c_str(), b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -814,6 +1132,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this operator converts a string into its value (with base = 10)
|
||||||
|
*/
|
||||||
|
Int<value_size> & operator=(const wchar_t * s)
|
||||||
|
{
|
||||||
|
FromString(s);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this operator converts a string into its value (with base = 10)
|
this operator converts a string into its value (with base = 10)
|
||||||
*/
|
*/
|
||||||
@@ -825,6 +1154,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this operator converts a string into its value (with base = 10)
|
||||||
|
*/
|
||||||
|
Int<value_size> & operator=(const std::wstring & s)
|
||||||
|
{
|
||||||
|
FromString( s.c_str() );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1104,9 +1442,15 @@ public:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for outputing to standard streams
|
||||||
|
*/
|
||||||
|
template<class ostream_type, class string_type>
|
||||||
|
static ostream_type & OutputToStream(ostream_type & s, const Int<value_size> & l)
|
||||||
{
|
{
|
||||||
std::string ss;
|
string_type ss;
|
||||||
|
|
||||||
l.ToString(ss);
|
l.ToString(ss);
|
||||||
s << ss;
|
s << ss;
|
||||||
@@ -1116,12 +1460,40 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
|
public:
|
||||||
{
|
|
||||||
std::string ss;
|
|
||||||
|
|
||||||
// char for operator>>
|
|
||||||
unsigned char z;
|
/*!
|
||||||
|
output to standard streams
|
||||||
|
*/
|
||||||
|
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
|
||||||
|
{
|
||||||
|
return OutputToStream<std::ostream, std::string>(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
output to standard streams
|
||||||
|
*/
|
||||||
|
friend std::wostream & operator<<(std::wostream & s, const Int<value_size> & l)
|
||||||
|
{
|
||||||
|
return OutputToStream<std::wostream, std::wstring>(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for converting from a string
|
||||||
|
*/
|
||||||
|
template<class istream_type, class string_type, class char_type>
|
||||||
|
static istream_type & InputFromStream(istream_type & s, Int<value_size> & l)
|
||||||
|
{
|
||||||
|
string_type ss;
|
||||||
|
|
||||||
|
// char or wchar_t for operator>>
|
||||||
|
char_type 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;
|
||||||
@@ -1133,10 +1505,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we're reading only digits (base=10)
|
// we're reading only digits (base=10)
|
||||||
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
|
while( s.good() && Misc::CharToDigit(z, 10)>=0 )
|
||||||
{
|
{
|
||||||
ss += z;
|
ss += z;
|
||||||
z = s.get();
|
z = static_cast<char_type>(s.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're leaving the last readed character
|
// we're leaving the last readed character
|
||||||
@@ -1148,9 +1520,28 @@ public:
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
input from standard streams
|
||||||
|
*/
|
||||||
|
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
|
||||||
|
{
|
||||||
|
return InputFromStream<std::istream, std::string, char>(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
input from standard streams
|
||||||
|
*/
|
||||||
|
friend std::wistream & operator>>(std::wistream & s, Int<value_size> & l)
|
||||||
|
{
|
||||||
|
return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
243
ttmath/ttmathmisc.h
Normal file
243
ttmath/ttmathmisc.h
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfilettmathmisc
|
||||||
|
#define headerfilettmathmisc
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmathmisc.h
|
||||||
|
\brief some helpful functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
some helpful functions
|
||||||
|
*/
|
||||||
|
class Misc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* AssignString(result, str)
|
||||||
|
* result = str
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result = str
|
||||||
|
*/
|
||||||
|
static void AssignString(std::string & result, const char * str)
|
||||||
|
{
|
||||||
|
result = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result = str
|
||||||
|
*/
|
||||||
|
static void AssignString(std::wstring & result, const char * str)
|
||||||
|
{
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
for( ; *str ; ++str )
|
||||||
|
result += *str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result = str
|
||||||
|
*/
|
||||||
|
static void AssignString(std::wstring & result, const std::string & str)
|
||||||
|
{
|
||||||
|
return AssignString(result, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result = str
|
||||||
|
*/
|
||||||
|
static void AssignString(std::string & result, const wchar_t * str)
|
||||||
|
{
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
for( ; *str ; ++str )
|
||||||
|
result += static_cast<char>(*str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result = str
|
||||||
|
*/
|
||||||
|
static void AssignString(std::string & result, const std::wstring & str)
|
||||||
|
{
|
||||||
|
return AssignString(result, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* AddString(result, str)
|
||||||
|
* result += str
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result += str
|
||||||
|
*/
|
||||||
|
static void AddString(std::string & result, const char * str)
|
||||||
|
{
|
||||||
|
result += str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
result += str
|
||||||
|
*/
|
||||||
|
static void AddString(std::wstring & result, const char * str)
|
||||||
|
{
|
||||||
|
for( ; *str ; ++str )
|
||||||
|
result += *str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this method omits any white characters from the string
|
||||||
|
char_type is char or wchar_t
|
||||||
|
*/
|
||||||
|
template<class char_type>
|
||||||
|
static void SkipWhiteCharacters(const char_type * & c)
|
||||||
|
{
|
||||||
|
// 13 is at the end in a DOS text file (\r\n)
|
||||||
|
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this static method converts one character into its value
|
||||||
|
|
||||||
|
for example:
|
||||||
|
1 -> 1
|
||||||
|
8 -> 8
|
||||||
|
A -> 10
|
||||||
|
f -> 15
|
||||||
|
|
||||||
|
this method don't check whether c is correct or not
|
||||||
|
*/
|
||||||
|
static uint CharToDigit(uint c)
|
||||||
|
{
|
||||||
|
if(c>='0' && c<='9')
|
||||||
|
return c-'0';
|
||||||
|
|
||||||
|
if(c>='a' && c<='z')
|
||||||
|
return c-'a'+10;
|
||||||
|
|
||||||
|
return c-'A'+10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method changes a character 'c' into its value
|
||||||
|
(if there can't be a correct value it returns -1)
|
||||||
|
|
||||||
|
for example:
|
||||||
|
c=2, base=10 -> function returns 2
|
||||||
|
c=A, base=10 -> function returns -1
|
||||||
|
c=A, base=16 -> function returns 10
|
||||||
|
*/
|
||||||
|
static sint CharToDigit(uint c, uint base)
|
||||||
|
{
|
||||||
|
if( c>='0' && c<='9' )
|
||||||
|
c=c-'0';
|
||||||
|
else
|
||||||
|
if( c>='a' && c<='z' )
|
||||||
|
c=c-'a'+10;
|
||||||
|
else
|
||||||
|
if( c>='A' && c<='Z' )
|
||||||
|
c=c-'A'+10;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
if( c >= base )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
return sint(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts a digit into a char
|
||||||
|
digit should be from <0,F>
|
||||||
|
(we don't have to get a base)
|
||||||
|
|
||||||
|
for example:
|
||||||
|
1 -> 1
|
||||||
|
8 -> 8
|
||||||
|
10 -> A
|
||||||
|
15 -> F
|
||||||
|
*/
|
||||||
|
static uint DigitToChar(uint digit)
|
||||||
|
{
|
||||||
|
if( digit < 10 )
|
||||||
|
return digit + '0';
|
||||||
|
|
||||||
|
return digit - 10 + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}; // struct Misc
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* This file is a part of TTMath Mathematical Library
|
* This file is a part of TTMath Mathematical Library
|
||||||
* and is distributed under the (new) BSD licence.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -44,12 +44,13 @@
|
|||||||
\brief Mathematic functions.
|
\brief Mathematic functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ttmathtypes.h"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "ttmathtypes.h"
|
||||||
|
#include "ttmathmisc.h"
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
@@ -73,6 +74,7 @@ public:
|
|||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
// name of a variable of a function
|
// name of a variable of a function
|
||||||
|
// internally we store variables and funcions as std::string (not std::wstring even when wide characters are used)
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
// number of parameters required by the function
|
// number of parameters required by the function
|
||||||
@@ -97,12 +99,12 @@ public:
|
|||||||
if 'can_be_digit' is true that means when the 'c' is a digit this
|
if 'can_be_digit' is true that means when the 'c' is a digit this
|
||||||
method returns true otherwise it returns false
|
method returns true otherwise it returns false
|
||||||
*/
|
*/
|
||||||
static bool CorrectCharacter(int c, bool can_be_digit)
|
static bool CorrectCharacter(wchar_t c, bool can_be_digit)
|
||||||
{
|
{
|
||||||
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( can_be_digit && (c>='0' && c<='9') )
|
if( can_be_digit && ((c>='0' && c<='9') || c=='_') )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -112,7 +114,8 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
this method returns true if the name can be as a name of an object
|
this method returns true if the name can be as a name of an object
|
||||||
*/
|
*/
|
||||||
static bool IsNameCorrect(const std::string & name)
|
template<class string_type>
|
||||||
|
static bool IsNameCorrect(const string_type & name)
|
||||||
{
|
{
|
||||||
if( name.empty() )
|
if( name.empty() )
|
||||||
return false;
|
return false;
|
||||||
@@ -120,7 +123,7 @@ public:
|
|||||||
if( !CorrectCharacter(name[0], false) )
|
if( !CorrectCharacter(name[0], false) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string::const_iterator i=name.begin();
|
typename string_type::const_iterator i = name.begin();
|
||||||
|
|
||||||
for(++i ; i!=name.end() ; ++i)
|
for(++i ; i!=name.end() ; ++i)
|
||||||
if( !CorrectCharacter(*i, true) )
|
if( !CorrectCharacter(*i, true) )
|
||||||
@@ -130,6 +133,37 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if such an object is defined (name exists)
|
||||||
|
*/
|
||||||
|
bool IsDefined(const std::string & name)
|
||||||
|
{
|
||||||
|
Iterator i = table.find(name);
|
||||||
|
|
||||||
|
if( i != table.end() )
|
||||||
|
// we have this object in our table
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if such an object is defined (name exists)
|
||||||
|
*/
|
||||||
|
bool IsDefined(const std::wstring & name)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
|
||||||
|
return IsDefined(str_tmp1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds one object (variable of function) into the table
|
this method adds one object (variable of function) into the table
|
||||||
*/
|
*/
|
||||||
@@ -150,6 +184,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds one object (variable of function) into the table
|
||||||
|
*/
|
||||||
|
ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
Misc::AssignString(str_tmp2, value);
|
||||||
|
|
||||||
|
return Add(str_tmp1, str_tmp2, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns 'true' if the table is empty
|
this method returns 'true' if the table is empty
|
||||||
*/
|
*/
|
||||||
@@ -207,6 +258,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method changes the value and the number of parameters for a specific object
|
||||||
|
*/
|
||||||
|
ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
Misc::AssignString(str_tmp2, value);
|
||||||
|
|
||||||
|
return EditValue(str_tmp1, str_tmp2, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method changes the name of a specific object
|
this method changes the name of a specific object
|
||||||
*/
|
*/
|
||||||
@@ -238,6 +306,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method changes the name of a specific object
|
||||||
|
*/
|
||||||
|
ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, old_name);
|
||||||
|
Misc::AssignString(str_tmp2, new_name);
|
||||||
|
|
||||||
|
return EditName(str_tmp1, str_tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method deletes an object
|
this method deletes an object
|
||||||
*/
|
*/
|
||||||
@@ -258,7 +343,23 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value of a specific object
|
this method deletes an object
|
||||||
|
*/
|
||||||
|
ErrorCode Delete(const std::wstring & name)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
|
||||||
|
return Delete(str_tmp1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method gets the value of a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||||
{
|
{
|
||||||
@@ -280,7 +381,25 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value of a specific object
|
this method gets the value of a specific object
|
||||||
|
*/
|
||||||
|
ErrorCode GetValue(const std::wstring & name, std::wstring & value)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
ErrorCode err = GetValue(str_tmp1, str_tmp2);
|
||||||
|
Misc::AssignString(value, str_tmp2);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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 std::string & name, const char ** value) const
|
||||||
@@ -303,7 +422,24 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value and the number of parameters
|
this method gets the value of a specific object
|
||||||
|
(this version is used for not copying the whole string)
|
||||||
|
*/
|
||||||
|
ErrorCode GetValue(const std::wstring & name, const char ** value)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
|
||||||
|
return GetValue(str_tmp1, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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 std::string & name, std::string & value, int * param) const
|
||||||
@@ -327,6 +463,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method gets the value and the number of parameters
|
||||||
|
of a specific object
|
||||||
|
*/
|
||||||
|
ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param);
|
||||||
|
Misc::AssignString(value, str_tmp2);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value and the number of parameters
|
this method sets the value and the number of parameters
|
||||||
of a specific object
|
of a specific object
|
||||||
@@ -353,6 +508,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets the value and the number of parameters
|
||||||
|
of a specific object
|
||||||
|
(this version is used for not copying the whole string
|
||||||
|
but in fact we make one copying during AssignString())
|
||||||
|
*/
|
||||||
|
ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param)
|
||||||
|
{
|
||||||
|
// we should check whether the name (in wide characters) are correct
|
||||||
|
// before calling AssignString() function
|
||||||
|
if( !IsNameCorrect(name) )
|
||||||
|
return err_incorrect_name;
|
||||||
|
|
||||||
|
Misc::AssignString(str_tmp1, name);
|
||||||
|
|
||||||
|
return GetValueAndParam(str_tmp1, value, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns a pointer into the table
|
this method returns a pointer into the table
|
||||||
*/
|
*/
|
||||||
@@ -365,6 +539,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
Table table;
|
Table table;
|
||||||
|
std::string str_tmp1, str_tmp2;
|
||||||
|
|
||||||
}; // end of class Objects
|
}; // end of class Objects
|
||||||
|
|
||||||
@@ -411,11 +586,11 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
default constructor
|
default constructor
|
||||||
default max size of the History's container is 10 items
|
default max size of the History's container is 15 items
|
||||||
*/
|
*/
|
||||||
History()
|
History()
|
||||||
{
|
{
|
||||||
buffer_max_size = 10;
|
buffer_max_size = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -472,10 +647,118 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this methods deletes an item
|
||||||
|
|
||||||
|
we assume that there is only one item with the 'key'
|
||||||
|
(this methods removes the first one)
|
||||||
|
*/
|
||||||
|
bool Remove(const ValueType & key)
|
||||||
|
{
|
||||||
|
typename buffer_type::iterator i = buffer.begin();
|
||||||
|
|
||||||
|
for( ; i != buffer.end() ; ++i )
|
||||||
|
{
|
||||||
|
if( i->key == key )
|
||||||
|
{
|
||||||
|
buffer.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // end of class History
|
}; // end of class History
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this is an auxiliary class used when calculating Gamma() or Factorial()
|
||||||
|
|
||||||
|
in multithreaded environment you can provide an object of this class to
|
||||||
|
the Gamma() or Factorial() function, e.g;
|
||||||
|
typedef Big<1, 3> MyBig;
|
||||||
|
MyBig x = 123456;
|
||||||
|
CGamma<MyBig> cgamma;
|
||||||
|
std::cout << Gamma(x, cgamma);
|
||||||
|
each thread should have its own CGamma<> object
|
||||||
|
|
||||||
|
in a single-thread environment a CGamma<> object is a static variable
|
||||||
|
in a second version of Gamma() and you don't have to explicitly use it, e.g.
|
||||||
|
typedef Big<1, 3> MyBig;
|
||||||
|
MyBig x = 123456;
|
||||||
|
std::cout << Gamma(x);
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
struct CGamma
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
this table holds factorials
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
6
|
||||||
|
24
|
||||||
|
120
|
||||||
|
720
|
||||||
|
.......
|
||||||
|
*/
|
||||||
|
std::vector<ValueType> fact;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this table holds Bernoulli numbers
|
||||||
|
1
|
||||||
|
-0.5
|
||||||
|
0.166666666666666666666666667
|
||||||
|
0
|
||||||
|
-0.0333333333333333333333333333
|
||||||
|
0
|
||||||
|
0.0238095238095238095238095238
|
||||||
|
0
|
||||||
|
-0.0333333333333333333333333333
|
||||||
|
0
|
||||||
|
0.075757575757575757575757576
|
||||||
|
.....
|
||||||
|
*/
|
||||||
|
std::vector<ValueType> bern;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
here we store some calculated values
|
||||||
|
(this is for speeding up, if the next argument of Gamma() or Factorial()
|
||||||
|
is in the 'history' then the result we are not calculating but simply
|
||||||
|
return from the 'history' object)
|
||||||
|
*/
|
||||||
|
History<ValueType> history;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method prepares some coefficients: factorials and Bernoulli numbers
|
||||||
|
stored in 'fact' and 'bern' objects
|
||||||
|
|
||||||
|
how many values should be depends on the size of the mantissa - if
|
||||||
|
the mantissa is larger then we must calculate more values
|
||||||
|
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
|
||||||
|
we have to calculate about 30 values (the size of fact and bern will be 30),
|
||||||
|
and for a 2048 bits mantissa we have to calculate 306 coefficients
|
||||||
|
|
||||||
|
you don't have to call this method, these coefficients will be automatically calculated
|
||||||
|
when they are needed
|
||||||
|
|
||||||
|
you must note that calculating these coefficients is a little time-consuming operation,
|
||||||
|
(especially when the mantissa is large) and first call to Gamma() or Factorial()
|
||||||
|
can take more time than next calls, and in the end this is the point when InitAll()
|
||||||
|
comes in handy: you can call this method somewhere at the beginning of your program
|
||||||
|
*/
|
||||||
|
void InitAll();
|
||||||
|
// definition is in ttmath.h
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
File diff suppressed because it is too large
Load Diff
250
ttmath/ttmaththreads.h
Normal file
250
ttmath/ttmaththreads.h
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef headerfilettmaththreads
|
||||||
|
#define headerfilettmaththreads
|
||||||
|
|
||||||
|
#include "ttmathtypes.h"
|
||||||
|
|
||||||
|
#ifdef TTMATH_WIN32_THREADS
|
||||||
|
#include <windows.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TTMATH_POSIX_THREADS
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmaththreads.h
|
||||||
|
\brief Some objects used in multithreads environment
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is a simple skeleton of a program in multithreads environment:
|
||||||
|
|
||||||
|
#define TTMATH_MULTITHREADS
|
||||||
|
#include<ttmath/ttmath.h>
|
||||||
|
|
||||||
|
TTMATH_MULTITHREADS_HELPER
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
[...]
|
||||||
|
}
|
||||||
|
|
||||||
|
make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file)
|
||||||
|
use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_WIN32_THREADS
|
||||||
|
|
||||||
|
/*
|
||||||
|
we use win32 threads
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||||
|
somewhere in *.cpp file
|
||||||
|
|
||||||
|
(at the moment in win32 this macro does nothing)
|
||||||
|
*/
|
||||||
|
#define TTMATH_MULTITHREADS_HELPER
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
objects of this class are used to synchronize
|
||||||
|
*/
|
||||||
|
class ThreadLock
|
||||||
|
{
|
||||||
|
HANDLE mutex_handle;
|
||||||
|
|
||||||
|
|
||||||
|
void CreateName(char * buffer) const
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable : 4996)
|
||||||
|
// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId());
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (default : 4996)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool Lock()
|
||||||
|
{
|
||||||
|
char buffer[50];
|
||||||
|
|
||||||
|
CreateName(buffer);
|
||||||
|
mutex_handle = CreateMutexA(0, false, buffer);
|
||||||
|
|
||||||
|
if( mutex_handle == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WaitForSingleObject(mutex_handle, INFINITE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ThreadLock()
|
||||||
|
{
|
||||||
|
mutex_handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~ThreadLock()
|
||||||
|
{
|
||||||
|
if( mutex_handle != 0 )
|
||||||
|
{
|
||||||
|
ReleaseMutex(mutex_handle);
|
||||||
|
CloseHandle(mutex_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #ifdef TTMATH_WIN32_THREADS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_POSIX_THREADS
|
||||||
|
|
||||||
|
/*
|
||||||
|
we use posix threads
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||||
|
somewhere in *.cpp file
|
||||||
|
(this macro defines a pthread_mutex_t object used by TTMath library)
|
||||||
|
*/
|
||||||
|
#define TTMATH_MULTITHREADS_HELPER \
|
||||||
|
namespace ttmath \
|
||||||
|
{ \
|
||||||
|
pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro
|
||||||
|
*/
|
||||||
|
extern pthread_mutex_t ttmath_mutex;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
objects of this class are used to synchronize
|
||||||
|
*/
|
||||||
|
class ThreadLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool Lock()
|
||||||
|
{
|
||||||
|
if( pthread_mutex_lock(&ttmath_mutex) != 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~ThreadLock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&ttmath_mutex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #ifdef TTMATH_POSIX_THREADS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||||
|
|
||||||
|
/*!
|
||||||
|
we don't use win32 and pthreads
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
#define TTMATH_MULTITHREADS_HELPER
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
objects of this class are used to synchronize
|
||||||
|
actually we don't synchronize, the method Lock() returns always 'false'
|
||||||
|
*/
|
||||||
|
class ThreadLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool Lock()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* This file is a part of TTMath Mathematical Library
|
* This file is a part of TTMath Bignum Library
|
||||||
* and is distributed under the (new) BSD licence.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -54,14 +54,18 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the version of the library
|
the version of the library
|
||||||
|
|
||||||
|
TTMATH_PRERELEASE_VER is either zero or one
|
||||||
|
if zero that means this is the release version of the library
|
||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 8
|
#define TTMATH_MINOR_VER 9
|
||||||
#define TTMATH_REVISION_VER 0
|
#define TTMATH_REVISION_VER 0
|
||||||
|
#define TTMATH_PRERELEASE_VER 0
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -79,7 +83,7 @@
|
|||||||
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
||||||
or by defining this macro in your code before using any header files of this library
|
or by defining this macro in your code before using any header files of this library
|
||||||
|
|
||||||
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set
|
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
|
||||||
*/
|
*/
|
||||||
#ifndef TTMATH_RELEASE
|
#ifndef TTMATH_RELEASE
|
||||||
#define TTMATH_DEBUG
|
#define TTMATH_DEBUG
|
||||||
@@ -108,6 +112,15 @@ namespace ttmath
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
|
||||||
|
*/
|
||||||
|
#if !defined _MSC_VER && !defined __GNUC__
|
||||||
|
#define TTMATH_NOASM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM32
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -116,6 +129,20 @@ 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
|
||||||
|
(64bit on a 32bit platforms)
|
||||||
|
|
||||||
|
although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long)
|
||||||
|
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
|
||||||
|
|
||||||
|
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
|
||||||
|
but only on a 32bit platform
|
||||||
|
*/
|
||||||
|
#ifdef TTMATH_NOASM
|
||||||
|
typedef unsigned long long int ulint;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
how many bits there are in the uint type
|
how many bits there are in the uint type
|
||||||
*/
|
*/
|
||||||
@@ -137,15 +164,37 @@ namespace ttmath
|
|||||||
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 128u
|
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this macro returns the number of machine words
|
||||||
|
capable to hold min_bits bits
|
||||||
|
e.g. TTMATH_BITS(128) returns 4
|
||||||
|
*/
|
||||||
|
#define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||||
*/
|
*/
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* in VC 'long' type has 32 bits, __int64 is VC extension */
|
||||||
|
typedef unsigned __int64 uint;
|
||||||
|
typedef signed __int64 sint;
|
||||||
|
#else
|
||||||
typedef unsigned long uint;
|
typedef unsigned long uint;
|
||||||
typedef signed long sint;
|
typedef signed long sint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
on 64bit platform we do not define ulint
|
||||||
|
sizeof(long long) is 8 (64bit) but we need 128bit
|
||||||
|
|
||||||
|
on 64 bit platform (when there is defined TTMATH_NOASM macro)
|
||||||
|
methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit
|
||||||
|
*/
|
||||||
|
//typedef unsigned long long int ulint;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
how many bits there are in the uint type
|
how many bits there are in the uint type
|
||||||
@@ -168,29 +217,31 @@ namespace ttmath
|
|||||||
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 64ul
|
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this macro returns the number of machine words
|
||||||
|
capable to hold min_bits bits
|
||||||
|
e.g. TTMATH_BITS(128) returns 2
|
||||||
|
*/
|
||||||
|
#define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC)
|
||||||
|
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||||
|
|
||||||
/*!
|
#if defined(_WIN32)
|
||||||
characters which represent the comma operator
|
#define TTMATH_WIN32_THREADS
|
||||||
|
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
||||||
|
#define TTMATH_POSIX_THREADS
|
||||||
|
#endif
|
||||||
|
|
||||||
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing
|
#endif
|
||||||
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
|
#endif
|
||||||
that means you can input values for example 1.2345 and 1,2345 as well
|
|
||||||
|
|
||||||
if you don't want it just put 0 there e.g.
|
|
||||||
#define TTMATH_COMMA_CHARACTER_2 0
|
|
||||||
then only TTMATH_COMMA_CHARACTER_1 will be used
|
|
||||||
|
|
||||||
don't put there any special character which is used by the parser
|
|
||||||
(for example a semicolon ';' shouldn't be there)
|
|
||||||
*/
|
|
||||||
#define TTMATH_COMMA_CHARACTER_1 '.'
|
|
||||||
#define TTMATH_COMMA_CHARACTER_2 ','
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -209,10 +260,59 @@ namespace ttmath
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this is a limit when calculating Karatsuba multiplication
|
||||||
|
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
|
||||||
|
the Karatsuba algorithm will use standard schoolbook multiplication
|
||||||
|
*/
|
||||||
|
#ifdef TTMATH_DEBUG_LOG
|
||||||
|
// if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler
|
||||||
|
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||||
|
#else
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||||
|
#else
|
||||||
|
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this is a special value used when calculating the Gamma(x) function
|
||||||
|
if x is greater than this value then the Gamma(x) will be calculated using
|
||||||
|
some kind of series
|
||||||
|
|
||||||
|
don't use smaller values than about 100
|
||||||
|
*/
|
||||||
|
#define TTMATH_GAMMA_BOUNDARY 2000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
lib type codes:
|
||||||
|
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||||
|
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||||
|
asm_vc_64 - with asm for VC (64 bit)
|
||||||
|
asm_gcc_64 - with asm for GCC (64 bit)
|
||||||
|
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||||
|
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||||
|
*/
|
||||||
|
enum LibTypeCode
|
||||||
|
{
|
||||||
|
asm_vc_32 = 0,
|
||||||
|
asm_gcc_32,
|
||||||
|
asm_vc_64,
|
||||||
|
asm_gcc_64,
|
||||||
|
no_asm_32,
|
||||||
|
no_asm_64
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
error codes
|
error codes
|
||||||
*/
|
*/
|
||||||
@@ -243,10 +343,132 @@ namespace ttmath
|
|||||||
err_object_exists,
|
err_object_exists,
|
||||||
err_unknown_object,
|
err_unknown_object,
|
||||||
err_still_calculating,
|
err_still_calculating,
|
||||||
err_too_big_factorial
|
err_in_short_form_used_function,
|
||||||
|
err_percent_from
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this struct is used when converting to/from a string
|
||||||
|
/temporarily only in Big::ToString() and Big::FromString()/
|
||||||
|
*/
|
||||||
|
struct Conv
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
base (radix) on which the value will be shown (or read)
|
||||||
|
default: 10
|
||||||
|
*/
|
||||||
|
uint base;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
used only in Big::ToString()
|
||||||
|
if true the value will be always shown in the scientific mode, e.g: 123e+30
|
||||||
|
default: false
|
||||||
|
*/
|
||||||
|
bool scient;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
used only in Big::ToString()
|
||||||
|
if scient is false then the value will be print in the scientific mode
|
||||||
|
only if the exponent is greater than scien_from
|
||||||
|
default: 15
|
||||||
|
*/
|
||||||
|
sint scient_from;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
|
||||||
|
and the result value is not an integer then we make an additional rounding
|
||||||
|
(after converting the last digit from the result is skipped)
|
||||||
|
default: true
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
Conv c;
|
||||||
|
c.base_round = false;
|
||||||
|
Big<1, 1> a = "0.1"; // decimal input
|
||||||
|
std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999
|
||||||
|
*/
|
||||||
|
bool base_round;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
used only in Big::ToString()
|
||||||
|
tells how many digits after comma are possible
|
||||||
|
default: -1 which means all digits are printed
|
||||||
|
|
||||||
|
set it to zero if you want integer value only
|
||||||
|
|
||||||
|
for example when the value is:
|
||||||
|
12.345678 and 'round' is 4
|
||||||
|
then the result will be
|
||||||
|
12.3457 (the last digit was rounded)
|
||||||
|
*/
|
||||||
|
sint round;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
if true that not mattered digits in the mantissa will be cut off
|
||||||
|
(zero characters at the end -- after the comma operator)
|
||||||
|
e.g. 1234,78000 will be: 1234,78
|
||||||
|
default: true
|
||||||
|
*/
|
||||||
|
bool trim_zeroes;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the main comma operator (used when reading and writing)
|
||||||
|
default is a dot '.'
|
||||||
|
*/
|
||||||
|
uint comma;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
additional comma operator (used only when reading)
|
||||||
|
if you don't want it just set it to zero
|
||||||
|
default is a comma ','
|
||||||
|
|
||||||
|
this allowes you to convert from a value:
|
||||||
|
123.45 as well as from 123,45
|
||||||
|
*/
|
||||||
|
uint comma2;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
it sets the character which is used for grouping
|
||||||
|
if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
|
||||||
|
|
||||||
|
if you don't want grouping just set it to zero (which is default)
|
||||||
|
*/
|
||||||
|
uint group;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
uint group_exp; // not implemented yet
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Conv()
|
||||||
|
{
|
||||||
|
// default values
|
||||||
|
base = 10;
|
||||||
|
scient = false;
|
||||||
|
scient_from = 15;
|
||||||
|
base_round = true;
|
||||||
|
round = -1;
|
||||||
|
trim_zeroes = true;
|
||||||
|
comma = '.';
|
||||||
|
comma2 = ',';
|
||||||
|
group = 0;
|
||||||
|
group_exp = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this simple class can be used in multithreading model
|
this simple class can be used in multithreading model
|
||||||
(you can write your own class derived from this one)
|
(you can write your own class derived from this one)
|
||||||
@@ -300,7 +522,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) 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)
|
||||||
|
|
||||||
@@ -320,7 +542,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:
|
||||||
|
|
||||||
@@ -348,11 +570,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) 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:
|
||||||
|
|
||||||
@@ -401,7 +623,24 @@ namespace ttmath
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_DEBUG_LOG
|
||||||
|
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
|
||||||
|
#define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout);
|
||||||
|
#define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len);
|
||||||
|
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len);
|
||||||
|
#else
|
||||||
|
#define TTMATH_LOG(msg)
|
||||||
|
#define TTMATH_LOGC(msg, carry)
|
||||||
|
#define TTMATH_VECTOR_LOG(msg, vector, len)
|
||||||
|
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
2846
ttmath/ttmathuint.h
2846
ttmath/ttmathuint.h
File diff suppressed because it is too large
Load Diff
@@ -1,943 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of TTMath Mathematical Library
|
|
||||||
* and is distributed under the (new) BSD licence.
|
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
|
||||||
* project may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file ttmathuint.h
|
|
||||||
\brief template class UInt<uint> for 64bit processors
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
|
||||||
{
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* basic mathematic functions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
in 64bit platforms we must define additional operators and contructors
|
|
||||||
in order to allow a user initializing the objects in this way:
|
|
||||||
UInt<...> type = 20;
|
|
||||||
or
|
|
||||||
UInt<...> type;
|
|
||||||
type = 30;
|
|
||||||
|
|
||||||
decimal constants such as 20, 30 etc. are integer literal of type int,
|
|
||||||
if the value is greater it can even be long int,
|
|
||||||
0 is an octal integer of type int
|
|
||||||
(ISO 14882 p2.13.1 Integer literals)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this operator converts the unsigned int type to this class
|
|
||||||
|
|
||||||
***this operator is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size> & UInt<value_size>::operator=(unsigned int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
a constructor for converting the unsigned int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size>::UInt(unsigned int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
an operator for converting the signed int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
|
|
||||||
look at the description of UInt::operator=(sint)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size> & UInt<value_size>::operator=(signed int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
a constructor for converting the signed int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
|
|
||||||
look at the description of UInt::operator=(sint)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size>::UInt(signed int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method copies the value stored in an another table
|
|
||||||
(warning: first values in temp_table are the highest words -- it's different
|
|
||||||
from our table)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
we copy as many words as it is possible
|
|
||||||
|
|
||||||
if temp_table_len is bigger than value_size we'll try to round
|
|
||||||
the lowest word from table depending on the last not used bit in temp_table
|
|
||||||
(this rounding isn't a perfect rounding -- look at the description below)
|
|
||||||
|
|
||||||
and if temp_table_len is smaller than value_size we'll clear the rest words
|
|
||||||
in the table
|
|
||||||
|
|
||||||
warning: we're using 'temp_table' as a pointer at 32bit words
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
void UInt<value_size>::SetFromTable(const unsigned int * temp_table, uint temp_table_len)
|
|
||||||
{
|
|
||||||
uint temp_table_index = 0;
|
|
||||||
sint i; // 'i' with a sign
|
|
||||||
|
|
||||||
for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
|
|
||||||
{
|
|
||||||
table[i] = uint(temp_table[ temp_table_index ]) << 32;
|
|
||||||
|
|
||||||
++temp_table_index;
|
|
||||||
|
|
||||||
if( temp_table_index<temp_table_len )
|
|
||||||
table[i] |= temp_table[ temp_table_index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// rounding mantissa
|
|
||||||
if( temp_table_index < temp_table_len )
|
|
||||||
{
|
|
||||||
if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
very simply rounding
|
|
||||||
if the bit from not used last word from temp_table is set to one
|
|
||||||
we're rouding the lowest word in the table
|
|
||||||
|
|
||||||
in fact there should be a normal addition but
|
|
||||||
we don't use Add() or AddTwoInts() because these methods
|
|
||||||
can set a carry and then there'll be a small problem
|
|
||||||
for optimization
|
|
||||||
*/
|
|
||||||
if( table[0] != TTMATH_UINT_MAX_VALUE )
|
|
||||||
++table[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleaning the rest of the mantissa
|
|
||||||
for( ; i >= 0 ; --i)
|
|
||||||
table[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adding ss2 to the this and adding carry if it's defined
|
|
||||||
(this = this + ss2 + c)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
|
||||||
function returns carry (1) (if it was)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
/*
|
|
||||||
this part should be compiled with gcc
|
|
||||||
*/
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"subq %%rsi, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"movq (%%rbx),%%rax \n"
|
|
||||||
"adcq (%%rdx),%%rax \n"
|
|
||||||
"movq %%rax,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
"movq %%rax, %%rsi \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=S" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adds one word (at a specific position)
|
|
||||||
and returns a carry (if it was)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
|
|
||||||
if we've got (value_size=3):
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30;
|
|
||||||
table[2] = 5;
|
|
||||||
and we call:
|
|
||||||
AddInt(2,1)
|
|
||||||
then it'll be:
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30 + 2;
|
|
||||||
table[2] = 5;
|
|
||||||
|
|
||||||
of course if there was a carry from table[3] it would be returned
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::AddInt(uint value, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq %%rsi, %%rdx \n"
|
|
||||||
"clc \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (value)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adds only two unsigned words to the existing value
|
|
||||||
and these words begin on the 'index' position
|
|
||||||
(it's used in the multiplication algorithm 2)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
|
||||||
x1 - lower word, x2 - higher word
|
|
||||||
|
|
||||||
for example if we've got value_size equal 4 and:
|
|
||||||
table[0] = 3
|
|
||||||
table[1] = 4
|
|
||||||
table[2] = 5
|
|
||||||
table[3] = 6
|
|
||||||
then let
|
|
||||||
x1 = 10
|
|
||||||
x2 = 20
|
|
||||||
and
|
|
||||||
index = 1
|
|
||||||
|
|
||||||
the result of this method will be:
|
|
||||||
table[0] = 3
|
|
||||||
table[1] = 4 + x1 = 14
|
|
||||||
table[2] = 5 + x2 = 25
|
|
||||||
table[3] = 6
|
|
||||||
|
|
||||||
and no carry at the end of table[3]
|
|
||||||
|
|
||||||
(of course if there was a carry in table[2](5+20) then
|
|
||||||
this carry would be passed to the table[3] etc.)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"addq %%rsi, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdi, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"dec %%rcx \n"
|
|
||||||
"dec %%rcx \n"
|
|
||||||
"jz 2f \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (x1), "D" (x2)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method's subtracting ss2 from the 'this' and subtracting
|
|
||||||
carry if it has been defined
|
|
||||||
(this = this - ss2 - c)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
|
||||||
function returns carry (1) (if it was)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"subq %%rsi, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"movq (%%rbx),%%rax \n"
|
|
||||||
"sbbq (%%rdx),%%rax \n"
|
|
||||||
"movq %%rax,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
"movq %%rax, %%rsi \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=S" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method subtracts one word (at a specific position)
|
|
||||||
and returns a carry (if it was)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
if we've got (value_size=3):
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30;
|
|
||||||
table[2] = 5;
|
|
||||||
and we call:
|
|
||||||
SubInt(2,1)
|
|
||||||
then it'll be:
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30 - 2;
|
|
||||||
table[2] = 5;
|
|
||||||
|
|
||||||
of course if there was a carry from table[3] it would be returned
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::SubInt(uint value, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq %%rsi, %%rdx \n"
|
|
||||||
"clc \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"sbbq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (value)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method moving once all bits into the left side
|
|
||||||
return value <- this <- C
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
the lowest bit will hold value of 'c' and
|
|
||||||
function returns the highest bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Rcl(uint c)
|
|
||||||
{
|
|
||||||
register sint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
|
|
||||||
"movq $0,%%rax \n"
|
|
||||||
"subq %%rdx,%%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"rclq $1,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx,%%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=d" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method moving once all bits into the right side
|
|
||||||
C -> *this -> return value
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
the highest bit will be held value of 'c' and
|
|
||||||
function returns the lowest bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Rcr(uint c)
|
|
||||||
{
|
|
||||||
register sint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"subq %%rdx, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
|
|
||||||
"rcrq $1,(%%rbx) \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx,%%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=d" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
this method returns the number of the highest set bit in one 32-bit word
|
|
||||||
if the 'x' is zero this method returns '-1'
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
|
||||||
{
|
|
||||||
register sint result;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
|
|
||||||
"bsrq %%rbx, %%rax \n"
|
|
||||||
"jnz 1f \n"
|
|
||||||
"movq $-1, %%rax \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
: "=a" (result)
|
|
||||||
: "b" (x)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method sets a special bit in the 'value'
|
|
||||||
and returns the result
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
bit is from <0,31>
|
|
||||||
|
|
||||||
e.g.
|
|
||||||
SetBitInWord(0,0) = 1
|
|
||||||
SetBitInWord(0,2) = 4
|
|
||||||
SetBitInWord(10, 8) = 266
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::SetBitInWord(uint value, uint bit)
|
|
||||||
{
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"btsq %%rbx,%%rax \n"
|
|
||||||
|
|
||||||
: "=a" (value)
|
|
||||||
: "0" (value), "b" (bit)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* Multiplication
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
multiplication: result2:result1 = a * b
|
|
||||||
result2 - higher word
|
|
||||||
result1 - lower word of the result
|
|
||||||
|
|
||||||
this methos never returns a carry
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
it is an auxiliary method for version two of the multiplication algorithm
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
we must use these temporary variables in order to inform the compilator
|
|
||||||
that value pointed with result1 and result2 has changed
|
|
||||||
|
|
||||||
this has no effect in visual studio but it's usefull when
|
|
||||||
using gcc and options like -O
|
|
||||||
*/
|
|
||||||
register uint result1_;
|
|
||||||
register uint result2_;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"mulq %%rdx \n"
|
|
||||||
|
|
||||||
: "=a" (result1_), "=d" (result2_)
|
|
||||||
: "0" (a), "1" (b)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
*result1 = result1_;
|
|
||||||
*result2 = result2_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* Division
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
|
||||||
r = a:b / c and rest - remainder
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
*
|
|
||||||
* WARNING:
|
|
||||||
* if r (one word) is too small for the result or c is equal zero
|
|
||||||
* there'll be a hardware interruption (0)
|
|
||||||
* and probably the end of your program
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
|
|
||||||
{
|
|
||||||
register uint r_;
|
|
||||||
register uint rest_;
|
|
||||||
/*
|
|
||||||
these variables have similar meaning like those in
|
|
||||||
the multiplication algorithm MulTwoWords
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"divq %%rcx \n"
|
|
||||||
|
|
||||||
: "=a" (r_), "=d" (rest_)
|
|
||||||
: "d" (a), "a" (b), "c" (c)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
*r = r_;
|
|
||||||
*rest = rest_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
992
ttmath/ttmathuint_noasm.h
Normal file
992
ttmath/ttmathuint_noasm.h
Normal file
@@ -0,0 +1,992 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfilettmathuint_noasm
|
||||||
|
#define headerfilettmathuint_noasm
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_NOASM
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmathuint_noasm.h
|
||||||
|
\brief template class UInt<uint> with methods without any assembler code
|
||||||
|
|
||||||
|
this file is included at the end of ttmathuint.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
returning the string represents the currect type of the library
|
||||||
|
we have following types:
|
||||||
|
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||||
|
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||||
|
asm_vc_64 - with asm for VC (64 bit)
|
||||||
|
asm_gcc_64 - with asm for GCC (64 bit)
|
||||||
|
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||||
|
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
const char * UInt<value_size>::LibTypeStr()
|
||||||
|
{
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
static const char info[] = "no_asm_32";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
static const char info[] = "no_asm_64";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
returning the currect type of the library
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
LibTypeCode UInt<value_size>::LibType()
|
||||||
|
{
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
LibTypeCode info = no_asm_32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
LibTypeCode info = no_asm_64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds two words together
|
||||||
|
returns carry
|
||||||
|
|
||||||
|
this method is created only when TTMATH_NOASM macro is defined
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adding ss2 to the this and adding carry if it's defined
|
||||||
|
(this = this + ss2 + c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Add", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
AddInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 + 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size )
|
||||||
|
|
||||||
|
|
||||||
|
c = AddTwoWords(table[index], value, 0, &table[index]);
|
||||||
|
|
||||||
|
for(i=index+1 ; i<value_size && c ; ++i)
|
||||||
|
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::AddInt", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds only two unsigned words to the existing value
|
||||||
|
and these words begin on the 'index' position
|
||||||
|
(it's used in the multiplication algorithm 2)
|
||||||
|
|
||||||
|
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
||||||
|
x1 - lower word, x2 - higher word
|
||||||
|
|
||||||
|
for example if we've got value_size equal 4 and:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4
|
||||||
|
table[2] = 5
|
||||||
|
table[3] = 6
|
||||||
|
then let
|
||||||
|
x1 = 10
|
||||||
|
x2 = 20
|
||||||
|
and
|
||||||
|
index = 1
|
||||||
|
|
||||||
|
the result of this method will be:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4 + x1 = 14
|
||||||
|
table[2] = 5 + x2 = 25
|
||||||
|
table[3] = 6
|
||||||
|
|
||||||
|
and no carry at the end of table[3]
|
||||||
|
|
||||||
|
(of course if there was a carry in table[2](5+20) then
|
||||||
|
this carry would be passed to the table[3] etc.)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size - 1 )
|
||||||
|
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::AddTwoInts", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this static method addes one vector to the other
|
||||||
|
'ss1' is larger in size or equal to 'ss2'
|
||||||
|
|
||||||
|
ss1 points to the first (larger) vector
|
||||||
|
ss2 points to the second vector
|
||||||
|
ss1_size - size of the ss1 (and size of the result too)
|
||||||
|
ss2_size - size of the ss2
|
||||||
|
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||||
|
|
||||||
|
Example: ss1_size is 5, ss2_size is 3
|
||||||
|
ss1: ss2: result (output):
|
||||||
|
5 1 5+1
|
||||||
|
4 3 4+3
|
||||||
|
2 7 2+7
|
||||||
|
6 6
|
||||||
|
9 9
|
||||||
|
of course the carry is propagated and will be returned from the last item
|
||||||
|
(this method is used by the Karatsuba multiplication algorithm)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||||
|
{
|
||||||
|
uint i, c = 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||||
|
|
||||||
|
for(i=0 ; i<ss2_size ; ++i)
|
||||||
|
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||||
|
|
||||||
|
for( ; i<ss1_size ; ++i)
|
||||||
|
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||||
|
|
||||||
|
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method subtractes one word from the other
|
||||||
|
returns carry
|
||||||
|
|
||||||
|
this method is created only when TTMATH_NOASM macro is defined
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
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 method's subtracting ss2 from the 'this' and subtracting
|
||||||
|
carry if it has been defined
|
||||||
|
(this = this - ss2 - c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Sub", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method subtracts one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
SubInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 - 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size )
|
||||||
|
|
||||||
|
|
||||||
|
c = SubTwoWords(table[index], value, 0, &table[index]);
|
||||||
|
|
||||||
|
for(i=index+1 ; i<value_size && c ; ++i)
|
||||||
|
c = SubTwoWords(table[i], 0, c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::SubInt", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this static method subtractes one vector from the other
|
||||||
|
'ss1' is larger in size or equal to 'ss2'
|
||||||
|
|
||||||
|
ss1 points to the first (larger) vector
|
||||||
|
ss2 points to the second vector
|
||||||
|
ss1_size - size of the ss1 (and size of the result too)
|
||||||
|
ss2_size - size of the ss2
|
||||||
|
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||||
|
|
||||||
|
Example: ss1_size is 5, ss2_size is 3
|
||||||
|
ss1: ss2: result (output):
|
||||||
|
5 1 5-1
|
||||||
|
4 3 4-3
|
||||||
|
2 7 2-7
|
||||||
|
6 6-1 (the borrow from previous item)
|
||||||
|
9 9
|
||||||
|
return (carry): 0
|
||||||
|
of course the carry (borrow) is propagated and will be returned from the last item
|
||||||
|
(this method is used by the Karatsuba multiplication algorithm)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||||
|
{
|
||||||
|
uint i, c = 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||||
|
|
||||||
|
for(i=0 ; i<ss2_size ; ++i)
|
||||||
|
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||||
|
|
||||||
|
for( ; i<ss1_size ; ++i)
|
||||||
|
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||||
|
|
||||||
|
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2_one(uint c)
|
||||||
|
{
|
||||||
|
uint i, new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = 1;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
{
|
||||||
|
new_c = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
table[i] = (table[i] << 1) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Rcl2_one", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
c -> this -> return value
|
||||||
|
|
||||||
|
the highest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2_one(uint c)
|
||||||
|
{
|
||||||
|
sint i; // signed i
|
||||||
|
uint new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_HIGHEST_BIT;
|
||||||
|
|
||||||
|
for(i=sint(value_size)-1 ; i>=0 ; --i)
|
||||||
|
{
|
||||||
|
new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0;
|
||||||
|
table[i] = (table[i] >> 1) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Rcr2_one", c)
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint move = TTMATH_BITS_PER_UINT - bits;
|
||||||
|
uint i, new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_MAX_VALUE >> move;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
{
|
||||||
|
new_c = table[i] >> move;
|
||||||
|
table[i] = (table[i] << bits) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Rcl2", c)
|
||||||
|
|
||||||
|
return (c & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
C -> this -> return value
|
||||||
|
|
||||||
|
the highest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint move = TTMATH_BITS_PER_UINT - bits;
|
||||||
|
sint i; // signed
|
||||||
|
uint new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_MAX_VALUE << move;
|
||||||
|
|
||||||
|
for(i=value_size-1 ; i>=0 ; --i)
|
||||||
|
{
|
||||||
|
new_c = table[i] << move;
|
||||||
|
table[i] = (table[i] >> bits) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOGC("UInt::Rcr2", c)
|
||||||
|
|
||||||
|
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns the number of the highest set bit in x
|
||||||
|
if the 'x' is zero this method returns '-1'
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||||
|
{
|
||||||
|
if( x == 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint bit = TTMATH_BITS_PER_UINT - 1;
|
||||||
|
|
||||||
|
while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 )
|
||||||
|
{
|
||||||
|
x = x << 1;
|
||||||
|
--bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets a special bit in the 'value'
|
||||||
|
and returns the last state of the bit (zero or one)
|
||||||
|
|
||||||
|
bit is from <0,TTMATH_BITS_PER_UINT-1>
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
uint x = 100;
|
||||||
|
uint bit = SetBitInWord(x, 3);
|
||||||
|
now: x = 108 and bit = 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint mask = 1;
|
||||||
|
|
||||||
|
if( bit > 0 )
|
||||||
|
mask = mask << bit;
|
||||||
|
|
||||||
|
uint last = value & mask;
|
||||||
|
value = value | mask;
|
||||||
|
|
||||||
|
return (last != 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Multiplication
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result_high:result_low = a * b
|
||||||
|
result_high - higher word of the result
|
||||||
|
result_low - lower word of the result
|
||||||
|
|
||||||
|
this methos never returns a carry
|
||||||
|
this method is used in the second version of the multiplication algorithms
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
|
||||||
|
{
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
/*
|
||||||
|
on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace
|
||||||
|
this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit
|
||||||
|
*/
|
||||||
|
|
||||||
|
union uint_
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint low; // 32 bits
|
||||||
|
uint high; // 32 bits
|
||||||
|
} u_;
|
||||||
|
|
||||||
|
ulint u; // 64 bits
|
||||||
|
} res;
|
||||||
|
|
||||||
|
res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits
|
||||||
|
|
||||||
|
*result_high = res.u_.high;
|
||||||
|
*result_low = res.u_.low;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
64 bits platforms
|
||||||
|
|
||||||
|
we don't have a native type which has 128 bits
|
||||||
|
then we're splitting 'a' and 'b' to 4 parts (high and low halves)
|
||||||
|
and using 4 multiplications (with additions and carry correctness)
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint_ a_;
|
||||||
|
uint_ b_;
|
||||||
|
uint_ res_high1, res_high2;
|
||||||
|
uint_ res_low1, res_low2;
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
|
||||||
|
/*
|
||||||
|
the multiplication is as follows (schoolbook algorithm with O(n^2) ):
|
||||||
|
|
||||||
|
32 bits 32 bits
|
||||||
|
|
||||||
|
+--------------------------------+
|
||||||
|
| a_.u_.high | a_.u_.low |
|
||||||
|
+--------------------------------+
|
||||||
|
| b_.u_.high | b_.u_.low |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
| res_high1.u | res_low1.u |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
| res_high2.u | res_low2.u |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
|
||||||
|
64 bits 64 bits
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
uint_ temp;
|
||||||
|
|
||||||
|
res_low1.u = uint(b_.u_.low) * uint(a_.u_.low);
|
||||||
|
|
||||||
|
temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high);
|
||||||
|
res_low1.u_.high = temp.u_.low;
|
||||||
|
res_high1.u_.low = temp.u_.high;
|
||||||
|
res_high1.u_.high = 0;
|
||||||
|
|
||||||
|
res_low2.u_.low = 0;
|
||||||
|
temp.u = uint(b_.u_.high) * uint(a_.u_.low);
|
||||||
|
res_low2.u_.high = temp.u_.low;
|
||||||
|
|
||||||
|
res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high);
|
||||||
|
|
||||||
|
uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u);
|
||||||
|
AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here
|
||||||
|
|
||||||
|
*result_high = res_high2.u;
|
||||||
|
*result_low = res_low2.u;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Division
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||||
|
r = a:b / c and rest - remainder
|
||||||
|
|
||||||
|
*
|
||||||
|
* WARNING:
|
||||||
|
* the c has to be suitably large for the result being keeped in one word,
|
||||||
|
* if c is equal zero there'll be a hardware interruption (0)
|
||||||
|
* and probably the end of your program
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
|
||||||
|
{
|
||||||
|
// (a < c ) for the result to be one word
|
||||||
|
TTMATH_ASSERT( c != 0 && a < c )
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint low; // 32 bits
|
||||||
|
uint high; // 32 bits
|
||||||
|
} u_;
|
||||||
|
|
||||||
|
ulint u; // 64 bits
|
||||||
|
} ab;
|
||||||
|
|
||||||
|
ab.u_.high = a;
|
||||||
|
ab.u_.low = b;
|
||||||
|
|
||||||
|
*r = uint(ab.u / c);
|
||||||
|
*rest = uint(ab.u % c);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint_ c_;
|
||||||
|
c_.u = c;
|
||||||
|
|
||||||
|
|
||||||
|
if( a == 0 )
|
||||||
|
{
|
||||||
|
*r = b / c;
|
||||||
|
*rest = b % c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( c_.u_.high == 0 )
|
||||||
|
{
|
||||||
|
// higher half of 'c' is zero
|
||||||
|
// then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c')
|
||||||
|
uint_ a_, b_, res_, temp1, temp2;
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
|
||||||
|
temp1.u_.high = a_.u_.low;
|
||||||
|
temp1.u_.low = b_.u_.high;
|
||||||
|
|
||||||
|
res_.u_.high = (unsigned int)(temp1.u / c);
|
||||||
|
temp2.u_.high = (unsigned int)(temp1.u % c);
|
||||||
|
temp2.u_.low = b_.u_.low;
|
||||||
|
|
||||||
|
res_.u_.low = (unsigned int)(temp2.u / c);
|
||||||
|
*rest = temp2.u % c;
|
||||||
|
|
||||||
|
*r = res_.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DivTwoWords2(a, b, c, r, rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method is available only on 64bit platforms
|
||||||
|
|
||||||
|
the same algorithm like the third division algorithm in ttmathuint.h
|
||||||
|
but now with the radix=2^32
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest)
|
||||||
|
{
|
||||||
|
// a is not zero
|
||||||
|
// c_.u_.high is not zero
|
||||||
|
|
||||||
|
uint_ a_, b_, c_, u_, q_;
|
||||||
|
unsigned int u3; // 32 bit
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
c_.u = c;
|
||||||
|
|
||||||
|
// normalizing
|
||||||
|
uint d = DivTwoWordsNormalize(a_, b_, c_);
|
||||||
|
|
||||||
|
// loop from j=1 to j=0
|
||||||
|
// the first step (for j=2) is skipped because our result is only in one word,
|
||||||
|
// (first 'q' were 0 and nothing would be changed)
|
||||||
|
u_.u_.high = a_.u_.high;
|
||||||
|
u_.u_.low = a_.u_.low;
|
||||||
|
u3 = b_.u_.high;
|
||||||
|
q_.u_.high = DivTwoWordsCalculate(u_, u3, c_);
|
||||||
|
MultiplySubtract(u_, u3, q_.u_.high, c_);
|
||||||
|
|
||||||
|
u_.u_.high = u_.u_.low;
|
||||||
|
u_.u_.low = u3;
|
||||||
|
u3 = b_.u_.low;
|
||||||
|
q_.u_.low = DivTwoWordsCalculate(u_, u3, c_);
|
||||||
|
MultiplySubtract(u_, u3, q_.u_.low, c_);
|
||||||
|
|
||||||
|
*r = q_.u;
|
||||||
|
|
||||||
|
// unnormalizing for the remainder
|
||||||
|
u_.u_.high = u_.u_.low;
|
||||||
|
u_.u_.low = u3;
|
||||||
|
*rest = DivTwoWordsUnnormalize(u_.u, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_)
|
||||||
|
{
|
||||||
|
uint d = 0;
|
||||||
|
|
||||||
|
for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
|
||||||
|
{
|
||||||
|
c_.u = c_.u << 1;
|
||||||
|
|
||||||
|
uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b'
|
||||||
|
|
||||||
|
b_.u = b_.u << 1;
|
||||||
|
a_.u = a_.u << 1; // carry bits from 'a' are simply skipped
|
||||||
|
|
||||||
|
if( bc )
|
||||||
|
a_.u = a_.u | 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d)
|
||||||
|
{
|
||||||
|
if( d == 0 )
|
||||||
|
return u;
|
||||||
|
|
||||||
|
u = u >> d;
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
unsigned int UInt<value_size>::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_)
|
||||||
|
{
|
||||||
|
bool next_test;
|
||||||
|
uint_ qp_, rp_, temp_;
|
||||||
|
|
||||||
|
qp_.u = u_.u / uint(v_.u_.high);
|
||||||
|
rp_.u = u_.u % uint(v_.u_.high);
|
||||||
|
|
||||||
|
TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 )
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bool decrease = false;
|
||||||
|
|
||||||
|
if( qp_.u_.high == 1 )
|
||||||
|
decrease = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp_.u_.high = rp_.u_.low;
|
||||||
|
temp_.u_.low = u3;
|
||||||
|
|
||||||
|
if( qp_.u * uint(v_.u_.low) > temp_.u )
|
||||||
|
decrease = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_test = false;
|
||||||
|
|
||||||
|
if( decrease )
|
||||||
|
{
|
||||||
|
--qp_.u;
|
||||||
|
rp_.u += v_.u_.high;
|
||||||
|
|
||||||
|
if( rp_.u_.high == 0 )
|
||||||
|
next_test = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( next_test );
|
||||||
|
|
||||||
|
return qp_.u_.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_)
|
||||||
|
{
|
||||||
|
uint_ temp_;
|
||||||
|
|
||||||
|
uint res_high;
|
||||||
|
uint res_low;
|
||||||
|
|
||||||
|
MulTwoWords(v_.u, q, &res_high, &res_low);
|
||||||
|
|
||||||
|
uint_ sub_res_high_;
|
||||||
|
uint_ sub_res_low_;
|
||||||
|
|
||||||
|
temp_.u_.high = u_.u_.low;
|
||||||
|
temp_.u_.low = u3;
|
||||||
|
|
||||||
|
uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u);
|
||||||
|
|
||||||
|
temp_.u_.high = 0;
|
||||||
|
temp_.u_.low = u_.u_.high;
|
||||||
|
c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u);
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
--q;
|
||||||
|
|
||||||
|
c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u);
|
||||||
|
AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
u_.u_.high = sub_res_high_.u_.low;
|
||||||
|
u_.u_.low = sub_res_low_.u_.high;
|
||||||
|
u3 = sub_res_low_.u_.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ifdef TTMATH_NOASM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1558
ttmath/ttmathuint_x86.h
Normal file
1558
ttmath/ttmathuint_x86.h
Normal file
File diff suppressed because it is too large
Load Diff
1173
ttmath/ttmathuint_x86_64.h
Normal file
1173
ttmath/ttmathuint_x86_64.h
Normal file
File diff suppressed because it is too large
Load Diff
548
ttmath/ttmathuint_x86_64_msvc.asm
Normal file
548
ttmath/ttmathuint_x86_64_msvc.asm
Normal file
@@ -0,0 +1,548 @@
|
|||||||
|
;
|
||||||
|
; This file is a part of TTMath Bignum Library
|
||||||
|
; and is distributed under the (new) BSD licence.
|
||||||
|
; Author: Christian Kaiser <chk@online.de>
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; Copyright (c) 2009, Christian Kaiser
|
||||||
|
; All rights reserved.
|
||||||
|
;
|
||||||
|
; Redistribution and use in source and binary forms, with or without
|
||||||
|
; modification, are permitted provided that the following conditions are met:
|
||||||
|
;
|
||||||
|
; * Redistributions of source code must retain the above copyright notice,
|
||||||
|
; this list of conditions and the following disclaimer.
|
||||||
|
;
|
||||||
|
; * Redistributions in binary form must reproduce the above copyright
|
||||||
|
; notice, this list of conditions and the following disclaimer in the
|
||||||
|
; documentation and/or other materials provided with the distribution.
|
||||||
|
;
|
||||||
|
; * Neither the name Christian Kaiser nor the names of contributors to this
|
||||||
|
; project may be used to endorse or promote products derived
|
||||||
|
; from this software without specific prior written permission.
|
||||||
|
;
|
||||||
|
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
; THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; compile with debug info: ml64.exe /Zd /Zi ttmathuint_x86_64_msvc.asm
|
||||||
|
; compile without debug info: ml64.exe ttmathuint_x86_64_msvc.asm
|
||||||
|
; this create ttmathuint_x86_64_msvc.obj file which can be linked with your program
|
||||||
|
;
|
||||||
|
|
||||||
|
PUBLIC ttmath_adc_x64
|
||||||
|
PUBLIC ttmath_addindexed_x64
|
||||||
|
PUBLIC ttmath_addindexed2_x64
|
||||||
|
PUBLIC ttmath_addvector_x64
|
||||||
|
|
||||||
|
PUBLIC ttmath_sbb_x64
|
||||||
|
PUBLIC ttmath_subindexed_x64
|
||||||
|
PUBLIC ttmath_subvector_x64
|
||||||
|
|
||||||
|
PUBLIC ttmath_rcl_x64
|
||||||
|
PUBLIC ttmath_rcr_x64
|
||||||
|
|
||||||
|
PUBLIC ttmath_rcl2_x64
|
||||||
|
PUBLIC ttmath_rcr2_x64
|
||||||
|
|
||||||
|
PUBLIC ttmath_div_x64
|
||||||
|
|
||||||
|
;
|
||||||
|
; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx
|
||||||
|
;
|
||||||
|
; "rax, rcx, rdx, r8-r11 are volatile."
|
||||||
|
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
.CODE
|
||||||
|
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_adc_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = p2
|
||||||
|
; r8 = nSize
|
||||||
|
; r9 = nCarry
|
||||||
|
|
||||||
|
xor rax, rax
|
||||||
|
xor r11, r11
|
||||||
|
sub rax, r9 ; sets CARRY if r9 != 0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
mov rax,qword ptr [rdx + r11 * 8]
|
||||||
|
adc qword ptr [rcx + r11 * 8], rax
|
||||||
|
lea r11, [r11+1]
|
||||||
|
dec r8
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
setc al
|
||||||
|
movzx rax, al
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_adc_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_addindexed_x64 PROC
|
||||||
|
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = nSize
|
||||||
|
; r8 = nPos
|
||||||
|
; r9 = nValue
|
||||||
|
|
||||||
|
xor rax, rax ; rax = result
|
||||||
|
sub rdx, r8 ; rdx = remaining count of uints
|
||||||
|
|
||||||
|
add qword ptr [rcx + r8 * 8], r9
|
||||||
|
jc next1
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
next1:
|
||||||
|
mov r9, 1
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
dec rdx
|
||||||
|
jz done_with_cy
|
||||||
|
lea r8, [r8+1]
|
||||||
|
add qword ptr [rcx + r8 * 8], r9
|
||||||
|
jc loop1
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
done_with_cy:
|
||||||
|
lea rax, [rax+1] ; rax = 1
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_addindexed_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_addindexed2_x64 PROC
|
||||||
|
|
||||||
|
; rcx = p1 (pointer)
|
||||||
|
; rdx = b (value size)
|
||||||
|
; r8 = nPos
|
||||||
|
; r9 = nValue1
|
||||||
|
; [esp+0x28] = nValue2
|
||||||
|
|
||||||
|
xor rax, rax ; return value
|
||||||
|
mov r11, rcx ; table
|
||||||
|
sub rdx, r8 ; rdx = remaining count of uints
|
||||||
|
mov r10, [esp+028h] ; r10 = nValue2
|
||||||
|
|
||||||
|
add qword ptr [r11 + r8 * 8], r9
|
||||||
|
lea r8, [r8+1]
|
||||||
|
lea rdx, [rdx-1]
|
||||||
|
adc qword ptr [r11 + r8 * 8], r10
|
||||||
|
jc next
|
||||||
|
ret
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
lea r8, [r8+1]
|
||||||
|
add qword ptr [r11 + r8 * 8], 1
|
||||||
|
jc next
|
||||||
|
ret
|
||||||
|
|
||||||
|
next:
|
||||||
|
dec rdx ; does not modify CY too...
|
||||||
|
jnz loop1
|
||||||
|
lea rax, [rax+1]
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_addindexed2_x64 ENDP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
ttmath_addvector_x64 PROC
|
||||||
|
; rcx = ss1
|
||||||
|
; rdx = ss2
|
||||||
|
; r8 = ss1_size
|
||||||
|
; r9 = ss2_size
|
||||||
|
; [esp+0x28] = result
|
||||||
|
|
||||||
|
mov r10, [esp+028h]
|
||||||
|
sub r8, r9
|
||||||
|
xor r11, r11 ; r11=0, cf=0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
mov rax, qword ptr [rcx + r11 * 8]
|
||||||
|
adc rax, qword ptr [rdx + r11 * 8]
|
||||||
|
mov qword ptr [r10 + r11 * 8], rax
|
||||||
|
inc r11
|
||||||
|
dec r9
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
adc r9, r9 ; r9 has the cf state
|
||||||
|
|
||||||
|
or r8, r8
|
||||||
|
jz done
|
||||||
|
|
||||||
|
neg r9 ; setting cf from r9
|
||||||
|
mov r9, 0 ; don't use xor here (cf is used)
|
||||||
|
loop2:
|
||||||
|
mov rax, qword ptr [rcx + r11 * 8]
|
||||||
|
adc rax, r9
|
||||||
|
mov qword ptr [r10 + r11 * 8], rax
|
||||||
|
inc r11
|
||||||
|
dec r8
|
||||||
|
jnz loop2
|
||||||
|
|
||||||
|
adc r8, r8
|
||||||
|
mov rax, r8
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
done:
|
||||||
|
mov rax, r9
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_addvector_x64 ENDP
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_sbb_x64 PROC
|
||||||
|
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = p2
|
||||||
|
; r8 = nCount
|
||||||
|
; r9 = nCarry
|
||||||
|
|
||||||
|
xor rax, rax
|
||||||
|
xor r11, r11
|
||||||
|
sub rax, r9 ; sets CARRY if r9 != 0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
mov rax,qword ptr [rdx + r11 * 8]
|
||||||
|
sbb qword ptr [rcx + r11 * 8], rax
|
||||||
|
lea r11, [r11+1]
|
||||||
|
dec r8
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
setc al
|
||||||
|
movzx rax, al
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_sbb_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_subindexed_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = nSize
|
||||||
|
; r8 = nPos
|
||||||
|
; r9 = nValue
|
||||||
|
|
||||||
|
sub rdx, r8 ; rdx = remaining count of uints
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
sub qword ptr [rcx + r8 * 8], r9
|
||||||
|
jnc done
|
||||||
|
|
||||||
|
lea r8, [r8+1]
|
||||||
|
mov r9, 1
|
||||||
|
dec rdx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
mov rax, 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
done:
|
||||||
|
xor rax, rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_subindexed_x64 ENDP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb'
|
||||||
|
|
||||||
|
ttmath_subvector_x64 PROC
|
||||||
|
; rcx = ss1
|
||||||
|
; rdx = ss2
|
||||||
|
; r8 = ss1_size
|
||||||
|
; r9 = ss2_size
|
||||||
|
; [esp+0x28] = result
|
||||||
|
|
||||||
|
mov r10, [esp+028h]
|
||||||
|
sub r8, r9
|
||||||
|
xor r11, r11 ; r11=0, cf=0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
mov rax, qword ptr [rcx + r11 * 8]
|
||||||
|
sbb rax, qword ptr [rdx + r11 * 8]
|
||||||
|
mov qword ptr [r10 + r11 * 8], rax
|
||||||
|
inc r11
|
||||||
|
dec r9
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
adc r9, r9 ; r9 has the cf state
|
||||||
|
|
||||||
|
or r8, r8
|
||||||
|
jz done
|
||||||
|
|
||||||
|
neg r9 ; setting cf from r9
|
||||||
|
mov r9, 0 ; don't use xor here (cf is used)
|
||||||
|
loop2:
|
||||||
|
mov rax, qword ptr [rcx + r11 * 8]
|
||||||
|
sbb rax, r9
|
||||||
|
mov qword ptr [r10 + r11 * 8], rax
|
||||||
|
inc r11
|
||||||
|
dec r8
|
||||||
|
jnz loop2
|
||||||
|
|
||||||
|
adc r8, r8
|
||||||
|
mov rax, r8
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
done:
|
||||||
|
mov rax, r9
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_subvector_x64 ENDP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_rcl_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = b
|
||||||
|
; r8 = nLowestBit
|
||||||
|
|
||||||
|
mov r11, rcx ; table
|
||||||
|
xor r10, r10
|
||||||
|
neg r8 ; CY set if r8 <> 0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
rcl qword ptr [r11 + r10 * 8], 1
|
||||||
|
lea r10, [r10+1]
|
||||||
|
dec rdx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
setc al
|
||||||
|
movzx rax, al
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_rcl_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_rcr_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = nSize
|
||||||
|
; r8 = nLowestBit
|
||||||
|
|
||||||
|
xor r10, r10
|
||||||
|
neg r8 ; CY set if r8 <> 0
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
rcr qword ptr -8[rcx + rdx * 8], 1
|
||||||
|
dec rdx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
setc al
|
||||||
|
movzx rax, al
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_rcr_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_div_x64 PROC
|
||||||
|
|
||||||
|
; rcx = &Hi
|
||||||
|
; rdx = &Lo
|
||||||
|
; r8 = nDiv
|
||||||
|
|
||||||
|
mov r11, rcx
|
||||||
|
mov r10, rdx
|
||||||
|
|
||||||
|
mov rdx, qword ptr [r11]
|
||||||
|
mov rax, qword ptr [r10]
|
||||||
|
div r8
|
||||||
|
mov qword ptr [r10], rdx ; remainder
|
||||||
|
mov qword ptr [r11], rax ; value
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_div_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_rcl2_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = nSize
|
||||||
|
; r8 = bits
|
||||||
|
; r9 = c
|
||||||
|
|
||||||
|
push rbx
|
||||||
|
|
||||||
|
mov r10, rcx ; r10 = p1
|
||||||
|
xor rax, rax
|
||||||
|
|
||||||
|
mov rcx, 64
|
||||||
|
sub rcx, r8
|
||||||
|
|
||||||
|
mov r11, -1
|
||||||
|
shr r11, cl ; r11 = mask
|
||||||
|
|
||||||
|
mov rcx, r8 ; rcx = count of bits
|
||||||
|
|
||||||
|
mov rbx, rax ; rbx = old value = 0
|
||||||
|
or r9, r9
|
||||||
|
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||||
|
|
||||||
|
mov r9, rax ; r9 = index (0..nSize-1)
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
rol qword ptr [r10+r9*8], cl
|
||||||
|
mov rax, qword ptr [r10+r9*8]
|
||||||
|
and rax, r11
|
||||||
|
xor qword ptr [r10+r9*8], rax
|
||||||
|
or qword ptr [r10+r9*8], rbx
|
||||||
|
mov rbx, rax
|
||||||
|
|
||||||
|
lea r9, [r9+1]
|
||||||
|
dec rdx
|
||||||
|
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
and rax, 1
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_rcl2_x64 ENDP
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ALIGN 8
|
||||||
|
|
||||||
|
;----------------------------------------
|
||||||
|
|
||||||
|
ttmath_rcr2_x64 PROC
|
||||||
|
; rcx = p1
|
||||||
|
; rdx = nSize
|
||||||
|
; r8 = bits
|
||||||
|
; r9 = c
|
||||||
|
|
||||||
|
push rbx
|
||||||
|
mov r10, rcx ; r10 = p1
|
||||||
|
xor rax, rax
|
||||||
|
|
||||||
|
mov rcx, 64
|
||||||
|
sub rcx, r8
|
||||||
|
|
||||||
|
mov r11, -1
|
||||||
|
shl r11, cl ; r11 = mask
|
||||||
|
|
||||||
|
mov rcx, r8 ; rcx = count of bits
|
||||||
|
|
||||||
|
mov rbx, rax ; rbx = old value = 0
|
||||||
|
or r9, r9
|
||||||
|
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||||
|
|
||||||
|
mov r9, rdx ; r9 = index (0..nSize-1)
|
||||||
|
lea r9, [r9-1]
|
||||||
|
|
||||||
|
ALIGN 16
|
||||||
|
loop1:
|
||||||
|
ror qword ptr [r10+r9*8], cl
|
||||||
|
mov rax, qword ptr [r10+r9*8]
|
||||||
|
and rax, r11
|
||||||
|
xor qword ptr [r10+r9*8], rax
|
||||||
|
or qword ptr [r10+r9*8], rbx
|
||||||
|
mov rbx, rax
|
||||||
|
|
||||||
|
lea r9, [r9-1]
|
||||||
|
dec rdx
|
||||||
|
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
rol rax, 1
|
||||||
|
and rax, 1
|
||||||
|
pop rbx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ttmath_rcr2_x64 ENDP
|
||||||
|
|
||||||
|
END
|
Reference in New Issue
Block a user