- update to current root trunc's version

- update to root trunc's UNICODE support

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@182 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Christian Kaiser 2009-07-29 10:46:48 +00:00
commit 51e938eaa7
12 changed files with 2250 additions and 1520 deletions

View File

@ -1,3 +1,28 @@
Version 0.9.0 prerelease (2009.07.16):
* added: support for wide characters (wchar_t)
wide characters are used when macro TTMATH_USE_WCHAR is defined
this macro is defined automatically when there is macro UNICODE or _UNICODE defined
some types have been changed
char -> tt_char
std::string -> tt_string
std::ostringstream -> tt_ostringstream
std::ostream -> tt_ostream
std::istream -> tt_istream
normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on)
(all typedef's are in ttmathtypes.h)
* added: Big::IsInteger()
returns true if the value is integer (without fraction)
(NaN flag is not checked)
* added: global Gamma() function
* added: gamma() function to the parser
* added: CGamma<ValueType> class
is used with Gamma() and Factorial() in multithreaded environment
* changed: Factorial() is using the Gamma() function now
* removed: Parser<>::SetFactorialMax() method
the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial
Version 0.8.5 (2009.06.16): Version 0.8.5 (2009.06.16):
* fixed: Big::Mod(x) didn't correctly return a carry * fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x) and the result was sometimes very big (even greater than x)

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -45,12 +45,14 @@
\brief Mathematics functions. \brief Mathematics functions.
*/ */
#include "ttmathconfig.h" #ifdef _MSC_VER
//warning C4127: conditional expression is constant
#pragma warning( disable: 4127 )
#endif
#include "ttmathbig.h" #include "ttmathbig.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"
#include <string>
namespace ttmath namespace ttmath
{ {
@ -72,7 +74,7 @@ namespace ttmath
/*! /*!
this method skips the fraction from x this function skips the fraction from x
e.g 2.2 = 2 e.g 2.2 = 2
2.7 = 2 2.7 = 2
-2.2 = 2 -2.2 = 2
@ -89,7 +91,7 @@ namespace ttmath
/*! /*!
this method rounds to the nearest integer value this function rounds to the nearest integer value
e.g 2.2 = 2 e.g 2.2 = 2
2.7 = 3 2.7 = 3
-2.2 = -2 -2.2 = -2
@ -221,7 +223,7 @@ namespace ttmath
/*! /*!
this method calculates the natural logarithm (logarithm with the base 'e') this function calculates the natural logarithm (logarithm with the base 'e')
*/ */
template<class ValueType> template<class ValueType>
ValueType Ln(const ValueType & x, ErrorCode * err = 0) ValueType Ln(const ValueType & x, ErrorCode * err = 0)
@ -262,7 +264,7 @@ namespace ttmath
/*! /*!
this method calculates the logarithm this function calculates the logarithm
*/ */
template<class ValueType> template<class ValueType>
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
@ -303,7 +305,7 @@ namespace ttmath
/*! /*!
this method calculates the expression e^x this function calculates the expression e^x
*/ */
template<class ValueType> template<class ValueType>
ValueType Exp(const ValueType & x, ErrorCode * err = 0) ValueType Exp(const ValueType & x, ErrorCode * err = 0)
@ -1936,10 +1938,7 @@ namespace ttmath
template<class ValueType> template<class ValueType>
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
{ {
ValueType indexfrac(index); if( !index.IsInteger() )
indexfrac.RemainFraction();
if( !indexfrac.IsZero() )
{ {
// index must be integer // index must be integer
if( err ) if( err )
@ -2071,156 +2070,6 @@ namespace ttmath
namespace auxiliaryfunctions
{
template<class ValueType>
uint FactorialInt( const ValueType & x, ErrorCode * err,
const volatile StopCalculating * stop,
ValueType & result)
{
uint maxvalue = TTMATH_UINT_MAX_VALUE;
if( x < TTMATH_UINT_MAX_VALUE )
x.ToUInt(maxvalue);
uint multipler = 1;
uint carry = 0;
while( !carry && multipler<maxvalue )
{
if( stop && (multipler & 127)==0 ) // it means 'stop && (multipler % 128)==0'
{
// after each 128 iterations we make a test
if( stop->WasStopSignal() )
{
if( err )
*err = err_interrupt;
return 2;
}
}
++multipler;
carry += result.MulUInt(multipler);
}
if( err )
*err = carry ? err_overflow : err_ok;
return carry ? 1 : 0;
}
template<class ValueType>
int FactorialMore( const ValueType & x, ErrorCode * err,
const volatile StopCalculating * stop,
ValueType & result)
{
ValueType multipler(TTMATH_UINT_MAX_VALUE);
ValueType one;
one.SetOne();
uint carry = 0;
uint iter = 1; // only for testing the stop object
while( !carry && multipler < x )
{
if( stop && (iter & 31)==0 ) // it means 'stop && (iter % 32)==0'
{
// after each 32 iterations we make a test
if( stop->WasStopSignal() )
{
if( err )
*err = err_interrupt;
return 2;
}
}
carry += multipler.Add(one);
carry += result.Mul(multipler);
++iter;
}
if( err )
*err = carry ? err_overflow : err_ok;
return carry ? 1 : 0;
}
} // namespace
/*!
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)
{
using namespace auxiliaryfunctions;
static History<ValueType> history;
ValueType result;
if( x.IsNan() || x.IsSign() )
{
if( err )
*err = err_improper_argument;
return result; // NaN set by default
}
result.SetOne();
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;
result.SetNan();
return result;
}
ErrorCode err_tmp;
TTMATH_USE_THREADSAFE_OBJ(history);
if( history.Get(x, result, err_tmp) )
{
if( err )
*err = err_tmp;
return result;
}
uint status = FactorialInt(x, err, stop, result);
if( status == 0 )
status = FactorialMore(x, err, stop, result);
if( status == 2 )
{
// the calculation has been interrupted
result.SetNan();
return result;
}
err_tmp = status==1 ? err_overflow : err_ok;
history.Add(x, result, err_tmp);
return result;
}
/*! /*!
absolute value of x absolute value of x
e.g. -2 = 2 e.g. -2 = 2
@ -2255,7 +2104,7 @@ namespace ttmath
the remainder from a division the remainder from a division
e.g. e.g.
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
mod( 12.6 ; -3) = 0.6 mod( 12.6 ; -3) = 0.6
mod(-12.6 ; -3) = -0.6 mod(-12.6 ; -3) = -0.6
@ -2281,6 +2130,653 @@ namespace ttmath
namespace auxiliaryfunctions
{
/*!
this function is used to store factorials in a given container
'more' means how many values should be added at the end
e.g.
std::vector<ValueType> fact;
SetFactorialSequence(fact, 3);
// now the container has three values: 1 1 2
SetFactorialSequence(fact, 2);
// now the container has five values: 1 1 2 6 24
*/
template<class ValueType>
void SetFactorialSequence(std::vector<ValueType> & fact, uint more = 20)
{
if( more == 0 )
more = 1;
uint start = static_cast<uint>(fact.size());
fact.resize(fact.size() + more);
if( start == 0 )
{
fact[0] = 1;
++start;
}
for(uint i=start ; i<fact.size() ; ++i)
{
fact[i] = fact[i-1];
fact[i].MulInt(i);
}
}
/*!
an auxiliary function used to calculate Bernoulli numbers
this function returns a sum:
sum(m) = sum_{k=0}^{m-1} {2^k * (m k) * B(k)} k in [0, m-1] (m k) means binomial coefficient = (m! / (k! * (m-k)!))
you should have sufficient factorials in cgamma.fact
(cgamma.fact should have at least m items)
n_ should be equal 2
*/
template<class ValueType>
ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
const volatile StopCalculating * stop = 0)
{
ValueType k_, temp, temp2, temp3, sum;
sum.SetZero();
for(uint k=0 ; k<m ; ++k) // k<m means k<=m-1
{
if( stop && (k & 15)==0 ) // means: k % 16 == 0
if( stop->WasStopSignal() )
return ValueType(); // NaN
if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero
continue;
k_ = k;
temp = n_; // n_ is equal 2
temp.Pow(k_);
// temp = 2^k
temp2 = cgamma.fact[m];
temp3 = cgamma.fact[k];
temp3.Mul(cgamma.fact[m-k]);
temp2.Div(temp3);
// temp2 = (m k) = m! / ( k! * (m-k)! )
temp.Mul(temp2);
temp.Mul(cgamma.bern[k]);
sum.Add(temp);
// sum += 2^k * (m k) * B(k)
if( sum.IsNan() )
break;
}
return sum;
}
/*!
an auxiliary function used to calculate Bernoulli numbers
start is >= 2
we use the recurrence formula:
B(m) = 1 / (2*(1 - 2^m)) * sum(m)
where sum(m) is calculated by SetBernoulliNumbersSum()
*/
template<class ValueType>
bool SetBernoulliNumbersMore(CGamma<ValueType> & cgamma, uint start, const volatile StopCalculating * stop = 0)
{
ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_;
const uint n = 2;
n_ = n;
// start is >= 2
for(uint m=start ; m<cgamma.bern.size() ; ++m)
{
if( (m & 1) == 1 )
{
cgamma.bern[m].SetZero();
}
else
{
m_ = m;
temp = n_; // n_ = 2
temp.Pow(m_);
// temp = 2^m
denominator.SetOne();
denominator.Sub(temp);
if( denominator.exponent.AddOne() ) // it means: denominator.MulInt(2)
denominator.SetNan();
// denominator = 2 * (1 - 2^m)
cgamma.bern[m] = SetBernoulliNumbersSum(cgamma, n_, m, stop);
if( stop && stop->WasStopSignal() )
{
cgamma.bern.resize(m); // valid numbers are in [0, m-1]
return false;
}
cgamma.bern[m].Div(denominator);
}
}
return true;
}
/*!
this function is used to calculate Bernoulli numbers,
returns false if there was a stop signal,
'more' means how many values should be added at the end
e.g.
typedef Big<1,2> MyBig;
CGamma<MyBig> cgamma;
SetBernoulliNumbers(cgamma, 3);
// now we have three first Bernoulli numbers: 1 -0.5 0.16667
SetBernoulliNumbers(cgamma, 4);
// now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238
*/
template<class ValueType>
bool SetBernoulliNumbers(CGamma<ValueType> & cgamma, uint more = 20, const volatile StopCalculating * stop = 0)
{
if( more == 0 )
more = 1;
uint start = static_cast<uint>(cgamma.bern.size());
cgamma.bern.resize(cgamma.bern.size() + more);
if( start == 0 )
{
cgamma.bern[0].SetOne();
++start;
}
if( cgamma.bern.size() == 1 )
return true;
if( start == 1 )
{
cgamma.bern[1].Set05();
cgamma.bern[1].ChangeSign();
++start;
}
// we should have sufficient factorials in cgamma.fact
if( cgamma.fact.size() < cgamma.bern.size() )
SetFactorialSequence(cgamma.fact, static_cast<uint>(cgamma.bern.size() - cgamma.fact.size()));
return SetBernoulliNumbersMore(cgamma, start, stop);
}
/*!
an auxiliary function used to calculate the Gamma() function
we calculate a sum:
sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ...
B(m) means a mth Bernoulli number
the sum starts from m=2, we calculate as long as the value will not change after adding a next part
*/
template<class ValueType>
ValueType GammaFactorialHighSum(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
const volatile StopCalculating * stop)
{
ValueType temp, temp2, denominator, sum, oldsum;
sum.SetZero();
for(uint m=2 ; m<TTMATH_ARITHMETIC_MAX_LOOP ; m+=2)
{
if( stop && (m & 3)==0 ) // (m & 3)==0 means: (m % 4)==0
if( stop->WasStopSignal() )
{
err = err_interrupt;
return ValueType(); // NaN
}
temp = (m-1);
denominator = n;
denominator.Pow(temp);
// denominator = n ^ (m-1)
temp = m;
temp2 = temp;
temp.Mul(temp2);
temp.Sub(temp2);
// temp = m^2 - m
denominator.Mul(temp);
// denominator = (m^2 - m) * n ^ (m-1)
if( m >= cgamma.bern.size() )
{
if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed
{
// there was the stop signal
err = err_interrupt;
return ValueType(); // NaN
}
}
temp = cgamma.bern[m];
temp.Div(denominator);
oldsum = sum;
sum.Add(temp);
if( sum.IsNan() || oldsum==sum )
break;
}
return sum;
}
/*!
an auxiliary function used to calculate the Gamma() function
we calculate a helper function GammaFactorialHigh() by using Stirling's series:
n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) )
where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY)
and sum(n) is calculated by GammaFactorialHighSum()
*/
template<class ValueType>
ValueType GammaFactorialHigh(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
const volatile StopCalculating * stop)
{
ValueType temp, temp2, temp3, denominator, sum;
temp.Set2Pi();
temp.Mul(n);
temp2 = Sqrt(temp);
// temp2 = sqrt(2*pi*n)
temp = n;
temp3.SetE();
temp.Div(temp3);
temp.Pow(n);
// temp = (n/e)^n
sum = GammaFactorialHighSum(n, cgamma, err, stop);
temp3.Exp(sum);
// temp3 = exp(sum)
temp.Mul(temp2);
temp.Mul(temp3);
return temp;
}
/*!
an auxiliary function used to calculate the Gamma() function
Gamma(x) = GammaFactorialHigh(x-1)
*/
template<class ValueType>
ValueType GammaPlusHigh(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
{
ValueType one;
one.SetOne();
n.Sub(one);
return GammaFactorialHigh(n, cgamma, err, stop);
}
/*!
an auxiliary function used to calculate the Gamma() function
we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
we use the formula:
gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1)
*/
template<class ValueType>
ValueType GammaPlusLowIntegerInt(uint n, CGamma<ValueType> & cgamma)
{
TTMATH_ASSERT( n > 0 )
if( n - 1 < static_cast<uint>(cgamma.fact.size()) )
return cgamma.fact[n - 1];
ValueType res;
uint start = 2;
if( cgamma.fact.size() < 2 )
{
res.SetOne();
}
else
{
start = static_cast<uint>(cgamma.fact.size());
res = cgamma.fact[start-1];
}
for(uint i=start ; i<n ; ++i)
res.MulInt(i);
return res;
}
/*!
an auxiliary function used to calculate the Gamma() function
we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
*/
template<class ValueType>
ValueType GammaPlusLowInteger(const ValueType & n, CGamma<ValueType> & cgamma)
{
sint n_;
n.ToInt(n_);
return GammaPlusLowIntegerInt(n_, cgamma);
}
/*!
an auxiliary function used to calculate the Gamma() function
we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
we use a recurrence formula:
gamma(z+1) = z * gamma(z)
then: gamma(z) = gamma(z+1) / z
e.g.
gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 )
*/
template<class ValueType>
ValueType GammaPlusLow(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
{
ValueType one, denominator, temp, boundary;
if( n.IsInteger() )
return GammaPlusLowInteger(n, cgamma);
one.SetOne();
denominator = n;
boundary = TTMATH_GAMMA_BOUNDARY;
while( n < boundary )
{
n.Add(one);
denominator.Mul(n);
}
n.Add(one);
// now n is sufficient big
temp = GammaPlusHigh(n, cgamma, err, stop);
temp.Div(denominator);
return temp;
}
/*!
an auxiliary function used to calculate the Gamma() function
*/
template<class ValueType>
ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
{
if( n > TTMATH_GAMMA_BOUNDARY )
return GammaPlusHigh(n, cgamma, err, stop);
return GammaPlusLow(n, cgamma, err, stop);
}
/*!
an auxiliary function used to calculate the Gamma() function
this function is used when n is negative
we use the reflection formula:
gamma(1-z) * gamma(z) = pi / sin(pi*z)
then: gamma(z) = pi / (sin(pi*z) * gamma(1-z))
*/
template<class ValueType>
ValueType GammaMinus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
{
ValueType pi, denominator, temp, temp2;
if( n.IsInteger() )
{
// gamma function is not defined when n is negative and integer
err = err_improper_argument;
return temp; // NaN
}
pi.SetPi();
temp = pi;
temp.Mul(n);
temp2 = Sin(temp);
// temp2 = sin(pi * n)
temp.SetOne();
temp.Sub(n);
temp = GammaPlus(temp, cgamma, err, stop);
// temp = gamma(1 - n)
temp.Mul(temp2);
pi.Div(temp);
return pi;
}
} // namespace auxiliaryfunctions
/*!
this function calculates the Gamma function
it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma()
e.g.
typedef Big<1,2> MyBig;
MyBig x=234, y=345.53;
CGamma<MyBig> cgamma;
std::cout << Gamma(x, cgamma) << std::endl;
std::cout << Gamma(y, cgamma) << std::endl;
in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
and they will be reused in next calls to the function
each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too
*/
template<class ValueType>
ValueType Gamma(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
const volatile StopCalculating * stop = 0)
{
using namespace auxiliaryfunctions;
ValueType result;
ErrorCode err_tmp;
if( n.IsNan() )
{
if( err )
*err = err_improper_argument;
return result; // NaN is set by default
}
TTMATH_USE_THREADSAFE_OBJ(cgamma.history);
if( cgamma.history.Get(n, result, err_tmp) )
{
if( err )
*err = err_tmp;
return result;
}
err_tmp = err_ok;
if( n.IsSign() )
{
result = GammaMinus(n, cgamma, err_tmp, stop);
}
else
if( n.IsZero() )
{
err_tmp = err_improper_argument;
result.SetNan();
}
else
{
result = GammaPlus(n, cgamma, err_tmp, stop);
}
if( result.IsNan() && err_tmp==err_ok )
err_tmp = err_overflow;
if( err )
*err = err_tmp;
if( stop && !stop->WasStopSignal() )
cgamma.history.Add(n, result, err_tmp);
return result;
}
/*!
this function calculates the Gamma function
note: this function should be used only in a single-thread environment
*/
template<class ValueType>
ValueType Gamma(const ValueType & n, ErrorCode * err = 0)
{
// warning: this static object is not thread safe
static CGamma<ValueType> cgamma;
return Gamma(n, cgamma, err);
}
namespace auxiliaryfunctions
{
/*!
an auxiliary function for calculating the factorial function
we use the formula:
x! = gamma(x+1)
*/
template<class ValueType>
ValueType Factorial2(ValueType x, CGamma<ValueType> * cgamma = 0, ErrorCode * err = 0,
const volatile StopCalculating * stop = 0)
{
ValueType result, one;
if( x.IsNan() || x.IsSign() || !x.IsInteger() )
{
if( err )
*err = err_improper_argument;
return result; // NaN set by default
}
one.SetOne();
x.Add(one);
if( cgamma )
return Gamma(x, *cgamma, err, stop);
return Gamma(x, err);
}
} // namespace auxiliaryfunctions
/*!
the factorial from given 'x'
e.g.
Factorial(4) = 4! = 1*2*3*4
it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial()
e.g.
typedef Big<1,2> MyBig;
MyBig x=234, y=345.53;
CGamma<MyBig> cgamma;
std::cout << Factorial(x, cgamma) << std::endl;
std::cout << Factorial(y, cgamma) << std::endl;
in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
and they will be reused in next calls to the function
each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too
*/
template<class ValueType>
ValueType Factorial(const ValueType & x, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
const volatile StopCalculating * stop = 0)
{
return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop);
}
/*!
the factorial from given 'x'
e.g.
Factorial(4) = 4! = 1*2*3*4
note: this function should be used only in a single-thread environment
*/
template<class ValueType>
ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
{
return auxiliaryfunctions::Factorial2(x, 0, err, 0);
}
/*!
this method prepares some coefficients: factorials and Bernoulli numbers
stored in 'fact' and 'bern' objects
we're defining the method here because we're using Gamma() function which
is not available in ttmathobjects.h
read the doc info in ttmathobjects.h file where CGamma<> struct is declared
*/
template<class ValueType>
void CGamma<ValueType>::InitAll()
{
ValueType x = TTMATH_GAMMA_BOUNDARY + 1;
// history.Remove(x) removes only one object
// we must be sure that there are not others objects with the key 'x'
while( history.Remove(x) )
{
}
// the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1)
// when x is larger then less coefficients we need
Gamma(x, *this);
}
} // namespace } // namespace
@ -2296,5 +2792,4 @@ namespace ttmath
//warning C4127: conditional expression is constant //warning C4127: conditional expression is constant
#endif #endif
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -38,6 +38,8 @@
#ifndef headerfilettmathbig #ifndef headerfilettmathbig
#define headerfilettmathbig #define headerfilettmathbig
#include "ttmathconfig.h"
/*! /*!
\file ttmathbig.h \file ttmathbig.h
\brief A Class for representing floating point numbers \brief A Class for representing floating point numbers
@ -85,7 +87,7 @@ public:
Int<exp> exponent; Int<exp> exponent;
UInt<man> mantissa; UInt<man> mantissa;
tchar_t info; tt_char info;
/*! /*!
@ -271,7 +273,7 @@ private:
// 3101 digits were taken from this website // 3101 digits were taken from this website
// (later the digits were compared with: // (later the digits were compared with:
// http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html ) // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
// and they were set into Big<1,400> type (using operator=(const tchar_t*) on a 32bit platform) // and they were set into Big<1,400> type (using operator=(const tt_char*) on a 32bit platform)
// and then the first 256 words were taken into this table // and then the first 256 words were taken into this table
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
// and on 64bit platform value 128 (256/2=128)) // and on 64bit platform value 128 (256/2=128))
@ -1369,10 +1371,7 @@ public:
if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 ) if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
{ {
Big<exp, man> pow_frac( pow ); if( pow.IsInteger() )
pow_frac.RemainFraction();
if( pow_frac.IsZero() )
return PowInt( pow ); return PowInt( pow );
} }
@ -2718,20 +2717,20 @@ public:
output: output:
return value: return value:
0 - ok and 'result' will be an object of type tstr_t which holds the value 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
1 - if there was a carry (shoudn't be in a normal situation - if is that means there 1 - if there was a carry (shoudn't be in a normal situation - if is that means there
is somewhere an error in the library) is somewhere an error in the library)
*/ */
uint ToString( tstr_t & result, uint ToString( tt_string & result,
uint base = 10, uint base = 10,
bool always_scientific = false, bool always_scientific = false,
sint when_scientific = 15, sint when_scientific = 15,
sint max_digit_after_comma = -1, sint max_digit_after_comma = -1,
bool remove_trailing_zeroes = true, bool remove_trailing_zeroes = true,
tchar_t decimal_point = TTMATH_COMMA_CHARACTER_1 ) const tt_char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
{ {
static tchar_t error_overflow_msg[] = TTMATH_TEXT("overflow"); static tt_char error_overflow_msg[] = TTMATH_TEXT("overflow");
static tchar_t error_nan_msg[] = TTMATH_TEXT("NaN"); static tt_char error_nan_msg[] = TTMATH_TEXT("NaN");
result.erase(); result.erase();
if( IsNan() ) if( IsNan() )
@ -2748,7 +2747,7 @@ public:
if( IsZero() ) if( IsZero() )
{ {
result = TTMATH_TEXT("0"); result = '0';
return 0; return 0;
} }
@ -2873,7 +2872,7 @@ private:
but we need 'new'exp' as integer then we take: but we need 'new'exp' as integer then we take:
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
*/ */
uint ToString_CreateNewMantissaAndExponent( tstr_t & new_man, uint base, uint ToString_CreateNewMantissaAndExponent( tt_string & new_man, uint base,
Int<exp+1> & new_exp) const Int<exp+1> & new_exp) const
{ {
uint c = 0; uint c = 0;
@ -3057,7 +3056,7 @@ private:
(we can make that speciality when the base is 4,8 or 16 as well (we can make that speciality when the base is 4,8 or 16 as well
but maybe in further time) but maybe in further time)
*/ */
uint ToString_CreateNewMantissaAndExponent_Base2( tstr_t & new_man, uint ToString_CreateNewMantissaAndExponent_Base2( tt_string & new_man,
Int<exp+1> & new_exp ) const Int<exp+1> & new_exp ) const
{ {
for( sint i=man-1 ; i>=0 ; --i ) for( sint i=man-1 ; i>=0 ; --i )
@ -3087,13 +3086,13 @@ private:
this method roundes the last character from the new mantissa this method roundes the last character from the new mantissa
(it's used in systems where the base is different from 2) (it's used in systems where the base is different from 2)
*/ */
uint ToString_RoundMantissa(tstr_t & new_man, uint base, Int<exp+1> & new_exp, tchar_t decimal_point) const uint ToString_RoundMantissa(tt_string & new_man, uint base, Int<exp+1> & new_exp, tt_char decimal_point) const
{ {
// we must have minimum two characters // we must have minimum two characters
if( new_man.length() < 2 ) if( new_man.length() < 2 )
return 0; return 0;
tstr_t::size_type i = new_man.length() - 1; tt_string::size_type i = new_man.length() - 1;
// we're erasing the last character // we're erasing the last character
uint digit = UInt<man>::CharToDigit( new_man[i] ); uint digit = UInt<man>::CharToDigit( new_man[i] );
@ -3114,7 +3113,7 @@ private:
this method addes one into the new mantissa this method addes one into the new mantissa
*/ */
void ToString_RoundMantissa_AddOneIntoMantissa(tstr_t & new_man, uint base, tchar_t decimal_point) const void ToString_RoundMantissa_AddOneIntoMantissa(tt_string & new_man, uint base, tt_char decimal_point) const
{ {
if( new_man.empty() ) if( new_man.empty() )
return; return;
@ -3138,7 +3137,7 @@ private:
else else
was_carry = false; was_carry = false;
new_man[i] = static_cast<char>( UInt<man>::DigitToChar(digit) ); new_man[i] = static_cast<tt_char>( UInt<man>::DigitToChar(digit) );
} }
if( i<0 && was_carry ) if( i<0 && was_carry )
@ -3152,13 +3151,13 @@ private:
this method sets the comma operator and/or puts the exponent this method sets the comma operator and/or puts the exponent
into the string into the string
*/ */
uint ToString_SetCommaAndExponent( tstr_t & new_man, uint base, uint ToString_SetCommaAndExponent( tt_string & new_man, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
bool always_scientific, bool always_scientific,
sint when_scientific, sint when_scientific,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
uint carry = 0; uint carry = 0;
@ -3198,12 +3197,12 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal( void ToString_SetCommaAndExponent_Normal(
tstr_t & new_man, tt_string & new_man,
uint base, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
if( !new_exp.IsSign() ) //if( new_exp >= 0 ) if( !new_exp.IsSign() ) //if( new_exp >= 0 )
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
@ -3215,7 +3214,7 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal_AddingZero(tstr_t & new_man, void ToString_SetCommaAndExponent_Normal_AddingZero(tt_string & new_man,
Int<exp+1> & new_exp) const Int<exp+1> & new_exp) const
{ {
// we're adding zero characters at the end // we're adding zero characters at the end
@ -3235,12 +3234,12 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal_SetCommaInside( void ToString_SetCommaAndExponent_Normal_SetCommaInside(
tstr_t & new_man, tt_string & new_man,
uint base, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
// new_exp is < 0 // new_exp is < 0
@ -3259,7 +3258,7 @@ private:
// we're adding zero characters before the mantissa // we're adding zero characters before the mantissa
uint how_many = e - new_man_len; uint how_many = e - new_man_len;
tstr_t man_temp(how_many+1, '0'); tt_string man_temp(how_many+1, '0');
man_temp.insert( man_temp.begin()+1, decimal_point); man_temp.insert( man_temp.begin()+1, decimal_point);
new_man.insert(0, man_temp); new_man.insert(0, man_temp);
@ -3272,12 +3271,12 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Scientific( tstr_t & new_man, void ToString_SetCommaAndExponent_Scientific( tt_string & new_man,
uint base, uint base,
Int<exp+1> & scientific_exp, Int<exp+1> & scientific_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
if( new_man.empty() ) if( new_man.empty() )
return; return;
@ -3291,7 +3290,7 @@ private:
new_man += 'e'; new_man += 'e';
if( !scientific_exp.IsSign() ) if( !scientific_exp.IsSign() )
new_man += TTMATH_TEXT("+"); new_man += '+';
} }
else else
{ {
@ -3300,7 +3299,7 @@ private:
new_man += TTMATH_TEXT("*10^"); new_man += TTMATH_TEXT("*10^");
} }
tstr_t temp_exp; tt_string temp_exp;
scientific_exp.ToString( temp_exp, base ); scientific_exp.ToString( temp_exp, base );
new_man += temp_exp; new_man += temp_exp;
@ -3310,11 +3309,11 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma( tstr_t & new_man, void ToString_CorrectDigitsAfterComma( tt_string & new_man,
uint base, uint base,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
if( max_digit_after_comma >= 0 ) if( max_digit_after_comma >= 0 )
ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point); ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point);
@ -3328,8 +3327,8 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
tstr_t & new_man, tt_string & new_man,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
// minimum two characters // minimum two characters
if( new_man.length() < 2 ) if( new_man.length() < 2 )
@ -3347,7 +3346,7 @@ private:
// we must have a comma // we must have a comma
// (the comma can be removed by ToString_CorrectDigitsAfterComma_Round // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
// which is called before) // which is called before)
if( new_man.find_last_of(decimal_point, i) == tstr_t::npos ) if( new_man.find_last_of(decimal_point, i) == tt_string::npos )
return; return;
// if directly before the first zero is the comma operator // if directly before the first zero is the comma operator
@ -3363,26 +3362,26 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma_Round( void ToString_CorrectDigitsAfterComma_Round(
tstr_t & new_man, tt_string & new_man,
uint base, uint base,
sint max_digit_after_comma, sint max_digit_after_comma,
tchar_t decimal_point) const tt_char decimal_point) const
{ {
// first we're looking for the comma operator // first we're looking for the comma operator
tstr_t::size_type index = new_man.find(decimal_point, 0); tt_string::size_type index = new_man.find(decimal_point, 0);
if( index == tstr_t::npos ) if( index == tt_string::npos )
// nothing was found (actually there can't be this situation) // nothing was found (actually there can't be this situation)
return; return;
// we're calculating how many digits there are at the end (after the comma) // we're calculating how many digits there are at the end (after the comma)
// 'after_comma' will be greater than zero because at the end // 'after_comma' will be greater than zero because at the end
// we have at least one digit // we have at least one digit
tstr_t::size_type after_comma = new_man.length() - index - 1; tt_string::size_type after_comma = new_man.length() - index - 1;
// if 'max_digit_after_comma' is greater than 'after_comma' (or equal) // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
// we don't have anything for cutting // we don't have anything for cutting
if( tstr_t::size_type(max_digit_after_comma) >= after_comma ) if( tt_string::size_type(max_digit_after_comma) >= after_comma )
return; return;
uint last_digit = UInt<man>::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base ); uint last_digit = UInt<man>::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base );
@ -3418,6 +3417,7 @@ public:
all digits after the comma we can ignore all digits after the comma we can ignore
'source' - pointer to the string for parsing 'source' - pointer to the string for parsing
'const char*' or 'const wchar_t*'
if 'after_source' is set that when this method finishes if 'after_source' is set that when this method finishes
it sets the pointer to the new first character after parsed value it sets the pointer to the new first character after parsed value
@ -3428,7 +3428,7 @@ public:
no value has been read (there are no digits) no value has been read (there are no digits)
on other words if 'value_read' is true -- there is at least one digit in the string on other words if 'value_read' is true -- there is at least one digit in the string
*/ */
uint FromString(const tchar_t * source, uint base = 10, const tchar_t ** after_source = 0, bool * value_read = 0) uint FromString(const tt_char * source, uint base = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{ {
bool is_sign; bool is_sign;
bool value_read_temp = false; bool value_read_temp = false;
@ -3479,7 +3479,7 @@ private:
(this method is used from 'FromString_ReadPartScientific' too) (this method is used from 'FromString_ReadPartScientific' too)
*/ */
void FromString_TestSign( const tchar_t * & source, bool & is_sign ) void FromString_TestSign( const tt_char * & source, bool & is_sign )
{ {
UInt<man>::SkipWhiteCharacters(source); UInt<man>::SkipWhiteCharacters(source);
@ -3501,7 +3501,7 @@ private:
/*! /*!
we're testing whether there's a comma operator we're testing whether there's a comma operator
*/ */
bool FromString_TestCommaOperator(const tchar_t * & source) bool FromString_TestCommaOperator(const tt_char * & source)
{ {
if( (*source == TTMATH_COMMA_CHARACTER_1) || if( (*source == TTMATH_COMMA_CHARACTER_1) ||
(*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
@ -3519,7 +3519,7 @@ private:
this method reads the first part of a string this method reads the first part of a string
(before the comma operator) (before the comma operator)
*/ */
uint FromString_ReadPartBeforeComma( const tchar_t * & source, uint base, bool & value_read ) uint FromString_ReadPartBeforeComma( const tt_char * & source, uint base, bool & value_read )
{ {
sint character; sint character;
Big<exp, man> temp; Big<exp, man> temp;
@ -3548,7 +3548,7 @@ private:
this method reads the second part of a string this method reads the second part of a string
(after the comma operator) (after the comma operator)
*/ */
uint FromString_ReadPartAfterComma( const tchar_t * & source, uint base, bool & value_read ) uint FromString_ReadPartAfterComma( const tt_char * & source, uint base, bool & value_read )
{ {
sint character; sint character;
uint c = 0, index = 1; uint c = 0, index = 1;
@ -3606,12 +3606,12 @@ private:
it is called when the base is 10 and some digits were read before it is called when the base is 10 and some digits were read before
*/ */
int FromString_ReadScientificIfExists(const tchar_t * & source) uint FromString_ReadScientificIfExists(const tt_char * & source)
{ {
uint c = 0; uint c = 0;
bool scientific_read = false; bool scientific_read = false;
const tchar_t * before_scientific = source; const tt_char * before_scientific = source;
if( FromString_TestScientific(source) ) if( FromString_TestScientific(source) )
c += FromString_ReadPartScientific( source, scientific_read ); c += FromString_ReadPartScientific( source, scientific_read );
@ -3629,7 +3629,7 @@ private:
this character is only allowed when we're using the base equals 10 this character is only allowed when we're using the base equals 10
*/ */
bool FromString_TestScientific(const tchar_t * & source) bool FromString_TestScientific(const tt_char * & source)
{ {
UInt<man>::SkipWhiteCharacters(source); UInt<man>::SkipWhiteCharacters(source);
@ -3648,7 +3648,7 @@ private:
this method reads the exponent (after 'e' character) when there's a scientific this method reads the exponent (after 'e' character) when there's a scientific
format of value and only when we're using the base equals 10 format of value and only when we're using the base equals 10
*/ */
uint FromString_ReadPartScientific( const tchar_t * & source, bool & scientific_read ) uint FromString_ReadPartScientific( const tt_char * & source, bool & scientific_read )
{ {
uint c = 0; uint c = 0;
Big<exp, man> new_exponent, temp; Big<exp, man> new_exponent, temp;
@ -3675,7 +3675,7 @@ private:
this method reads the value of the extra exponent when scientific format is used this method reads the value of the extra exponent when scientific format is used
(only when base == 10) (only when base == 10)
*/ */
uint FromString_ReadPartScientific_ReadExponent( const tchar_t * & source, Big<exp, man> & new_exponent, bool & scientific_read ) uint FromString_ReadPartScientific_ReadExponent( const tt_char * & source, Big<exp, man> & new_exponent, bool & scientific_read )
{ {
sint character; sint character;
Big<exp, man> base, temp; Big<exp, man> base, temp;
@ -3708,7 +3708,7 @@ public:
/*! /*!
a method for converting a string into its value a method for converting a string into its value
*/ */
uint FromString(const tstr_t & string, uint base = 10) uint FromString(const tt_string & string, uint base = 10)
{ {
return FromString( string.c_str(), base ); return FromString( string.c_str(), base );
} }
@ -3717,7 +3717,7 @@ public:
/*! /*!
a constructor for converting a string into this class a constructor for converting a string into this class
*/ */
Big(const tchar_t * string) Big(const tt_char * string)
{ {
FromString( string ); FromString( string );
} }
@ -3726,7 +3726,7 @@ public:
/*! /*!
a constructor for converting a string into this class a constructor for converting a string into this class
*/ */
Big(const tstr_t & string) Big(const tt_string & string)
{ {
FromString( string.c_str() ); FromString( string.c_str() );
} }
@ -3735,7 +3735,7 @@ public:
/*! /*!
an operator= for converting a string into its value an operator= for converting a string into its value
*/ */
Big<exp, man> & operator=(const tchar_t * string) Big<exp, man> & operator=(const tt_char * string)
{ {
FromString( string ); FromString( string );
@ -3746,7 +3746,7 @@ public:
/*! /*!
an operator= for converting a string into its value an operator= for converting a string into its value
*/ */
Big<exp, man> & operator=(const tstr_t & string) Big<exp, man> & operator=(const tt_string & string)
{ {
FromString( string.c_str() ); FromString( string.c_str() );
@ -3905,7 +3905,7 @@ public:
mandiff = man2; mandiff = man2;
mandiff.Sub(man1); mandiff.Sub(man1);
break; break;
case 0: default:
if (man2 > man1) if (man2 > man1)
{ {
mandiff = man2; mandiff = man2;
@ -4175,6 +4175,47 @@ public:
/*!
this method returns true if the value is integer
(there is no a fraction)
(we don't check nan)
*/
bool IsInteger() const
{
if( IsZero() )
return true;
if( !exponent.IsSign() )
// exponent >=0 -- the value don't have any fractions
return true;
if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
// the value is from (-1,1)
return false;
// exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
sint e = exponent.ToInt();
e = -e; // e means how many bits we must check
uint len = e / TTMATH_BITS_PER_UINT;
uint rest = e % TTMATH_BITS_PER_UINT;
uint i = 0;
for( ; i<len ; ++i )
if( mantissa.table[i] != 0 )
return false;
if( rest > 0 )
{
uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
if( (mantissa.table[i] & rest_mask) != 0 )
return false;
}
return true;
}
/*! /*!
this method rounds to the nearest integer value this method rounds to the nearest integer value
@ -4223,9 +4264,14 @@ public:
* *
*/ */
friend tostrm_t & operator<<(tostrm_t & s, const Big<exp,man> & l) /*!
output for standard streams
tt_ostream is either std::ostream or std::wostream
*/
friend tt_ostream & operator<<(tt_ostream & s, const Big<exp,man> & l)
{ {
tstr_t ss; tt_string ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -4234,12 +4280,17 @@ public:
} }
friend tistrm_t & operator>>(tistrm_t & s, Big<exp,man> & l) /*!
input from standard streams
tt_istream is either std::istream or std::wistream
*/
friend tt_istream & operator>>(tt_istream & s, Big<exp,man> & l)
{ {
tstr_t ss; tt_string ss;
// 'tchar_t' for operator>> // 'tt_char' for operator>>
unsigned tchar_t z; tt_char z;
bool was_comma = false; bool was_comma = false;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
@ -4252,7 +4303,7 @@ public:
} }
// we're reading only digits (base=10) and only one comma operator // we're reading only digits (base=10) and only one comma operator
for( ; s.good() ; z=s.get() ) for( ; s.good() ; z=static_cast<tt_char>(s.get()) )
{ {
if( z == TTMATH_COMMA_CHARACTER_1 || if( z == TTMATH_COMMA_CHARACTER_1 ||
( z == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) ( z == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )

View File

@ -35,26 +35,6 @@
namespace ttmath namespace ttmath
{ {
#if defined(TTMATH_USE_WCHAR)
typedef wchar_t tchar_t;
typedef std::wstring tstr_t;
typedef std::wostringstream tostrstrm_t;
typedef std::wostream tostrm_t;
typedef std::wistream tistrm_t;
#define __TTMATH_TEXT(quote) L ## quote
#else
typedef char tchar_t;
typedef std::string tstr_t;
typedef std::ostringstream tostrstrm_t;
typedef std::ostream tostrm_t;
typedef std::istream tistrm_t;
#define __TTMATH_TEXT(quote) quote
#endif
#define TTMATH_TEXT(quote) __TTMATH_TEXT(quote)
#if defined(WIN32) #if defined(WIN32)
#include <windows.h> #include <windows.h>

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -831,7 +831,7 @@ public:
/*! /*!
a constructor for converting string to this class (with the base=10) a constructor for converting string to this class (with the base=10)
*/ */
Int(const tchar_t * s) Int(const tt_char * s)
{ {
FromString(s); FromString(s);
} }
@ -840,7 +840,7 @@ public:
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
Int(const tstr_t & s) Int(const tt_string & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
} }
@ -879,7 +879,7 @@ public:
/*! /*!
this method converts the value to a string with a base equal 'b' this method converts the value to a string with a base equal 'b'
*/ */
void ToString(tstr_t & result, uint b = 10) const void ToString(tt_string & result, uint b = 10) const
{ {
if( IsSign() ) if( IsSign() )
{ {
@ -900,12 +900,14 @@ public:
/*! /*!
this method converts a string into its value this method converts a string into its value
string is given either as 'const char *' or 'const wchar_t *'
it returns carry=1 if the value will be too big or an incorrect base 'b' is given it returns carry=1 if the value will be too big or an incorrect base 'b' is given
string is ended with a non-digit value, for example: string is ended with a non-digit value, for example:
"-12" will be translated to -12 "-12" will be translated to -12
as well as: as well as:
"- 12foo" will be translated to 12 too "- 12foo" will be translated to -12 too
existing first white characters will be ommited existing first white characters will be ommited
(between '-' and a first digit can be white characters too) (between '-' and a first digit can be white characters too)
@ -914,7 +916,7 @@ public:
value_read (if exists) tells whether something has actually been read (at least one digit) value_read (if exists) tells whether something has actually been read (at least one digit)
*/ */
uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0) uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{ {
bool is_sign = false; bool is_sign = false;
@ -971,16 +973,16 @@ public:
this method converts a string into its value this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given it returns carry=1 if the value will be too big or an incorrect base 'b' is given
*/ */
uint FromString(const tstr_t & s, uint b = 10) uint FromString(const tt_string & s, uint b = 10)
{ {
return FromString( s.c_str() ); return FromString( s.c_str(), b );
} }
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const tchar_t * s) Int<value_size> & operator=(const tt_char * s)
{ {
FromString(s); FromString(s);
@ -991,7 +993,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const tstr_t & s) Int<value_size> & operator=(const tt_string & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
@ -1278,9 +1280,14 @@ public:
* *
*/ */
friend tostrm_t & operator<<(tostrm_t & s, const Int<value_size> & l) /*!
output for standard streams
tt_ostream is either std::ostream or std::wostream
*/
friend tt_ostream & operator<<(tt_ostream & s, const Int<value_size> & l)
{ {
tstr_t ss; tt_string ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -1289,13 +1296,17 @@ public:
} }
/*!
input from standard streams
friend tistrm_t & operator>>(tistrm_t & s, Int<value_size> & l) tt_istream is either std::istream or std::wistream
*/
friend tt_istream & operator>>(tt_istream & s, Int<value_size> & l)
{ {
tstr_t ss; tt_string ss;
// tchar_t for operator>> // tt_char for operator>>
unsigned tchar_t z; tt_char z;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
s >> z; s >> z;
@ -1310,7 +1321,7 @@ public:
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 ) while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
{ {
ss += z; ss += z;
z = s.get(); z = static_cast<tt_char>(s.get());
} }
// we're leaving the last readed character // we're leaving the last readed character

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Mathematical Library * This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -47,6 +47,7 @@
#include "ttmathtypes.h" #include "ttmathtypes.h"
#include <string> #include <string>
#include <vector>
#include <list> #include <list>
#include <map> #include <map>
@ -73,18 +74,19 @@ public:
struct Item struct Item
{ {
// name of a variable of a function // name of a variable of a function
tstr_t value; // (either std::string or std::wstring)
tt_string value;
// number of parameters required by the function // number of parameters required by the function
// (if there's a variable this 'param' is ignored) // (if there's a variable this 'param' is ignored)
int param; int param;
Item() {} Item() {}
Item(const tstr_t & v, int p) : value(v), param(p) {} Item(const tt_string & v, int p) : value(v), param(p) {}
}; };
// 'Table' is the type of our table // 'Table' is the type of our table
typedef std::map<tstr_t, Item> Table; typedef std::map<tt_string, Item> Table;
typedef Table::iterator Iterator; typedef Table::iterator Iterator;
typedef Table::const_iterator CIterator; typedef Table::const_iterator CIterator;
@ -112,7 +114,7 @@ public:
/*! /*!
this method returns true if the name can be as a name of an object this method returns true if the name can be as a name of an object
*/ */
static bool IsNameCorrect(const tstr_t & name) static bool IsNameCorrect(const tt_string & name)
{ {
if( name.empty() ) if( name.empty() )
return false; return false;
@ -120,7 +122,7 @@ public:
if( !CorrectCharacter(name[0], false) ) if( !CorrectCharacter(name[0], false) )
return false; return false;
tstr_t::const_iterator i=name.begin(); tt_string::const_iterator i=name.begin();
for(++i ; i!=name.end() ; ++i) for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) ) if( !CorrectCharacter(*i, true) )
@ -133,7 +135,7 @@ public:
/*! /*!
this method returns true if such an object is defined (name exists) this method returns true if such an object is defined (name exists)
*/ */
bool IsDefined(const tstr_t & name) bool IsDefined(const tt_string & name)
{ {
Iterator i = table.find(name); Iterator i = table.find(name);
@ -148,7 +150,7 @@ public:
/*! /*!
this method adds one object (variable of function) into the table this method adds one object (variable of function) into the table
*/ */
ErrorCode Add(const tstr_t & name, const tstr_t & value, int param = 0) ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -205,7 +207,7 @@ public:
/*! /*!
this method changes the value and the number of parameters for a specific object this method changes the value and the number of parameters for a specific object
*/ */
ErrorCode EditValue(const tstr_t & name, const tstr_t & value, int param = 0) ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -225,7 +227,7 @@ public:
/*! /*!
this method changes the name of a specific object this method changes the name of a specific object
*/ */
ErrorCode EditName(const tstr_t & old_name, const tstr_t & new_name) ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
{ {
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
return err_incorrect_name; return err_incorrect_name;
@ -256,7 +258,7 @@ public:
/*! /*!
this method deletes an object this method deletes an object
*/ */
ErrorCode Delete(const tstr_t & name) ErrorCode Delete(const tt_string & name)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -275,7 +277,7 @@ public:
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
*/ */
ErrorCode GetValue(const tstr_t & name, tstr_t & value) const ErrorCode GetValue(const tt_string & name, tt_string & value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -298,7 +300,7 @@ public:
this method gets the value of a specific object this method gets the value of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValue(const tstr_t & name, const tchar_t ** value) const ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -321,7 +323,7 @@ public:
this method gets the value and the number of parameters this method gets the value and the number of parameters
of a specific object of a specific object
*/ */
ErrorCode GetValueAndParam(const tstr_t & name, tstr_t & value, int * param) const ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -347,7 +349,7 @@ public:
of a specific object of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValueAndParam(const tstr_t & name, const tchar_t ** value, int * param) const ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -430,7 +432,7 @@ public:
*/ */
History() History()
{ {
buffer_max_size = 10; buffer_max_size = 15;
} }
@ -487,11 +489,118 @@ public:
return false; return false;
} }
TTMATH_IMPLEMENT_THREADSAFE_OBJ
/*!
this methods deletes an item
we assume that there is only one item with the 'key'
(this methods removes the first one)
*/
bool Remove(const ValueType & key)
{
typename buffer_type::iterator i = buffer.begin();
for( ; i != buffer.end() ; ++i )
{
if( i->key == key )
{
buffer.erase(i);
return true;
}
}
return false;
}
}; // end of class History }; // end of class History
/*!
this is an auxiliary class used when calculating Gamma() or Factorial()
in multithreaded environment you can provide an object of this class to
the Gamma() or Factorial() function, e.g;
typedef Big<1, 3> MyBig;
MyBig x = 123456;
CGamma<MyBig> cgamma;
std::cout << Gamma(x, cgamma);
each thread should have its own CGamma<> object
in a single-thread environment a CGamma<> object is a static variable
in a second version of Gamma() and you don't have to explicitly use it, e.g.
typedef Big<1, 3> MyBig;
MyBig x = 123456;
std::cout << Gamma(x);
*/
template<class ValueType>
struct CGamma
{
/*!
this table holds factorials
1
1
2
6
24
120
720
.......
*/
std::vector<ValueType> fact;
/*!
this table holds Bernoulli numbers
1
-0.5
0.166666666666666666666666667
0
-0.0333333333333333333333333333
0
0.0238095238095238095238095238
0
-0.0333333333333333333333333333
0
0.075757575757575757575757576
.....
*/
std::vector<ValueType> bern;
/*!
here we store some calculated values
(this is for speeding up, if the next argument of Gamma() or Factorial()
is in the 'history' then the result we are not calculating but simply
return from the 'history' object)
*/
History<ValueType> history;
/*!
this method prepares some coefficients: factorials and Bernoulli numbers
stored in 'fact' and 'bern' objects
how many values should be depends on the size of the mantissa - if
the mantissa is larger then we must calculate more values
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
we have to calculate about 30 values (the size of fact and bern will be 30),
and for a 2048 bits mantissa we have to calculate 306 coefficients
you don't have to call this method, these coefficients will be automatically calculated
when they are needed
you must note that calculating of the coefficients is a little time-consuming operation,
(especially when the mantissa is large) and first called to Gamma() or Factorial()
can take more time than next calls, and in the end this is the point when InitAll()
comes in handy: you can call this method somewhere at the beginning of your program
*/
void InitAll();
// definition is in ttmath.h
};
} // namespace } // namespace

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -45,7 +45,7 @@
\brief A mathematical parser \brief A mathematical parser
*/ */
#include <fstream> #include <cstdio>
#include <vector> #include <vector>
#include <map> #include <map>
#include <set> #include <set>
@ -137,7 +137,6 @@ namespace ttmath
template<class ValueType> template<class ValueType>
class Parser class Parser
{ {
private: private:
/*! /*!
@ -256,7 +255,7 @@ public:
bool function; bool function;
// if function is true // if function is true
tstr_t function_name; tt_string function_name;
/* /*
the sign of value the sign of value
@ -310,11 +309,12 @@ ErrorCode error;
/*! /*!
pointer to the currently reading tchar_t pointer to the currently reading char
it's either char* or wchar_t*
when an error has occured it may be used to count the index of the wrong character when an error has occured it may be used to count the index of the wrong character
*/ */
const tchar_t * pstring; const tt_char * pstring;
/*! /*!
@ -351,7 +351,7 @@ const Objects * puser_variables;
const Objects * puser_functions; const Objects * puser_functions;
typedef std::map<tstr_t, ValueType> FunctionLocalVariables; typedef std::map<tt_string, ValueType> FunctionLocalVariables;
/*! /*!
a pointer to the local variables of a function a pointer to the local variables of a function
@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
/*! /*!
a temporary set using during parsing user defined variables a temporary set using during parsing user defined variables
*/ */
std::set<tstr_t> visited_variables; std::set<tt_string> visited_variables;
/*! /*!
a temporary set using during parsing user defined functions a temporary set using during parsing user defined functions
*/ */
std::set<tstr_t> visited_functions; std::set<tt_string> visited_functions;
@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
table of mathematic functions table of mathematic functions
this map consists of: this map consists of:
tstr_t - function's name tt_string - function's name
pfunction - pointer to specific function pfunction - pointer to specific function
*/ */
typedef std::map<tstr_t, pfunction> FunctionsTable; typedef std::map<tt_string, pfunction> FunctionsTable;
FunctionsTable functions_table; FunctionsTable functions_table;
@ -407,10 +407,10 @@ FunctionsTable functions_table;
table of mathematic operators table of mathematic operators
this map consists of: this map consists of:
tstr_t - operators's name tt_string - operators's name
MatOperator::Type - type of the operator MatOperator::Type - type of the operator
*/ */
typedef std::map<tstr_t, typename MatOperator::Type> OperatorsTable; typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
OperatorsTable operators_table; OperatorsTable operators_table;
@ -418,18 +418,17 @@ OperatorsTable operators_table;
table of mathematic variables table of mathematic variables
this map consists of: this map consists of:
tstr_t - variable's name tt_string - variable's name
pfunction_var - pointer to specific function which returns value of variable pfunction_var - pointer to specific function which returns value of variable
*/ */
typedef std::map<tstr_t, pfunction_var> VariablesTable; typedef std::map<tt_string, pfunction_var> VariablesTable;
VariablesTable variables_table; VariablesTable variables_table;
/*! /*!
you can't calculate the factorial if the argument is greater than 'factorial_max' some coefficients used when calculating the gamma (or factorial) function
default value is zero which means there are not any limitations
*/ */
ValueType factorial_max; CGamma<ValueType> cgamma;
/*! /*!
@ -456,7 +455,7 @@ void SkipWhiteCharacters()
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tstr_t & name) void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
{ {
@ -474,7 +473,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tstr_t & name) void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
visited_variables.insert( name ); visited_variables.insert( name );
@ -486,7 +485,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tstr_t &
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tstr_t & name) void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
visited_variables.erase( name ); visited_variables.erase( name );
@ -505,7 +504,8 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tstr_t
(there can be a recurrence here therefore we're using 'visited_variables' (there can be a recurrence here therefore we're using 'visited_variables'
and 'visited_functions' sets to make a stop condition) and 'visited_functions' sets to make a stop condition)
*/ */
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tstr_t & name, const tchar_t * new_string, FunctionLocalVariables * local_variables = 0) ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tt_string & name, const tt_char * new_string,
FunctionLocalVariables * local_variables = 0)
{ {
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
RecurrenceParsingVariablesOrFunction_AddName(variable, name); RecurrenceParsingVariablesOrFunction_AddName(variable, name);
@ -548,12 +548,12 @@ public:
/*! /*!
this method returns the user-defined value of a variable this method returns the user-defined value of a variable
*/ */
bool GetValueOfUserDefinedVariable(const tstr_t & variable_name,ValueType & result) bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
{ {
if( !puser_variables ) if( !puser_variables )
return false; return false;
const tchar_t * string_value; const tt_char * string_value;
if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
return false; return false;
@ -567,7 +567,7 @@ return true;
/*! /*!
this method returns the value of a local variable of a function this method returns the value of a local variable of a function
*/ */
bool GetValueOfFunctionLocalVariable(const tstr_t & variable_name, ValueType & result) bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
{ {
if( !pfunction_local_variables ) if( !pfunction_local_variables )
return false; return false;
@ -589,7 +589,7 @@ return true;
we make an object of type ValueType then call a method which we make an object of type ValueType then call a method which
sets the correct value in it and finally we'll return the object sets the correct value in it and finally we'll return the object
*/ */
ValueType GetValueOfVariable(const tstr_t & variable_name) ValueType GetValueOfVariable(const tt_string & variable_name)
{ {
ValueType result; ValueType result;
@ -600,7 +600,7 @@ ValueType result;
return result; return result;
typename std::map<tstr_t, pfunction_var>::iterator i = typename std::map<tt_string, pfunction_var>::iterator i =
variables_table.find(variable_name); variables_table.find(variable_name);
if( i == variables_table.end() ) if( i == variables_table.end() )
@ -674,6 +674,20 @@ return result;
} }
void Gamma(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
ErrorCode err;
result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok)
Error( err );
}
/*! /*!
factorial factorial
result = 1 * 2 * 3 * 4 * .... * x result = 1 * 2 * 3 * 4 * .... * x
@ -684,11 +698,8 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
ErrorCode err; ErrorCode err;
if( !factorial_max.IsZero() && stack[sindex].value > factorial_max )
Error( err_too_big_factorial );
result = ttmath::Factorial(stack[sindex].value, &err, pstop_calculating); result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok) if(err != err_ok)
Error( err ); Error( err );
@ -708,7 +719,11 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) ); ErrorCode err;
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
} }
void Cos(int sindex, int amount_of_args, ValueType & result) void Cos(int sindex, int amount_of_args, ValueType & result)
@ -716,7 +731,11 @@ void Cos(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) ); ErrorCode err;
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
} }
void Tan(int sindex, int amount_of_args, ValueType & result) void Tan(int sindex, int amount_of_args, ValueType & result)
@ -757,7 +776,10 @@ void Round(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); Error( err_improper_amount_of_arguments );
result = ttmath::Round(stack[sindex].value); result = stack[sindex].value;
if( result.Round() )
Error( err_overflow );
} }
@ -973,7 +995,7 @@ void Not(int sindex, int amount_of_args, ValueType & result)
void DegToRad(int sindex, int amount_of_args, ValueType & result) void DegToRad(int sindex, int amount_of_args, ValueType & result)
{ {
ErrorCode err = err_ok; ErrorCode err = err_ok;
if( amount_of_args == 1 ) if( amount_of_args == 1 )
{ {
@ -1052,7 +1074,7 @@ void RadToGrad(int sindex, int amount_of_args, ValueType & result)
void DegToGrad(int sindex, int amount_of_args, ValueType & result) void DegToGrad(int sindex, int amount_of_args, ValueType & result)
{ {
ErrorCode err = err_ok; ErrorCode err = err_ok;
if( amount_of_args == 1 ) if( amount_of_args == 1 )
{ {
@ -1333,17 +1355,34 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
} }
/*!
we use such a method because 'wvsprintf' is not everywhere defined
*/
void Sprintf(tt_char * buffer, int par)
{
char buf[30]; // char, not tt_char
int i;
sprintf(buf, "%d", par);
for(i=0 ; buf[i] != 0 ; ++i)
buffer[i] = buf[i];
buffer[i] = 0;
}
/*! /*!
this method returns the value from a user-defined function this method returns the value from a user-defined function
(look at the description in 'CallFunction(...)') (look at the description in 'CallFunction(...)')
*/ */
bool GetValueOfUserDefinedFunction(const tstr_t & function_name, int amount_of_args, int sindex) bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
{ {
if( !puser_functions ) if( !puser_functions )
return false; return false;
const tchar_t * string_value; const tt_char * string_value;
int param; int param;
if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok ) if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
@ -1357,15 +1396,17 @@ bool GetValueOfUserDefinedFunction(const tstr_t & function_name, int amount_of_a
if( amount_of_args > 0 ) if( amount_of_args > 0 )
{ {
tchar_t buffer[20]; tt_char buffer[30];
// x = x1 // x = x1
sprintf(buffer,"x"); buffer[0] = 'x';
buffer[1] = 0;
local_variables.insert( std::make_pair(buffer, stack[sindex].value) ); local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
for(int i=0 ; i<amount_of_args ; ++i) for(int i=0 ; i<amount_of_args ; ++i)
{ {
sprintf(buffer,"x%d",i+1); buffer[0] = 'x';
Sprintf(buffer+1, i+1);
local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) ); local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
} }
} }
@ -1389,7 +1430,7 @@ return true;
result will be stored in 'stack[sindex-1].value' result will be stored in 'stack[sindex-1].value'
(we don't have to set the correct type of this element, it'll be set later) (we don't have to set the correct type of this element, it'll be set later)
*/ */
void CallFunction(const tstr_t & function_name, int amount_of_args, int sindex) void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
{ {
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
return; return;
@ -1415,9 +1456,9 @@ void CallFunction(const tstr_t & function_name, int amount_of_args, int sindex)
function_name - name of the function function_name - name of the function
pf - pointer to the function (to the wrapper) pf - pointer to the function (to the wrapper)
*/ */
void InsertFunctionToTable(const tchar_t * function_name, pfunction pf) void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
{ {
functions_table.insert( std::make_pair(tstr_t(function_name), pf)); functions_table.insert( std::make_pair(tt_string(function_name), pf));
} }
@ -1428,9 +1469,9 @@ void InsertFunctionToTable(const tchar_t * function_name, pfunction pf)
variable_name - name of the function variable_name - name of the function
pf - pointer to the function pf - pointer to the function
*/ */
void InsertVariableToTable(const tchar_t * variable_name, pfunction_var pf) void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
{ {
variables_table.insert( std::make_pair(tstr_t(variable_name), pf)); variables_table.insert( std::make_pair(tt_string(variable_name), pf));
} }
@ -1439,67 +1480,65 @@ void InsertVariableToTable(const tchar_t * variable_name, pfunction_var pf)
*/ */
void CreateFunctionsTable() void CreateFunctionsTable()
{ {
/* InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
names of functions should consist of small letters InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
*/ InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial); InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
InsertFunctionToTable("abs", &Parser<ValueType>::Abs); InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
InsertFunctionToTable("sin", &Parser<ValueType>::Sin); InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
InsertFunctionToTable("cos", &Parser<ValueType>::Cos); InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
InsertFunctionToTable("tan", &Parser<ValueType>::Tan); InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
InsertFunctionToTable("tg", &Parser<ValueType>::Tan); InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
InsertFunctionToTable("cot", &Parser<ValueType>::Cot); InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot); InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
InsertFunctionToTable("int", &Parser<ValueType>::Int); InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
InsertFunctionToTable("round", &Parser<ValueType>::Round); InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
InsertFunctionToTable("ln", &Parser<ValueType>::Ln); InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
InsertFunctionToTable("log", &Parser<ValueType>::Log); InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
InsertFunctionToTable("exp", &Parser<ValueType>::Exp); InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
InsertFunctionToTable("max", &Parser<ValueType>::Max); InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
InsertFunctionToTable("min", &Parser<ValueType>::Min); InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
InsertFunctionToTable("asin", &Parser<ValueType>::ASin); InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
InsertFunctionToTable("acos", &Parser<ValueType>::ACos); InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
InsertFunctionToTable("atan", &Parser<ValueType>::ATan); InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
InsertFunctionToTable("atg", &Parser<ValueType>::ATan); InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
InsertFunctionToTable("acot", &Parser<ValueType>::ACot); InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
InsertFunctionToTable("actg", &Parser<ValueType>::ACot); InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn); InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
InsertFunctionToTable("mod", &Parser<ValueType>::Mod); InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
InsertFunctionToTable("if", &Parser<ValueType>::If); InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
InsertFunctionToTable("or", &Parser<ValueType>::Or); InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
InsertFunctionToTable("and", &Parser<ValueType>::And); InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
InsertFunctionToTable("not", &Parser<ValueType>::Not); InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad); InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg); InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg); InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad); InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad); InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad); InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg); InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil); InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
InsertFunctionToTable("floor", &Parser<ValueType>::Floor); InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt); InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh); InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh); InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh); InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh); InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
InsertFunctionToTable("coth", &Parser<ValueType>::Coth); InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth); InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
InsertFunctionToTable("root", &Parser<ValueType>::Root); InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh); InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh); InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh); InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh); InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth); InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth); InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd); InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr); InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor); InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd); InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr); InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor); InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
} }
@ -1508,11 +1547,8 @@ void CreateFunctionsTable()
*/ */
void CreateVariablesTable() void CreateVariablesTable()
{ {
/* InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
names of variables should consist of small letters InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
*/
InsertVariableToTable("pi", &ValueType::SetPi);
InsertVariableToTable("e", &ValueType::SetE);
} }
@ -1538,7 +1574,7 @@ return c;
what should be returned is tested just by a '(' character that means if there's what should be returned is tested just by a '(' character that means if there's
a '(' character after a name that function returns 'true' a '(' character after a name that function returns 'true'
*/ */
bool ReadName(tstr_t & result) bool ReadName(tt_string & result)
{ {
int character; int character;
@ -1555,7 +1591,7 @@ int character;
do do
{ {
result += static_cast<char>( character ); result += static_cast<tt_char>( character );
character = * ++pstring; character = * ++pstring;
} }
while( (character>='a' && character<='z') || while( (character>='a' && character<='z') ||
@ -1610,7 +1646,7 @@ return false;
*/ */
bool ReadVariableOrFunction(Item & result) bool ReadVariableOrFunction(Item & result)
{ {
tstr_t name; tt_string name;
bool is_it_name_of_function = ReadName(name); bool is_it_name_of_function = ReadName(name);
if( is_it_name_of_function ) if( is_it_name_of_function )
@ -1639,7 +1675,7 @@ return is_it_name_of_function;
*/ */
void ReadValue(Item & result, int reading_base) void ReadValue(Item & result, int reading_base)
{ {
const tchar_t * new_stack_pointer; const tt_char * new_stack_pointer;
bool value_read; bool value_read;
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read); int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
@ -1812,9 +1848,9 @@ return 0;
} }
void InsertOperatorToTable(const tstr_t & name, typename MatOperator::Type type) void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
{ {
operators_table.insert( std::make_pair(name, type) ); operators_table.insert( std::make_pair(tt_string(name), type) );
} }
@ -1823,19 +1859,19 @@ void InsertOperatorToTable(const tstr_t & name, typename MatOperator::Type type)
*/ */
void CreateMathematicalOperatorsTable() void CreateMathematicalOperatorsTable()
{ {
InsertOperatorToTable(tstr_t("||"), MatOperator::lor); InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
InsertOperatorToTable(tstr_t("&&"), MatOperator::land); InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
InsertOperatorToTable(tstr_t("!="), MatOperator::neq); InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
InsertOperatorToTable(tstr_t("=="), MatOperator::eq); InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
InsertOperatorToTable(tstr_t(">="), MatOperator::get); InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
InsertOperatorToTable(tstr_t("<="), MatOperator::let); InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
InsertOperatorToTable(tstr_t(">"), MatOperator::gt); InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
InsertOperatorToTable(tstr_t("<"), MatOperator::lt); InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
InsertOperatorToTable(tstr_t("-"), MatOperator::sub); InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
InsertOperatorToTable(tstr_t("+"), MatOperator::add); InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
InsertOperatorToTable(tstr_t("/"), MatOperator::div); InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
InsertOperatorToTable(tstr_t("*"), MatOperator::mul); InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
InsertOperatorToTable(tstr_t("^"), MatOperator::pow); InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
} }
@ -1845,12 +1881,12 @@ void CreateMathematicalOperatorsTable()
e.g. e.g.
true when str1="test" and str2="te" true when str1="test" and str2="te"
*/ */
bool IsSubstring(const tstr_t & str1, const tstr_t & str2) bool IsSubstring(const tt_string & str1, const tt_string & str2)
{ {
if( str2.length() > str1.length() ) if( str2.length() > str1.length() )
return false; return false;
for(tstr_t::size_type i=0 ; i<str2.length() ; ++i) for(tt_string::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] ) if( str1[i] != str2[i] )
return false; return false;
@ -1863,7 +1899,7 @@ return true;
*/ */
void ReadMathematicalOperator(Item & result) void ReadMathematicalOperator(Item & result)
{ {
tstr_t oper; tt_string oper;
typename OperatorsTable::iterator iter_old, iter_new; typename OperatorsTable::iterator iter_old, iter_new;
iter_old = operators_table.end(); iter_old = operators_table.end();
@ -2393,7 +2429,6 @@ Parser(): default_stack_size(100)
base = 10; base = 10;
deg_rad_grad = 1; deg_rad_grad = 1;
error = err_ok; error = err_ok;
factorial_max.SetZero();
CreateFunctionsTable(); CreateFunctionsTable();
CreateVariablesTable(); CreateVariablesTable();
@ -2410,10 +2445,9 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
puser_variables = p.puser_variables; puser_variables = p.puser_variables;
puser_functions = p.puser_functions; puser_functions = p.puser_functions;
pfunction_local_variables = 0; pfunction_local_variables = 0;
base = p.base; base = p.base;
deg_rad_grad = p.deg_rad_grad; deg_rad_grad = p.deg_rad_grad;
error = err_ok; error = err_ok;
factorial_max = p.factorial_max;
/* /*
we don't have to call 'CreateFunctionsTable()' etc. we don't have to call 'CreateFunctionsTable()' etc.
@ -2495,22 +2529,11 @@ void SetFunctions(const Objects * pf)
} }
/*!
you will not be allowed to calculate the factorial
if its argument is greater than 'm'
there'll be: ErrorCode::err_too_big_factorial
default 'factorial_max' is zero which means you can calculate what you want to
*/
void SetFactorialMax(const ValueType & m)
{
factorial_max = m;
}
/*! /*!
the main method using for parsing string the main method using for parsing string
*/ */
ErrorCode Parse(const tchar_t * str) ErrorCode Parse(const tt_char * str)
{ {
stack_index = 0; stack_index = 0;
pstring = str; pstring = str;
@ -2533,11 +2556,11 @@ return error;
} }
}; };
} // namespace } // namespace

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -54,7 +54,7 @@
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
#include <vector>
/*! /*!
the version of the library the version of the library
@ -63,9 +63,9 @@
if zero that means this is the release version of the library if zero that means this is the release version of the library
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 9
#define TTMATH_REVISION_VER 5 #define TTMATH_REVISION_VER 0
#define TTMATH_PRERELEASE_VER 0 #define TTMATH_PRERELEASE_VER 1
/*! /*!
@ -196,6 +196,36 @@ namespace ttmath
} }
#if defined(UNICODE) || defined(_UNICODE)
#define TTMATH_USE_WCHAR
#endif
#ifdef TTMATH_USE_WCHAR
typedef wchar_t tt_char;
typedef std::wstring tt_string;
typedef std::wostringstream tt_ostringstream;
typedef std::wostream tt_ostream;
typedef std::wistream tt_istream;
#define TTMATH_TEXT_HELPER(txt) L##txt
#else
typedef char tt_char;
typedef std::string tt_string;
typedef std::ostringstream tt_ostringstream;
typedef std::ostream tt_ostream;
typedef std::istream tt_istream;
#define TTMATH_TEXT_HELPER(txt) txt
#endif
#define TTMATH_TEXT(txt) TTMATH_TEXT_HELPER(txt)
/*! /*!
characters which represent the comma operator characters which represent the comma operator
@ -243,6 +273,19 @@ namespace ttmath
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
#endif #endif
/*!
this is a special value used when calculating the Gamma(x) function
if x is greater than this value then the Gamma(x) will be calculated using
some kind of series
don't use smaller values than about 100
*/
#define TTMATH_GAMMA_BOUNDARY 2000
namespace ttmath namespace ttmath
{ {
@ -276,7 +319,6 @@ namespace ttmath
err_object_exists, err_object_exists,
err_unknown_object, err_unknown_object,
err_still_calculating, err_still_calculating,
err_too_big_factorial,
err_in_short_form_used_function err_in_short_form_used_function
}; };
@ -307,19 +349,19 @@ namespace ttmath
*/ */
class ExceptionInfo class ExceptionInfo
{ {
const tchar_t * file; const tt_char * file;
int line; int line;
public: public:
ExceptionInfo() : file(0), line(0) {} ExceptionInfo() : file(0), line(0) {}
ExceptionInfo(const tchar_t * f, int l) : file(f), line(l) {} ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
tstr_t Where() const tt_string Where() const
{ {
if( !file ) if( !file )
return(TTMATH_TEXT("unknown")); return TTMATH_TEXT("unknown");
tostrstrm_t result; tt_ostringstream result;
result << file << TTMATH_TEXT(":") << line; result << file << TTMATH_TEXT(":") << line;
return result.str(); return result.str();
@ -334,7 +376,7 @@ namespace ttmath
can throw an exception of this type can throw an exception of this type
If you compile with gcc you can get a small benefit If you compile with gcc you can get a small benefit
from using method Where() (it returns tstr_t with from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used) was used)
@ -362,12 +404,12 @@ namespace ttmath
{ {
} }
ReferenceError(const tchar_t * f, int l) : ReferenceError(const tt_char * f, int l) :
std::logic_error ("reference error"), ExceptionInfo(f,l) std::logic_error ("reference error"), ExceptionInfo(f,l)
{ {
} }
tstr_t Where() const tt_string Where() const
{ {
return ExceptionInfo::Where(); return ExceptionInfo::Where();
} }
@ -382,7 +424,7 @@ namespace ttmath
of this type of this type
if you compile with gcc you can get a small benefit if you compile with gcc you can get a small benefit
from using method Where() (it returns tstr_t with from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_ASSERT the name and the line of a file where the macro TTMATH_ASSERT
was used) was used)
*/ */
@ -394,12 +436,12 @@ namespace ttmath
{ {
} }
RuntimeError(const tchar_t * f, int l) : RuntimeError(const tt_char * f, int l) :
std::runtime_error ("internal error"), ExceptionInfo(f,l) std::runtime_error ("internal error"), ExceptionInfo(f,l)
{ {
} }
tstr_t Where() const tt_string Where() const
{ {
return ExceptionInfo::Where(); return ExceptionInfo::Where();
} }
@ -414,11 +456,19 @@ namespace ttmath
#if defined(__FILE__) && defined(__LINE__) #if defined(__FILE__) && defined(__LINE__)
#ifdef TTMATH_USE_WCHAR
#define TTMATH_FILE_HELPER2(arg) L##arg
#define TTMATH_FILE_HELPER(x) TTMATH_FILE_HELPER2(x)
#define TTMATH_FILE TTMATH_FILE_HELPER(__FILE__)
#else
#define TTMATH_FILE __FILE__
#endif
#define TTMATH_REFERENCE_ASSERT(expression) \ #define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_TEXT(__FILE__), __LINE__); if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
#define TTMATH_ASSERT(expression) \ #define TTMATH_ASSERT(expression) \
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__); if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
#define TTMATH_VERIFY(expression) \ #define TTMATH_VERIFY(expression) \
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__); if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
@ -447,15 +497,15 @@ namespace ttmath
#ifdef TTMATH_DEBUG_LOG #ifdef TTMATH_DEBUG_LOG
#define TTMATH_LOG(pszMsg) \ #ifdef TTMATH_USE_WCHAR
{ \ #define TTMATH_LOG_HELPER(msg) \
ttmath::tostrstrm_t ss; \ PrintLog(L##msg, std::wcout);
PrintLog(TTMATH_TEXT(pszMsg),ss); \ #else
LOG_PRINTF(TTMATH_TEXT("%s"),ss.str().c_str()); \ #define TTMATH_LOG_HELPER(msg) \
} PrintLog(msg, std::cout);
#endif
//#define TTMATH_LOG(msg) \ #define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
// PrintLog(msg, std::cout);
#else #else
@ -464,7 +514,9 @@ namespace ttmath
#endif #endif
} // namespace } // namespace
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -88,7 +88,10 @@ public:
it prints the table in a nice form of several columns it prints the table in a nice form of several columns
*/ */
void PrintTable(tostrm_t & output) const #ifndef TTMATH_USE_WCHAR
// gcc has a problem with std::setfill when wchar_t is used
void PrintTable(tt_ostream & output) const
{ {
// how many columns there'll be // how many columns there'll be
const int columns = 8; const int columns = 8;
@ -96,7 +99,7 @@ public:
int c = 1; int c = 1;
for(int i=value_size-1 ; i>=0 ; --i) for(int i=value_size-1 ; i>=0 ; --i)
{ {
output << "0x" << std::setfill('0'); output << TTMATH_TEXT("0x") << std::setfill('0');
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
output << std::setw(8); output << std::setw(8);
@ -108,7 +111,7 @@ public:
if( i>0 ) if( i>0 )
{ {
output << ", "; output << TTMATH_TEXT(", ");
if( ++c > columns ) if( ++c > columns )
{ {
@ -120,14 +123,14 @@ public:
output << std::dec << std::endl; output << std::dec << std::endl;
} }
#endif
void PrintLog(const tt_char * msg, tt_ostream & output) const
void PrintLog(const tchar_t * msg, tostrm_t & output) const
{ {
output << msg << std::endl; output << msg << std::endl;
for(uint i=0 ; i<value_size ; ++i) for(uint i=0 ; i<value_size ; ++i)
output << " table[" << i << "]: " << table[i] << std::endl; output << TTMATH_TEXT(" table[") << i << TTMATH_TEXT("]: ") << table[i] << std::endl;
} }
@ -2369,7 +2372,7 @@ public:
/*! /*!
this method converts a digit into a tchar_t this method converts a digit into a tt_char
digit should be from <0,F> digit should be from <0,F>
(we don't have to get a base) (we don't have to get a base)
@ -2379,12 +2382,12 @@ public:
10 -> A 10 -> A
15 -> F 15 -> F
*/ */
static tchar_t DigitToChar(uint digit) static tt_char DigitToChar(uint digit)
{ {
if( digit < 10 ) if( digit < 10 )
return (tchar_t)(digit + '0'); return (tt_char)(digit + '0');
return((tchar_t)(digit - 10 + 'A')); return((tt_char)(digit - 10 + 'A'));
} }
@ -2505,7 +2508,7 @@ public:
this constant 10 has the int type (signed int), if we don't give such this constant 10 has the int type (signed int), if we don't give such
operators and constructors the compiler will not compile the program, operators and constructors the compiler will not compile the program,
because it has to make a conversion and doesn't know into which type because it has to make a conversion and doesn't know into which type
(the UInt class has operator=(const tchar_t*), operator=(uint) etc.) (the UInt class has operator=(const tt_char*), operator=(uint) etc.)
*/ */
UInt<value_size> & operator=(sint i) UInt<value_size> & operator=(sint i)
{ {
@ -2620,18 +2623,18 @@ public:
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
UInt(const tchar_t * s) UInt(const tt_char * s)
{ {
FromString(s); FromString(s);
TTMATH_LOG("UInt::UInt(const tchar_t *)") TTMATH_LOG("UInt::UInt(const tt_char *)")
} }
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
UInt(const tstr_t & s) UInt(const tt_string & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
} }
@ -2646,6 +2649,7 @@ public:
{ {
} }
/*! /*!
a copy constructor a copy constructor
*/ */
@ -2696,10 +2700,10 @@ public:
/*! /*!
this method converts the value to a string with a base equal 'b' this method converts the value to a string with a base equal 'b'
*/ */
void ToString(tstr_t & result, uint b = 10) const void ToString(tt_string & result, uint b = 10) const
{ {
UInt<value_size> temp( *this ); UInt<value_size> temp( *this );
tchar_t character; tt_char character;
uint rem; uint rem;
result.clear(); result.clear();
@ -2710,7 +2714,7 @@ public:
do do
{ {
temp.DivInt(b, &rem); temp.DivInt(b, &rem);
character = static_cast<char>( DigitToChar(rem) ); character = static_cast<tt_char>( DigitToChar(rem) );
result.insert(result.begin(), character); result.insert(result.begin(), character);
} }
while( !temp.IsZero() ); while( !temp.IsZero() );
@ -2724,7 +2728,7 @@ public:
/* /*
this method's ommiting any white characters from the string this method's ommiting any white characters from the string
*/ */
static void SkipWhiteCharacters(const tchar_t * & c) static void SkipWhiteCharacters(const tt_char * & c)
{ {
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
++c; ++c;
@ -2748,7 +2752,7 @@ public:
value_read (if exists) tells whether something has actually been read (at least one digit) value_read (if exists) tells whether something has actually been read (at least one digit)
*/ */
uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0) uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{ {
UInt<value_size> base( b ); UInt<value_size> base( b );
UInt<value_size> temp; UInt<value_size> temp;
@ -2798,7 +2802,7 @@ public:
(it returns carry=1 if the value will be too big or an incorrect base 'b' is given) (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
*/ */
uint FromString(const tstr_t & s, uint b = 10) uint FromString(const tt_string & s, uint b = 10)
{ {
return FromString( s.c_str(), b ); return FromString( s.c_str(), b );
} }
@ -2808,11 +2812,11 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
UInt<value_size> & operator=(const tchar_t * s) UInt<value_size> & operator=(const tt_char * s)
{ {
FromString(s); FromString(s);
TTMATH_LOG("UInt::operator=(const tchar_t *)") TTMATH_LOG("UInt::operator=(const tt_char *)")
return *this; return *this;
} }
@ -2821,7 +2825,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
UInt<value_size> & operator=(const tstr_t & s) UInt<value_size> & operator=(const tt_string & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
@ -3189,9 +3193,15 @@ public:
* *
*/ */
friend tostrm_t & operator<<(tostrm_t & s, const UInt<value_size> & l)
/*!
output for standard streams
tt_ostream is either std::ostream or std::wostream
*/
friend tt_ostream & operator<<(tt_ostream & s, const UInt<value_size> & l)
{ {
tstr_t ss; tt_string ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -3201,12 +3211,17 @@ public:
friend tistrm_t & operator>>(tistrm_t & s, UInt<value_size> & l) /*!
{ input from standard streams
tstr_t ss;
// tchar_t for operator>> tt_istream is either std::istream or std::wistream
tchar_t z; */
friend tt_istream & operator>>(tt_istream & s, UInt<value_size> & l)
{
tt_string ss;
// tt_char for operator>>
tt_char z;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
s >> z; s >> z;
@ -3215,10 +3230,10 @@ public:
while( s.good() && CharToDigit(z, 10)>=0 ) while( s.good() && CharToDigit(z, 10)>=0 )
{ {
ss += z; ss += z;
z = s.get(); z = static_cast<tt_char>(s.get());
} }
// we're leaving the last readed character // we're leaving the last read character
// (it's not belonging to the value) // (it's not belonging to the value)
s.unget(); s.unget();
@ -3238,13 +3253,9 @@ public:
ttmathuint_noasm.h ttmathuint_noasm.h
*/ */
#if defined(TTMATH_NOASM) || !defined(__GNUC__)
// not yet implemented in 64 bit ASM
static uint AddTwoWords(uint a, uint b, uint carry, uint * result); static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
static uint SubTwoWords(uint a, uint b, uint carry, uint * result); static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
#endif
#if defined(TTMATH_NOASM)
#ifdef TTMATH_PLATFORM64 #ifdef TTMATH_PLATFORM64
union uint_ union uint_
@ -3266,8 +3277,6 @@ public:
static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
#endif // TTMATH_PLATFORM64 #endif // TTMATH_PLATFORM64
#endif // TTMATH_NOASM
private: private:
uint Rcl2_one(uint c); uint Rcl2_one(uint c);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -462,8 +462,6 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt::AddVector")
return c; return c;
} }
@ -766,8 +764,6 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt::SubVector")
return c; return c;
} }

View File

@ -1,7 +1,7 @@
/* /*
* This file is a part of TTMath Bignum Library * This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
@ -118,7 +118,7 @@ namespace ttmath
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n" "movq (%%rsi,%%rdx,8), %%rax \n"
@ -136,7 +136,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Add") TTMATH_LOG("UInt::Add")
return c; return c;
} }
@ -161,7 +161,7 @@ namespace ttmath
table[1] = 30 + 2; table[1] = 30 + 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::AddInt(uint value, uint index) uint UInt<value_size>::AddInt(uint value, uint index)
@ -201,12 +201,12 @@ namespace ttmath
"movzx %%al, %%rdx \n" "movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2) : "=d" (c), "=a" (dummy), "=c" (dummy2)
: "a" (value), "c" (b), "0" (index), "b" (p1) : "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::AddInt") TTMATH_LOG("UInt::AddInt")
return c; return c;
} }
@ -318,13 +318,12 @@ namespace ttmath
"movzx %%al, %%rax \n" "movzx %%al, %%rax \n"
: "=a" (c), "=c" (dummy), "=d" (dummy2) : "=a" (c), "=c" (dummy), "=d" (dummy2)
: "1" (b), "2" (index), "b" (p1), "S" (x1), "0" (x2) : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt::AddTwoInts")
TTMATH_LOG("UInt64::AddTwoInts")
return c; return c;
} }
@ -368,7 +367,7 @@ namespace ttmath
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n" "movq (%%rsi,%%rdx,8), %%rax \n"
@ -387,7 +386,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Sub") TTMATH_LOG("UInt::Sub")
return c; return c;
} }
@ -410,7 +409,7 @@ namespace ttmath
table[1] = 30 - 2; table[1] = 30 - 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubInt(uint value, uint index) uint UInt<value_size>::SubInt(uint value, uint index)
@ -449,8 +448,8 @@ namespace ttmath
"setc %%al \n" "setc %%al \n"
"movzx %%al, %%rdx \n" "movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2) : "=d" (c), "=a" (dummy), "=c" (dummy2)
: "1" (value), "2" (b), "0" (index), "b" (p1) : "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
@ -495,7 +494,7 @@ namespace ttmath
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" // rdx=0 "xorq %%rdx, %%rdx \n" // rdx=0
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rclq $1, (%%rbx, %%rdx, 8) \n" "rclq $1, (%%rbx, %%rdx, 8) \n"
@ -507,12 +506,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n" "adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy), "=d" (dummy2) : "=c" (c), "=a" (dummy), "=d" (dummy2)
: "1" (c), "0" (b), "b" (p1) : "0" (b), "1" (c), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::Rcl2_one") TTMATH_LOG("UInt::Rcl2_one")
return c; return c;
} }
@ -551,7 +550,7 @@ namespace ttmath
__asm__ __volatile__( __asm__ __volatile__(
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rcrq $1, -8(%%rbx, %%rcx, 8) \n" "rcrq $1, -8(%%rbx, %%rcx, 8) \n"
@ -562,12 +561,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n" "adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy) : "=c" (c), "=a" (dummy)
: "1" (c), "0" (b), "b" (p1) : "0" (b), "1" (c), "b" (p1)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOG("UInt64::Rcr2_one") TTMATH_LOG("UInt::Rcr2_one")
return c; return c;
} }
@ -644,7 +643,7 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Rcl2") TTMATH_LOG("UInt::Rcl2")
return c; return c;
} }
@ -724,14 +723,14 @@ namespace ttmath
#endif #endif
TTMATH_LOG("UInt64::Rcr2") TTMATH_LOG("UInt::Rcr2")
return c; return c;
} }
/* /*
this method returns the number of the highest set bit in one 32-bit word this method returns the number of the highest set bit in one 64-bit word
if the 'x' is zero this method returns '-1' if the 'x' is zero this method returns '-1'
***this method is created only on a 64bit platform*** ***this method is created only on a 64bit platform***
@ -755,16 +754,17 @@ namespace ttmath
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( uint dummy;
"bsrq %1, %0 \n" __asm__ (
"jnz 1f \n"
"movq $-1, %0 \n"
"1: \n"
: "=R" (result) "movq $-1, %1 \n"
: "R" (x) "bsrq %2, %0 \n"
: "cc" ); "cmovz %1, %0 \n"
: "=r" (result), "=&r" (dummy)
: "r" (x)
: "cc" );
#endif #endif
@ -808,15 +808,15 @@ namespace ttmath
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__(
__asm__ (
"btsq %%rbx, %%rax \n" "btsq %%rbx, %%rax \n"
"setc %%bl \n" "setc %%bl \n"
"movzx %%bl, %%rbx \n" "movzx %%bl, %%rbx \n"
: "=a" (v), "=b" (old_bit) : "=a" (v), "=b" (old_bit)
: "0" (v), "1" (bit) : "0" (v), "1" (bit)
: "cc" ); : "cc" );
#endif #endif
@ -836,18 +836,17 @@ namespace ttmath
/*! /*!
multiplication: result2:result1 = a * b multiplication: result_high:result_low = a * b
result2 - higher word result_high - higher word of the result
result1 - lower word of the result result_low - lower word of the result
this methos never returns a carry this methos never returns a carry
this method is used in the second version of the multiplication algorithms
***this method is created only on a 64bit platform*** ***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> template<uint value_size>
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1) void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
{ {
/* /*
we must use these temporary variables in order to inform the compilator we must use these temporary variables in order to inform the compilator
@ -856,8 +855,8 @@ namespace ttmath
this has no effect in visual studio but it's usefull when this has no effect in visual studio but it's usefull when
using gcc and options like -O using gcc and options like -O
*/ */
register uint result1_; uint result1_;
register uint result2_; uint result2_;
#ifndef __GNUC__ #ifndef __GNUC__
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -869,19 +868,19 @@ namespace ttmath
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ (
"mulq %%rdx \n" "mulq %%rdx \n"
: "=a" (result1_), "=d" (result2_) : "=a" (result1_), "=d" (result2_)
: "0" (a), "1" (b) : "0" (a), "1" (b)
: "cc" ); : "cc" );
#endif #endif
*result1 = result1_; *result_low = result1_;
*result2 = result2_; *result_high = result2_;
} }
@ -912,8 +911,8 @@ namespace ttmath
template<uint value_size> template<uint value_size>
void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
{ {
register uint r_; uint r_;
register uint rest_; uint rest_;
/* /*
these variables have similar meaning like those in these variables have similar meaning like those in
the multiplication algorithm MulTwoWords the multiplication algorithm MulTwoWords
@ -932,8 +931,8 @@ namespace ttmath
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ (
"divq %%rcx \n" "divq %%rcx \n"