added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x), Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/ changed: class Objects in ttmathobjects.h has been completely rewritten, we can change the names of user-defined variables or functions, and the names are case-sensitive now added: class History which is used in functions which take a lot of time during calculating e.g. Factorial(x) added: Tg(x) a wrapper for Tan(x) changed: CTan(x) is Cot(x) now added: Ctg(x) a wrapper for Cot(x) added: ATg(x) a wrapper for ATan(x) changed: ACTan(x) is ACot(x) now added: ACtg(x) a wrapper for ACot(x) added: UInt::PrintTable() (for debugging etc.) changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have been rewritten, now they have 128 32bit words (it's about 1232 valid decimal digits) fixed: previous values from Big::SetPi() Big::SetE() and Big::SetLn2() were not too much accurate (last 2-3 words were wrong) added: Big::SetLn10() (128 32bit words as well) added: macro: TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on 32bit platforms and 64ul on 64bit platforms (128/2=64) added: macros: TTMATH_PLATFORM32 and TTMATH_PLATFORM64 changed: a small optimisation in UInt::Mul2Big() added: at the end of ttmath.h: #include "ttmathparser.h" this is for convenience for a programmer, he can only use #include with ttmath.h even if he uses the parser added: to samples: big.cpp, parser.cpp fixed: constructor Big::Big(uint) - it was wrong because it was using the method Big::FromInt(sint) which could produce wrong values (if the 'uint' couldn't correctly be casted into the 'sint') added: Big::FromUInt(uint) changed: Big::FromInt(sint), Big::SetOne(), renamed Big::SetDotOne() into Big::Set05() (they are a little faster now) added: Big::operator=(uint) changed: in 64bit mode: constructor: Big::Big(int) added: in 64bit mode: constructor: Big::Big(unsigned int), operators: Big::operator=(signed int) and Big::operator=(unsigned int) (these operators and the constructor take a 32bit value) deleted: the word 'virtual' from destructors: UInt, Int, Big (types in this library are not projected to be base-classes for another ones derived from them) changed: UInt::operator=(uint), UInt::UInt(uint), Int::operator=(sint), Int::Int(sint) added: UInt::FromUInt(uint), UInt::operator=(sint), UInt::UInt(sint), Int::FromInt(sint), Int::operator=(uint), Int::Int(uint), Int::operator==(const Int<>&), Int::operator!=(const Int<>&) added: in 64bit mode: UInt::operator=(unsigned int), UInt::UInt(unsigned int), UInt::operator=(signed int), UInt::UInt(signed int) (these operators and the constructors take a 32bit value) added: in 64bit mode: Int::operator=(signed int), Int::Int(signed int), Int::operator=(unsigned int), Int::Int(unsigned int) (these operators and the constructors take a 32bit value) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@25 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
abb8f292ab
commit
837490e8b9
44
CHANGELOG
44
CHANGELOG
|
@ -1,9 +1,49 @@
|
|||
Version 0.8.0 (2007.03.28):
|
||||
* added: into the parser: SetFactorialMax()
|
||||
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
||||
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x),
|
||||
Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/
|
||||
* changed: class Objects in ttmathobjects.h has been completely rewritten,
|
||||
we can change the names of user-defined variables or functions, and the
|
||||
names are case-sensitive now
|
||||
* added: class History which is used in functions which take a lot of time
|
||||
during calculating e.g. Factorial(x)
|
||||
* added: Tg(x) a wrapper for Tan(x)
|
||||
* changed: CTan(x) is Cot(x) now
|
||||
* added: Ctg(x) a wrapper for Cot(x)
|
||||
* added: ATg(x) a wrapper for ATan(x)
|
||||
* changed: ACTan(x) is ACot(x) now
|
||||
* added: ACtg(x) a wrapper for ACot(x)
|
||||
* added: UInt::PrintTable() (for debugging etc.)
|
||||
* changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have
|
||||
been rewritten, now they have 128 32bit words (it's about 1232 valid
|
||||
decimal digits)
|
||||
* fixed: previous values from Big::SetPi() Big::SetE() and
|
||||
Big::SetLn2() were not too much accurate (last 2-3 words were wrong)
|
||||
* added: Big::SetLn10() (128 32bit words as well)
|
||||
* added: macro: TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on
|
||||
32bit platforms and 64ul on 64bit platforms (128/2=64)
|
||||
* added: macros: TTMATH_PLATFORM32 and TTMATH_PLATFORM64
|
||||
* changed: a small optimisation in UInt::Mul2Big()
|
||||
* added: at the end of ttmath.h: #include "ttmathparser.h"
|
||||
this is for convenience for a programmer, he can only use #include
|
||||
with ttmath.h even if he uses the parser
|
||||
* added: to samples: big.cpp, parser.cpp
|
||||
* added/changes/fixed: in copy-constructors and operators= in Int,
|
||||
Uint and Big (more info in the commit log)
|
||||
* renamed Big::SetDotOne() into Big::Set05()
|
||||
* changes: a few small optimisations in Big
|
||||
* deleted: the word 'virtual' from destructors: UInt, Int, Big
|
||||
(types in this library are not projected to be base-classes for
|
||||
another ones derived from them)
|
||||
* and more small changes (look at the commit log)
|
||||
|
||||
Version 0.7.2 (2007.03.09):
|
||||
* added: Big::Mod - the remainder from a division
|
||||
* added: Big::Sgn - the 'sign' from the value (-1,0,1)
|
||||
* added: global functions Mod and Sgn too
|
||||
* added: checking whether an user gives a correct value of a variable or function
|
||||
(user-defined variables/functions in the mathematical parser)
|
||||
* added: checking whether a user gives a correct value of a variable or function
|
||||
(user-defined variables/functions in the mathematical parser)
|
||||
* added: into the parser: logical operators: > < >= <= == != && ||
|
||||
* added: into the parser: logical functions: and() or() not() if()
|
||||
* added: ErrorCode::err_unknown_operator when the parser couldn't read an operator
|
||||
|
|
22
README
22
README
|
@ -1,2 +1,24 @@
|
|||
TTMath - a bignum library for C++
|
||||
|
||||
TTMath is a small library which allows one to perform arithmetic operations
|
||||
with big unsigned integer, big signed integer and big floating point
|
||||
numbers. It provides standard mathematical operations like adding,
|
||||
subtracting, multiplying, dividing etc. With the library also goes
|
||||
a mathematical parser which helps you solving input formulas read directly
|
||||
from a user.
|
||||
|
||||
TTMath is developed under the (new) BSD licence which means that it is free
|
||||
for both personal and commercial use but the library has some technical
|
||||
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
|
||||
way as the standard types like int, float, etc. It does not need to be
|
||||
compiled first because the whole library is written as the C++ templates.
|
||||
This means only C++ developers can use this library and one thing they have
|
||||
to do is to use 'include' directive of the preprocessor. How big the
|
||||
values can be is set directly in the source code by the programmer.
|
||||
|
||||
Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl>
|
||||
Home page: http://sourceforge.net/projects/ttmath
|
||||
|
|
8
TODO
8
TODO
|
@ -1,7 +1,7 @@
|
|||
TODO TTMath Library
|
||||
===================
|
||||
|
||||
* to add operators (or functions) and, or, xor
|
||||
* to add functions for generating random values
|
||||
* to add constructors (UInt, Int) for 64bit platforms (constractors which take int and unsigned)
|
||||
* to add 'history' for functions like 'factorial' which take a lot of time during calculating
|
||||
* Add bitwise operators (or functions) and, or, xor
|
||||
* Add functions for generating random values
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ CFLAGS = -Wall -pedantic -s -O2 -I..
|
|||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
|
||||
all: uint int
|
||||
all: uint int big parser
|
||||
|
||||
|
||||
uint: uint.o
|
||||
|
@ -17,9 +17,17 @@ uint: uint.o
|
|||
int: int.o
|
||||
$(CC) -o int $(CFLAGS) int.o
|
||||
|
||||
big: big.o
|
||||
$(CC) -o big $(CFLAGS) big.o
|
||||
|
||||
parser: parser.o
|
||||
$(CC) -o parser $(CFLAGS) parser.o
|
||||
|
||||
|
||||
uint.o: uint.cpp
|
||||
int.o: int.cpp
|
||||
big.o: big.cpp
|
||||
parser.o: parser.cpp
|
||||
|
||||
|
||||
clean:
|
||||
|
@ -27,4 +35,7 @@ clean:
|
|||
rm -f *.s
|
||||
rm -f uint
|
||||
rm -f int
|
||||
rm -f big
|
||||
rm -f parser
|
||||
# on MS Windows can automatically be added suffixes .exe to the names of output programs
|
||||
rm -f *.exe
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#include <ttmath/ttmath.h>
|
||||
#include <iostream>
|
||||
|
||||
// for convenience we're defining MyBig type
|
||||
// this type has 2 words for its mantissa and 1 word for its exponent
|
||||
// (on a 32bit platform one word means a word of 32 bits,
|
||||
// and on a 64bit platform one word means a word of 64 bits)
|
||||
typedef ttmath::Big<1,2> MyBig;
|
||||
|
||||
|
||||
void SimpleCalculating(const MyBig & a, const MyBig & b)
|
||||
{
|
||||
std::cout << "Simple calculating" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
std::cout << "a + b = " << a+b << std::endl;
|
||||
std::cout << "a - b = " << a-b << std::endl;
|
||||
std::cout << "a * b = " << a*b << std::endl;
|
||||
std::cout << "a / b = " << a/b << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void CalculatingWithCarry(const MyBig & a, const MyBig & b)
|
||||
{
|
||||
MyBig atemp;
|
||||
|
||||
std::cout << "Calculating with a carry" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Add(b) )
|
||||
std::cout << "a + b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a + b = (carry) " << atemp << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Sub(b) )
|
||||
std::cout << "a - b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a - b = (carry) " << atemp << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Mul(b) )
|
||||
std::cout << "a * b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a * b = (carry: the result is too big) " << std::endl;
|
||||
// it have no sense to print 'atemp' (it's undefined)
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Div(b) )
|
||||
std::cout << "a / b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a / b = (carry or division by zero) " << std::endl;
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
MyBig a,b;
|
||||
|
||||
// conversion from 'const char *'
|
||||
a = "123456.543456";
|
||||
b = "98767878.124322";
|
||||
|
||||
SimpleCalculating(a,b);
|
||||
|
||||
// 'a' will have the max value which can be held in this type
|
||||
a.SetMax();
|
||||
|
||||
// at the moment conversions from double (or float etc.) are not supported
|
||||
// you cannot do that: b = 456.32f
|
||||
b = "456.32";
|
||||
|
||||
// Look at the value 'a' and the product from a+b and a-b
|
||||
// Don't worry this is the nature of floating point numbers
|
||||
CalculatingWithCarry(a,b);
|
||||
}
|
||||
|
||||
/*
|
||||
the result (on 32 bit platform):
|
||||
|
||||
Simple calculating
|
||||
a = 123456.543456
|
||||
b = 98767878.124322
|
||||
a + b = 98891334.667778
|
||||
a - b = -98644421.580866
|
||||
a * b = 12193540837712.2708
|
||||
a / b = 0.0012499665458095765
|
||||
Calculating with a carry
|
||||
a = 1.624801256070839555e+646457012
|
||||
b = 456.32
|
||||
a + b = 1.624801256070839555e+646457012
|
||||
a - b = 1.624801256070839555e+646457012
|
||||
a * b = (carry: the result is too big)
|
||||
a / b = 3.56066193914542329e+646457009
|
||||
*/
|
|
@ -1,4 +1,4 @@
|
|||
#include <ttmath/ttmathint.h>
|
||||
#include <ttmath/ttmath.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ void CalculatingWithCarry(const ttmath::Int<2> & a, const ttmath::Int<2> & b)
|
|||
{
|
||||
ttmath::Int<2> atemp;
|
||||
|
||||
std::cout << "Calculating with carry" << std::endl;
|
||||
std::cout << "Calculating with a carry" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
|
||||
|
@ -26,13 +26,13 @@ ttmath::Int<2> atemp;
|
|||
if( !atemp.Add(b) )
|
||||
std::cout << "a + b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a + b = (carry: the result is too big) " << atemp << std::endl;
|
||||
std::cout << "a + b = (carry) " << atemp << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Sub(b) )
|
||||
std::cout << "a - b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a - b = (carry: 'a' was smaller than 'b') " << atemp << std::endl;
|
||||
std::cout << "a - b = (carry) " << atemp << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Mul(b) )
|
||||
|
@ -52,17 +52,19 @@ ttmath::Int<2> atemp;
|
|||
int main()
|
||||
{
|
||||
// on 32bit platforms: 'a' and 'b' have 2-words (two 32bit words)
|
||||
// in other words a,b are from <-2^63, 2^63 - 1>
|
||||
// it means a,b are from <-2^63, 2^63 - 1>
|
||||
ttmath::Int<2> a,b;
|
||||
|
||||
// conversion from int
|
||||
a = 123456;
|
||||
|
||||
// conversion from 'const char *'
|
||||
a = "123456";
|
||||
b = "98767878";
|
||||
|
||||
SimpleCalculating(a,b);
|
||||
|
||||
// 'a' will have the max value which can be held in this type
|
||||
a.SetMaxValue();
|
||||
a.SetMax();
|
||||
|
||||
// conversion from 'int'
|
||||
b = 10;
|
||||
|
@ -71,7 +73,7 @@ ttmath::Int<2> a,b;
|
|||
}
|
||||
|
||||
/*
|
||||
the result:
|
||||
the result (on 32 bit platform):
|
||||
|
||||
Simple calculating
|
||||
a = 123456
|
||||
|
@ -80,11 +82,11 @@ a + b = 98891334
|
|||
a - b = -98644422
|
||||
a * b = 12193487146368
|
||||
a / b = 0
|
||||
Calculating with carry
|
||||
Calculating with a carry
|
||||
a = 9223372036854775807
|
||||
b = 10
|
||||
a + b = (carry: the result is too big) -9223372036854775799
|
||||
a + b = (carry) -9223372036854775799
|
||||
a - b = 9223372036854775797
|
||||
a * b = (carry: the result is too big)
|
||||
a * b = (carry) the result is too big)
|
||||
a / b = 922337203685477580
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#include <ttmath/ttmath.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// for convenience we're defining MyBig type
|
||||
// this type has 2 words for its mantissa and 1 word for its exponent
|
||||
// (on a 32bit platform one word means a word of 32 bits,
|
||||
// and on a 64bit platform one word means a word of 64 bits)
|
||||
typedef ttmath::Big<1,2> MyBig;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
ttmath::Parser<MyBig> parser;
|
||||
|
||||
// the sine function takes its parameter as being in radians,
|
||||
// the product from the arcus tangent will be in radians as well
|
||||
const char equation[] = " (34 + 24) * 123 - 34.32 ^ 6 * sin(2.56) - atan(10)";
|
||||
|
||||
ttmath::ErrorCode err = parser.Parse(equation);
|
||||
|
||||
if( err == ttmath::err_ok )
|
||||
std::cout << parser.stack[0].value << std::endl;
|
||||
else
|
||||
std::cout << "Error: "
|
||||
<< static_cast<int>(err)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
the result (on 32 bit platform):
|
||||
|
||||
-897705014.52573107
|
||||
*/
|
|
@ -1,4 +1,4 @@
|
|||
#include <ttmath/ttmathuint.h>
|
||||
#include <ttmath/ttmath.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ void CalculatingWithCarry(const ttmath::UInt<2> & a, const ttmath::UInt<2> & b)
|
|||
{
|
||||
ttmath::UInt<2> atemp;
|
||||
|
||||
std::cout << "Calculating with carry" << std::endl;
|
||||
std::cout << "Calculating with a carry" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
|
||||
|
@ -53,17 +53,19 @@ ttmath::UInt<2> atemp;
|
|||
int main()
|
||||
{
|
||||
// on 32bit platforms: 'a' and 'b' have 2-words (two 32bit words)
|
||||
// in other words a,b are from <0, 2^64 - 1>
|
||||
// it means a,b are from <0, 2^64 - 1>
|
||||
ttmath::UInt<2> a,b;
|
||||
|
||||
// conversion from 'const char *'
|
||||
a = "123456";
|
||||
b = "9876";
|
||||
|
||||
// conversion from int
|
||||
b = 9876;
|
||||
|
||||
SimpleCalculating(a,b);
|
||||
|
||||
// 'a' will have the max value which can be held in this type
|
||||
a.SetMaxValue();
|
||||
a.SetMax();
|
||||
|
||||
// conversion from 'int'
|
||||
b = 5;
|
||||
|
@ -72,7 +74,7 @@ ttmath::UInt<2> a,b;
|
|||
}
|
||||
|
||||
/*
|
||||
the result:
|
||||
the result (on 32 bit platform):
|
||||
|
||||
Simple calculating
|
||||
a = 123456
|
||||
|
@ -81,7 +83,7 @@ a + b = 133332
|
|||
a - b = 113580
|
||||
a * b = 1219251456
|
||||
a / b = 12
|
||||
Calculating with carry
|
||||
Calculating with a carry
|
||||
a = 18446744073709551615
|
||||
b = 5
|
||||
a + b = (carry: the result is too big) 4
|
||||
|
|
754
ttmath/ttmath.h
754
ttmath/ttmath.h
|
@ -46,126 +46,21 @@
|
|||
*/
|
||||
|
||||
#include "ttmathbig.h"
|
||||
#include "ttmathobjects.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
the factorial from given 'x'
|
||||
e.g.
|
||||
Factorial(4) = 4! = 1*2*3*4
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
ValueType result;
|
||||
/*
|
||||
*
|
||||
* functions for rounding
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
result.SetOne();
|
||||
|
||||
if( x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !x.exponent.IsSign() && !x.exponent.IsZero() )
|
||||
{
|
||||
// when x.exponent>0 there's no sense to calculate the formula
|
||||
// (we can't add one into the x bacause
|
||||
// we don't have enough bits in the mantissa)
|
||||
if( err )
|
||||
*err = err_overflow;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ValueType multipler;
|
||||
ValueType one;
|
||||
uint carry = 0;
|
||||
|
||||
one = result; // =1
|
||||
multipler = result; // =1
|
||||
|
||||
while( !carry && multipler < x )
|
||||
{
|
||||
if( stop && stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
carry += multipler.Add(one);
|
||||
carry += result.Mul(multipler);
|
||||
}
|
||||
|
||||
|
||||
if( err )
|
||||
{
|
||||
if( carry )
|
||||
*err = err_overflow;
|
||||
else
|
||||
*err = err_ok;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
absolute value of x
|
||||
e.g. -2 = 2
|
||||
2 = 2
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Abs(const ValueType & x)
|
||||
{
|
||||
ValueType result( x );
|
||||
result.Abs();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
it returns the sign of the value
|
||||
e.g. -2 = 1
|
||||
0 = 0
|
||||
10 = 1
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Sgn(ValueType x)
|
||||
{
|
||||
x.Sgn();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the remainder from the division
|
||||
|
||||
e.g.
|
||||
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
|
||||
mod(-12.6 ; 3) = -0.6
|
||||
mod( 12.6 ; -3) = 0.6
|
||||
mod(-12.6 ; -3) = -0.6
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Mod(ValueType a, const ValueType & b)
|
||||
{
|
||||
a.Mod(b);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/*!
|
||||
this method skips the fraction from x
|
||||
|
@ -200,6 +95,94 @@ namespace ttmath
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this function returns a value representing the smallest integer
|
||||
that is greater than or equal to x
|
||||
|
||||
Ceil(-3.7) = -3
|
||||
Ceil(-3.1) = -3
|
||||
Ceil(-3.0) = -3
|
||||
Ceil(4.0) = 4
|
||||
Ceil(4.2) = 5
|
||||
Ceil(4.8) = 5
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Ceil(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType result(x);
|
||||
uint c = 0;
|
||||
|
||||
result.SkipFraction();
|
||||
|
||||
if( result != x )
|
||||
{
|
||||
// x is with fraction
|
||||
// if x is negative we don't have to do anything
|
||||
if( !x.IsSign() )
|
||||
{
|
||||
ValueType one;
|
||||
one.SetOne();
|
||||
|
||||
c += result.Add(one);
|
||||
}
|
||||
}
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function returns a value representing the largest integer
|
||||
that is less than or equal to x
|
||||
|
||||
Floor(-3.6) = -4
|
||||
Floor(-3.1) = -4
|
||||
Floor(-3) = -3
|
||||
Floor(2) = 2
|
||||
Floor(2.3) = 2
|
||||
Floor(2.8) = 2
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Floor(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType result(x);
|
||||
uint c = 0;
|
||||
|
||||
result.SkipFraction();
|
||||
|
||||
if( result != x )
|
||||
{
|
||||
// x is with fraction
|
||||
// if x is positive we don't have to do anything
|
||||
if( x.IsSign() )
|
||||
{
|
||||
ValueType one;
|
||||
one.SetOne();
|
||||
|
||||
c += result.Sub(one);
|
||||
}
|
||||
}
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* logarithms and the exponent
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
this method calculates the natural logarithm (logarithm with the base 'e')
|
||||
|
@ -277,13 +260,10 @@ namespace ttmath
|
|||
{
|
||||
ValueType result;
|
||||
|
||||
uint state = result.Exp(x);
|
||||
uint c = result.Exp(x);
|
||||
|
||||
if( err )
|
||||
if( state!=0 )
|
||||
*err = err_overflow;
|
||||
else
|
||||
*err = err_ok;
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -299,7 +279,7 @@ namespace ttmath
|
|||
{
|
||||
|
||||
/*!
|
||||
an auxiliary function for calculating the Sin
|
||||
an auxiliary function for calculating the Sine
|
||||
(you don't have to call this function)
|
||||
*/
|
||||
template<class ValueType>
|
||||
|
@ -349,7 +329,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
an auxiliary function for calculating the Sin
|
||||
an auxiliary function for calculating the Sine
|
||||
(you don't have to call this function)
|
||||
|
||||
it returns Sin(x) where 'x' is from <0, PI/2>
|
||||
|
@ -457,8 +437,10 @@ namespace ttmath
|
|||
|
||||
} // namespace auxiliaryfunctions
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this function calulates the Sin
|
||||
this function calculates the Sine
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Sin(ValueType x)
|
||||
|
@ -490,7 +472,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
this function calulates the Cos
|
||||
this function calulates the Cosine
|
||||
we're using the formula cos(x) = sin(x + PI/2)
|
||||
*/
|
||||
template<class ValueType>
|
||||
|
@ -506,14 +488,14 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
this function calulates the Tan
|
||||
this function calulates the Tangent
|
||||
we're using the formula tan(x) = sin(x) / cos(x)
|
||||
|
||||
it takes more time than calculating the Tan directly
|
||||
from for example Taylor series but should be a bit preciser
|
||||
because Tan receives its values from -infinity to +infinity
|
||||
and when we calculate it from any series then we can make
|
||||
a small mistake than calculating 'sin/cos'
|
||||
a greater mistake than calculating 'sin/cos'
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Tan(const ValueType & x, ErrorCode * err = 0)
|
||||
|
@ -536,14 +518,27 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
this function calulates the CTan
|
||||
this function calulates the Tangent
|
||||
look at the description of Tan(...)
|
||||
|
||||
(the abbreviation of Tangent can be 'tg' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Tg(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return Tan(x, err);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calulates the Cotangent
|
||||
we're using the formula tan(x) = cos(x) / sin(x)
|
||||
|
||||
(why do we make it in this way?
|
||||
look at information in Tan() function)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType CTan(const ValueType & x, ErrorCode * err = 0)
|
||||
ValueType Cot(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType result = Sin(x);
|
||||
|
||||
|
@ -562,6 +557,19 @@ namespace ttmath
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calulates the Cotangent
|
||||
look at the description of Cot(...)
|
||||
|
||||
(the abbreviation of Cotangent can be 'ctg' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Ctg(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return Cot(x, err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* inverse trigonometric functions
|
||||
|
@ -573,7 +581,7 @@ namespace ttmath
|
|||
{
|
||||
|
||||
/*!
|
||||
arcus sin
|
||||
an auxiliary function for calculating the Arc Sine
|
||||
|
||||
we're calculating asin from the following formula:
|
||||
asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ...
|
||||
|
@ -635,7 +643,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arcus sin
|
||||
an auxiliary function for calculating the Arc Sine
|
||||
|
||||
we're calculating asin from the following formula:
|
||||
asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp
|
||||
|
@ -718,7 +726,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc sin (x)
|
||||
this function calculates the Arc Sine
|
||||
x is from <-1,1>
|
||||
*/
|
||||
template<class ValueType>
|
||||
|
@ -765,7 +773,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc cos (x)
|
||||
this function calculates the Arc Cosine
|
||||
|
||||
we're using the formula:
|
||||
acos(x) = pi/2 - asin(x)
|
||||
|
@ -786,8 +794,9 @@ namespace ttmath
|
|||
namespace auxiliaryfunctions
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary function for calculating the Arc Tangent
|
||||
|
||||
arc tan (x) where x is in <0; 0.5)
|
||||
(x can be in (-0.5 ; 0.5) too)
|
||||
|
||||
|
@ -841,13 +850,15 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc tan (x) where x is in <0 ; 1>
|
||||
an auxiliary function for calculating the Arc Tangent
|
||||
|
||||
where x is in <0 ; 1>
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ATan01(const ValueType & x)
|
||||
{
|
||||
ValueType half;
|
||||
half.SetDotOne();
|
||||
half.Set05();
|
||||
|
||||
/*
|
||||
it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here
|
||||
|
@ -908,7 +919,8 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc tan (x) where x > 1
|
||||
an auxiliary function for calculating the Arc Tangent
|
||||
where x > 1
|
||||
|
||||
we're using the formula:
|
||||
atan(x) = pi/2 - atan(1/x) for x>0
|
||||
|
@ -939,7 +951,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc tan
|
||||
this function calculates the Arc Tangent
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ATan(ValueType x)
|
||||
|
@ -971,13 +983,26 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
arc ctan
|
||||
this function calculates the Arc Tangent
|
||||
look at the description of ATan(...)
|
||||
|
||||
(the abbreviation of Arc Tangent can be 'atg' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ATg(const ValueType & x)
|
||||
{
|
||||
return ATan(x);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Arc Cotangent
|
||||
|
||||
we're using the formula:
|
||||
actan(x) = pi/2 - atan(x)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ACTan(const ValueType & x)
|
||||
ValueType ACot(const ValueType & x)
|
||||
{
|
||||
ValueType result;
|
||||
|
||||
|
@ -988,7 +1013,464 @@ namespace ttmath
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Arc Cotangent
|
||||
look at the description of ACot(...)
|
||||
|
||||
(the abbreviation of Arc Cotangent can be 'actg' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ACtg(const ValueType & x)
|
||||
{
|
||||
return ACot(x);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hyperbolic functions
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Sine
|
||||
|
||||
we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Sinh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType ex, emx;
|
||||
uint c = 0;
|
||||
|
||||
c += ex.Exp(x);
|
||||
c += emx.Exp(-x);
|
||||
|
||||
c += ex.Sub(emx);
|
||||
c += ex.exponent.SubOne();
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Cosine
|
||||
|
||||
we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Cosh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType ex, emx;
|
||||
uint c = 0;
|
||||
|
||||
c += ex.Exp(x);
|
||||
c += emx.Exp(-x);
|
||||
|
||||
c += ex.Add(emx);
|
||||
c += ex.exponent.SubOne();
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Tangent
|
||||
|
||||
we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) )
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Tanh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType ex, emx, nominator, denominator;
|
||||
uint c = 0;
|
||||
|
||||
c += ex.Exp(x);
|
||||
c += emx.Exp(-x);
|
||||
|
||||
nominator = ex;
|
||||
c += nominator.Sub(emx);
|
||||
denominator = ex;
|
||||
c += denominator.Add(emx);
|
||||
|
||||
c += nominator.Div(denominator);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return nominator;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Tangent
|
||||
look at the description of Tanh(...)
|
||||
|
||||
(the abbreviation of Hyperbolic Tangent can be 'tgh' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Tgh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return Tanh(x, err);
|
||||
}
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Cotangent
|
||||
|
||||
we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) )
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Coth(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
ValueType ex, emx, nominator, denominator;
|
||||
uint c = 0;
|
||||
|
||||
c += ex.Exp(x);
|
||||
c += emx.Exp(-x);
|
||||
|
||||
nominator = ex;
|
||||
c += nominator.Add(emx);
|
||||
denominator = ex;
|
||||
c += denominator.Sub(emx);
|
||||
|
||||
c += nominator.Div(denominator);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return nominator;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the Hyperbolic Cotangent
|
||||
look at the description of Coth(...)
|
||||
|
||||
(the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Ctgh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return Coth(x, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* functions for converting between degrees and radians
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
this function converts degrees to radians
|
||||
|
||||
it returns: x * pi / 180
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType DegToRad(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType result, delimiter;
|
||||
uint c = 0;
|
||||
|
||||
result.SetPi();
|
||||
c += result.Mul(x);
|
||||
|
||||
delimiter = 180;
|
||||
c += result.Div(delimiter);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function converts radians to degrees
|
||||
|
||||
it returns: x * 180 / pi
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType result, delimiter;
|
||||
uint c = 0;
|
||||
|
||||
result = 180;
|
||||
c += result.Mul(x);
|
||||
|
||||
delimiter.SetPi();
|
||||
c += result.Div(delimiter);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function converts degrees in the long format into one value
|
||||
|
||||
long format: (degrees, minutes, seconds)
|
||||
minutes and seconds must be greater than or equal zero
|
||||
|
||||
result:
|
||||
if d>=0 : result= d + ((s/60)+m)/60
|
||||
if d<0 : result= d - ((s/60)+m)/60
|
||||
|
||||
((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because
|
||||
there's only one division)
|
||||
|
||||
for example:
|
||||
DegToDeg(10, 30, 0) = 10.5
|
||||
DegToDeg(10, 24, 35.6)=10.4098(8)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s,
|
||||
ErrorCode * err = 0)
|
||||
{
|
||||
ValueType delimiter, multipler;
|
||||
uint c = 0;
|
||||
|
||||
if( m.IsSign() || s.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return delimiter;
|
||||
}
|
||||
|
||||
multipler = 60;
|
||||
delimiter = 3600;
|
||||
|
||||
c += multipler.Mul(m);
|
||||
c += multipler.Add(s);
|
||||
c += multipler.Div(delimiter);
|
||||
|
||||
if( d.IsSign() )
|
||||
multipler.ChangeSign();
|
||||
|
||||
c += multipler.Add(d);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return multipler;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this function converts degrees in the long format to radians
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s,
|
||||
ErrorCode * err = 0)
|
||||
{
|
||||
ValueType temp_deg = DegToDeg(d,m,s,err);
|
||||
|
||||
if( err && *err!=err_ok )
|
||||
return temp_deg;
|
||||
|
||||
return DegToRad(temp_deg, err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* another functions
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the square root
|
||||
|
||||
Sqrt(9) = 3
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Sqrt(ValueType x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// Sqrt(0) = 0
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
ValueType pow;
|
||||
pow.Set05();
|
||||
|
||||
// PowFrac can return only a carry because x is greater than zero
|
||||
uint c = x.PowFrac(pow);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the factorial from given 'x'
|
||||
e.g.
|
||||
Factorial(4) = 4! = 1*2*3*4
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
static History<ValueType> history;
|
||||
ValueType result;
|
||||
|
||||
result.SetOne();
|
||||
|
||||
if( x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !x.exponent.IsSign() && !x.exponent.IsZero() )
|
||||
{
|
||||
// when x.exponent>0 there's no sense to calculate the formula
|
||||
// (we can't add one into the x bacause
|
||||
// we don't have enough bits in the mantissa)
|
||||
if( err )
|
||||
*err = err_overflow;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ErrorCode err_tmp;
|
||||
|
||||
if( history.Get(x, result, err_tmp) )
|
||||
{
|
||||
if( err )
|
||||
*err = err_tmp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ValueType multipler;
|
||||
ValueType one;
|
||||
uint carry = 0;
|
||||
|
||||
one = result; // =1
|
||||
multipler = result; // =1
|
||||
|
||||
while( !carry && multipler < x )
|
||||
{
|
||||
if( stop && stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
carry += multipler.Add(one);
|
||||
carry += result.Mul(multipler);
|
||||
}
|
||||
|
||||
err_tmp = carry ? err_overflow : err_ok;
|
||||
history.Add(x, result, err_tmp);
|
||||
|
||||
if( err )
|
||||
*err = carry ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
absolute value of x
|
||||
e.g. -2 = 2
|
||||
2 = 2
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Abs(const ValueType & x)
|
||||
{
|
||||
ValueType result( x );
|
||||
result.Abs();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
it returns the sign of the value
|
||||
e.g. -2 = 1
|
||||
0 = 0
|
||||
10 = 1
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Sgn(ValueType x)
|
||||
{
|
||||
x.Sgn();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the remainder from a division
|
||||
|
||||
e.g.
|
||||
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
|
||||
mod(-12.6 ; 3) = -0.6
|
||||
mod( 12.6 ; -3) = 0.6
|
||||
mod(-12.6 ; -3) = -0.6
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Mod(ValueType a, const ValueType & b)
|
||||
{
|
||||
a.Mod(b);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
/*!
|
||||
this is for convenience for the user
|
||||
he can only use '#include <ttmath/ttmath.h>' even if he uses the parser
|
||||
*/
|
||||
#include "ttmathparser.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,19 +40,19 @@
|
|||
|
||||
/*!
|
||||
\file ttmathbig.h
|
||||
\brief A Class for representing big numbers
|
||||
\brief A Class for representing floating point numbers
|
||||
*/
|
||||
|
||||
#include "ttmathint.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief it implements the big value
|
||||
\brief Big implements the floating point numbers
|
||||
*/
|
||||
template <uint exp,uint man>
|
||||
class Big
|
||||
|
@ -147,6 +147,7 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
|
||||
/*!
|
||||
it sets value zero
|
||||
*/
|
||||
|
@ -167,19 +168,16 @@ public:
|
|||
*/
|
||||
void SetOne()
|
||||
{
|
||||
info = 0;
|
||||
mantissa.SetOne();
|
||||
exponent.SetZero();
|
||||
Standardizing();
|
||||
FromUInt(1);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
it sets value 0.5
|
||||
*/
|
||||
void SetDotOne()
|
||||
void Set05()
|
||||
{
|
||||
SetOne();
|
||||
FromUInt(1);
|
||||
exponent.SubOne();
|
||||
}
|
||||
|
||||
|
@ -189,6 +187,10 @@ public:
|
|||
*/
|
||||
void SetPi()
|
||||
{
|
||||
// this is a static table which represents the value Pi (mantissa of it)
|
||||
// (first is the highest word)
|
||||
// we must define this table as 'unsigned int' because
|
||||
// both on 32bit and 64bit platforms this table is 32bit
|
||||
static const unsigned int temp_table[] = {
|
||||
0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22,
|
||||
0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245,
|
||||
|
@ -199,13 +201,26 @@ public:
|
|||
0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5,
|
||||
0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64,
|
||||
0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7,
|
||||
0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf0139f9d, 0x88e637cb
|
||||
0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64,
|
||||
0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31,
|
||||
0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26,
|
||||
0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
|
||||
0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
|
||||
0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
|
||||
0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646df // (last one was: 0x602646de)
|
||||
// 0xc9751e76, ...
|
||||
// (the last word was rounded up because the next one is 0xc9751e76 -- first bit is one 0xc..)
|
||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
||||
};
|
||||
// 78 unsigned 32bits words
|
||||
// this is static table which represents the value Pi (mantissa of its)
|
||||
// (first is the highest word)
|
||||
// we must define this table as 'unsigned int' because
|
||||
// on 32bits and 64bits platforms this table is 32bits
|
||||
|
||||
// the value of PI is comming from the website "Paul's 8192 Digits of Pi"
|
||||
// http://www.escape.com/~paulg53/math/pi/8192.html
|
||||
// 2999 digits were taken from this website
|
||||
// (later they were compared with http://zenwerx.com/pi.php)
|
||||
// and they were set into Big<1,300> type (using operator=(const char*) on 32bit platform)
|
||||
// and then the first 128 words were taken into this table
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
||||
// and on 64bit platform value 64 (128/2=64))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||
|
@ -235,7 +250,7 @@ public:
|
|||
|
||||
/*!
|
||||
it sets value e
|
||||
(the base of natural logarithm)
|
||||
(the base of the natural logarithm)
|
||||
*/
|
||||
void SetE()
|
||||
{
|
||||
|
@ -249,9 +264,24 @@ public:
|
|||
0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2,
|
||||
0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238,
|
||||
0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270,
|
||||
0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x645b2194, 0x41468794
|
||||
0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e,
|
||||
0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef,
|
||||
0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6,
|
||||
0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
|
||||
0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
|
||||
0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
|
||||
0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a
|
||||
//0x23ba4442,...
|
||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
||||
};
|
||||
|
||||
|
||||
// above value was calculated using Big<1,300> on 32bit platform
|
||||
// and then the first 128 words were taken,
|
||||
// the calculating was made by using ExpSurrounding0(1) method
|
||||
// which took 1110 iterations
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
||||
// and on 64bit platform value 64 (128/2=64))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||
info = 0;
|
||||
|
@ -274,23 +304,93 @@ public:
|
|||
0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c,
|
||||
0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b,
|
||||
0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b,
|
||||
0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef8, 0x6e1adf84, 0x08689fa8
|
||||
0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982,
|
||||
0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2,
|
||||
0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c,
|
||||
0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
|
||||
0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
|
||||
0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
|
||||
0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd9 // (last one was: 0xc8daadd8)
|
||||
// 0x85db6ab0, ...
|
||||
// (the last word was rounded up because the next one is 0x85db6ab0 -- first bit is one 0x8..)
|
||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
||||
};
|
||||
|
||||
// above value was calculated using Big<1,300> on 32bit platform
|
||||
// and then the first 128 words were taken,
|
||||
// the calculating was made by using LnSurrounding1(2) method
|
||||
// which took 3030 iterations
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
||||
// and on 64bit platform value 64 (128/2=64))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
||||
info = 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
it sets value ln(10)
|
||||
the natural logarithm from value 10
|
||||
|
||||
I introduced this constant especially to make the conversion ToString()
|
||||
being faster. In fact the method ToString() is keeping values of logarithms
|
||||
it has calculated but it must calculate the logarithm at least once.
|
||||
If a program, which uses this library, is running for a long time this
|
||||
would be ok, but for programs which are running shorter, for example for
|
||||
CGI applications which only once are printing values, this would be much
|
||||
inconvenience. Then if we're printing with base (radix) 10 and the mantissa
|
||||
of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE
|
||||
we don't calculate the logarithm but take it from this constant.
|
||||
*/
|
||||
void SetLn10()
|
||||
{
|
||||
static const unsigned int temp_table[] = {
|
||||
0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72,
|
||||
0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6,
|
||||
0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb,
|
||||
0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981,
|
||||
0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0,
|
||||
0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e,
|
||||
0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5,
|
||||
0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e,
|
||||
0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47,
|
||||
0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834,
|
||||
0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a,
|
||||
0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d,
|
||||
0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
|
||||
0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
|
||||
0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
|
||||
0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f9 // (last one was: 0xba83c7f8)
|
||||
///0xfb5f06c3, ...
|
||||
//(the last word was rounded up because the next one is 0xfb5f06c3 -- first bit is one 0xf..)
|
||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
||||
};
|
||||
|
||||
// above value was calculated using Big<1,300> on 32bit platform
|
||||
// and then the first 128 32bit words were taken,
|
||||
// the calculating was made by using LnSurrounding1(10) method
|
||||
// which took 16555 iterations
|
||||
// (the formula used in LnSurrounding1(x) converges badly when
|
||||
// the x is greater than one but in fact we can use it, only the
|
||||
// number of iterations will be greater)
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
||||
// and on 64bit platform value 64 (128/2=64))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||
info = 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
it sets the maximum value which can be held in this type
|
||||
*/
|
||||
void SetMax()
|
||||
{
|
||||
info = 0;
|
||||
mantissa.SetMaxValue();
|
||||
exponent.SetMaxValue();
|
||||
mantissa.SetMax();
|
||||
exponent.SetMax();
|
||||
|
||||
// we don't have to use 'Standardizing()' because the last bit from
|
||||
// the mantissa is set
|
||||
|
@ -304,8 +404,8 @@ public:
|
|||
{
|
||||
info = 0;
|
||||
|
||||
mantissa.SetMaxValue();
|
||||
exponent.SetMaxValue();
|
||||
mantissa.SetMax();
|
||||
exponent.SetMax();
|
||||
SetSign();
|
||||
|
||||
// we don't have to use 'Standardizing()' because the last bit from
|
||||
|
@ -775,7 +875,29 @@ public:
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
power this = this ^ pow
|
||||
this *must* be greater than zero (this > 0)
|
||||
pow can be negative and with fraction
|
||||
|
||||
return values:
|
||||
1 - carry
|
||||
2 - incorrect argument ('this')
|
||||
*/
|
||||
uint PowFrac(const Big<exp, man> & pow)
|
||||
{
|
||||
TTMATH_REFERENCE_ASSERT( pow )
|
||||
|
||||
Big<exp, man> temp;
|
||||
uint c = temp.Ln(*this);
|
||||
c += temp.Mul(pow);
|
||||
c += Exp(temp);
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
power this = this ^ pow
|
||||
|
@ -803,23 +925,13 @@ public:
|
|||
Big<exp, man> pow_frac( pow );
|
||||
pow_frac.RemainFraction();
|
||||
|
||||
|
||||
if( pow_frac.IsZero() )
|
||||
return PowBInt( pow );
|
||||
|
||||
// pow is with fraction (not integer)
|
||||
// result = e^(pow * ln(this) ) where 'this' must be greater than 0
|
||||
|
||||
// IsZero() was tested before
|
||||
if( IsSign() )
|
||||
return 2;
|
||||
|
||||
Big<exp, man> temp;
|
||||
uint c = temp.Ln(*this);
|
||||
c += temp.Mul(pow);
|
||||
c += Exp(temp);
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
return PowFrac(pow);
|
||||
}
|
||||
|
||||
|
||||
|
@ -843,6 +955,10 @@ private:
|
|||
denominator.SetOne();
|
||||
denominator_i.SetOne();
|
||||
|
||||
// this is only to avoid getting a warning about an uninitialized object
|
||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
||||
old_value.info = 0;
|
||||
|
||||
// every 'step_test' times we make a test
|
||||
const uint step_test = 5;
|
||||
|
@ -969,10 +1085,6 @@ private:
|
|||
|
||||
we're using the formula:
|
||||
ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
|
||||
|
||||
parts - it's used for approximation, it means how many parts of the above formula
|
||||
will be caltulated, when equals 0 then it is ommited
|
||||
|
||||
*/
|
||||
void LnSurrounding1(const Big<exp,man> & x)
|
||||
{
|
||||
|
@ -998,9 +1110,13 @@ private:
|
|||
|
||||
denominator.SetOne();
|
||||
SetZero();
|
||||
|
||||
// every 'step_test' times we make a test
|
||||
|
||||
// this is only to avoid getting a warning about an uninitialized object
|
||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
||||
old_value.info = 0;
|
||||
|
||||
// every 'step_test' times we make a test
|
||||
const uint step_test = 5;
|
||||
|
||||
// we begin from 1 in order to not testing at the beginning
|
||||
|
@ -1253,7 +1369,7 @@ public:
|
|||
if( IsSign() )
|
||||
{
|
||||
Int<int_size> min;
|
||||
min.SetMinValue();
|
||||
min.SetMin();
|
||||
|
||||
if( result == min )
|
||||
return 0;
|
||||
|
@ -1270,6 +1386,24 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting 'uint' to this class
|
||||
*/
|
||||
void FromUInt(uint value)
|
||||
{
|
||||
info = 0;
|
||||
|
||||
for(uint i=0 ; i<man-1 ; ++i)
|
||||
mantissa.table[i] = 0;
|
||||
|
||||
mantissa.table[man-1] = value;
|
||||
exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT);
|
||||
|
||||
// there shouldn't be a carry because 'value' has the 'uint' type
|
||||
Standardizing();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting 'sint' to this class
|
||||
*/
|
||||
|
@ -1279,19 +1413,14 @@ public:
|
|||
|
||||
if( value < 0 )
|
||||
{
|
||||
value = -value;
|
||||
value = -value;
|
||||
is_sign = true;
|
||||
}
|
||||
|
||||
info = 0;
|
||||
mantissa = value;
|
||||
exponent.SetZero();
|
||||
FromUInt(uint(value));
|
||||
|
||||
if( is_sign )
|
||||
SetSign();
|
||||
|
||||
// there shouldn't be a carry because 'value' has the type 'sint'
|
||||
Standardizing();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1307,31 +1436,101 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a constructor for converting 'sint' and 'uint' to this class
|
||||
an operator= for converting 'uint' to this class
|
||||
*/
|
||||
Big<exp, man> & operator=(uint value)
|
||||
{
|
||||
FromUInt(value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting 'sint' to this class
|
||||
*/
|
||||
Big(sint value)
|
||||
{
|
||||
FromInt(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
a constructor for converting 'uint' to this class
|
||||
*/
|
||||
Big(uint value)
|
||||
{
|
||||
FromInt( sint(value) );
|
||||
FromUInt(value);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
#if defined _M_X64 || defined __x86_64__
|
||||
/*!
|
||||
a constructor for converting 'int' to this class
|
||||
(on 64bit platforms 'sint' has 64 bits and 'int' has 32 bits
|
||||
in 64bit platforms we must define additional operators and contructors
|
||||
in order to allow a user initializing the objects in this way:
|
||||
Big<...> type = 20;
|
||||
or
|
||||
Big<...> 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)
|
||||
*/
|
||||
Big(int value)
|
||||
|
||||
/*!
|
||||
an operator= for converting 'signed int' to this class
|
||||
***this operator is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
|
||||
|
||||
*/
|
||||
Big<exp, man> & operator=(signed int value)
|
||||
{
|
||||
FromInt( sint(value) );
|
||||
FromInt(sint(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
an operator= for converting 'unsigned int' to this class
|
||||
***this operator is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
*/
|
||||
Big<exp, man> & operator=(unsigned int value)
|
||||
{
|
||||
FromUInt(uint(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting 'signed int' to this class
|
||||
***this constructor is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
*/
|
||||
Big(signed int value)
|
||||
{
|
||||
FromInt(sint(value));
|
||||
}
|
||||
|
||||
/*!
|
||||
a constructor for converting 'unsigned int' to this class
|
||||
***this constructor is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
*/
|
||||
Big(unsigned int value)
|
||||
{
|
||||
FromUInt(uint(value));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
a method for converting from 'Int<int_size>' to this class
|
||||
*/
|
||||
|
@ -1401,7 +1600,7 @@ public:
|
|||
/*!
|
||||
a destructor
|
||||
*/
|
||||
virtual ~Big()
|
||||
~Big()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1712,28 +1911,44 @@ private:
|
|||
// (LnSurrounding1() will return one immediately)
|
||||
uint c = Ln(x);
|
||||
|
||||
static Big<exp,man> log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint index = base - 2;
|
||||
|
||||
if( log_history[index].IsZero() )
|
||||
{
|
||||
// we don't have 'base' in 'log_history' then we calculate it now
|
||||
Big<exp,man> base_(base);
|
||||
c += temp.Ln(base_);
|
||||
c += Div(temp);
|
||||
|
||||
// the next time we'll get the 'Ln(base)' from the history,
|
||||
// this 'log_history' can have (16-2+1) items max
|
||||
log_history[index] = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've calculated the 'Ln(base)' beforehand and we're getting it now
|
||||
c += Div( log_history[index] );
|
||||
}
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
static Big<exp,man> log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
/*
|
||||
static Big<exp,man> log_history[15] = { sint(0),sint(0),sint(0),sint(0),sint(0),
|
||||
sint(0),sint(0),sint(0),sint(0),sint(0),
|
||||
sint(0),sint(0),sint(0),sint(0),sint(0) };
|
||||
*/
|
||||
uint index = base - 2;
|
||||
|
||||
if( log_history[index].IsZero() )
|
||||
{
|
||||
// we don't have 'base' in 'log_history' then we calculate it now
|
||||
|
||||
if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE )
|
||||
{
|
||||
// for the base equal 10 we're using SelLn10() instead of calculating it
|
||||
// (only if we have sufficient big the constant)
|
||||
temp.SetLn10();
|
||||
}
|
||||
else
|
||||
{
|
||||
Big<exp,man> base_(base);
|
||||
c += temp.Ln(base_);
|
||||
}
|
||||
|
||||
// the next time we'll get the 'Ln(base)' from the history,
|
||||
// this 'log_history' can have (16-2+1) items max
|
||||
log_history[index] = temp;
|
||||
|
||||
c += Div(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've calculated the 'Ln(base)' beforehand and we're getting it now
|
||||
c += Div( log_history[index] );
|
||||
}
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -2269,6 +2484,11 @@ private:
|
|||
|
||||
// we don't remove any white characters here
|
||||
|
||||
// this is only to avoid getting a warning about an uninitialized object
|
||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
||||
old_value.info = 0;
|
||||
|
||||
power.SetOne();
|
||||
|
||||
for( ; (character=UInt<man>::CharToDigit(*source, base)) != -1 ; ++source, ++index )
|
||||
|
@ -2804,7 +3024,7 @@ public:
|
|||
Big<exp,man> half;
|
||||
uint c;
|
||||
|
||||
half.SetDotOne();
|
||||
half.Set05();
|
||||
|
||||
if( IsSign() )
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
\brief it implements a big integer value with a sign
|
||||
\brief Int implements a big integer value with a sign
|
||||
|
||||
value_size - how many bytes specify our value
|
||||
on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
|
||||
|
@ -68,9 +68,9 @@ public:
|
|||
this method sets the max value which this class can hold
|
||||
(all bits will be one besides the last one)
|
||||
*/
|
||||
void SetMaxValue()
|
||||
void SetMax()
|
||||
{
|
||||
UInt<value_size>::SetMaxValue();
|
||||
UInt<value_size>::SetMax();
|
||||
UInt<value_size>::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
this method sets the min value which this class can hold
|
||||
(all bits will be zero besides the last one which is one)
|
||||
*/
|
||||
void SetMinValue()
|
||||
void SetMin()
|
||||
{
|
||||
UInt<value_size>::SetZero();
|
||||
UInt<value_size>::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT;
|
||||
|
@ -92,7 +92,7 @@ public:
|
|||
*/
|
||||
void SetSignOne()
|
||||
{
|
||||
UInt<value_size>::SetMaxValue();
|
||||
UInt<value_size>::SetMax();
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,10 +106,10 @@ public:
|
|||
{
|
||||
Int<value_size> temp;
|
||||
|
||||
temp.SetMinValue();
|
||||
temp.SetMin();
|
||||
|
||||
/*
|
||||
if the value is equal that one which has been returned from SetMinValue
|
||||
if the value is equal that one which has been returned from SetMin
|
||||
that means we can't change sign because the value is too big (bigger about one)
|
||||
|
||||
e.g. when value_size = 1 and value is -2147483648 we can't change it to the
|
||||
|
@ -138,7 +138,8 @@ public:
|
|||
e.g. 1 -> -1
|
||||
-2 -> -2
|
||||
|
||||
from a positive value we always make a negative value
|
||||
from a positive value we make a negative value,
|
||||
if the value is negative we do nothing
|
||||
*/
|
||||
void SetSign()
|
||||
{
|
||||
|
@ -382,8 +383,8 @@ public:
|
|||
1. if the signs were the same that means the result is too big
|
||||
(the result must be without a sign)
|
||||
2. if the signs were different that means if the result
|
||||
is different from that one which has been returned from SetMinValue()
|
||||
that is carry (result too big) but if the result is equal SetMinValue()
|
||||
is different from that one which has been returned from SetMin()
|
||||
that is carry (result too big) but if the result is equal SetMin()
|
||||
there'll be ok (and the next SetSign will has no effect because
|
||||
the value is actually negative -- look at description of that case
|
||||
in ChangeSign())
|
||||
|
@ -392,13 +393,13 @@ public:
|
|||
{
|
||||
/*
|
||||
there can be one case where signs are different and
|
||||
the result will be equal the value from SetMinValue()
|
||||
the result will be equal the value from SetMin()
|
||||
(this situation is ok)
|
||||
*/
|
||||
if( ss1_is_sign != ss2_is_sign )
|
||||
{
|
||||
Int<value_size> temp;
|
||||
temp.SetMinValue();
|
||||
temp.SetMin();
|
||||
|
||||
if( operator!=(temp) )
|
||||
/*
|
||||
|
@ -493,8 +494,6 @@ public:
|
|||
UInt<value_size>::table[i] = p.table[i];
|
||||
|
||||
|
||||
// if( i < value_size )
|
||||
|
||||
if( value_size > argument_size )
|
||||
{
|
||||
// 'this' is longer than 'p'
|
||||
|
@ -516,6 +515,20 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method converts the sint type into this class
|
||||
*/
|
||||
void FromInt(sint value)
|
||||
{
|
||||
uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
|
||||
|
||||
for(uint i=1 ; i<value_size ; ++i)
|
||||
UInt<value_size>::table[i] = fill;
|
||||
|
||||
UInt<value_size>::table[0] = uint(value);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this operator converts an UInt<another_size> type to this class
|
||||
|
||||
|
@ -542,32 +555,103 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
this method converts an sint type to this class
|
||||
this method converts the sint type to this class
|
||||
*/
|
||||
Int<value_size> & operator=(sint i)
|
||||
{
|
||||
if(i<0)
|
||||
SetSignOne();
|
||||
else
|
||||
UInt<value_size>::SetZero();
|
||||
|
||||
UInt<value_size>::table[0] = uint(i);
|
||||
FromInt(i);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting an uint to this class
|
||||
a constructor for converting the uint to this class
|
||||
*/
|
||||
Int(sint i)
|
||||
{
|
||||
operator=(i);
|
||||
FromInt(i);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting string to this class (with base=10)
|
||||
this method converts the uint type to this class
|
||||
*/
|
||||
Int<value_size> & operator=(uint i)
|
||||
{
|
||||
UInt<value_size>::FromUInt(i);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting the uint to this class
|
||||
*/
|
||||
Int(uint i)
|
||||
{
|
||||
UInt<value_size>::FromUInt(i);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
/*!
|
||||
this method converts the signed int type to this class
|
||||
|
||||
***this operator is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
*/
|
||||
Int<value_size> & operator=(signed int i)
|
||||
{
|
||||
FromInt(sint(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
|
||||
*/
|
||||
Int(signed int i)
|
||||
{
|
||||
FromInt(sint(i));
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method converts the unsigned int type to this class
|
||||
|
||||
***this operator is created only on a 64bit platform***
|
||||
it takes one argument of 32bit
|
||||
*/
|
||||
Int<value_size> & operator=(unsigned int i)
|
||||
{
|
||||
UInt<value_size>::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
|
||||
*/
|
||||
Int(unsigned int i)
|
||||
{
|
||||
UInt<value_size>::FromUInt(uint(i));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting string to this class (with the base=10)
|
||||
*/
|
||||
Int(const char * s)
|
||||
{
|
||||
|
@ -576,7 +660,7 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a constructor for converting string to this class (with base=10)
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
Int(const std::string & s)
|
||||
{
|
||||
|
@ -595,7 +679,7 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a copy constructor
|
||||
the copy constructor
|
||||
*/
|
||||
template<uint argument_size>
|
||||
Int(const Int<argument_size> & u) : UInt<value_size>::size(value_size)
|
||||
|
@ -607,9 +691,9 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a destructor
|
||||
the destructor
|
||||
*/
|
||||
virtual ~Int()
|
||||
~Int()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -683,7 +767,7 @@ public:
|
|||
{
|
||||
Int<value_size> mmin;
|
||||
|
||||
mmin.SetMinValue();
|
||||
mmin.SetMin();
|
||||
|
||||
/*
|
||||
the reference to mmin will be automatically converted to the reference
|
||||
|
@ -699,7 +783,7 @@ public:
|
|||
{
|
||||
Int<value_size> mmax;
|
||||
|
||||
mmax.SetMaxValue();
|
||||
mmax.SetMax();
|
||||
|
||||
if( UInt<value_size>::operator>( mmax ) )
|
||||
return 1;
|
||||
|
@ -747,10 +831,19 @@ public:
|
|||
*
|
||||
* methods for comparing
|
||||
*
|
||||
* operators == and != will be the same as in the base class (UInt<value_size>)
|
||||
*
|
||||
*/
|
||||
|
||||
bool operator==(const Int<value_size> & l) const
|
||||
{
|
||||
return UInt<value_size>::operator==(l);
|
||||
}
|
||||
|
||||
bool operator!=(const Int<value_size> & l) const
|
||||
{
|
||||
return UInt<value_size>::operator!=(l);
|
||||
}
|
||||
|
||||
bool operator<(const Int<value_size> & l) const
|
||||
{
|
||||
sint i=value_size-1;
|
||||
|
|
|
@ -36,160 +36,83 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmathobject
|
||||
#define headerfilettmathobject
|
||||
|
||||
/*!
|
||||
\file ttmathobjects.h
|
||||
\brief Mathematic functions.
|
||||
*/
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
objects of this class are used with the mathematical parser
|
||||
they hold variables or functions defined by a user
|
||||
|
||||
each object has its own table in which we're keeping variables or functions
|
||||
*/
|
||||
class Objects
|
||||
{
|
||||
public:
|
||||
|
||||
struct ObjectValue
|
||||
|
||||
/*!
|
||||
one item (variable or function)
|
||||
'items' will be on the table
|
||||
*/
|
||||
struct Item
|
||||
{
|
||||
// name of a variable of a function
|
||||
std::string value;
|
||||
|
||||
// number of parameters required by the function
|
||||
// (if there's a variable this 'param' is ignored)
|
||||
int param;
|
||||
|
||||
ObjectValue() {}
|
||||
ObjectValue(const std::string & v, int p) : value(v), param(p) {}
|
||||
Item() {}
|
||||
Item(const std::string & v, int p) : value(v), param(p) {}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, ObjectValue> Table;
|
||||
// 'Table' is the type of our table
|
||||
typedef std::map<std::string, Item> Table;
|
||||
typedef Table::iterator Iterator;
|
||||
typedef Table::const_iterator CIterator;
|
||||
|
||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !CorrectCharacters(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
if( AreBigLetters(name) )
|
||||
{
|
||||
std::string name_copy(name);
|
||||
ToSmallLetters(name_copy);
|
||||
|
||||
return AddAfterChecking(name_copy, value, param);
|
||||
}
|
||||
else
|
||||
return AddAfterChecking(name, value, param);
|
||||
}
|
||||
|
||||
|
||||
bool Empty() const
|
||||
{
|
||||
return table.empty();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
return table.clear();
|
||||
}
|
||||
|
||||
CIterator Begin() const
|
||||
{
|
||||
return table.begin();
|
||||
}
|
||||
|
||||
CIterator End() const
|
||||
{
|
||||
return table.end();
|
||||
}
|
||||
|
||||
ErrorCode Edit(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
Table::iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
// we don't have this variable in our table
|
||||
return err_unknown_object;
|
||||
|
||||
i->second.value = value;
|
||||
i->second.param = param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
ErrorCode Delete(const std::string & name)
|
||||
{
|
||||
Table::iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
// we don't have this variable in our table
|
||||
return err_unknown_object;
|
||||
|
||||
table.erase( i );
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
ErrorCode GetValue(const std::string & name, const char * * value) const
|
||||
{
|
||||
Table::const_iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
// we don't have this variable in our table
|
||||
*value = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
ErrorCode GetValueParam(const std::string & name, const char * * value, int * param) const
|
||||
{
|
||||
Table::const_iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
// we don't have this variable in our table
|
||||
*value = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
*param = i->second.param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
Table * GetTable()
|
||||
{
|
||||
return &table;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Table table;
|
||||
|
||||
|
||||
bool CorrectCharacter(int c, bool digit)
|
||||
/*!
|
||||
this method returns true if a character 'c' is a character
|
||||
which can be in a name
|
||||
|
||||
if 'can_be_digit' is true that means when the 'c' is a digit this
|
||||
method returns true otherwise it returns false
|
||||
*/
|
||||
static bool CorrectCharacter(int c, bool can_be_digit)
|
||||
{
|
||||
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
||||
return true;
|
||||
|
||||
if( digit && (c>='0' && c<='9') )
|
||||
if( can_be_digit && (c>='0' && c<='9') )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CorrectCharacters(const std::string & name)
|
||||
/*!
|
||||
this method returns true if the name can be as a name of an object
|
||||
*/
|
||||
static bool IsNameCorrect(const std::string & name)
|
||||
{
|
||||
if( name.empty() )
|
||||
return false;
|
||||
|
@ -205,52 +128,355 @@ private:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int SmallLetter(int c)
|
||||
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( c>='A' && c<='Z' )
|
||||
return c-'A'+'a';
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static bool AreBigLetters(const std::string & name)
|
||||
{
|
||||
std::string::const_iterator i;
|
||||
|
||||
for(i=name.begin() ; i!=name.end() ; ++i)
|
||||
if( *i>='A' && *i<='Z' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ToSmallLetters(std::string & name)
|
||||
{
|
||||
std::string::iterator i;
|
||||
|
||||
for(i=name.begin() ; i!=name.end() ; ++i)
|
||||
*i = SmallLetter(*i);
|
||||
}
|
||||
|
||||
|
||||
ErrorCode AddAfterChecking(const std::string & name, const std::string & value, int param)
|
||||
{
|
||||
Table::iterator i = table.find(name);
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i != table.end() )
|
||||
// we have this object in our table
|
||||
return err_object_exists;
|
||||
|
||||
table.insert( std::make_pair(name, ObjectValue(value, param)) );
|
||||
table.insert( std::make_pair(name, Item(value, param)) );
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
this method returns 'true' if the table is empty
|
||||
*/
|
||||
bool Empty() const
|
||||
{
|
||||
return table.empty();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method clears the table
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
return table.clear();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'const_iterator' on the first item on the table
|
||||
*/
|
||||
CIterator Begin() const
|
||||
{
|
||||
return table.begin();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'const_iterator' pointing at the space after last item
|
||||
(returns table.end())
|
||||
*/
|
||||
CIterator End() const
|
||||
{
|
||||
return table.end();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
i->second.value = value;
|
||||
i->second.param = param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
|
||||
{
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator old_i = table.find(old_name);
|
||||
if( old_i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
if( old_name == new_name )
|
||||
// the new name is the same as the old one
|
||||
// we treat it as a normal situation
|
||||
return err_ok;
|
||||
|
||||
ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param);
|
||||
|
||||
if( err == err_ok )
|
||||
{
|
||||
old_i = table.find(old_name);
|
||||
TTMATH_ASSERT( old_i != table.end() )
|
||||
|
||||
table.erase(old_i);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const std::string & name)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Iterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
return err_unknown_object;
|
||||
|
||||
table.erase( i );
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
value.clear();
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
value = i->second.value;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
*value = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
value.empty();
|
||||
*param = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
value = i->second.value;
|
||||
*param = i->second.param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
CIterator i = table.find(name);
|
||||
|
||||
if( i == table.end() )
|
||||
{
|
||||
*value = 0;
|
||||
*param = 0;
|
||||
return err_unknown_object;
|
||||
}
|
||||
|
||||
*value = i->second.value.c_str();
|
||||
*param = i->second.param;
|
||||
|
||||
return err_ok;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns a pointer into the table
|
||||
*/
|
||||
Table * GetTable()
|
||||
{
|
||||
return &table;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Table table;
|
||||
|
||||
}; // end of class Objects
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
objects of the class History are used to keep values in functions
|
||||
which take a lot of time during calculating, for instance in the
|
||||
function Factorial(x)
|
||||
|
||||
it means that when we're calculating e.g. Factorial(1000) and the
|
||||
Factorial finds that we have calculated it before, the value (result)
|
||||
is taken from the history
|
||||
*/
|
||||
template<class ValueType>
|
||||
class History
|
||||
{
|
||||
/*!
|
||||
one item in the History's object holds a key, a value for the key
|
||||
and a corresponding error code
|
||||
*/
|
||||
struct Item
|
||||
{
|
||||
ValueType key, value;
|
||||
ErrorCode err;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
we use std::list for simply deleting the first item
|
||||
but because we're searching through the whole container
|
||||
(in the method Get) the container should not be too big
|
||||
(linear time of searching)
|
||||
*/
|
||||
typedef std::list<Item> buffer_type;
|
||||
buffer_type buffer;
|
||||
typename buffer_type::size_type buffer_max_size;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
default constructor
|
||||
default max size of the History's container is 10 items
|
||||
*/
|
||||
History()
|
||||
{
|
||||
buffer_max_size = 10;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor which takes another value of the max size
|
||||
of the History's container
|
||||
*/
|
||||
History(typename buffer_type::size_type new_size)
|
||||
{
|
||||
buffer_max_size = new_size;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method adds one item into the History
|
||||
if the size of the container is greater than buffer_max_size
|
||||
the first item will be removed
|
||||
*/
|
||||
void Add(const ValueType & key, const ValueType & value, ErrorCode err)
|
||||
{
|
||||
Item item;
|
||||
item.key = key;
|
||||
item.value = value;
|
||||
item.err = err;
|
||||
|
||||
buffer.insert( buffer.end(), item );
|
||||
|
||||
if( buffer.size() > buffer_max_size )
|
||||
buffer.erase(buffer.begin());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method checks whether we have an item which has the key equal 'key'
|
||||
|
||||
if there's such item the method sets the 'value' and the 'err'
|
||||
and returns true otherwise it returns false and 'value' and 'err'
|
||||
remain unchanged
|
||||
*/
|
||||
bool Get(const ValueType & key, ValueType & value, ErrorCode & err)
|
||||
{
|
||||
typename buffer_type::iterator i = buffer.begin();
|
||||
|
||||
for( ; i != buffer.end() ; ++i )
|
||||
{
|
||||
if( i->key == key )
|
||||
{
|
||||
value = i->value;
|
||||
err = i->err;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // end of class History
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
/*!
|
||||
\file ttmathparser.h
|
||||
\brief Mathematical parser
|
||||
\brief A mathematical parser
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
|
@ -654,13 +654,13 @@ void Tan(int sindex, int amount_of_args, ValueType & result)
|
|||
Error( err );
|
||||
}
|
||||
|
||||
void CTan(int sindex, int amount_of_args, ValueType & result)
|
||||
void Cot(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::CTan(stack[sindex].value, &err);
|
||||
result = ttmath::Cot(stack[sindex].value, &err);
|
||||
|
||||
if(err != err_ok)
|
||||
Error( err );
|
||||
|
@ -794,12 +794,12 @@ void ATan(int sindex, int amount_of_args, ValueType & result)
|
|||
}
|
||||
|
||||
|
||||
void ACTan(int sindex, int amount_of_args, ValueType & result)
|
||||
void ACot(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
result = ttmath::ACTan(stack[sindex].value);
|
||||
result = ttmath::ACot(stack[sindex].value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -889,6 +889,147 @@ void Not(int sindex, int amount_of_args, ValueType & result)
|
|||
result.SetZero();
|
||||
}
|
||||
|
||||
|
||||
void DegToRad(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
ErrorCode err;
|
||||
|
||||
if( amount_of_args == 1 )
|
||||
{
|
||||
result = ttmath::DegToRad(stack[sindex].value, &err);
|
||||
}
|
||||
else
|
||||
if( amount_of_args == 3 )
|
||||
{
|
||||
result = ttmath::DegToRad( stack[sindex].value, stack[sindex+2].value,
|
||||
stack[sindex+4].value, &err);
|
||||
}
|
||||
else
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void RadToDeg(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
ErrorCode err;
|
||||
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
result = ttmath::RadToDeg(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void DegToDeg(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 3 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::DegToDeg( stack[sindex].value, stack[sindex+2].value,
|
||||
stack[sindex+4].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
void Ceil(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Ceil(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Floor(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Floor(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
void Sqrt(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Sqrt(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Sinh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Sinh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Cosh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Cosh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Tanh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Tanh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Coth(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Coth(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns the value from a user-defined function
|
||||
|
||||
|
@ -902,7 +1043,7 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
|
|||
const char * string_value;
|
||||
int param;
|
||||
|
||||
if( puser_functions->GetValueParam(function_name, &string_value, ¶m) != err_ok )
|
||||
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok )
|
||||
return false;
|
||||
|
||||
if( param != amount_of_args )
|
||||
|
@ -1003,7 +1144,9 @@ void CreateFunctionsTable()
|
|||
InsertFunctionToTable(std::string("sin"), &Parser<ValueType>::Sin);
|
||||
InsertFunctionToTable(std::string("cos"), &Parser<ValueType>::Cos);
|
||||
InsertFunctionToTable(std::string("tan"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(std::string("ctan"), &Parser<ValueType>::CTan);
|
||||
InsertFunctionToTable(std::string("tg"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(std::string("cot"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(std::string("ctg"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(std::string("int"), &Parser<ValueType>::Int);
|
||||
InsertFunctionToTable(std::string("round"), &Parser<ValueType>::Round);
|
||||
InsertFunctionToTable(std::string("ln"), &Parser<ValueType>::Ln);
|
||||
|
@ -1014,13 +1157,27 @@ void CreateFunctionsTable()
|
|||
InsertFunctionToTable(std::string("asin"), &Parser<ValueType>::ASin);
|
||||
InsertFunctionToTable(std::string("acos"), &Parser<ValueType>::ACos);
|
||||
InsertFunctionToTable(std::string("atan"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(std::string("actan"), &Parser<ValueType>::ACTan);
|
||||
InsertFunctionToTable(std::string("atg"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(std::string("acot"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(std::string("actg"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(std::string("sgn"), &Parser<ValueType>::Sgn);
|
||||
InsertFunctionToTable(std::string("mod"), &Parser<ValueType>::Mod);
|
||||
InsertFunctionToTable(std::string("if"), &Parser<ValueType>::If);
|
||||
InsertFunctionToTable(std::string("or"), &Parser<ValueType>::Or);
|
||||
InsertFunctionToTable(std::string("and"), &Parser<ValueType>::And);
|
||||
InsertFunctionToTable(std::string("not"), &Parser<ValueType>::Not);
|
||||
InsertFunctionToTable(std::string("degtorad"), &Parser<ValueType>::DegToRad);
|
||||
InsertFunctionToTable(std::string("radtodeg"), &Parser<ValueType>::RadToDeg);
|
||||
InsertFunctionToTable(std::string("degtodeg"), &Parser<ValueType>::DegToDeg);
|
||||
InsertFunctionToTable(std::string("ceil"), &Parser<ValueType>::Ceil);
|
||||
InsertFunctionToTable(std::string("floor"), &Parser<ValueType>::Floor);
|
||||
InsertFunctionToTable(std::string("sqrt"), &Parser<ValueType>::Sqrt);
|
||||
InsertFunctionToTable(std::string("sinh"), &Parser<ValueType>::Sinh);
|
||||
InsertFunctionToTable(std::string("cosh"), &Parser<ValueType>::Cosh);
|
||||
InsertFunctionToTable(std::string("tanh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(std::string("tgh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(std::string("ctgh"), &Parser<ValueType>::Coth);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,14 +41,14 @@
|
|||
|
||||
/*!
|
||||
\file ttmathtypes.h
|
||||
\brief constants which are used in the library
|
||||
\brief constants used in the library
|
||||
|
||||
As our library is written in header files (templates) we cannot use
|
||||
constants like 'const int' etc. because we should have some source files
|
||||
*.cpp to define this variables. Only what we can have are constants
|
||||
defined by #define preprocessor macro.
|
||||
defined by #define preprocessor macros.
|
||||
|
||||
All macros are preceded TTMATH_ part
|
||||
All macros are preceded by TTMATH_ prefix
|
||||
*/
|
||||
|
||||
|
||||
|
@ -60,8 +60,8 @@
|
|||
the version of the library
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 7
|
||||
#define TTMATH_REVISION_VER 2
|
||||
#define TTMATH_MINOR_VER 8
|
||||
#define TTMATH_REVISION_VER 0
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -74,7 +74,7 @@
|
|||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_RELEASE
|
||||
if you are confident that your code is without bugs you can define TTMATH_RELEASE
|
||||
if you are confident that your code is perfect you can define TTMATH_RELEASE
|
||||
macro for example by using -D option in gcc
|
||||
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
||||
or by defining this macro in your code before using any header files of this library
|
||||
|
@ -86,23 +86,33 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
VC doesn't have these macros
|
||||
#if !defined(__i386__) && !defined(__amd64__)
|
||||
#error "This code is designed only for x86/amd64 platforms (amd64 is very experimental now)"
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
/*!
|
||||
on 32bit platforms one word will be equal 32bits
|
||||
on 64bit platforms one word will be 64bits
|
||||
*/
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*!
|
||||
we're using a 32bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
we're using a 64bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
/*!
|
||||
on 32bit platforms one word (uint, sint) will be equal 32bits
|
||||
*/
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
|
@ -116,16 +126,24 @@ namespace ttmath
|
|||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 32bit word (2^32 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||
|
||||
/*!
|
||||
the number of words (32bit words on 32bit platform)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128u
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||
*/
|
||||
typedef unsigned long uint;
|
||||
typedef signed long sint;
|
||||
|
||||
|
@ -139,13 +157,18 @@ namespace ttmath
|
|||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
||||
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 64bit word (2^64 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
||||
|
||||
/*!
|
||||
the number of words (64bit words on 64bit platforms)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 64ul
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -159,12 +182,12 @@ namespace ttmath
|
|||
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
|
||||
that means you can input values for example 1.2345 and 1,2345 as well
|
||||
|
||||
if you don't want it just put 0 there eg.
|
||||
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 here any special character which is used by the parser
|
||||
(for example a semicolon ';' shouldn't be here)
|
||||
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 ','
|
||||
|
@ -180,16 +203,16 @@ namespace ttmath
|
|||
note! there'll not be so many iterations, iterations are stopped when
|
||||
there is no sense to continue calculating (for example when the result
|
||||
still remains unchanged after adding next series and we know that the next
|
||||
series are smaller than previous)
|
||||
series are smaller than previous ones)
|
||||
*/
|
||||
#define TTMATH_ARITHMETIC_MAX_LOOP 5000
|
||||
|
||||
#define TTMATH_ARITHMETIC_MAX_LOOP 10000
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
error codes
|
||||
*/
|
||||
|
@ -225,7 +248,14 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
this simple class can be used in multithreading model
|
||||
(you can write your own class derived from this one)
|
||||
|
||||
for example: in some functions like Factorial()
|
||||
/at the moment only Factorial/ you can give a pointer to
|
||||
the 'stop object', if the method WasStopSignal() of this
|
||||
object returns true that means we should break the calculating
|
||||
and return
|
||||
*/
|
||||
class StopCalculating
|
||||
{
|
||||
|
@ -274,7 +304,7 @@ namespace ttmath
|
|||
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
|
||||
was used)
|
||||
|
||||
What is it the 'reference' error?
|
||||
What is the 'reference' error?
|
||||
Some kind of methods use a reference as their argument to another object,
|
||||
and the another object not always can be the same which is calling, e.g.
|
||||
Big<1,2> foo(10);
|
||||
|
@ -343,24 +373,28 @@ namespace ttmath
|
|||
|
||||
|
||||
|
||||
/*!
|
||||
look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
|
||||
*/
|
||||
#ifdef TTMATH_DEBUG
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||
#if defined(__FILE__) && defined(__LINE__)
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||
|
||||
/*
|
||||
if your compiler doesn't support macros __FILE__ and __LINE__
|
||||
you can above asserts change to:
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ReferenceError();
|
||||
#else
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ReferenceError();
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
#endif
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
*/
|
||||
#else
|
||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||
#define TTMATH_ASSERT(expression)
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
\brief template class UInt<uint>
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
|
@ -54,7 +56,7 @@ namespace ttmath
|
|||
{
|
||||
|
||||
/*!
|
||||
\brief it implements a big integer value without a sign
|
||||
\brief UInt implements a big integer value without a sign
|
||||
|
||||
value_size - how many bytes specify our value
|
||||
on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits
|
||||
|
@ -73,6 +75,47 @@ public:
|
|||
uint table[value_size];
|
||||
|
||||
|
||||
/*!
|
||||
this method is only for debugging purposes or when we want to make
|
||||
a table of a variable (constant) in ttmathbig.h
|
||||
|
||||
it prints the table in a nice form of several columns
|
||||
*/
|
||||
void PrintTable(std::ostream & output) const
|
||||
{
|
||||
// how many columns there'll be
|
||||
const int columns = 8;
|
||||
|
||||
int c = 1;
|
||||
for(int i=value_size-1 ; i>=0 ; --i)
|
||||
{
|
||||
output << "0x" << std::setfill('0');
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
output << std::setw(8);
|
||||
#else
|
||||
output << std::setw(16);
|
||||
#endif
|
||||
|
||||
output << std::hex << table[i];
|
||||
|
||||
if( i>0 )
|
||||
{
|
||||
output << ", ";
|
||||
|
||||
if( ++c > columns )
|
||||
{
|
||||
output << std::endl;
|
||||
c = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
it returns the size of the table
|
||||
*/
|
||||
|
@ -106,7 +149,7 @@ public:
|
|||
this method sets the max value which this class can hold
|
||||
(all bits will be one)
|
||||
*/
|
||||
void SetMaxValue()
|
||||
void SetMax()
|
||||
{
|
||||
for(uint i=0 ; i<value_size ; ++i)
|
||||
table[i] = TTMATH_UINT_MAX_VALUE;
|
||||
|
@ -117,12 +160,14 @@ public:
|
|||
this method sets the min value which this class can hold
|
||||
(for an unsigned integer value the zero is the smallest value)
|
||||
*/
|
||||
void SetMinValue()
|
||||
void SetMin()
|
||||
{
|
||||
SetZero();
|
||||
}
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
/*!
|
||||
this method copies the value stored in an another table
|
||||
|
@ -833,7 +878,7 @@ public:
|
|||
}
|
||||
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -1140,7 +1185,9 @@ public:
|
|||
return moving;
|
||||
}
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
/*
|
||||
this method returns the number of the highest set bit in one 32-bit word
|
||||
|
@ -1218,7 +1265,8 @@ public:
|
|||
}
|
||||
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
/*!
|
||||
this method sets a special bit in the 'value'
|
||||
|
@ -1291,7 +1339,9 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -1534,18 +1584,26 @@ public:
|
|||
*/
|
||||
void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
|
||||
{
|
||||
uint r2,r1,x1size,x2size,x1start,x2start;
|
||||
uint r2,r1;
|
||||
uint x1size=value_size, x2size=value_size;
|
||||
uint x1start=0, x2start=0;
|
||||
|
||||
result.SetZero();
|
||||
|
||||
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
|
||||
if( value_size > 2 )
|
||||
{
|
||||
// if the value_size is smaller than or equal to 2
|
||||
// there is no sense to set x1size (and others) to another values
|
||||
|
||||
if( x1size==0 || x2size==0 )
|
||||
return;
|
||||
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
|
||||
|
||||
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
|
||||
if( x1size==0 || x2size==0 )
|
||||
return;
|
||||
|
||||
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
|
||||
}
|
||||
|
||||
for(uint x1=x1start ; x1<x1size ; ++x1)
|
||||
{
|
||||
|
@ -1570,7 +1628,7 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -2486,7 +2544,7 @@ public:
|
|||
this method converts an UInt<another_size> type to this class
|
||||
|
||||
this operation has mainly sense if the value from p is
|
||||
equal or smaller than that one which is returned from UInt<value_size>::SetMaxValue()
|
||||
equal or smaller than that one which is returned from UInt<value_size>::SetMax()
|
||||
|
||||
it returns a carry if the value 'p' is too big
|
||||
*/
|
||||
|
@ -2518,6 +2576,18 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method converts the uint type to this class
|
||||
*/
|
||||
void FromUInt(uint value)
|
||||
{
|
||||
for(uint i=1 ; i<value_size ; ++i)
|
||||
table[i] = 0;
|
||||
|
||||
table[0] = value;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this operator converts an UInt<another_size> type to this class
|
||||
|
||||
|
@ -2541,29 +2611,60 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method convert an uint type to this class
|
||||
this method converts the uint type to this class
|
||||
*/
|
||||
UInt<value_size> & operator=(uint i)
|
||||
{
|
||||
SetZero();
|
||||
table[0] = i;
|
||||
FromUInt(i);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting an uint to this class
|
||||
a constructor for converting the uint to this class
|
||||
*/
|
||||
UInt(uint i)
|
||||
{
|
||||
operator=(i);
|
||||
FromUInt(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method converts the sint type to this class
|
||||
|
||||
we provide operator(sint) and the constructor(sint) in order to allow
|
||||
the programmer do that:
|
||||
UInt<..> type = 10;
|
||||
|
||||
this constant 10 has the int type (signed int), if we don't give such
|
||||
operators and constructors the compiler will not compile the program,
|
||||
because it has to make a conversion and doesn't know into which type
|
||||
(the UInt class has operator=(const char*), operator=(uint) etc.)
|
||||
*/
|
||||
UInt<value_size> & operator=(sint i)
|
||||
{
|
||||
FromUInt(uint(i));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting string to this class (with base=10)
|
||||
a constructor for converting the sint to this class
|
||||
|
||||
look at the description of UInt::operator=(sint)
|
||||
*/
|
||||
UInt(sint i)
|
||||
{
|
||||
FromUInt(uint(i));
|
||||
}
|
||||
|
||||
/*!
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
UInt(const char * s)
|
||||
{
|
||||
|
@ -2572,7 +2673,7 @@ public:
|
|||
|
||||
|
||||
/*!
|
||||
a constructor for converting string to this class (with base=10)
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
UInt(const std::string & s)
|
||||
{
|
||||
|
@ -2615,12 +2716,11 @@ public:
|
|||
/*!
|
||||
a destructor
|
||||
*/
|
||||
virtual ~UInt()
|
||||
~UInt()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method returns the lowest value from table
|
||||
|
||||
|
@ -3081,10 +3181,13 @@ public:
|
|||
}
|
||||
|
||||
|
||||
#if defined _M_X64 || defined __x86_64__
|
||||
|
||||
// these methods for 64bit processors are defined in 'ttmathuint64.h'
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
// these methods are for 64bit processors and are defined in 'ttmathuint64.h'
|
||||
UInt<value_size> & operator=(unsigned int i);
|
||||
UInt(unsigned int i);
|
||||
UInt<value_size> & operator=(signed int i);
|
||||
UInt(signed int i);
|
||||
void SetFromTable(const unsigned int * temp_table, uint temp_table_len);
|
||||
uint Add(const UInt<value_size> & ss2, uint c=0);
|
||||
uint AddInt(uint value, uint index = 0);
|
||||
|
|
|
@ -52,7 +52,83 @@ namespace ttmath
|
|||
*
|
||||
*/
|
||||
|
||||
#if defined _M_X64 || defined __x86_64__
|
||||
#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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -60,6 +136,8 @@ namespace ttmath
|
|||
(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
|
||||
|
@ -119,6 +197,8 @@ namespace ttmath
|
|||
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)
|
||||
*/
|
||||
|
@ -131,16 +211,8 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
/*
|
||||
this part might be compiled with for example visual c
|
||||
*/
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -206,7 +278,8 @@ namespace ttmath
|
|||
this method adds one word (at a specific position)
|
||||
and returns a carry (if it was)
|
||||
|
||||
e.g.
|
||||
***this method is created only on a 64bit platform***
|
||||
|
||||
|
||||
if we've got (value_size=3):
|
||||
table[0] = 10;
|
||||
|
@ -229,14 +302,8 @@ namespace ttmath
|
|||
register uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
@ -297,6 +364,8 @@ namespace ttmath
|
|||
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
|
||||
|
||||
|
@ -330,14 +399,8 @@ namespace ttmath
|
|||
register uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
@ -420,6 +483,8 @@ namespace ttmath
|
|||
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)
|
||||
*/
|
||||
|
@ -431,16 +496,9 @@ namespace ttmath
|
|||
register uint * p2 = const_cast<uint*>(ss2.table);
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -499,7 +557,7 @@ namespace ttmath
|
|||
this method subtracts one word (at a specific position)
|
||||
and returns a carry (if it was)
|
||||
|
||||
e.g.
|
||||
***this method is created only on a 64bit platform***
|
||||
|
||||
if we've got (value_size=3):
|
||||
table[0] = 10;
|
||||
|
@ -522,14 +580,8 @@ namespace ttmath
|
|||
register uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
@ -589,6 +641,8 @@ namespace ttmath
|
|||
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
|
||||
*/
|
||||
|
@ -598,17 +652,10 @@ namespace ttmath
|
|||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -653,6 +700,8 @@ namespace ttmath
|
|||
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
|
||||
*/
|
||||
|
@ -664,12 +713,7 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -718,6 +762,8 @@ namespace ttmath
|
|||
/*
|
||||
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)
|
||||
|
@ -725,15 +771,9 @@ namespace ttmath
|
|||
register sint result;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -758,6 +798,8 @@ namespace ttmath
|
|||
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.
|
||||
|
@ -769,15 +811,9 @@ namespace ttmath
|
|||
uint UInt<value_size>::SetBitInWord(uint value, uint bit)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -808,6 +844,8 @@ namespace ttmath
|
|||
|
||||
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>
|
||||
|
@ -824,16 +862,9 @@ namespace ttmath
|
|||
register uint result2_;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
@ -865,6 +896,8 @@ namespace ttmath
|
|||
/*!
|
||||
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:
|
||||
|
@ -884,15 +917,9 @@ namespace ttmath
|
|||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
|
||||
__asm
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
|
Loading…
Reference in New Issue