- 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:
commit
51e938eaa7
25
CHANGELOG
25
CHANGELOG
|
@ -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)
|
||||||
|
|
825
ttmath/ttmath.h
825
ttmath/ttmath.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is a part of TTMath Bignum Library
|
* This file is a part of TTMath Bignum Library
|
||||||
* and is distributed under the (new) BSD licence.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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 ) )
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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, ¶m) != err_ok )
|
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != 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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue