From 837490e8b978c4ef33215b156552a3b33159bbcf Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 28 Mar 2007 22:27:57 +0000 Subject: [PATCH] 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 --- CHANGELOG | 44 ++- README | 22 ++ TODO | 8 +- samples/Makefile | 13 +- samples/big.cpp | 97 ++++++ samples/int.cpp | 24 +- samples/parser.cpp | 34 ++ samples/uint.cpp | 16 +- ttmath/ttmath.h | 754 +++++++++++++++++++++++++++++++++-------- ttmath/ttmathbig.h | 380 ++++++++++++++++----- ttmath/ttmathint.h | 155 +++++++-- ttmath/ttmathobjects.h | 528 ++++++++++++++++++++--------- ttmath/ttmathparser.h | 173 +++++++++- ttmath/ttmathtypes.h | 110 +++--- ttmath/ttmathuint.h | 161 +++++++-- ttmath/ttmathuint64.h | 183 +++++----- 16 files changed, 2126 insertions(+), 576 deletions(-) create mode 100644 samples/big.cpp create mode 100644 samples/parser.cpp diff --git a/CHANGELOG b/CHANGELOG index b00da9f..6e872be 100644 --- a/CHANGELOG +++ b/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 diff --git a/README b/README index 139597f..fceebc2 100644 --- a/README +++ b/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 +Home page: http://sourceforge.net/projects/ttmath diff --git a/TODO b/TODO index ebf3cc1..4be364f 100644 --- a/TODO +++ b/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 + + diff --git a/samples/Makefile b/samples/Makefile index 72ef525..187b9a9 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -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 diff --git a/samples/big.cpp b/samples/big.cpp new file mode 100644 index 0000000..a120d84 --- /dev/null +++ b/samples/big.cpp @@ -0,0 +1,97 @@ +#include +#include + +// 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 +*/ diff --git a/samples/int.cpp b/samples/int.cpp index 735f26b..13760d2 100644 --- a/samples/int.cpp +++ b/samples/int.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -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 */ diff --git a/samples/parser.cpp b/samples/parser.cpp new file mode 100644 index 0000000..ba103dc --- /dev/null +++ b/samples/parser.cpp @@ -0,0 +1,34 @@ +#include +#include + + +// 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 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(err) + << std::endl; +} + +/* +the result (on 32 bit platform): + +-897705014.52573107 +*/ diff --git a/samples/uint.cpp b/samples/uint.cpp index 0104f9e..f6b0df4 100644 --- a/samples/uint.cpp +++ b/samples/uint.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -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 diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 66c392c..665c928 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -46,126 +46,21 @@ */ #include "ttmathbig.h" +#include "ttmathobjects.h" #include - namespace ttmath { - /*! - the factorial from given 'x' - e.g. - Factorial(4) = 4! = 1*2*3*4 - */ - template - 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 - 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 - 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 - 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 + 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 + 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 @@ -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 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 @@ -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 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 + 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 - 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 + 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 @@ -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 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 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 + 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 - 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) + { + static History 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 + 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 + 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 + 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 ' even if he uses the parser +*/ +#include "ttmathparser.h" + #endif diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 79ba286..6119a17 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -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 namespace ttmath { /*! - \brief it implements the big value + \brief Big implements the floating point numbers */ template 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 & pow) + { + TTMATH_REFERENCE_ASSERT( pow ) + + Big 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 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 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 & 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 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 & 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 & 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 & 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' 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 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 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 log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +/* + static Big 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 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::CharToDigit(*source, base)) != -1 ; ++source, ++index ) @@ -2804,7 +3024,7 @@ public: Big half; uint c; - half.SetDotOne(); + half.Set05(); if( IsSign() ) { diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index 6cb2800..0cfd275 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -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::SetMaxValue(); + UInt::SetMax(); UInt::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::SetZero(); UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; @@ -92,7 +92,7 @@ public: */ void SetSignOne() { - UInt::SetMaxValue(); + UInt::SetMax(); } @@ -106,10 +106,10 @@ public: { Int 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 temp; - temp.SetMinValue(); + temp.SetMin(); if( operator!=(temp) ) /* @@ -493,8 +494,6 @@ public: UInt::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::table[i] = fill; + + UInt::table[0] = uint(value); + } + + /*! this operator converts an UInt 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 & operator=(sint i) { - if(i<0) - SetSignOne(); - else - UInt::SetZero(); - - UInt::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 & operator=(uint i) + { + UInt::FromUInt(i); + + return *this; + } + + + /*! + a constructor for converting the uint to this class + */ + Int(uint i) + { + UInt::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 & 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 & operator=(unsigned int i) + { + UInt::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::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 Int(const Int & u) : UInt::size(value_size) @@ -607,9 +691,9 @@ public: /*! - a destructor + the destructor */ - virtual ~Int() + ~Int() { } @@ -683,7 +767,7 @@ public: { Int mmin; - mmin.SetMinValue(); + mmin.SetMin(); /* the reference to mmin will be automatically converted to the reference @@ -699,7 +783,7 @@ public: { Int mmax; - mmax.SetMaxValue(); + mmax.SetMax(); if( UInt::operator>( mmax ) ) return 1; @@ -747,10 +831,19 @@ public: * * methods for comparing * - * operators == and != will be the same as in the base class (UInt) * */ + bool operator==(const Int & l) const + { + return UInt::operator==(l); + } + + bool operator!=(const Int & l) const + { + return UInt::operator!=(l); + } + bool operator<(const Int & l) const { sint i=value_size-1; diff --git a/ttmath/ttmathobjects.h b/ttmath/ttmathobjects.h index 4dc0b7b..0d76a10 100644 --- a/ttmath/ttmathobjects.h +++ b/ttmath/ttmathobjects.h @@ -36,160 +36,83 @@ */ - #ifndef headerfilettmathobject #define headerfilettmathobject +/*! + \file ttmathobjects.h + \brief Mathematic functions. +*/ + #include "ttmathtypes.h" #include +#include #include -#include + 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 Table; + // 'Table' is the type of our table + typedef std::map 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 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 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 diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index aedd014..99380d8 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -42,7 +42,7 @@ /*! \file ttmathparser.h - \brief Mathematical parser + \brief A mathematical parser */ #include @@ -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::Sin); InsertFunctionToTable(std::string("cos"), &Parser::Cos); InsertFunctionToTable(std::string("tan"), &Parser::Tan); - InsertFunctionToTable(std::string("ctan"), &Parser::CTan); + InsertFunctionToTable(std::string("tg"), &Parser::Tan); + InsertFunctionToTable(std::string("cot"), &Parser::Cot); + InsertFunctionToTable(std::string("ctg"), &Parser::Cot); InsertFunctionToTable(std::string("int"), &Parser::Int); InsertFunctionToTable(std::string("round"), &Parser::Round); InsertFunctionToTable(std::string("ln"), &Parser::Ln); @@ -1014,13 +1157,27 @@ void CreateFunctionsTable() InsertFunctionToTable(std::string("asin"), &Parser::ASin); InsertFunctionToTable(std::string("acos"), &Parser::ACos); InsertFunctionToTable(std::string("atan"), &Parser::ATan); - InsertFunctionToTable(std::string("actan"), &Parser::ACTan); + InsertFunctionToTable(std::string("atg"), &Parser::ATan); + InsertFunctionToTable(std::string("acot"), &Parser::ACot); + InsertFunctionToTable(std::string("actg"), &Parser::ACot); InsertFunctionToTable(std::string("sgn"), &Parser::Sgn); InsertFunctionToTable(std::string("mod"), &Parser::Mod); InsertFunctionToTable(std::string("if"), &Parser::If); InsertFunctionToTable(std::string("or"), &Parser::Or); InsertFunctionToTable(std::string("and"), &Parser::And); InsertFunctionToTable(std::string("not"), &Parser::Not); + InsertFunctionToTable(std::string("degtorad"), &Parser::DegToRad); + InsertFunctionToTable(std::string("radtodeg"), &Parser::RadToDeg); + InsertFunctionToTable(std::string("degtodeg"), &Parser::DegToDeg); + InsertFunctionToTable(std::string("ceil"), &Parser::Ceil); + InsertFunctionToTable(std::string("floor"), &Parser::Floor); + InsertFunctionToTable(std::string("sqrt"), &Parser::Sqrt); + InsertFunctionToTable(std::string("sinh"), &Parser::Sinh); + InsertFunctionToTable(std::string("cosh"), &Parser::Cosh); + InsertFunctionToTable(std::string("tanh"), &Parser::Tanh); + InsertFunctionToTable(std::string("tgh"), &Parser::Tanh); + InsertFunctionToTable(std::string("coth"), &Parser::Coth); + InsertFunctionToTable(std::string("ctgh"), &Parser::Coth); } diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index f5b9549..c3bc2e7 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -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) diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index 4b43954..43a6013 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -45,6 +45,8 @@ \brief template class UInt */ +#include +#include #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 & ss2, UInt & 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 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::SetMaxValue() + equal or smaller than that one which is returned from UInt::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 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 & 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 & 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 & operator=(unsigned int i); + UInt(unsigned int i); + UInt & operator=(signed int i); + UInt(signed int i); void SetFromTable(const unsigned int * temp_table, uint temp_table_len); uint Add(const UInt & ss2, uint c=0); uint AddInt(uint value, uint index = 0); diff --git a/ttmath/ttmathuint64.h b/ttmath/ttmathuint64.h index 123ddac..381805e 100644 --- a/ttmath/ttmathuint64.h +++ b/ttmath/ttmathuint64.h @@ -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 & UInt::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::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 & UInt::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::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(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 sint UInt::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::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 @@ -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__(