Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
5584adb23d | |||
a4bb0b6f64 | |||
e046aba6d2 | |||
5ef27bdbd0 | |||
b80f73f16b |
41
CHANGELOG
41
CHANGELOG
@@ -1,26 +1,21 @@
|
||||
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.6 (2009.10.25):
|
||||
* fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
|
||||
equal 1 (should be set 2)
|
||||
this affected only no-asm parts - when macro TTMATH_NOASM was defined
|
||||
* fixed: UInt<value_size>::MulInt(uint ss2)
|
||||
there was a buffer overflow when value_size was equal 1
|
||||
* fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
|
||||
when macro TTMATH_NOASM was defined
|
||||
* fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
|
||||
* fixed: Int::FromString(const tt_string & s, uint b = 10)
|
||||
didn't use 'b' (always was '10')
|
||||
* fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
|
||||
* fixed: powering algorithm in:
|
||||
UInt::Pow(UInt<value_size> pow)
|
||||
Big::Pow(UInt<pow_size> pow)
|
||||
Big::PowUInt(Big<exp, man> pow)
|
||||
when 'pow' was sufficient large the algorithm returned carry
|
||||
but the result could have been calculated correctly
|
||||
|
||||
|
||||
Version 0.8.5 (2009.06.16):
|
||||
|
830
ttmath/ttmath.h
830
ttmath/ttmath.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -50,9 +50,12 @@
|
||||
#pragma warning( disable: 4127 )
|
||||
#endif
|
||||
|
||||
|
||||
#include "ttmathbig.h"
|
||||
#include "ttmathobjects.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
@@ -64,7 +67,6 @@ namespace ttmath
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* functions for rounding
|
||||
@@ -74,7 +76,7 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this function skips the fraction from x
|
||||
this method skips the fraction from x
|
||||
e.g 2.2 = 2
|
||||
2.7 = 2
|
||||
-2.2 = 2
|
||||
@@ -91,7 +93,7 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this function rounds to the nearest integer value
|
||||
this method rounds to the nearest integer value
|
||||
e.g 2.2 = 2
|
||||
2.7 = 3
|
||||
-2.2 = -2
|
||||
@@ -223,7 +225,7 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the natural logarithm (logarithm with the base 'e')
|
||||
this method calculates the natural logarithm (logarithm with the base 'e')
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Ln(const ValueType & x, ErrorCode * err = 0)
|
||||
@@ -236,7 +238,7 @@ namespace ttmath
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Ln(x);
|
||||
|
||||
if( err )
|
||||
@@ -264,7 +266,7 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the logarithm
|
||||
this method calculates the logarithm
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
|
||||
@@ -277,7 +279,7 @@ namespace ttmath
|
||||
return ValueType(); // default NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Log(x, base);
|
||||
|
||||
if( err )
|
||||
@@ -305,7 +307,7 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this function calculates the expression e^x
|
||||
this method calculates the expression e^x
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Exp(const ValueType & x, ErrorCode * err = 0)
|
||||
@@ -318,7 +320,7 @@ namespace ttmath
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint c = result.Exp(x);
|
||||
|
||||
if( err )
|
||||
@@ -516,7 +518,7 @@ namespace ttmath
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
@@ -584,7 +586,7 @@ namespace ttmath
|
||||
*err = err_overflow;
|
||||
|
||||
return ValueType(); // result is undefined (NaN is set by default)
|
||||
}
|
||||
}
|
||||
|
||||
return Sin(x, err);
|
||||
}
|
||||
@@ -897,7 +899,7 @@ namespace ttmath
|
||||
ValueType temp;
|
||||
|
||||
temp.Set05Pi();
|
||||
temp.Sub(ASin(x,err));
|
||||
temp.Sub(ASin(x, err));
|
||||
|
||||
return temp;
|
||||
}
|
||||
@@ -1625,7 +1627,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return delimiter; // NaN is set by default
|
||||
return delimiter ; // NaN is set by default
|
||||
}
|
||||
|
||||
multipler = 60;
|
||||
@@ -1938,7 +1940,10 @@ namespace ttmath
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( !index.IsInteger() )
|
||||
ValueType indexfrac(index);
|
||||
indexfrac.RemainFraction();
|
||||
|
||||
if( !indexfrac.IsZero() )
|
||||
{
|
||||
// index must be integer
|
||||
if( err )
|
||||
@@ -2070,6 +2075,154 @@ 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;
|
||||
|
||||
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
|
||||
e.g. -2 = 2
|
||||
@@ -2130,653 +2283,6 @@ 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
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -38,8 +38,6 @@
|
||||
#ifndef headerfilettmathbig
|
||||
#define headerfilettmathbig
|
||||
|
||||
#include "ttmathconfig.h"
|
||||
|
||||
/*!
|
||||
\file ttmathbig.h
|
||||
\brief A Class for representing floating point numbers
|
||||
@@ -49,10 +47,6 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
@@ -85,9 +79,9 @@ class Big
|
||||
|
||||
public:
|
||||
|
||||
Int<exp> exponent;
|
||||
UInt<man> mantissa;
|
||||
tt_char info;
|
||||
Int<exp> exponent;
|
||||
UInt<man> mantissa;
|
||||
unsigned char info;
|
||||
|
||||
|
||||
/*!
|
||||
@@ -273,7 +267,7 @@ private:
|
||||
// 3101 digits were taken from this website
|
||||
// (later the digits were compared with:
|
||||
// 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 tt_char*) on a 32bit platform)
|
||||
// and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform)
|
||||
// and then the first 256 words were taken into this table
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
|
||||
// and on 64bit platform value 128 (256/2=128))
|
||||
@@ -426,7 +420,7 @@ public:
|
||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
|
||||
// and on 64bit platform value 128 (256/2=128))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(unsigned int));
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
||||
info = 0;
|
||||
}
|
||||
@@ -760,10 +754,10 @@ public:
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
@@ -811,10 +805,10 @@ public:
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
@@ -859,10 +853,10 @@ public:
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
@@ -913,7 +907,7 @@ public:
|
||||
{
|
||||
// 'i' will be from 0 to TTMATH_BITS_PER_UINT
|
||||
i = man_result.CompensationToLeft();
|
||||
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
mantissa.table[i] = man_result.table[i+1];
|
||||
@@ -1034,7 +1028,7 @@ public:
|
||||
|
||||
UInt<man*2> man1;
|
||||
UInt<man*2> man2;
|
||||
uint i,c;
|
||||
uint i,c = 0;
|
||||
|
||||
if( IsNan() || ss2.IsNan() || ss2.IsZero() )
|
||||
return CheckCarry(1);
|
||||
@@ -1055,7 +1049,9 @@ public:
|
||||
|
||||
i = man1.CompensationToLeft();
|
||||
|
||||
c = exponent.Sub(i);
|
||||
if( i )
|
||||
c += exponent.Sub(i);
|
||||
|
||||
c += exponent.Sub(ss2.exponent);
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
@@ -1076,8 +1072,8 @@ public:
|
||||
the remainder from a division
|
||||
|
||||
e.g.
|
||||
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
|
||||
-12.6 mod 3 = -0.6
|
||||
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
|
||||
-12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
|
||||
12.6 mod -3 = 0.6
|
||||
-12.6 mod -3 = -0.6
|
||||
|
||||
@@ -1111,6 +1107,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
power this = this ^ pow
|
||||
(pow without a sign)
|
||||
@@ -1128,7 +1125,7 @@ public:
|
||||
if( IsNan() )
|
||||
return 1;
|
||||
|
||||
if(pow.IsZero() && IsZero())
|
||||
if( pow.IsZero() && IsZero() )
|
||||
{
|
||||
// we don't define zero^zero
|
||||
SetNan();
|
||||
@@ -1140,15 +1137,17 @@ public:
|
||||
result.SetOne();
|
||||
uint c = 0;
|
||||
|
||||
while( !c && !pow.IsZero() )
|
||||
while( !c )
|
||||
{
|
||||
if( pow.table[0] & 1 )
|
||||
c += result.Mul(start);
|
||||
|
||||
pow.Rcr(1);
|
||||
if( pow.IsZero() )
|
||||
break;
|
||||
|
||||
start_temp = start;
|
||||
c += start.Mul(start_temp);
|
||||
|
||||
pow.Rcr(1);
|
||||
}
|
||||
|
||||
*this = result;
|
||||
@@ -1250,15 +1249,18 @@ public:
|
||||
one.SetOne();
|
||||
result = one;
|
||||
|
||||
while( !c && pow >= one )
|
||||
while( !c )
|
||||
{
|
||||
if( pow.Mod2() )
|
||||
c += result.Mul(start);
|
||||
|
||||
c += pow.exponent.Sub( e_one );
|
||||
|
||||
if( pow < one )
|
||||
break;
|
||||
|
||||
start_temp = start;
|
||||
c += start.Mul(start_temp);
|
||||
|
||||
c += pow.exponent.Sub( e_one );
|
||||
}
|
||||
|
||||
*this = result;
|
||||
@@ -1371,7 +1373,10 @@ public:
|
||||
|
||||
if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
|
||||
{
|
||||
if( pow.IsInteger() )
|
||||
Big<exp, man> pow_frac( pow );
|
||||
pow_frac.RemainFraction();
|
||||
|
||||
if( pow_frac.IsZero() )
|
||||
return PowInt( pow );
|
||||
}
|
||||
|
||||
@@ -1429,11 +1434,11 @@ public:
|
||||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next few parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
// we've added next few parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
}
|
||||
|
||||
// we set the denominator and the numerator for a next part of the formula
|
||||
@@ -1595,11 +1600,11 @@ public:
|
||||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next (step_test) parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
// we've added next (step_test) parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
}
|
||||
|
||||
if( x1.Mul(x2) )
|
||||
@@ -1769,7 +1774,7 @@ public:
|
||||
// MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'):
|
||||
// warning C4307: '*' : integral constant overflow
|
||||
// but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here
|
||||
#ifndef __GNUC__
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable: 4307 )
|
||||
#endif
|
||||
|
||||
@@ -1785,7 +1790,7 @@ public:
|
||||
c += exponent.AddInt(man_diff, 0);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( default: 4307 )
|
||||
#endif
|
||||
|
||||
@@ -1887,6 +1892,7 @@ public:
|
||||
if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
|
||||
// if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||
// into the 'Int<int_size>' type (it's too big)
|
||||
return 1;
|
||||
|
||||
if( exponent <= maxbit )
|
||||
// our value is from range (-1,1) and we return zero
|
||||
@@ -2010,7 +2016,7 @@ public:
|
||||
// error but I leave it at the moment as is
|
||||
TTMATH_ASSERT( sizeof(double) == 8 )
|
||||
|
||||
// I am not sure what will be on a plaltform which has
|
||||
// I am not sure what will be on a platform which has
|
||||
// a different endianness... but we use this library only
|
||||
// on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
|
||||
union
|
||||
@@ -2175,7 +2181,7 @@ public:
|
||||
// then V=(-1)**S * 2 ** (-1022) * (0.F)
|
||||
// These are "unnormalized" values.
|
||||
|
||||
FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
|
||||
FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
|
||||
e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
|
||||
Standardizing();
|
||||
}
|
||||
@@ -2653,7 +2659,7 @@ public:
|
||||
*/
|
||||
Big<exp,man> & operator=(const Big<exp,man> & value)
|
||||
{
|
||||
info = value.info;
|
||||
info = value.info;
|
||||
exponent = value.exponent;
|
||||
mantissa = value.mantissa;
|
||||
|
||||
@@ -2670,18 +2676,6 @@ public:
|
||||
operator=(value);
|
||||
}
|
||||
|
||||
class LogHistory
|
||||
{
|
||||
public:
|
||||
Big<exp,man> val[15];
|
||||
|
||||
LogHistory()
|
||||
{
|
||||
for (int i = 0; i < 15; ++i)
|
||||
val[i].SetZero();
|
||||
}
|
||||
TTMATH_IMPLEMENT_THREADSAFE_OBJ
|
||||
};
|
||||
|
||||
/*!
|
||||
a method for converting the value into a string with a base equal 'base'
|
||||
@@ -2717,20 +2711,20 @@ public:
|
||||
|
||||
output:
|
||||
return value:
|
||||
0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
|
||||
0 - ok and 'result' will be an object of type std::string which holds the value
|
||||
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)
|
||||
*/
|
||||
uint ToString( tt_string & result,
|
||||
uint ToString( std::string & result,
|
||||
uint base = 10,
|
||||
bool always_scientific = false,
|
||||
sint when_scientific = 15,
|
||||
sint max_digit_after_comma = -1,
|
||||
bool remove_trailing_zeroes = true,
|
||||
tt_char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
|
||||
char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
|
||||
{
|
||||
static tt_char error_overflow_msg[] = TTMATH_TEXT("overflow");
|
||||
static tt_char error_nan_msg[] = TTMATH_TEXT("NaN");
|
||||
static char error_overflow_msg[] = "overflow";
|
||||
static char error_nan_msg[] = "NaN";
|
||||
result.erase();
|
||||
|
||||
if( IsNan() )
|
||||
@@ -2739,7 +2733,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(base<2 || base>16)
|
||||
if( base<2 || base>16 )
|
||||
{
|
||||
result = error_overflow_msg;
|
||||
return 1;
|
||||
@@ -2747,7 +2741,7 @@ public:
|
||||
|
||||
if( IsZero() )
|
||||
{
|
||||
result = '0';
|
||||
result = "0";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2872,7 +2866,7 @@ private:
|
||||
but we need 'new'exp' as integer then we take:
|
||||
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
|
||||
*/
|
||||
uint ToString_CreateNewMantissaAndExponent( tt_string & new_man, uint base,
|
||||
uint ToString_CreateNewMantissaAndExponent( std::string & new_man, uint base,
|
||||
Int<exp+1> & new_exp) const
|
||||
{
|
||||
uint c = 0;
|
||||
@@ -2976,12 +2970,11 @@ private:
|
||||
// (LnSurrounding1() will return one immediately)
|
||||
uint c = Ln(x);
|
||||
|
||||
// warning! this 'static' is not thread safe
|
||||
static Big<exp,man> log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint index = base - 2;
|
||||
|
||||
static LogHistory log_history;
|
||||
TTMATH_USE_THREADSAFE_OBJ(log_history);
|
||||
|
||||
if( log_history.val[index].IsZero() )
|
||||
if( log_history[index].IsZero() )
|
||||
{
|
||||
// we don't have 'base' in 'log_history' then we calculate it now
|
||||
|
||||
@@ -2999,14 +2992,14 @@ private:
|
||||
|
||||
// the next time we'll get the 'Ln(base)' from the history,
|
||||
// this 'log_history' can have (16-2+1) items max
|
||||
log_history.val[index] = temp;
|
||||
log_history[index] = temp;
|
||||
|
||||
c += Div(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've calculated the 'Ln(base)' beforehand and we're getting it now
|
||||
c += Div( log_history.val[index] );
|
||||
c += Div( log_history[index] );
|
||||
}
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
@@ -3056,7 +3049,7 @@ private:
|
||||
(we can make that speciality when the base is 4,8 or 16 as well
|
||||
but maybe in further time)
|
||||
*/
|
||||
uint ToString_CreateNewMantissaAndExponent_Base2( tt_string & new_man,
|
||||
uint ToString_CreateNewMantissaAndExponent_Base2( std::string & new_man,
|
||||
Int<exp+1> & new_exp ) const
|
||||
{
|
||||
for( sint i=man-1 ; i>=0 ; --i )
|
||||
@@ -3086,13 +3079,13 @@ private:
|
||||
this method roundes the last character from the new mantissa
|
||||
(it's used in systems where the base is different from 2)
|
||||
*/
|
||||
uint ToString_RoundMantissa(tt_string & new_man, uint base, Int<exp+1> & new_exp, tt_char decimal_point) const
|
||||
uint ToString_RoundMantissa(std::string & new_man, uint base, Int<exp+1> & new_exp, char decimal_point) const
|
||||
{
|
||||
// we must have minimum two characters
|
||||
if( new_man.length() < 2 )
|
||||
return 0;
|
||||
|
||||
tt_string::size_type i = new_man.length() - 1;
|
||||
std::string::size_type i = new_man.length() - 1;
|
||||
|
||||
// we're erasing the last character
|
||||
uint digit = UInt<man>::CharToDigit( new_man[i] );
|
||||
@@ -3113,7 +3106,7 @@ private:
|
||||
|
||||
this method addes one into the new mantissa
|
||||
*/
|
||||
void ToString_RoundMantissa_AddOneIntoMantissa(tt_string & new_man, uint base, tt_char decimal_point) const
|
||||
void ToString_RoundMantissa_AddOneIntoMantissa(std::string & new_man, uint base, char decimal_point) const
|
||||
{
|
||||
if( new_man.empty() )
|
||||
return;
|
||||
@@ -3137,7 +3130,7 @@ private:
|
||||
else
|
||||
was_carry = false;
|
||||
|
||||
new_man[i] = static_cast<tt_char>( UInt<man>::DigitToChar(digit) );
|
||||
new_man[i] = static_cast<char>( UInt<man>::DigitToChar(digit) );
|
||||
}
|
||||
|
||||
if( i<0 && was_carry )
|
||||
@@ -3151,13 +3144,13 @@ private:
|
||||
this method sets the comma operator and/or puts the exponent
|
||||
into the string
|
||||
*/
|
||||
uint ToString_SetCommaAndExponent( tt_string & new_man, uint base,
|
||||
uint ToString_SetCommaAndExponent( std::string & new_man, uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
bool always_scientific,
|
||||
sint when_scientific,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
uint carry = 0;
|
||||
|
||||
@@ -3197,12 +3190,12 @@ private:
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_SetCommaAndExponent_Normal(
|
||||
tt_string & new_man,
|
||||
std::string & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
if( !new_exp.IsSign() ) //if( new_exp >= 0 )
|
||||
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
|
||||
@@ -3214,7 +3207,7 @@ private:
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_SetCommaAndExponent_Normal_AddingZero(tt_string & new_man,
|
||||
void ToString_SetCommaAndExponent_Normal_AddingZero(std::string & new_man,
|
||||
Int<exp+1> & new_exp) const
|
||||
{
|
||||
// we're adding zero characters at the end
|
||||
@@ -3234,12 +3227,12 @@ private:
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_SetCommaAndExponent_Normal_SetCommaInside(
|
||||
tt_string & new_man,
|
||||
std::string & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & new_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
// new_exp is < 0
|
||||
|
||||
@@ -3258,7 +3251,7 @@ private:
|
||||
// we're adding zero characters before the mantissa
|
||||
|
||||
uint how_many = e - new_man_len;
|
||||
tt_string man_temp(how_many+1, '0');
|
||||
std::string man_temp(how_many+1, '0');
|
||||
|
||||
man_temp.insert( man_temp.begin()+1, decimal_point);
|
||||
new_man.insert(0, man_temp);
|
||||
@@ -3271,12 +3264,12 @@ private:
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_SetCommaAndExponent_Scientific( tt_string & new_man,
|
||||
void ToString_SetCommaAndExponent_Scientific( std::string & new_man,
|
||||
uint base,
|
||||
Int<exp+1> & scientific_exp,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
if( new_man.empty() )
|
||||
return;
|
||||
@@ -3290,16 +3283,16 @@ private:
|
||||
new_man += 'e';
|
||||
|
||||
if( !scientific_exp.IsSign() )
|
||||
new_man += '+';
|
||||
new_man += "+";
|
||||
}
|
||||
else
|
||||
{
|
||||
// the 10 here is meant as the base 'base'
|
||||
// (no matter which 'base' we're using there'll always be 10 here)
|
||||
new_man += TTMATH_TEXT("*10^");
|
||||
new_man += "*10^";
|
||||
}
|
||||
|
||||
tt_string temp_exp;
|
||||
std::string temp_exp;
|
||||
scientific_exp.ToString( temp_exp, base );
|
||||
|
||||
new_man += temp_exp;
|
||||
@@ -3309,11 +3302,11 @@ private:
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_CorrectDigitsAfterComma( tt_string & new_man,
|
||||
void ToString_CorrectDigitsAfterComma( std::string & new_man,
|
||||
uint base,
|
||||
sint max_digit_after_comma,
|
||||
bool remove_trailing_zeroes,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
if( max_digit_after_comma >= 0 )
|
||||
ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point);
|
||||
@@ -3327,8 +3320,8 @@ private:
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
|
||||
tt_string & new_man,
|
||||
tt_char decimal_point) const
|
||||
std::string & new_man,
|
||||
char decimal_point) const
|
||||
{
|
||||
// minimum two characters
|
||||
if( new_man.length() < 2 )
|
||||
@@ -3346,7 +3339,7 @@ private:
|
||||
// we must have a comma
|
||||
// (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
|
||||
// which is called before)
|
||||
if( new_man.find_last_of(decimal_point, i) == tt_string::npos )
|
||||
if( new_man.find_last_of(decimal_point, i) == std::string::npos )
|
||||
return;
|
||||
|
||||
// if directly before the first zero is the comma operator
|
||||
@@ -3362,26 +3355,26 @@ private:
|
||||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_CorrectDigitsAfterComma_Round(
|
||||
tt_string & new_man,
|
||||
std::string & new_man,
|
||||
uint base,
|
||||
sint max_digit_after_comma,
|
||||
tt_char decimal_point) const
|
||||
char decimal_point) const
|
||||
{
|
||||
// first we're looking for the comma operator
|
||||
tt_string::size_type index = new_man.find(decimal_point, 0);
|
||||
std::string::size_type index = new_man.find(decimal_point, 0);
|
||||
|
||||
if( index == tt_string::npos )
|
||||
if( index == std::string::npos )
|
||||
// nothing was found (actually there can't be this situation)
|
||||
return;
|
||||
|
||||
// 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
|
||||
// we have at least one digit
|
||||
tt_string::size_type after_comma = new_man.length() - index - 1;
|
||||
std::string::size_type after_comma = new_man.length() - index - 1;
|
||||
|
||||
// if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
|
||||
// we don't have anything for cutting
|
||||
if( tt_string::size_type(max_digit_after_comma) >= after_comma )
|
||||
if( std::string::size_type(max_digit_after_comma) >= after_comma )
|
||||
return;
|
||||
|
||||
uint last_digit = UInt<man>::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base );
|
||||
@@ -3417,7 +3410,6 @@ public:
|
||||
all digits after the comma we can ignore
|
||||
|
||||
'source' - pointer to the string for parsing
|
||||
'const char*' or 'const wchar_t*'
|
||||
|
||||
if 'after_source' is set that when this method finishes
|
||||
it sets the pointer to the new first character after parsed value
|
||||
@@ -3428,7 +3420,7 @@ public:
|
||||
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
|
||||
*/
|
||||
uint FromString(const tt_char * source, uint base = 10, const tt_char ** after_source = 0, bool * value_read = 0)
|
||||
uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
bool is_sign;
|
||||
bool value_read_temp = false;
|
||||
@@ -3479,7 +3471,7 @@ private:
|
||||
|
||||
(this method is used from 'FromString_ReadPartScientific' too)
|
||||
*/
|
||||
void FromString_TestSign( const tt_char * & source, bool & is_sign )
|
||||
void FromString_TestSign( const char * & source, bool & is_sign )
|
||||
{
|
||||
UInt<man>::SkipWhiteCharacters(source);
|
||||
|
||||
@@ -3501,7 +3493,7 @@ private:
|
||||
/*!
|
||||
we're testing whether there's a comma operator
|
||||
*/
|
||||
bool FromString_TestCommaOperator(const tt_char * & source)
|
||||
bool FromString_TestCommaOperator(const char * & source)
|
||||
{
|
||||
if( (*source == TTMATH_COMMA_CHARACTER_1) ||
|
||||
(*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
|
||||
@@ -3519,7 +3511,7 @@ private:
|
||||
this method reads the first part of a string
|
||||
(before the comma operator)
|
||||
*/
|
||||
uint FromString_ReadPartBeforeComma( const tt_char * & source, uint base, bool & value_read )
|
||||
uint FromString_ReadPartBeforeComma( const char * & source, uint base, bool & value_read )
|
||||
{
|
||||
sint character;
|
||||
Big<exp, man> temp;
|
||||
@@ -3548,7 +3540,7 @@ private:
|
||||
this method reads the second part of a string
|
||||
(after the comma operator)
|
||||
*/
|
||||
uint FromString_ReadPartAfterComma( const tt_char * & source, uint base, bool & value_read )
|
||||
uint FromString_ReadPartAfterComma( const char * & source, uint base, bool & value_read )
|
||||
{
|
||||
sint character;
|
||||
uint c = 0, index = 1;
|
||||
@@ -3606,12 +3598,12 @@ private:
|
||||
|
||||
it is called when the base is 10 and some digits were read before
|
||||
*/
|
||||
uint FromString_ReadScientificIfExists(const tt_char * & source)
|
||||
uint FromString_ReadScientificIfExists(const char * & source)
|
||||
{
|
||||
uint c = 0;
|
||||
|
||||
bool scientific_read = false;
|
||||
const tt_char * before_scientific = source;
|
||||
const char * before_scientific = source;
|
||||
|
||||
if( FromString_TestScientific(source) )
|
||||
c += FromString_ReadPartScientific( source, scientific_read );
|
||||
@@ -3629,7 +3621,7 @@ private:
|
||||
|
||||
this character is only allowed when we're using the base equals 10
|
||||
*/
|
||||
bool FromString_TestScientific(const tt_char * & source)
|
||||
bool FromString_TestScientific(const char * & source)
|
||||
{
|
||||
UInt<man>::SkipWhiteCharacters(source);
|
||||
|
||||
@@ -3648,7 +3640,7 @@ private:
|
||||
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
|
||||
*/
|
||||
uint FromString_ReadPartScientific( const tt_char * & source, bool & scientific_read )
|
||||
uint FromString_ReadPartScientific( const char * & source, bool & scientific_read )
|
||||
{
|
||||
uint c = 0;
|
||||
Big<exp, man> new_exponent, temp;
|
||||
@@ -3675,7 +3667,7 @@ private:
|
||||
this method reads the value of the extra exponent when scientific format is used
|
||||
(only when base == 10)
|
||||
*/
|
||||
uint FromString_ReadPartScientific_ReadExponent( const tt_char * & source, Big<exp, man> & new_exponent, bool & scientific_read )
|
||||
uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big<exp, man> & new_exponent, bool & scientific_read )
|
||||
{
|
||||
sint character;
|
||||
Big<exp, man> base, temp;
|
||||
@@ -3708,7 +3700,7 @@ public:
|
||||
/*!
|
||||
a method for converting a string into its value
|
||||
*/
|
||||
uint FromString(const tt_string & string, uint base = 10)
|
||||
uint FromString(const std::string & string, uint base = 10)
|
||||
{
|
||||
return FromString( string.c_str(), base );
|
||||
}
|
||||
@@ -3717,7 +3709,7 @@ public:
|
||||
/*!
|
||||
a constructor for converting a string into this class
|
||||
*/
|
||||
Big(const tt_char * string)
|
||||
Big(const char * string)
|
||||
{
|
||||
FromString( string );
|
||||
}
|
||||
@@ -3726,7 +3718,7 @@ public:
|
||||
/*!
|
||||
a constructor for converting a string into this class
|
||||
*/
|
||||
Big(const tt_string & string)
|
||||
Big(const std::string & string)
|
||||
{
|
||||
FromString( string.c_str() );
|
||||
}
|
||||
@@ -3735,7 +3727,7 @@ public:
|
||||
/*!
|
||||
an operator= for converting a string into its value
|
||||
*/
|
||||
Big<exp, man> & operator=(const tt_char * string)
|
||||
Big<exp, man> & operator=(const char * string)
|
||||
{
|
||||
FromString( string );
|
||||
|
||||
@@ -3746,7 +3738,7 @@ public:
|
||||
/*!
|
||||
an operator= for converting a string into its value
|
||||
*/
|
||||
Big<exp, man> & operator=(const tt_string & string)
|
||||
Big<exp, man> & operator=(const std::string & string)
|
||||
{
|
||||
FromString( string.c_str() );
|
||||
|
||||
@@ -3864,72 +3856,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AboutEqual(const Big<exp,man> & ss2, int nBitsToIgnore = 4) const
|
||||
{
|
||||
// we should check the mantissas beforehand because sometimes we can have
|
||||
// a mantissa set to zero but in the exponent something another value
|
||||
// (maybe we've forgotten about calling CorrectZero() ?)
|
||||
if( mantissa.IsZero())
|
||||
{
|
||||
if (ss2.mantissa.IsZero())
|
||||
return true;
|
||||
return(ss2.AboutEqual(*this,nBitsToIgnore));
|
||||
}
|
||||
|
||||
if (ss2.mantissa.IsZero())
|
||||
{
|
||||
return(this->exponent <= uint(2*(-sint(man*TTMATH_BITS_PER_UINT))+nBitsToIgnore));
|
||||
}
|
||||
|
||||
// exponents may not differ much!
|
||||
ttmath::Int<exp> expdiff(this->exponent - ss2.exponent);
|
||||
|
||||
// they may differ one if for example mantissa1=0x80000000, mantissa2=0xffffffff
|
||||
if (ttmath::Abs(expdiff) > 1)
|
||||
return(false);
|
||||
|
||||
// calculate the 'difference' mantissa
|
||||
ttmath::UInt<man> man1(this->mantissa);
|
||||
ttmath::UInt<man> man2(ss2.mantissa);
|
||||
ttmath::UInt<man> mandiff;
|
||||
|
||||
switch (expdiff.ToInt())
|
||||
{
|
||||
case +1:
|
||||
man2.Rcr(1,0);
|
||||
mandiff = man1;
|
||||
mandiff.Sub(man2);
|
||||
break;
|
||||
case -1:
|
||||
man1.Rcr(1,0);
|
||||
mandiff = man2;
|
||||
mandiff.Sub(man1);
|
||||
break;
|
||||
default:
|
||||
if (man2 > man1)
|
||||
{
|
||||
mandiff = man2;
|
||||
mandiff.Sub(man1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mandiff = man1;
|
||||
mandiff.Sub(man2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// faster to mask the bits!
|
||||
ASSERT(nBitsToIgnore < TTMATH_BITS_PER_UINT);
|
||||
|
||||
for (int n = man-1; n > 0; --n)
|
||||
{
|
||||
if (mandiff.table[n] != 0)
|
||||
return(false);
|
||||
}
|
||||
uint nMask = ~((1 << nBitsToIgnore) - 1);
|
||||
return((mandiff.table[0] & nMask) == 0);
|
||||
}
|
||||
|
||||
bool operator<(const Big<exp,man> & ss2) const
|
||||
{
|
||||
@@ -3961,6 +3887,8 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool operator>(const Big<exp,man> & ss2) const
|
||||
{
|
||||
if( IsSign() && !ss2.IsSign() )
|
||||
@@ -4175,47 +4103,6 @@ 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
|
||||
@@ -4264,14 +4151,9 @@ public:
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
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)
|
||||
friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
l.ToString(ss);
|
||||
s << ss;
|
||||
@@ -4280,18 +4162,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
input from standard streams
|
||||
|
||||
tt_istream is either std::istream or std::wistream
|
||||
*/
|
||||
friend tt_istream & operator>>(tt_istream & s, Big<exp,man> & l)
|
||||
friend std::istream & operator>>(std::istream & s, Big<exp,man> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
// 'tt_char' for operator>>
|
||||
tt_char z;
|
||||
// char for operator>>
|
||||
char z, old_z;
|
||||
bool was_comma = false;
|
||||
bool was_e = false;
|
||||
|
||||
|
||||
// operator>> omits white characters if they're set for ommiting
|
||||
s >> z;
|
||||
@@ -4302,24 +4181,43 @@ public:
|
||||
s >> z; // we're reading a next character (white characters can be ommited)
|
||||
}
|
||||
|
||||
old_z = 0;
|
||||
|
||||
// we're reading only digits (base=10) and only one comma operator
|
||||
for( ; s.good() ; z=static_cast<tt_char>(s.get()) )
|
||||
for( ; s.good() ; z=static_cast<char>(s.get()) )
|
||||
{
|
||||
if( z == TTMATH_COMMA_CHARACTER_1 ||
|
||||
( z == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
|
||||
{
|
||||
if( was_comma )
|
||||
// second comma operator
|
||||
if( was_comma || was_e )
|
||||
// second comma operator or comma operator after 'e' character
|
||||
break;
|
||||
|
||||
was_comma = true;
|
||||
}
|
||||
else
|
||||
if( z == 'e' || z == 'E' )
|
||||
{
|
||||
if( was_e )
|
||||
// second 'e' character
|
||||
break;
|
||||
|
||||
was_e = true;
|
||||
}
|
||||
else
|
||||
if( z == '+' || z == '-' )
|
||||
{
|
||||
if( old_z != 'e' && old_z != 'E' )
|
||||
// '+' or '-' is allowed only after 'e' character
|
||||
break;
|
||||
}
|
||||
else
|
||||
if( UInt<man>::CharToDigit(z, 10) < 0 )
|
||||
break;
|
||||
|
||||
|
||||
ss += z;
|
||||
ss += z;
|
||||
old_z = z;
|
||||
}
|
||||
|
||||
// we're leaving the last read character
|
||||
@@ -4333,9 +4231,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the PNG licence.
|
||||
* Author: Christian Kaiser <chk@online.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2009 Christian Kaiser
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#ifndef headerfilettmathconfig
|
||||
#define headerfilettmathconfig
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(_MT)
|
||||
class clsCrit
|
||||
{
|
||||
private:
|
||||
mutable CRITICAL_SECTION _Crit;
|
||||
|
||||
clsCrit(const clsCrit&) // inhibit copy (easy mistake to do; use clsCritObj instead!!!)
|
||||
{
|
||||
}
|
||||
clsCrit& operator=(const clsCrit& rhs); // inhibit assignment
|
||||
public:
|
||||
clsCrit(void)
|
||||
{
|
||||
InitializeCriticalSection(&_Crit);
|
||||
}
|
||||
virtual ~clsCrit(void)
|
||||
{
|
||||
DeleteCriticalSection(&_Crit);
|
||||
}
|
||||
|
||||
void Enter(void) const
|
||||
{
|
||||
EnterCriticalSection(&_Crit);
|
||||
}
|
||||
void Leave(void) const
|
||||
{
|
||||
LeaveCriticalSection(&_Crit);
|
||||
}
|
||||
};
|
||||
|
||||
class clsCritObj
|
||||
{
|
||||
private:
|
||||
const clsCrit& _Crit;
|
||||
|
||||
clsCritObj& operator=(const clsCritObj& rhs); // not applicable
|
||||
public:
|
||||
clsCritObj(const clsCrit& Sync)
|
||||
: _Crit(Sync)
|
||||
{
|
||||
_Crit.Enter();
|
||||
}
|
||||
~clsCritObj(void)
|
||||
{
|
||||
_Crit.Leave();
|
||||
}
|
||||
};
|
||||
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ \
|
||||
private: \
|
||||
clsCrit CritSect; \
|
||||
public: \
|
||||
operator clsCrit&() \
|
||||
{ \
|
||||
return(CritSect); \
|
||||
}
|
||||
#define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c)
|
||||
#endif
|
||||
#else // defined(WIN32)
|
||||
// not Windows world: no threading synchronization for now
|
||||
#endif
|
||||
|
||||
#if !defined(TTMATH_IMPLEMENT_THREADSAFE_OBJ)
|
||||
// if we don't know about serialization, make it a no-op
|
||||
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ /* */
|
||||
#define TTMATH_USE_THREADSAFE_OBJ(c) /* */
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // headerfilettmathconfig
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -47,10 +47,6 @@
|
||||
|
||||
#include "ttmathuint.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
@@ -645,14 +641,8 @@ public:
|
||||
|
||||
// there can be a carry here when the size of this value is equal one word
|
||||
// and the 'value' has the highest bit set
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
|
||||
return 1;
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -831,7 +821,7 @@ public:
|
||||
/*!
|
||||
a constructor for converting string to this class (with the base=10)
|
||||
*/
|
||||
Int(const tt_char * s)
|
||||
Int(const char * s)
|
||||
{
|
||||
FromString(s);
|
||||
}
|
||||
@@ -840,7 +830,7 @@ public:
|
||||
/*!
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
Int(const tt_string & s)
|
||||
Int(const std::string & s)
|
||||
{
|
||||
FromString( s.c_str() );
|
||||
}
|
||||
@@ -879,7 +869,7 @@ public:
|
||||
/*!
|
||||
this method converts the value to a string with a base equal 'b'
|
||||
*/
|
||||
void ToString(tt_string & result, uint b = 10) const
|
||||
void ToString(std::string & result, uint b = 10) const
|
||||
{
|
||||
if( IsSign() )
|
||||
{
|
||||
@@ -900,14 +890,12 @@ public:
|
||||
|
||||
/*!
|
||||
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
|
||||
|
||||
string is ended with a non-digit value, for example:
|
||||
"-12" will be translated to -12
|
||||
as well as:
|
||||
"- 12foo" will be translated to -12 too
|
||||
"- 12foo" will be translated to 12 too
|
||||
|
||||
existing first white characters will be ommited
|
||||
(between '-' and a first digit can be white characters too)
|
||||
@@ -916,7 +904,7 @@ public:
|
||||
|
||||
value_read (if exists) tells whether something has actually been read (at least one digit)
|
||||
*/
|
||||
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
|
||||
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
bool is_sign = false;
|
||||
|
||||
@@ -973,7 +961,7 @@ public:
|
||||
this method converts a string into its value
|
||||
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
|
||||
*/
|
||||
uint FromString(const tt_string & s, uint b = 10)
|
||||
uint FromString(const std::string & s, uint b = 10)
|
||||
{
|
||||
return FromString( s.c_str(), b );
|
||||
}
|
||||
@@ -982,7 +970,7 @@ public:
|
||||
/*!
|
||||
this operator converts a string into its value (with base = 10)
|
||||
*/
|
||||
Int<value_size> & operator=(const tt_char * s)
|
||||
Int<value_size> & operator=(const char * s)
|
||||
{
|
||||
FromString(s);
|
||||
|
||||
@@ -993,7 +981,7 @@ public:
|
||||
/*!
|
||||
this operator converts a string into its value (with base = 10)
|
||||
*/
|
||||
Int<value_size> & operator=(const tt_string & s)
|
||||
Int<value_size> & operator=(const std::string & s)
|
||||
{
|
||||
FromString( s.c_str() );
|
||||
|
||||
@@ -1280,14 +1268,9 @@ public:
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
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)
|
||||
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
l.ToString(ss);
|
||||
s << ss;
|
||||
@@ -1296,17 +1279,13 @@ public:
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
input from standard streams
|
||||
|
||||
tt_istream is either std::istream or std::wistream
|
||||
*/
|
||||
friend tt_istream & operator>>(tt_istream & s, Int<value_size> & l)
|
||||
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
// tt_char for operator>>
|
||||
tt_char z;
|
||||
// char for operator>>
|
||||
unsigned char z;
|
||||
|
||||
// operator>> omits white characters if they're set for ommiting
|
||||
s >> z;
|
||||
@@ -1321,7 +1300,7 @@ public:
|
||||
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
|
||||
{
|
||||
ss += z;
|
||||
z = static_cast<tt_char>(s.get());
|
||||
z = s.get();
|
||||
}
|
||||
|
||||
// we're leaving the last readed character
|
||||
@@ -1337,9 +1316,4 @@ public:
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Mathematical Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
@@ -74,19 +73,18 @@ public:
|
||||
struct Item
|
||||
{
|
||||
// name of a variable of a function
|
||||
// (either std::string or std::wstring)
|
||||
tt_string value;
|
||||
std::string value;
|
||||
|
||||
// number of parameters required by the function
|
||||
// (if there's a variable this 'param' is ignored)
|
||||
int param;
|
||||
|
||||
Item() {}
|
||||
Item(const tt_string & v, int p) : value(v), param(p) {}
|
||||
Item(const std::string & v, int p) : value(v), param(p) {}
|
||||
};
|
||||
|
||||
// 'Table' is the type of our table
|
||||
typedef std::map<tt_string, Item> Table;
|
||||
typedef std::map<std::string, Item> Table;
|
||||
typedef Table::iterator Iterator;
|
||||
typedef Table::const_iterator CIterator;
|
||||
|
||||
@@ -114,7 +112,7 @@ public:
|
||||
/*!
|
||||
this method returns true if the name can be as a name of an object
|
||||
*/
|
||||
static bool IsNameCorrect(const tt_string & name)
|
||||
static bool IsNameCorrect(const std::string & name)
|
||||
{
|
||||
if( name.empty() )
|
||||
return false;
|
||||
@@ -122,7 +120,7 @@ public:
|
||||
if( !CorrectCharacter(name[0], false) )
|
||||
return false;
|
||||
|
||||
tt_string::const_iterator i=name.begin();
|
||||
std::string::const_iterator i=name.begin();
|
||||
|
||||
for(++i ; i!=name.end() ; ++i)
|
||||
if( !CorrectCharacter(*i, true) )
|
||||
@@ -135,7 +133,7 @@ public:
|
||||
/*!
|
||||
this method returns true if such an object is defined (name exists)
|
||||
*/
|
||||
bool IsDefined(const tt_string & name)
|
||||
bool IsDefined(const std::string & name)
|
||||
{
|
||||
Iterator i = table.find(name);
|
||||
|
||||
@@ -150,7 +148,7 @@ public:
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
|
||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -207,7 +205,7 @@ public:
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
|
||||
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -227,7 +225,7 @@ public:
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
|
||||
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
|
||||
{
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
@@ -258,7 +256,7 @@ public:
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const tt_string & name)
|
||||
ErrorCode Delete(const std::string & name)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -277,7 +275,7 @@ public:
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const tt_string & name, tt_string & value) const
|
||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -300,7 +298,7 @@ public:
|
||||
this method gets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
|
||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -323,7 +321,7 @@ public:
|
||||
this method gets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
|
||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -349,7 +347,7 @@ public:
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
|
||||
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -432,7 +430,7 @@ public:
|
||||
*/
|
||||
History()
|
||||
{
|
||||
buffer_max_size = 15;
|
||||
buffer_max_size = 10;
|
||||
}
|
||||
|
||||
|
||||
@@ -489,118 +487,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this methods deletes an item
|
||||
|
||||
we assume that there is only one item with the 'key'
|
||||
(this methods removes the first one)
|
||||
*/
|
||||
bool Remove(const ValueType & key)
|
||||
{
|
||||
typename buffer_type::iterator i = buffer.begin();
|
||||
|
||||
for( ; i != buffer.end() ; ++i )
|
||||
{
|
||||
if( i->key == key )
|
||||
{
|
||||
buffer.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}; // end of class History
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -45,7 +45,7 @@
|
||||
\brief A mathematical parser
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -137,6 +137,7 @@ namespace ttmath
|
||||
template<class ValueType>
|
||||
class Parser
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
@@ -255,7 +256,7 @@ public:
|
||||
bool function;
|
||||
|
||||
// if function is true
|
||||
tt_string function_name;
|
||||
std::string function_name;
|
||||
|
||||
/*
|
||||
the sign of value
|
||||
@@ -310,11 +311,10 @@ ErrorCode error;
|
||||
|
||||
/*!
|
||||
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
|
||||
*/
|
||||
const tt_char * pstring;
|
||||
const char * pstring;
|
||||
|
||||
|
||||
/*!
|
||||
@@ -351,7 +351,7 @@ const Objects * puser_variables;
|
||||
const Objects * puser_functions;
|
||||
|
||||
|
||||
typedef std::map<tt_string, ValueType> FunctionLocalVariables;
|
||||
typedef std::map<std::string, ValueType> FunctionLocalVariables;
|
||||
|
||||
/*!
|
||||
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
|
||||
*/
|
||||
std::set<tt_string> visited_variables;
|
||||
std::set<std::string> visited_variables;
|
||||
|
||||
|
||||
/*!
|
||||
a temporary set using during parsing user defined functions
|
||||
*/
|
||||
std::set<tt_string> visited_functions;
|
||||
std::set<std::string> visited_functions;
|
||||
|
||||
|
||||
|
||||
@@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
|
||||
table of mathematic functions
|
||||
|
||||
this map consists of:
|
||||
tt_string - function's name
|
||||
pfunction - pointer to specific function
|
||||
std::string - function's name
|
||||
pfunction - pointer to specific function
|
||||
*/
|
||||
typedef std::map<tt_string, pfunction> FunctionsTable;
|
||||
typedef std::map<std::string, pfunction> FunctionsTable;
|
||||
FunctionsTable functions_table;
|
||||
|
||||
|
||||
@@ -407,10 +407,10 @@ FunctionsTable functions_table;
|
||||
table of mathematic operators
|
||||
|
||||
this map consists of:
|
||||
tt_string - operators's name
|
||||
std::string - operators's name
|
||||
MatOperator::Type - type of the operator
|
||||
*/
|
||||
typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
|
||||
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
|
||||
OperatorsTable operators_table;
|
||||
|
||||
|
||||
@@ -418,17 +418,18 @@ OperatorsTable operators_table;
|
||||
table of mathematic variables
|
||||
|
||||
this map consists of:
|
||||
tt_string - variable's name
|
||||
std::string - variable's name
|
||||
pfunction_var - pointer to specific function which returns value of variable
|
||||
*/
|
||||
typedef std::map<tt_string, pfunction_var> VariablesTable;
|
||||
typedef std::map<std::string, pfunction_var> VariablesTable;
|
||||
VariablesTable variables_table;
|
||||
|
||||
|
||||
/*!
|
||||
some coefficients used when calculating the gamma (or factorial) function
|
||||
you can't calculate the factorial if the argument is greater than 'factorial_max'
|
||||
default value is zero which means there are not any limitations
|
||||
*/
|
||||
CGamma<ValueType> cgamma;
|
||||
ValueType factorial_max;
|
||||
|
||||
|
||||
/*!
|
||||
@@ -455,7 +456,7 @@ void SkipWhiteCharacters()
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
|
||||
{
|
||||
if( variable )
|
||||
{
|
||||
@@ -473,7 +474,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
|
||||
{
|
||||
if( variable )
|
||||
visited_variables.insert( name );
|
||||
@@ -485,7 +486,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
|
||||
{
|
||||
if( variable )
|
||||
visited_variables.erase( name );
|
||||
@@ -504,8 +505,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_str
|
||||
(there can be a recurrence here therefore we're using 'visited_variables'
|
||||
and 'visited_functions' sets to make a stop condition)
|
||||
*/
|
||||
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tt_string & name, const tt_char * new_string,
|
||||
FunctionLocalVariables * local_variables = 0)
|
||||
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0)
|
||||
{
|
||||
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
|
||||
RecurrenceParsingVariablesOrFunction_AddName(variable, name);
|
||||
@@ -548,12 +548,12 @@ public:
|
||||
/*!
|
||||
this method returns the user-defined value of a variable
|
||||
*/
|
||||
bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
|
||||
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
|
||||
{
|
||||
if( !puser_variables )
|
||||
return false;
|
||||
|
||||
const tt_char * string_value;
|
||||
const char * string_value;
|
||||
|
||||
if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
|
||||
return false;
|
||||
@@ -567,7 +567,7 @@ return true;
|
||||
/*!
|
||||
this method returns the value of a local variable of a function
|
||||
*/
|
||||
bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
|
||||
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
|
||||
{
|
||||
if( !pfunction_local_variables )
|
||||
return false;
|
||||
@@ -589,7 +589,7 @@ return true;
|
||||
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
|
||||
*/
|
||||
ValueType GetValueOfVariable(const tt_string & variable_name)
|
||||
ValueType GetValueOfVariable(const std::string & variable_name)
|
||||
{
|
||||
ValueType result;
|
||||
|
||||
@@ -600,7 +600,7 @@ ValueType result;
|
||||
return result;
|
||||
|
||||
|
||||
typename std::map<tt_string, pfunction_var>::iterator i =
|
||||
typename std::map<std::string, pfunction_var>::iterator i =
|
||||
variables_table.find(variable_name);
|
||||
|
||||
if( i == variables_table.end() )
|
||||
@@ -674,20 +674,6 @@ 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
|
||||
result = 1 * 2 * 3 * 4 * .... * x
|
||||
@@ -699,7 +685,10 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
|
||||
|
||||
ErrorCode err;
|
||||
|
||||
result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
|
||||
if( !factorial_max.IsZero() && stack[sindex].value > factorial_max )
|
||||
Error( err_too_big_factorial );
|
||||
|
||||
result = ttmath::Factorial(stack[sindex].value, &err, pstop_calculating);
|
||||
|
||||
if(err != err_ok)
|
||||
Error( err );
|
||||
@@ -1355,34 +1344,17 @@ 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
|
||||
|
||||
(look at the description in 'CallFunction(...)')
|
||||
*/
|
||||
bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
|
||||
{
|
||||
if( !puser_functions )
|
||||
return false;
|
||||
|
||||
const tt_char * string_value;
|
||||
const char * string_value;
|
||||
int param;
|
||||
|
||||
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok )
|
||||
@@ -1396,17 +1368,15 @@ bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_o
|
||||
|
||||
if( amount_of_args > 0 )
|
||||
{
|
||||
tt_char buffer[30];
|
||||
char buffer[20];
|
||||
|
||||
// x = x1
|
||||
buffer[0] = 'x';
|
||||
buffer[1] = 0;
|
||||
sprintf(buffer,"x");
|
||||
local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
|
||||
|
||||
for(int i=0 ; i<amount_of_args ; ++i)
|
||||
{
|
||||
buffer[0] = 'x';
|
||||
Sprintf(buffer+1, i+1);
|
||||
sprintf(buffer,"x%d",i+1);
|
||||
local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
|
||||
}
|
||||
}
|
||||
@@ -1430,7 +1400,7 @@ return true;
|
||||
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)
|
||||
*/
|
||||
void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||
void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
|
||||
{
|
||||
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
|
||||
return;
|
||||
@@ -1456,9 +1426,9 @@ void CallFunction(const tt_string & function_name, int amount_of_args, int sinde
|
||||
function_name - name of the function
|
||||
pf - pointer to the function (to the wrapper)
|
||||
*/
|
||||
void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
|
||||
void InsertFunctionToTable(const char * function_name, pfunction pf)
|
||||
{
|
||||
functions_table.insert( std::make_pair(tt_string(function_name), pf));
|
||||
functions_table.insert( std::make_pair(std::string(function_name), pf));
|
||||
}
|
||||
|
||||
|
||||
@@ -1469,9 +1439,9 @@ void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
|
||||
variable_name - name of the function
|
||||
pf - pointer to the function
|
||||
*/
|
||||
void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
|
||||
void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
||||
{
|
||||
variables_table.insert( std::make_pair(tt_string(variable_name), pf));
|
||||
variables_table.insert( std::make_pair(std::string(variable_name), pf));
|
||||
}
|
||||
|
||||
|
||||
@@ -1480,65 +1450,67 @@ void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
|
||||
*/
|
||||
void CreateFunctionsTable()
|
||||
{
|
||||
InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
|
||||
InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
|
||||
InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
|
||||
InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
|
||||
InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
|
||||
InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
|
||||
InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
|
||||
InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
|
||||
InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
|
||||
InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
|
||||
InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
|
||||
InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
|
||||
InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
|
||||
InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
|
||||
InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
|
||||
InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
|
||||
InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
|
||||
/*
|
||||
names of functions should consist of small letters
|
||||
*/
|
||||
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
|
||||
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
|
||||
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
|
||||
InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
|
||||
InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable("int", &Parser<ValueType>::Int);
|
||||
InsertFunctionToTable("round", &Parser<ValueType>::Round);
|
||||
InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
|
||||
InsertFunctionToTable("log", &Parser<ValueType>::Log);
|
||||
InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
|
||||
InsertFunctionToTable("max", &Parser<ValueType>::Max);
|
||||
InsertFunctionToTable("min", &Parser<ValueType>::Min);
|
||||
InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
|
||||
InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
|
||||
InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
|
||||
InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
|
||||
InsertFunctionToTable("if", &Parser<ValueType>::If);
|
||||
InsertFunctionToTable("or", &Parser<ValueType>::Or);
|
||||
InsertFunctionToTable("and", &Parser<ValueType>::And);
|
||||
InsertFunctionToTable("not", &Parser<ValueType>::Not);
|
||||
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
|
||||
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
|
||||
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
|
||||
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
|
||||
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
|
||||
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
|
||||
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
|
||||
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
|
||||
InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
|
||||
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
|
||||
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
|
||||
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
|
||||
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable("root", &Parser<ValueType>::Root);
|
||||
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
|
||||
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
|
||||
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
|
||||
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
|
||||
}
|
||||
|
||||
|
||||
@@ -1547,8 +1519,11 @@ void CreateFunctionsTable()
|
||||
*/
|
||||
void CreateVariablesTable()
|
||||
{
|
||||
InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
|
||||
InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
|
||||
/*
|
||||
names of variables should consist of small letters
|
||||
*/
|
||||
InsertVariableToTable("pi", &ValueType::SetPi);
|
||||
InsertVariableToTable("e", &ValueType::SetE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1574,7 +1549,7 @@ return c;
|
||||
what should be returned is tested just by a '(' character that means if there's
|
||||
a '(' character after a name that function returns 'true'
|
||||
*/
|
||||
bool ReadName(tt_string & result)
|
||||
bool ReadName(std::string & result)
|
||||
{
|
||||
int character;
|
||||
|
||||
@@ -1591,7 +1566,7 @@ int character;
|
||||
|
||||
do
|
||||
{
|
||||
result += static_cast<tt_char>( character );
|
||||
result += static_cast<char>( character );
|
||||
character = * ++pstring;
|
||||
}
|
||||
while( (character>='a' && character<='z') ||
|
||||
@@ -1646,7 +1621,7 @@ return false;
|
||||
*/
|
||||
bool ReadVariableOrFunction(Item & result)
|
||||
{
|
||||
tt_string name;
|
||||
std::string name;
|
||||
bool is_it_name_of_function = ReadName(name);
|
||||
|
||||
if( is_it_name_of_function )
|
||||
@@ -1675,7 +1650,7 @@ return is_it_name_of_function;
|
||||
*/
|
||||
void ReadValue(Item & result, int reading_base)
|
||||
{
|
||||
const tt_char * new_stack_pointer;
|
||||
const char * new_stack_pointer;
|
||||
bool value_read;
|
||||
|
||||
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
||||
@@ -1848,9 +1823,9 @@ return 0;
|
||||
}
|
||||
|
||||
|
||||
void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
|
||||
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type)
|
||||
{
|
||||
operators_table.insert( std::make_pair(tt_string(name), type) );
|
||||
operators_table.insert( std::make_pair(name, type) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1859,19 +1834,19 @@ void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type
|
||||
*/
|
||||
void CreateMathematicalOperatorsTable()
|
||||
{
|
||||
InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
|
||||
InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
|
||||
InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
|
||||
InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
|
||||
InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
|
||||
InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
|
||||
InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
|
||||
InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
|
||||
InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
|
||||
InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
|
||||
InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
|
||||
InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
|
||||
InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
|
||||
InsertOperatorToTable(std::string("||"), MatOperator::lor);
|
||||
InsertOperatorToTable(std::string("&&"), MatOperator::land);
|
||||
InsertOperatorToTable(std::string("!="), MatOperator::neq);
|
||||
InsertOperatorToTable(std::string("=="), MatOperator::eq);
|
||||
InsertOperatorToTable(std::string(">="), MatOperator::get);
|
||||
InsertOperatorToTable(std::string("<="), MatOperator::let);
|
||||
InsertOperatorToTable(std::string(">"), MatOperator::gt);
|
||||
InsertOperatorToTable(std::string("<"), MatOperator::lt);
|
||||
InsertOperatorToTable(std::string("-"), MatOperator::sub);
|
||||
InsertOperatorToTable(std::string("+"), MatOperator::add);
|
||||
InsertOperatorToTable(std::string("/"), MatOperator::div);
|
||||
InsertOperatorToTable(std::string("*"), MatOperator::mul);
|
||||
InsertOperatorToTable(std::string("^"), MatOperator::pow);
|
||||
}
|
||||
|
||||
|
||||
@@ -1881,12 +1856,12 @@ void CreateMathematicalOperatorsTable()
|
||||
e.g.
|
||||
true when str1="test" and str2="te"
|
||||
*/
|
||||
bool IsSubstring(const tt_string & str1, const tt_string & str2)
|
||||
bool IsSubstring(const std::string & str1, const std::string & str2)
|
||||
{
|
||||
if( str2.length() > str1.length() )
|
||||
return false;
|
||||
|
||||
for(tt_string::size_type i=0 ; i<str2.length() ; ++i)
|
||||
for(std::string::size_type i=0 ; i<str2.length() ; ++i)
|
||||
if( str1[i] != str2[i] )
|
||||
return false;
|
||||
|
||||
@@ -1899,7 +1874,7 @@ return true;
|
||||
*/
|
||||
void ReadMathematicalOperator(Item & result)
|
||||
{
|
||||
tt_string oper;
|
||||
std::string oper;
|
||||
typename OperatorsTable::iterator iter_old, iter_new;
|
||||
|
||||
iter_old = operators_table.end();
|
||||
@@ -2429,6 +2404,7 @@ Parser(): default_stack_size(100)
|
||||
base = 10;
|
||||
deg_rad_grad = 1;
|
||||
error = err_ok;
|
||||
factorial_max.SetZero();
|
||||
|
||||
CreateFunctionsTable();
|
||||
CreateVariablesTable();
|
||||
@@ -2445,9 +2421,10 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
|
||||
puser_variables = p.puser_variables;
|
||||
puser_functions = p.puser_functions;
|
||||
pfunction_local_variables = 0;
|
||||
base = p.base;
|
||||
deg_rad_grad = p.deg_rad_grad;
|
||||
error = err_ok;
|
||||
base = p.base;
|
||||
deg_rad_grad = p.deg_rad_grad;
|
||||
error = err_ok;
|
||||
factorial_max = p.factorial_max;
|
||||
|
||||
/*
|
||||
we don't have to call 'CreateFunctionsTable()' etc.
|
||||
@@ -2529,11 +2506,22 @@ 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
|
||||
*/
|
||||
ErrorCode Parse(const tt_char * str)
|
||||
ErrorCode Parse(const char * str)
|
||||
{
|
||||
stack_index = 0;
|
||||
pstring = str;
|
||||
@@ -2556,11 +2544,11 @@ return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/*!
|
||||
the version of the library
|
||||
@@ -63,9 +63,9 @@
|
||||
if zero that means this is the release version of the library
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 9
|
||||
#define TTMATH_REVISION_VER 0
|
||||
#define TTMATH_PRERELEASE_VER 1
|
||||
#define TTMATH_MINOR_VER 8
|
||||
#define TTMATH_REVISION_VER 6
|
||||
#define TTMATH_PRERELEASE_VER 0
|
||||
|
||||
|
||||
/*!
|
||||
@@ -120,7 +120,6 @@ namespace ttmath
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
|
||||
/*!
|
||||
this type is twice bigger than uint
|
||||
(64bit on a 32bit platforms)
|
||||
@@ -129,39 +128,43 @@ namespace ttmath
|
||||
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
|
||||
|
||||
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
|
||||
but only on a 32bit platform
|
||||
*/
|
||||
typedef unsigned long long int ulint;
|
||||
#ifdef TTMATH_NOASM
|
||||
typedef unsigned long long int ulint;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 32u
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||
*/
|
||||
const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
|
||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 32bit word (2^32 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
|
||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||
|
||||
/*!
|
||||
the number of words (32bit words on 32bit platform)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 256u;
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned __int64 uint;
|
||||
typedef signed __int64 sint;
|
||||
#else
|
||||
typedef unsigned long long uint;
|
||||
typedef signed long long sint;
|
||||
#endif
|
||||
typedef unsigned long uint;
|
||||
typedef signed long sint;
|
||||
|
||||
/*!
|
||||
on 64bit platform we do not define ulint
|
||||
sizeof(long long) is 8 (64bit) but we need 128bit
|
||||
@@ -171,61 +174,33 @@ namespace ttmath
|
||||
*/
|
||||
//typedef unsigned long long int ulint;
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 64ul
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 64bit word (2^63)
|
||||
*/
|
||||
const uint TTMATH_UINT_HIGHEST_BIT = 0x8000000000000000ul;
|
||||
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 64bit word (2^64 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffffffffffful;
|
||||
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
||||
|
||||
/*!
|
||||
the number of words (64bit words on 64bit platforms)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 128ul;
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
||||
|
||||
#endif
|
||||
|
||||
const uint TTMATH_BITS_PER_UINT = (sizeof(uint)*8);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#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
|
||||
@@ -274,18 +249,6 @@ namespace ttmath
|
||||
#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
|
||||
{
|
||||
|
||||
@@ -319,6 +282,7 @@ namespace ttmath
|
||||
err_object_exists,
|
||||
err_unknown_object,
|
||||
err_still_calculating,
|
||||
err_too_big_factorial,
|
||||
err_in_short_form_used_function
|
||||
};
|
||||
|
||||
@@ -349,20 +313,20 @@ namespace ttmath
|
||||
*/
|
||||
class ExceptionInfo
|
||||
{
|
||||
const tt_char * file;
|
||||
const char * file;
|
||||
int line;
|
||||
|
||||
public:
|
||||
ExceptionInfo() : file(0), line(0) {}
|
||||
ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
|
||||
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
|
||||
|
||||
tt_string Where() const
|
||||
std::string Where() const
|
||||
{
|
||||
if( !file )
|
||||
return TTMATH_TEXT("unknown");
|
||||
return "unknown";
|
||||
|
||||
tt_ostringstream result;
|
||||
result << file << TTMATH_TEXT(":") << line;
|
||||
std::ostringstream result;
|
||||
result << file << ":" << line;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
@@ -376,7 +340,7 @@ namespace ttmath
|
||||
can throw an exception of this type
|
||||
|
||||
If you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string (or std::wstring) with
|
||||
from using method Where() (it returns std::string with
|
||||
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
|
||||
was used)
|
||||
|
||||
@@ -404,12 +368,12 @@ namespace ttmath
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceError(const tt_char * f, int l) :
|
||||
ReferenceError(const char * f, int l) :
|
||||
std::logic_error ("reference error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
tt_string Where() const
|
||||
std::string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
@@ -424,7 +388,7 @@ namespace ttmath
|
||||
of this type
|
||||
|
||||
if you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string (or std::wstring) with
|
||||
from using method Where() (it returns std::string with
|
||||
the name and the line of a file where the macro TTMATH_ASSERT
|
||||
was used)
|
||||
*/
|
||||
@@ -436,12 +400,12 @@ namespace ttmath
|
||||
{
|
||||
}
|
||||
|
||||
RuntimeError(const tt_char * f, int l) :
|
||||
RuntimeError(const char * f, int l) :
|
||||
std::runtime_error ("internal error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
tt_string Where() const
|
||||
std::string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
@@ -456,22 +420,11 @@ namespace ttmath
|
||||
|
||||
#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) \
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
|
||||
|
||||
#define TTMATH_VERIFY(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
|
||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
@@ -480,32 +433,19 @@ namespace ttmath
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
|
||||
#define TTMATH_VERIFY(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||
#define TTMATH_ASSERT(expression)
|
||||
#define TTMATH_VERIFY(expression) (void)(expression);
|
||||
#endif
|
||||
|
||||
#if !defined(LOG_PRINTF)
|
||||
#define LOG_PRINTF printf
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TTMATH_DEBUG_LOG
|
||||
|
||||
#ifdef TTMATH_USE_WCHAR
|
||||
#define TTMATH_LOG_HELPER(msg) \
|
||||
PrintLog(L##msg, std::wcout);
|
||||
#else
|
||||
#define TTMATH_LOG_HELPER(msg) \
|
||||
PrintLog(msg, std::cout);
|
||||
#endif
|
||||
|
||||
#define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
|
||||
#define TTMATH_LOG(msg) \
|
||||
PrintLog(msg, std::cout);
|
||||
|
||||
#else
|
||||
|
||||
@@ -514,9 +454,7 @@ namespace ttmath
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -52,9 +52,7 @@
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
\brief a namespace for the TTMath library
|
||||
@@ -88,10 +86,7 @@ public:
|
||||
|
||||
it prints the table in a nice form of several columns
|
||||
*/
|
||||
#ifndef TTMATH_USE_WCHAR
|
||||
// gcc has a problem with std::setfill when wchar_t is used
|
||||
|
||||
void PrintTable(tt_ostream & output) const
|
||||
void PrintTable(std::ostream & output) const
|
||||
{
|
||||
// how many columns there'll be
|
||||
const int columns = 8;
|
||||
@@ -99,7 +94,7 @@ public:
|
||||
int c = 1;
|
||||
for(int i=value_size-1 ; i>=0 ; --i)
|
||||
{
|
||||
output << TTMATH_TEXT("0x") << std::setfill('0');
|
||||
output << "0x" << std::setfill('0');
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
output << std::setw(8);
|
||||
@@ -111,7 +106,7 @@ public:
|
||||
|
||||
if( i>0 )
|
||||
{
|
||||
output << TTMATH_TEXT(", ");
|
||||
output << ", ";
|
||||
|
||||
if( ++c > columns )
|
||||
{
|
||||
@@ -123,14 +118,14 @@ public:
|
||||
|
||||
output << std::dec << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintLog(const tt_char * msg, tt_ostream & output) const
|
||||
|
||||
void PrintLog(const char * msg, std::ostream & output) const
|
||||
{
|
||||
output << msg << std::endl;
|
||||
|
||||
for(uint i=0 ; i<value_size ; ++i)
|
||||
output << TTMATH_TEXT(" table[") << i << TTMATH_TEXT("]: ") << table[i] << std::endl;
|
||||
output << " table[" << i << "]: " << table[i] << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -773,8 +768,7 @@ public:
|
||||
{
|
||||
MulTwoWords(u.table[x1], ss2, &r2, &r1 );
|
||||
|
||||
|
||||
if( x1 <= value_size - 2 )
|
||||
if( value_size>1 && x1<=value_size-2 )
|
||||
{
|
||||
if( AddTwoInts(r2,r1,x1) )
|
||||
return 1;
|
||||
@@ -1971,7 +1965,7 @@ private:
|
||||
for(uint i = j+1 ; i<value_size ; ++i)
|
||||
q.table[i] = 0;
|
||||
|
||||
for (;;)
|
||||
while( true )
|
||||
{
|
||||
u1 = table[j+n-1];
|
||||
u0 = table[j+n-2];
|
||||
@@ -2202,32 +2196,27 @@ public:
|
||||
UInt<value_size> start(*this), start_temp;
|
||||
UInt<value_size> result;
|
||||
result.SetOne();
|
||||
uint c = 0;
|
||||
|
||||
while( !pow.IsZero() )
|
||||
while( !c )
|
||||
{
|
||||
if( pow.table[0] & 1 )
|
||||
if( result.Mul(start) )
|
||||
{
|
||||
TTMATH_LOG("UInt::Pow(UInt<>)")
|
||||
return 1;
|
||||
}
|
||||
c += result.Mul(start);
|
||||
|
||||
pow.Rcr2_one(0);
|
||||
if( pow.IsZero() )
|
||||
break;
|
||||
|
||||
start_temp = start;
|
||||
// in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there)
|
||||
if( start.Mul(start_temp) )
|
||||
{
|
||||
TTMATH_LOG("UInt::Pow(UInt<>)")
|
||||
return 1;
|
||||
}
|
||||
|
||||
pow.Rcr2_one(0);
|
||||
c += start.Mul(start_temp);
|
||||
}
|
||||
|
||||
*this = result;
|
||||
|
||||
TTMATH_LOG("UInt::Pow(UInt<>)")
|
||||
|
||||
return 0;
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2288,7 +2277,7 @@ public:
|
||||
*/
|
||||
bool IsTheLowestBitSet() const
|
||||
{
|
||||
return (table[0] & 1) != 0;
|
||||
return (*table & 1) != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2372,7 +2361,7 @@ public:
|
||||
|
||||
|
||||
/*!
|
||||
this method converts a digit into a tt_char
|
||||
this method converts a digit into a char
|
||||
digit should be from <0,F>
|
||||
(we don't have to get a base)
|
||||
|
||||
@@ -2382,12 +2371,12 @@ public:
|
||||
10 -> A
|
||||
15 -> F
|
||||
*/
|
||||
static tt_char DigitToChar(uint digit)
|
||||
static uint DigitToChar(uint digit)
|
||||
{
|
||||
if( digit < 10 )
|
||||
return (tt_char)(digit + '0');
|
||||
return digit + '0';
|
||||
|
||||
return((tt_char)(digit - 10 + 'A'));
|
||||
return digit - 10 + 'A';
|
||||
}
|
||||
|
||||
|
||||
@@ -2508,7 +2497,7 @@ public:
|
||||
this constant 10 has the int type (signed int), if we don't give such
|
||||
operators and constructors the compiler will not compile the program,
|
||||
because it has to make a conversion and doesn't know into which type
|
||||
(the UInt class has operator=(const tt_char*), operator=(uint) etc.)
|
||||
(the UInt class has operator=(const char*), operator=(uint) etc.)
|
||||
*/
|
||||
UInt<value_size> & operator=(sint i)
|
||||
{
|
||||
@@ -2623,18 +2612,18 @@ public:
|
||||
/*!
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
UInt(const tt_char * s)
|
||||
UInt(const char * s)
|
||||
{
|
||||
FromString(s);
|
||||
|
||||
TTMATH_LOG("UInt::UInt(const tt_char *)")
|
||||
TTMATH_LOG("UInt::UInt(const char *)")
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a constructor for converting a string to this class (with the base=10)
|
||||
*/
|
||||
UInt(const tt_string & s)
|
||||
UInt(const std::string & s)
|
||||
{
|
||||
FromString( s.c_str() );
|
||||
}
|
||||
@@ -2649,7 +2638,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a copy constructor
|
||||
*/
|
||||
@@ -2700,10 +2688,10 @@ public:
|
||||
/*!
|
||||
this method converts the value to a string with a base equal 'b'
|
||||
*/
|
||||
void ToString(tt_string & result, uint b = 10) const
|
||||
void ToString(std::string & result, uint b = 10) const
|
||||
{
|
||||
UInt<value_size> temp( *this );
|
||||
tt_char character;
|
||||
char character;
|
||||
uint rem;
|
||||
|
||||
result.clear();
|
||||
@@ -2714,7 +2702,7 @@ public:
|
||||
do
|
||||
{
|
||||
temp.DivInt(b, &rem);
|
||||
character = static_cast<tt_char>( DigitToChar(rem) );
|
||||
character = static_cast<char>( DigitToChar(rem) );
|
||||
result.insert(result.begin(), character);
|
||||
}
|
||||
while( !temp.IsZero() );
|
||||
@@ -2728,7 +2716,7 @@ public:
|
||||
/*
|
||||
this method's ommiting any white characters from the string
|
||||
*/
|
||||
static void SkipWhiteCharacters(const tt_char * & c)
|
||||
static void SkipWhiteCharacters(const char * & c)
|
||||
{
|
||||
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
||||
++c;
|
||||
@@ -2752,7 +2740,7 @@ public:
|
||||
|
||||
value_read (if exists) tells whether something has actually been read (at least one digit)
|
||||
*/
|
||||
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
|
||||
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
UInt<value_size> base( b );
|
||||
UInt<value_size> temp;
|
||||
@@ -2802,7 +2790,7 @@ public:
|
||||
|
||||
(it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
|
||||
*/
|
||||
uint FromString(const tt_string & s, uint b = 10)
|
||||
uint FromString(const std::string & s, uint b = 10)
|
||||
{
|
||||
return FromString( s.c_str(), b );
|
||||
}
|
||||
@@ -2812,11 +2800,11 @@ public:
|
||||
/*!
|
||||
this operator converts a string into its value (with base = 10)
|
||||
*/
|
||||
UInt<value_size> & operator=(const tt_char * s)
|
||||
UInt<value_size> & operator=(const char * s)
|
||||
{
|
||||
FromString(s);
|
||||
|
||||
TTMATH_LOG("UInt::operator=(const tt_char *)")
|
||||
TTMATH_LOG("UInt::operator=(const char *)")
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -2825,7 +2813,7 @@ public:
|
||||
/*!
|
||||
this operator converts a string into its value (with base = 10)
|
||||
*/
|
||||
UInt<value_size> & operator=(const tt_string & s)
|
||||
UInt<value_size> & operator=(const std::string & s)
|
||||
{
|
||||
FromString( s.c_str() );
|
||||
|
||||
@@ -3193,15 +3181,9 @@ public:
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
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)
|
||||
friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
l.ToString(ss);
|
||||
s << ss;
|
||||
@@ -3211,17 +3193,12 @@ public:
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
input from standard streams
|
||||
|
||||
tt_istream is either std::istream or std::wistream
|
||||
*/
|
||||
friend tt_istream & operator>>(tt_istream & s, UInt<value_size> & l)
|
||||
friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
|
||||
{
|
||||
tt_string ss;
|
||||
std::string ss;
|
||||
|
||||
// tt_char for operator>>
|
||||
tt_char z;
|
||||
// char for operator>>
|
||||
unsigned char z;
|
||||
|
||||
// operator>> omits white characters if they're set for ommiting
|
||||
s >> z;
|
||||
@@ -3230,10 +3207,10 @@ public:
|
||||
while( s.good() && CharToDigit(z, 10)>=0 )
|
||||
{
|
||||
ss += z;
|
||||
z = static_cast<tt_char>(s.get());
|
||||
z = s.get();
|
||||
}
|
||||
|
||||
// we're leaving the last read character
|
||||
// we're leaving the last readed character
|
||||
// (it's not belonging to the value)
|
||||
s.unget();
|
||||
|
||||
@@ -3253,6 +3230,7 @@ public:
|
||||
ttmathuint_noasm.h
|
||||
*/
|
||||
|
||||
#ifdef TTMATH_NOASM
|
||||
static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
|
||||
static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
|
||||
|
||||
@@ -3277,6 +3255,8 @@ public:
|
||||
static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
|
||||
|
||||
#endif // TTMATH_PLATFORM64
|
||||
#endif // TTMATH_NOASM
|
||||
|
||||
|
||||
private:
|
||||
uint Rcl2_one(uint c);
|
||||
@@ -3318,10 +3298,6 @@ public:
|
||||
|
||||
} //namespace
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#include "ttmathuint_x86.h"
|
||||
#include "ttmathuint_x86_64.h"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -41,8 +41,6 @@
|
||||
|
||||
#ifdef TTMATH_NOASM
|
||||
|
||||
#pragma message("TTMATH_NOASM")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_noasm.h
|
||||
\brief template class UInt<uint> with methods without any assembler code
|
||||
@@ -226,7 +224,7 @@ namespace ttmath
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
//TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -353,7 +351,7 @@ namespace ttmath
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
//TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -555,7 +553,7 @@ namespace ttmath
|
||||
|
||||
uint mask = 1;
|
||||
|
||||
if( bit > 1 )
|
||||
if( bit > 0 )
|
||||
mask = mask << bit;
|
||||
|
||||
uint last = value & mask;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -36,13 +36,14 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmathuint_x86
|
||||
#define headerfilettmathuint_x86
|
||||
|
||||
|
||||
#ifndef TTMATH_NOASM
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
#pragma message("TTMATH_ASM32")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_x86.h
|
||||
@@ -65,6 +66,7 @@ namespace ttmath
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
adding ss2 to the this and adding carry if it's defined
|
||||
(this = this + ss2 + c)
|
||||
@@ -83,31 +85,46 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// this part might be compiled with for example visual c
|
||||
|
||||
__asm
|
||||
{
|
||||
xor eax,eax // eax=0
|
||||
xor edx,edx // edx=0
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
sub eax,[c] // CF=c
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4+0]
|
||||
adc [ebx+edx*4+0],eax
|
||||
mov eax,[esi+edx*4]
|
||||
adc [ebx+edx*4],eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -137,7 +154,7 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,8 +188,14 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
@@ -181,21 +204,26 @@ namespace ttmath
|
||||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
add [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -227,7 +255,7 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -268,46 +296,58 @@ namespace ttmath
|
||||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint c;
|
||||
uint c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
mov ecx, [b]
|
||||
mov edx, [index]
|
||||
mov ebx, [p1]
|
||||
mov eax, [x1]
|
||||
sub ecx, edx // max uints to add (value_size - index)
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov edx, [index]
|
||||
|
||||
mov eax, [x1]
|
||||
add [ebx+edx*4], eax
|
||||
lea ecx, [ecx-1]
|
||||
inc edx
|
||||
dec ecx
|
||||
|
||||
mov eax, [x2]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
adc [ebx+edx*4+4], eax
|
||||
adc [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 0
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%ecx \n"
|
||||
"push %%edx \n"
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"subl %%edx, %%ecx \n"
|
||||
|
||||
@@ -336,7 +376,7 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -374,19 +414,21 @@ namespace ttmath
|
||||
// this part might be compiled with for example visual c
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
||||
mov esi, [ss1]
|
||||
mov ebx, [ss2]
|
||||
mov edi, [result]
|
||||
ALIGN 16
|
||||
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
adc eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
@@ -405,7 +447,7 @@ namespace ttmath
|
||||
adc eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
@@ -413,6 +455,8 @@ namespace ttmath
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -462,6 +506,8 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -485,30 +531,40 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
xor eax, eax
|
||||
mov edx, eax
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
|
||||
sub eax, [c]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
sbb [ebx+edx*4], eax
|
||||
mov eax,[esi+edx*4]
|
||||
sbb [ebx+edx*4],eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -540,7 +596,7 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -575,8 +631,14 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
@@ -585,21 +647,26 @@ namespace ttmath
|
||||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
sub [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -675,6 +742,7 @@ namespace ttmath
|
||||
*/
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
@@ -688,7 +756,7 @@ namespace ttmath
|
||||
sbb eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1]
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
@@ -707,7 +775,7 @@ namespace ttmath
|
||||
sbb eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1]
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
@@ -715,6 +783,8 @@ namespace ttmath
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -764,6 +834,8 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -790,25 +862,29 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx
|
||||
mov ecx, edx
|
||||
sub ecx, [c]
|
||||
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcl dword ptr [ebx+edx*4], 1
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -864,22 +940,25 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
xor ecx, ecx
|
||||
sub ecx, [c]
|
||||
push ebx
|
||||
push ecx
|
||||
|
||||
mov ebx, [p1]
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcr dword ptr [ebx+ecx*4-4], 1
|
||||
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop ecx
|
||||
pop ebx
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -912,6 +991,13 @@ namespace ttmath
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4731)
|
||||
//warning C4731: frame pointer register 'ebp' modified by inline assembly code
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
@@ -929,47 +1015,62 @@ namespace ttmath
|
||||
{
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint mask;
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shr edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
|
||||
mov eax, [c]
|
||||
or eax, eax
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
|
||||
ttmath_loop:
|
||||
rol dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, [mask]
|
||||
and eax, ebp
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
inc edx
|
||||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
pop ebp // restoring ebp
|
||||
|
||||
and eax, 1
|
||||
mov dword ptr [c], eax
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1019,7 +1120,7 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -1044,37 +1145,43 @@ namespace ttmath
|
||||
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shl edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
add edx, edi
|
||||
dec edx // edx - is pointing at the last word
|
||||
|
||||
mov eax, [c]
|
||||
or eax, eax
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
add edx, edi
|
||||
dec edx // edx is pointing at the end of the table (on last word)
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
|
||||
ttmath_loop:
|
||||
ror dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, [mask]
|
||||
and eax, ebp
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
@@ -1083,10 +1190,18 @@ namespace ttmath
|
||||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
rol eax, 1 // bit 31 will be bit 0
|
||||
and eax, 1
|
||||
pop ebp // restoring ebp
|
||||
|
||||
mov dword ptr [c], eax
|
||||
rol eax, 1 // 31bit will be first
|
||||
and eax, 1
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1139,10 +1254,14 @@ namespace ttmath
|
||||
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default : 4731)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this method returns the number of the highest set bit in one 32-bit word
|
||||
@@ -1156,11 +1275,16 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx,-1
|
||||
bsr eax,[x]
|
||||
cmovz eax,edx
|
||||
|
||||
mov [result], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1208,14 +1332,20 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
push ebx
|
||||
push eax
|
||||
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
|
||||
pop eax
|
||||
pop ebx
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1234,7 +1364,8 @@ namespace ttmath
|
||||
#endif
|
||||
|
||||
value = v;
|
||||
return old_bit;
|
||||
|
||||
return old_bit;
|
||||
}
|
||||
|
||||
|
||||
@@ -1265,11 +1396,17 @@ namespace ttmath
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1332,12 +1469,18 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx, [a]
|
||||
mov eax, [b]
|
||||
div dword ptr [c]
|
||||
|
||||
mov [r_], eax
|
||||
mov [rest_], edx
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -39,10 +39,11 @@
|
||||
#ifndef headerfilettmathuint_x86_64
|
||||
#define headerfilettmathuint_x86_64
|
||||
|
||||
|
||||
#ifndef TTMATH_NOASM
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
#pragma message("TTMATH_ASM64")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_x86_64.h
|
||||
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
|
||||
@@ -50,31 +51,10 @@
|
||||
this file is included at the end of ttmathuint.h
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
#if defined(_M_X64)
|
||||
#include <intrin.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
|
||||
uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
|
||||
uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
};
|
||||
#endif
|
||||
|
||||
/*!
|
||||
*
|
||||
* basic mathematic functions
|
||||
@@ -103,15 +83,12 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = adc_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
/*
|
||||
this part should be compiled with gcc
|
||||
*/
|
||||
@@ -131,7 +108,7 @@ namespace ttmath
|
||||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
@@ -173,15 +150,11 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = addindexed_x64(p1,b,index,value);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -200,7 +173,7 @@ namespace ttmath
|
||||
"setc %%al \n"
|
||||
"movzx %%al, %%rdx \n"
|
||||
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "0" (index), "1" (value), "2" (b), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
@@ -247,30 +220,6 @@ namespace ttmath
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||
#if 0
|
||||
{
|
||||
uint i, c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
printf("add %Id + %Id\n",x1,x2);
|
||||
for(int i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
|
||||
c = AddTwoWords(table[index], x1, 0, &table[index]);
|
||||
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
|
||||
|
||||
for(i=index+2 ; i<value_size && c ; ++i)
|
||||
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||
for(i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
printf(" -> %d\n",c);
|
||||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
@@ -279,22 +228,11 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
//printf("add %Id + %Id\n",x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//if (table[0] == 1265784741359897913) DebugBreak();
|
||||
c = addindexed2_x64(p1,b,index,x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//printf(" -> %d\n",c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -327,7 +265,88 @@ namespace ttmath
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
// this part should be compiled with gcc
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"adc (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"adc %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -350,19 +369,16 @@ namespace ttmath
|
||||
uint * p1 = table;
|
||||
const uint * p2 = ss2.table;
|
||||
|
||||
|
||||
// we don't have to use TTMATH_REFERENCE_ASSERT here
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = sbb_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -380,10 +396,9 @@ namespace ttmath
|
||||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
@@ -417,20 +432,15 @@ namespace ttmath
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint c;
|
||||
uint dummy, dummy2;
|
||||
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = subindexed_x64(p1,b,index,value);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"subq %%rdx, %%rcx \n"
|
||||
@@ -454,12 +464,100 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt64::SubInt")
|
||||
TTMATH_LOG("UInt::SubInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
/*
|
||||
the asm code is nearly the same as in AddVector
|
||||
only two instructions 'adc' are changed to 'sbb'
|
||||
*/
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"sbb (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"sbb %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
@@ -480,12 +578,9 @@ namespace ttmath
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = rcl_x64(p1,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -537,12 +632,9 @@ namespace ttmath
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = rcr_x64(p1,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -595,12 +687,9 @@ namespace ttmath
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = rcl2_x64(p1,b,bits,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -618,7 +707,6 @@ namespace ttmath
|
||||
|
||||
"xorq %%rdx, %%rdx \n"
|
||||
"movq %%rdx, %%rsi \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%r8, %%rsi \n"
|
||||
|
||||
@@ -638,7 +726,7 @@ namespace ttmath
|
||||
"and $1, %%rax \n"
|
||||
|
||||
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
@@ -670,19 +758,14 @@ namespace ttmath
|
||||
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
c = rcr2_x64(p1,b,bits,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"movq %%rcx, %%rsi \n"
|
||||
@@ -697,7 +780,6 @@ namespace ttmath
|
||||
"movq %%rdx, %%rsi \n"
|
||||
"addq %%rdi, %%rdx \n"
|
||||
"decq %%rdx \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%R8, %%rsi \n"
|
||||
|
||||
@@ -705,7 +787,7 @@ namespace ttmath
|
||||
"rorq %%cl, (%%rbx,%%rdx,8) \n"
|
||||
|
||||
"movq (%%rbx,%%rdx,8), %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"xorq %%rax, (%%rbx,%%rdx,8) \n"
|
||||
"orq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||
"movq %%rax, %%rsi \n"
|
||||
@@ -738,19 +820,11 @@ namespace ttmath
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||
{
|
||||
register sint result;
|
||||
sint result;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long nIndex(0);
|
||||
|
||||
if (_BitScanReverse64(&nIndex,x) == 0)
|
||||
result = -1;
|
||||
else
|
||||
result = nIndex;
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -796,15 +870,7 @@ namespace ttmath
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(TTMATH_PLATFORM64)
|
||||
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
|
||||
#else
|
||||
old_bit = _bittestandset((long*)&value,bit) != 0;
|
||||
#endif
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -859,11 +925,7 @@ namespace ttmath
|
||||
uint result2_;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_MSC_VER)
|
||||
result1_ = _umul128(a,b,&result2_);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -893,7 +955,6 @@ namespace ttmath
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
/*!
|
||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||
@@ -921,13 +982,7 @@ namespace ttmath
|
||||
TTMATH_ASSERT( c != 0 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_MSC_VER)
|
||||
div_x64(&a,&b,c);
|
||||
r_ = a;
|
||||
rest_ = b;
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
@@ -947,132 +1002,6 @@ namespace ttmath
|
||||
*rest = rest_;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
uint temp;
|
||||
|
||||
if( carry == 0 )
|
||||
{
|
||||
temp = a + b;
|
||||
|
||||
if( temp < a )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
temp = a + b + carry;
|
||||
|
||||
if( temp > a ) // !(temp<=a)
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
*result = temp;
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
if( carry == 0 )
|
||||
{
|
||||
*result = a - b;
|
||||
|
||||
if( a < b )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
*result = a - b - carry;
|
||||
|
||||
if( a > b ) // !(a <= b )
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // #ifndef __GNUC__
|
||||
|
||||
} //namespace
|
||||
|
||||
|
@@ -1,386 +0,0 @@
|
||||
PUBLIC adc_x64
|
||||
PUBLIC addindexed_x64
|
||||
PUBLIC addindexed2_x64
|
||||
|
||||
PUBLIC sbb_x64
|
||||
PUBLIC subindexed_x64
|
||||
|
||||
PUBLIC rcl_x64
|
||||
PUBLIC rcr_x64
|
||||
|
||||
PUBLIC rcl2_x64
|
||||
PUBLIC rcr2_x64
|
||||
|
||||
PUBLIC div_x64
|
||||
|
||||
;
|
||||
; "rax, rcx, rdx, r8-r11 are volatile."
|
||||
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
|
||||
;
|
||||
|
||||
.CODE
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
adc_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
; r8 = nSize
|
||||
; r9 = nCarry
|
||||
|
||||
xor rax, rax
|
||||
xor r11, r11
|
||||
sub rax, r9 ; sets CARRY if r9 != 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax,qword ptr [rdx + r11 * 8]
|
||||
adc qword ptr [rcx + r11 * 8], rax
|
||||
lea r11, [r11+1]
|
||||
dec r8
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
adc_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
addindexed_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nPos
|
||||
; r9 = nValue
|
||||
|
||||
xor rax, rax ; rax = result
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
|
||||
add qword ptr [rcx + r8 * 8], r9
|
||||
jc next1
|
||||
|
||||
ret
|
||||
|
||||
next1:
|
||||
mov r9, 1
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
dec rdx
|
||||
jz done_with_cy
|
||||
lea r8, [r8+1]
|
||||
add qword ptr [rcx + r8 * 8], r9
|
||||
jc loop1
|
||||
|
||||
ret
|
||||
|
||||
done_with_cy:
|
||||
lea rax, [rax+1] ; rax = 1
|
||||
|
||||
ret
|
||||
|
||||
addindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
addindexed2_x64 PROC
|
||||
|
||||
; rcx = p1 (pointer)
|
||||
; rdx = b (value size)
|
||||
; r8 = nPos
|
||||
; r9 = nValue1
|
||||
; [esp+0x28] = nValue2
|
||||
|
||||
xor rax, rax ; return value
|
||||
mov r11, rcx ; table
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
mov r10, [esp+028h] ; r10 = nValue2
|
||||
|
||||
add qword ptr [r11 + r8 * 8], r9
|
||||
lea r8, [r8+1]
|
||||
lea rdx, [rdx-1]
|
||||
adc qword ptr [r11 + r8 * 8], r10
|
||||
jc next
|
||||
ret
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
lea r8, [r8+1]
|
||||
add qword ptr [r11 + r8 * 8], 1
|
||||
jc next
|
||||
ret
|
||||
|
||||
next:
|
||||
dec rdx ; does not modify CY too...
|
||||
jnz loop1
|
||||
lea rax, [rax+1]
|
||||
ret
|
||||
|
||||
addindexed2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
sbb_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
; r8 = nCount
|
||||
; r9 = nCarry
|
||||
|
||||
xor rax, rax
|
||||
xor r11, r11
|
||||
sub rax, r9 ; sets CARRY if r9 != 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax,qword ptr [rdx + r11 * 8]
|
||||
sbb qword ptr [rcx + r11 * 8], rax
|
||||
lea r11, [r11+1]
|
||||
dec r8
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
sbb_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
subindexed_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nPos
|
||||
; r9 = nValue
|
||||
|
||||
sub rdx, r8 ; rdx = remaining count of uints
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
sub qword ptr [rcx + r8 * 8], r9
|
||||
jnc done
|
||||
|
||||
lea r8, [r8+1]
|
||||
mov r9, 1
|
||||
dec rdx
|
||||
jnz loop1
|
||||
jc return_1 ; most of the times, there will be NO carry (I hope)
|
||||
|
||||
done:
|
||||
xor rax, rax
|
||||
ret
|
||||
|
||||
return_1:
|
||||
mov rax, 1
|
||||
ret
|
||||
|
||||
subindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
rcl_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = b
|
||||
; r8 = nLowestBit
|
||||
|
||||
mov r11, rcx ; table
|
||||
xor r10, r10
|
||||
neg r8 ; CY set if r8 <> 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rcl qword ptr [r11 + r10 * 8], 1
|
||||
lea r10, [r10+1]
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
rcl_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
rcr_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nLowestBit
|
||||
|
||||
xor r10, r10
|
||||
neg r8 ; CY set if r8 <> 0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rcr qword ptr -8[rcx + rdx * 8], 1
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
setc al
|
||||
movzx rax, al
|
||||
|
||||
ret
|
||||
|
||||
rcr_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
div_x64 PROC
|
||||
|
||||
; rcx = &Hi
|
||||
; rdx = &Lo
|
||||
; r8 = nDiv
|
||||
|
||||
mov r11, rcx
|
||||
mov r10, rdx
|
||||
|
||||
mov rdx, qword ptr [r11]
|
||||
mov rax, qword ptr [r10]
|
||||
div r8
|
||||
mov qword ptr [r10], rdx ; remainder
|
||||
mov qword ptr [r11], rax ; value
|
||||
|
||||
ret
|
||||
|
||||
div_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
rcl2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
; r9 = c
|
||||
|
||||
push rbx
|
||||
|
||||
mov r10, rcx ; r10 = p1
|
||||
xor rax, rax
|
||||
|
||||
mov rcx, 64
|
||||
sub rcx, r8
|
||||
|
||||
mov r11, -1
|
||||
shr r11, cl ; r11 = mask
|
||||
|
||||
mov rcx, r8 ; rcx = count of bits
|
||||
|
||||
mov rbx, rax ; rbx = old value = 0
|
||||
or r9, r9
|
||||
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||
|
||||
mov r9, rax ; r9 = index (0..nSize-1)
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
rol qword ptr [r10+r9*8], cl
|
||||
mov rax, qword ptr [r10+r9*8]
|
||||
and rax, r11
|
||||
xor qword ptr [r10+r9*8], rax
|
||||
or qword ptr [r10+r9*8], rbx
|
||||
mov rbx, rax
|
||||
|
||||
lea r9, [r9+1]
|
||||
dec rdx
|
||||
|
||||
jnz loop1
|
||||
|
||||
and rax, 1
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
rcl2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
rcr2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
; r9 = c
|
||||
|
||||
push rbx
|
||||
mov r10, rcx ; r10 = p1
|
||||
xor rax, rax
|
||||
|
||||
mov rcx, 64
|
||||
sub rcx, r8
|
||||
|
||||
mov r11, -1
|
||||
shl r11, cl ; r11 = mask
|
||||
|
||||
mov rcx, r8 ; rcx = count of bits
|
||||
|
||||
mov rbx, rax ; rbx = old value = 0
|
||||
or r9, r9
|
||||
cmovnz rbx, r11 ; if (c) then old value = mask
|
||||
|
||||
mov r9, rdx ; r9 = index (0..nSize-1)
|
||||
lea r9, [r9-1]
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
ror qword ptr [r10+r9*8], cl
|
||||
mov rax, qword ptr [r10+r9*8]
|
||||
and rax, r11
|
||||
xor qword ptr [r10+r9*8], rax
|
||||
or qword ptr [r10+r9*8], rbx
|
||||
mov rbx, rax
|
||||
|
||||
lea r9, [r9-1]
|
||||
dec rdx
|
||||
|
||||
jnz loop1
|
||||
|
||||
rol rax, 1
|
||||
and rax, 1
|
||||
pop rbx
|
||||
|
||||
ret
|
||||
|
||||
rcr2_x64 ENDP
|
||||
|
||||
END
|
Reference in New Issue
Block a user