Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb16c871c9 | |||
2116418f08 | |||
062881900a | |||
0170572f84 | |||
e40ed603c6 | |||
c97ebf282f |
38
CHANGELOG
38
CHANGELOG
@@ -1,3 +1,41 @@
|
||||
Version 0.8.1 (2007.04.17):
|
||||
* fixed: Big::PowFrac(..) didn't return a correct error code
|
||||
(when 'this' was negative)
|
||||
* added: Root(x; index) (and to the parser as well)
|
||||
* added: macro: TTMATH_PRERELEASE_VER (can be either zero or one)
|
||||
* added: UInt::MulInt(int, UInt<int another_size>::&)
|
||||
* added: Big::MulUInt(uint)
|
||||
* changed: Big::MulInt(sint)
|
||||
* added: Big::ToUInt(uint &)
|
||||
* changed: Big::ToInt(sint&)
|
||||
* changed: Factorial() it uses Big::MulUInt() at the beginning
|
||||
(faster now especially more on a 32bit platform)
|
||||
* added: doxygen.cfg for generating a documentation from the doxygen
|
||||
* changed: UInt::Rcl(uint c=0) and UInt::Rcr(uint c=0) into
|
||||
UInt::Rcl2(uint bits, uint c) and UInt::Rcr2(uint bits, uint c)
|
||||
now they can move more than one bit and they are only private
|
||||
* fixed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||
didn't correctly return a carry if the 'bits' were equal
|
||||
to 'value_size*TTMATH_BITS_PER_UINT'
|
||||
* changed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||
into UInt::Rcl(uint bits, uint c=0) and
|
||||
UInt::Rcr(uint bits, uint c=0)
|
||||
they are faster now when the bits is greater than a half of
|
||||
the TTMATH_BITS_PER_UINT
|
||||
* changed: UInt::CompensationToLeft() it's faster now
|
||||
* changed: more small changes where there were UInt::Rcl(uint c=0) and
|
||||
UInt::Rcr(uint c=0) used
|
||||
* changed: as the Big type uses UInt::Rcl() and UInt::Rcr() a lot then
|
||||
it is much faster now (about 5-25%)
|
||||
* added: ASinh(), ACosh(), ATanh() /ATgh()/, ACoth() /ACtgh()/
|
||||
and to the parser as well
|
||||
* added: UInt::BitAnd(), UInt::BitOr(), UInt::BitXor(), UInt::BitNot(),
|
||||
Big::BitAnd(), Big::BitOr(), Big::BitXor()
|
||||
* added: to the parser: bitand(), bitor(), bitxor()
|
||||
/band(), bor(), bxor()/
|
||||
* changed: the way of parsing operators in the mathematical parser
|
||||
(the parser is not too much greedy now)
|
||||
|
||||
Version 0.8.0 (2007.03.28):
|
||||
* added: into the parser: SetFactorialMax()
|
||||
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
||||
|
2
README
2
README
@@ -21,4 +21,4 @@ to do is to use 'include' directive of the preprocessor. How big the
|
||||
values can be is set directly in the source code by the programmer.
|
||||
|
||||
Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl>
|
||||
Home page: http://sourceforge.net/projects/ttmath
|
||||
Project page: http://sourceforge.net/projects/ttmath
|
||||
|
4
TODO
4
TODO
@@ -1,7 +1,5 @@
|
||||
TODO TTMath Library
|
||||
===================
|
||||
|
||||
* Add bitwise operators (or functions) and, or, xor
|
||||
* Add functions for generating random values
|
||||
|
||||
|
||||
* Add something like NaN to the Big<> type
|
||||
|
1257
doxygen.cfg
Normal file
1257
doxygen.cfg
Normal file
File diff suppressed because it is too large
Load Diff
459
ttmath/ttmath.h
459
ttmath/ttmath.h
@@ -1171,6 +1171,173 @@ namespace ttmath
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* inverse hyperbolic functions
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic sine
|
||||
|
||||
asinh(x) = ln( x + sqrt(x^2 + 1) )
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ASinh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType xx(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
||||
c += xx.Mul(x);
|
||||
c += xx.Add(one);
|
||||
one.exponent.SubOne(); // one=0.5
|
||||
// xx is >= 1
|
||||
c += xx.PowFrac(one); // xx=sqrt(xx)
|
||||
c += xx.Add(x);
|
||||
c += result.Ln(xx); // xx > 0
|
||||
|
||||
// here can only be a carry
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic cosine
|
||||
|
||||
acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ACosh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType xx(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
||||
if( x < one )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
c += xx.Mul(x);
|
||||
c += xx.Sub(one);
|
||||
// xx is >= 0
|
||||
// we can't call a PowFrac when the 'x' is zero
|
||||
// if x is 0 the sqrt(0) is 0
|
||||
if( !xx.IsZero() )
|
||||
{
|
||||
one.exponent.SubOne(); // one=0.5
|
||||
c += xx.PowFrac(one); // xx=sqrt(xx)
|
||||
}
|
||||
c += xx.Add(x);
|
||||
c += result.Ln(xx); // xx >= 1
|
||||
|
||||
// here can only be a carry
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic tangent
|
||||
|
||||
atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ATanh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType nominator(x), denominator, one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
||||
if( !x.SmallerWithoutSignThan(one) )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
c += nominator.Add(one);
|
||||
denominator = one;
|
||||
c += denominator.Sub(x);
|
||||
c += nominator.Div(denominator);
|
||||
c += result.Ln(nominator);
|
||||
c += result.exponent.SubOne();
|
||||
|
||||
// here can only be a carry
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic tantent
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ATgh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return ATanh(x, err);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic cotangent
|
||||
|
||||
acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ACoth(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
ValueType nominator(x), denominator(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
||||
if( !x.GreaterWithoutSignThan(one) )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
c += nominator.Add(one);
|
||||
c += denominator.Sub(one);
|
||||
c += nominator.Div(denominator);
|
||||
c += result.Ln(nominator);
|
||||
c += result.exponent.SubOne();
|
||||
|
||||
// here can only be a carry
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
inverse hyperbolic cotantent
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType ACtgh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return ACoth(x, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -1342,6 +1509,266 @@ namespace ttmath
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace auxiliaryfunctions
|
||||
{
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( index.IsSign() )
|
||||
{
|
||||
// index cannot be negative
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( index.IsZero() )
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// there isn't root(0;0)
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// root(x;0) is 1 (if x!=0)
|
||||
x.SetOne();
|
||||
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
ValueType one;
|
||||
one.SetOne();
|
||||
|
||||
if( index == one )
|
||||
{
|
||||
//root(x;1) is x
|
||||
// we do it because if we used the PowFrac function
|
||||
// we would lose the precision
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
ValueType indexfrac(index);
|
||||
indexfrac.RemainFraction();
|
||||
|
||||
if( !indexfrac.IsZero() )
|
||||
{
|
||||
// index must be integer
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// root(0;index) is zero (if index!=0)
|
||||
x.SetZero();
|
||||
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign)
|
||||
{
|
||||
*change_sign = false;
|
||||
|
||||
if( index.Mod2() )
|
||||
{
|
||||
// index is odd (1,3,5...)
|
||||
if( x.IsSign() )
|
||||
{
|
||||
*change_sign = true;
|
||||
x.Abs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// index is even
|
||||
// x cannot be negative
|
||||
if( x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
indexth Root of x
|
||||
index must be integer and not negative <0;1;2;3....)
|
||||
|
||||
if index==0 the result is one
|
||||
if x==0 the result is zero and we assume root(0;0) is not defined
|
||||
|
||||
if index is even (2;4;6...) the result is x^(1/index) and x>0
|
||||
if index is odd (1;2;3;...) the result is either
|
||||
-(abs(x)^(1/index)) if x<0 or
|
||||
x^(1/index)) if x>0
|
||||
|
||||
(for index==1 the result is equal x)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0)
|
||||
{
|
||||
using namespace auxiliaryfunctions;
|
||||
|
||||
if( RootCheckIndexSign(x, index, err) ) return x;
|
||||
if( RootCheckIndexZero(x, index, err) ) return x;
|
||||
if( RootCheckIndexOne (x, index, err) ) return x;
|
||||
if( RootCheckIndexFrac(x, index, err) ) return x;
|
||||
if( RootCheckXZero(x, index, err) ) return x;
|
||||
|
||||
// index integer and index!=0
|
||||
// x!=0
|
||||
|
||||
uint c = 0;
|
||||
bool change_sign;
|
||||
if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
|
||||
|
||||
ValueType newindex;
|
||||
newindex.SetOne();
|
||||
c += newindex.Div(index);
|
||||
c += x.PowFrac(newindex); // here can only be a carry
|
||||
|
||||
if( change_sign )
|
||||
x.SetSign();
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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 && 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;
|
||||
|
||||
while( !carry && multipler < x )
|
||||
{
|
||||
if( stop && stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
carry += multipler.Add(one);
|
||||
carry += result.Mul(multipler);
|
||||
}
|
||||
|
||||
if( err )
|
||||
*err = carry ? err_overflow : err_ok;
|
||||
|
||||
return carry ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
the factorial from given 'x'
|
||||
e.g.
|
||||
@@ -1350,6 +1777,8 @@ namespace ttmath
|
||||
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;
|
||||
|
||||
@@ -1384,33 +1813,17 @@ namespace ttmath
|
||||
return result;
|
||||
}
|
||||
|
||||
ValueType multipler;
|
||||
ValueType one;
|
||||
uint carry = 0;
|
||||
|
||||
one = result; // =1
|
||||
multipler = result; // =1
|
||||
|
||||
while( !carry && multipler < x )
|
||||
{
|
||||
if( stop && stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
uint status = FactorialInt(x, err, stop, result);
|
||||
if( status == 0 )
|
||||
status = FactorialMore(x, err, stop, result);
|
||||
|
||||
if( status == 2 )
|
||||
// the calculation has been interrupted
|
||||
return result;
|
||||
}
|
||||
|
||||
carry += multipler.Add(one);
|
||||
carry += result.Mul(multipler);
|
||||
}
|
||||
|
||||
err_tmp = carry ? err_overflow : err_ok;
|
||||
err_tmp = status==1 ? err_overflow : err_ok;
|
||||
history.Add(x, result, err_tmp);
|
||||
|
||||
if( err )
|
||||
*err = carry ? err_overflow : err_ok;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1432,7 +1845,7 @@ namespace ttmath
|
||||
|
||||
/*!
|
||||
it returns the sign of the value
|
||||
e.g. -2 = 1
|
||||
e.g. -2 = -1
|
||||
0 = 0
|
||||
10 = 1
|
||||
*/
|
||||
|
@@ -182,10 +182,13 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
it sets value pi
|
||||
sets the mantissa of the value pi
|
||||
*/
|
||||
void SetPi()
|
||||
void SetMantissaPi()
|
||||
{
|
||||
// this is a static table which represents the value Pi (mantissa of it)
|
||||
// (first is the highest word)
|
||||
@@ -223,8 +226,19 @@ public:
|
||||
// and on 64bit platform value 64 (128/2=64))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/*!
|
||||
sets the value of pi
|
||||
*/
|
||||
void SetPi()
|
||||
{
|
||||
SetMantissaPi();
|
||||
info = 0;
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +247,8 @@ public:
|
||||
*/
|
||||
void Set05Pi()
|
||||
{
|
||||
SetPi();
|
||||
SetMantissaPi();
|
||||
info = 0;
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
|
||||
}
|
||||
|
||||
@@ -243,7 +258,8 @@ public:
|
||||
*/
|
||||
void Set2Pi()
|
||||
{
|
||||
SetPi();
|
||||
SetMantissaPi();
|
||||
info = 0;
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
|
||||
}
|
||||
|
||||
@@ -450,7 +466,7 @@ public:
|
||||
|
||||
/*!
|
||||
it remains the 'sign' of the value
|
||||
e.g. -2 = 1
|
||||
e.g. -2 = -1
|
||||
0 = 0
|
||||
10 = 1
|
||||
*/
|
||||
@@ -495,10 +511,16 @@ public:
|
||||
*/
|
||||
void ChangeSign()
|
||||
{
|
||||
if( info & TTMATH_BIG_SIGN )
|
||||
{
|
||||
info &= ~TTMATH_BIG_SIGN;
|
||||
return;
|
||||
}
|
||||
|
||||
if( IsZero() )
|
||||
return;
|
||||
|
||||
info = (info & (~TTMATH_BIG_SIGN)) | ((~info) & TTMATH_BIG_SIGN);
|
||||
info |= TTMATH_BIG_SIGN;
|
||||
}
|
||||
|
||||
|
||||
@@ -527,7 +549,7 @@ public:
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
// (1) abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
@@ -545,11 +567,12 @@ public:
|
||||
else
|
||||
if( exp_offset < mantissa_size_in_bits )
|
||||
{
|
||||
// moving 'exp_offset' times
|
||||
// (2) moving 'exp_offset' times
|
||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// (3)
|
||||
// exp_offset == mantissa_size_in_bits
|
||||
// we're rounding 'this' about one (up or down depending on a ss2 sign)
|
||||
ss2.mantissa.SetOne();
|
||||
@@ -561,18 +584,19 @@ public:
|
||||
// values have the same signs
|
||||
if( mantissa.Add(ss2.mantissa) )
|
||||
{
|
||||
mantissa.Rcr(1);
|
||||
mantissa.Rcr(1,1);
|
||||
c = exponent.AddOne();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// values have different signs
|
||||
if( mantissa.Sub(ss2.mantissa) )
|
||||
{
|
||||
mantissa.Rcl(1);
|
||||
c = exponent.SubOne();
|
||||
}
|
||||
// there shouldn't be a carry here because
|
||||
// (1) (2) and (3) guarantee that the mantissa of this
|
||||
// is greater than the mantissa of the ss2
|
||||
uint c_temp = mantissa.Sub(ss2.mantissa);
|
||||
|
||||
TTMATH_ASSERT( c_temp == 0 )
|
||||
}
|
||||
|
||||
c += Standardizing();
|
||||
@@ -593,7 +617,213 @@ public:
|
||||
return Add(ss2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
bitwise AND
|
||||
|
||||
this and ss2 must be >= 0
|
||||
return values:
|
||||
0 - ok
|
||||
1 - carry
|
||||
2 - this or ss2 was negative
|
||||
*/
|
||||
uint BitAnd(Big<exp, man> ss2)
|
||||
{
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
{
|
||||
// the second value is too short
|
||||
SetZero();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
||||
mantissa.BitAnd(ss2.mantissa);
|
||||
|
||||
c += Standardizing();
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
bitwise OR
|
||||
|
||||
this and ss2 must be >= 0
|
||||
return values:
|
||||
0 - ok
|
||||
1 - carry
|
||||
2 - this or ss2 was negative
|
||||
*/
|
||||
uint BitOr(Big<exp, man> ss2)
|
||||
{
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
// the second value is too short
|
||||
return 0;
|
||||
|
||||
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
||||
mantissa.BitOr(ss2.mantissa);
|
||||
|
||||
c += Standardizing();
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
bitwise XOR
|
||||
|
||||
this and ss2 must be >= 0
|
||||
return values:
|
||||
0 - ok
|
||||
1 - carry
|
||||
2 - this or ss2 was negative
|
||||
*/
|
||||
uint BitXor(Big<exp, man> ss2)
|
||||
{
|
||||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
// the second value is too short
|
||||
return 0;
|
||||
|
||||
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
||||
mantissa.BitXor(ss2.mantissa);
|
||||
|
||||
c += Standardizing();
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
Multiplication this = this * ss2 (ss2 is uint)
|
||||
|
||||
ss2 without a sign
|
||||
*/
|
||||
uint MulUInt(uint ss2)
|
||||
{
|
||||
UInt<man+1> man_result;
|
||||
uint i,c = 0;
|
||||
|
||||
// man_result = mantissa * ss2.mantissa
|
||||
mantissa.MulInt(ss2, man_result);
|
||||
|
||||
int bit = UInt<man>::FindLeadingBitInWord(man_result.table[man]); // man - last word
|
||||
|
||||
if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) )
|
||||
{
|
||||
// 'i' will be from 0 to TTMATH_BITS_PER_UINT
|
||||
i = man_result.CompensationToLeft();
|
||||
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
mantissa.table[i] = man_result.table[i+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( bit != -1 )
|
||||
{
|
||||
man_result.Rcr(bit+1, 0);
|
||||
c += exponent.Add(bit+1);
|
||||
}
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
mantissa.table[i] = man_result.table[i];
|
||||
}
|
||||
|
||||
c += Standardizing();
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Multiplication this = this * ss2 (ss2 is sint)
|
||||
|
||||
ss2 with a sign
|
||||
*/
|
||||
uint MulInt(sint ss2)
|
||||
{
|
||||
if( IsSign() == (ss2<0) )
|
||||
{
|
||||
// the signs are the same, the result is positive
|
||||
Abs();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the signs are different, the result is negative
|
||||
SetSign();
|
||||
}
|
||||
|
||||
if( ss2<0 )
|
||||
ss2 = 0 - ss2;
|
||||
|
||||
return MulUInt( uint(ss2) );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
multiplication this = this * ss2
|
||||
this method returns carry
|
||||
@@ -747,7 +977,7 @@ public:
|
||||
if( start.Mul(start) )
|
||||
return 1;
|
||||
|
||||
pow.Rcr();
|
||||
pow.Rcr(1);
|
||||
}
|
||||
|
||||
*this = result;
|
||||
@@ -883,6 +1113,7 @@ public:
|
||||
pow can be negative and with fraction
|
||||
|
||||
return values:
|
||||
0 - ok
|
||||
1 - carry
|
||||
2 - incorrect argument ('this')
|
||||
*/
|
||||
@@ -892,6 +1123,10 @@ public:
|
||||
|
||||
Big<exp, man> temp;
|
||||
uint c = temp.Ln(*this);
|
||||
|
||||
if( c!= 0 )
|
||||
return c;
|
||||
|
||||
c += temp.Mul(pow);
|
||||
c += Exp(temp);
|
||||
|
||||
@@ -904,6 +1139,7 @@ public:
|
||||
pow can be negative and with fraction
|
||||
|
||||
return values:
|
||||
0 - ok
|
||||
1 - carry
|
||||
2 - incorrect argument ('this' or 'pow')
|
||||
*/
|
||||
@@ -1269,6 +1505,48 @@ public:
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
this method sets 'result' as the one word of type uint
|
||||
|
||||
if the value is too big this method returns a carry (1)
|
||||
*/
|
||||
uint ToUInt(uint & result, bool test_sign = true) const
|
||||
{
|
||||
result = 0;
|
||||
|
||||
if( IsZero() )
|
||||
return 0;
|
||||
|
||||
if( test_sign && IsSign() )
|
||||
// the result should be positive
|
||||
return 1;
|
||||
|
||||
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
||||
|
||||
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
|
||||
// if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||
// into the 'sint' type (it's too big)
|
||||
return 1;
|
||||
|
||||
if( exponent <= maxbit )
|
||||
// our value is from the range of (-1,1) and we return zero
|
||||
return 0;
|
||||
|
||||
UInt<man> mantissa_temp(mantissa);
|
||||
// exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
|
||||
sint how_many_bits = exponent.ToInt();
|
||||
|
||||
// how_many_bits is negative, we'll make it positive
|
||||
how_many_bits = -how_many_bits;
|
||||
|
||||
// we're taking into account only the last word in a mantissa table
|
||||
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
|
||||
result = mantissa_temp.table[ man-1 ];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method sets 'result' as the one word of type sint
|
||||
@@ -1278,42 +1556,23 @@ public:
|
||||
uint ToInt(sint & result) const
|
||||
{
|
||||
result = 0;
|
||||
uint result_uint;
|
||||
|
||||
if( IsZero() )
|
||||
return 0;
|
||||
|
||||
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
||||
|
||||
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
|
||||
// if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||
// into the 'sint' type (it's too big)
|
||||
if( ToUInt(result_uint, false) )
|
||||
return 1;
|
||||
|
||||
if( exponent <= maxbit )
|
||||
// our value is from range (-1,1) and we return zero
|
||||
return 0;
|
||||
|
||||
UInt<man> mantissa_temp(mantissa);
|
||||
// exponent is from a range of (-maxbit,0>
|
||||
sint how_many_bits = exponent.ToInt();
|
||||
|
||||
// how_many_bits is negative, we'll make it positive
|
||||
how_many_bits = -how_many_bits;
|
||||
|
||||
// we're taking into an account only the last word in a mantissa table
|
||||
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
|
||||
result = mantissa_temp.table[ man-1 ];
|
||||
result = static_cast<sint>( result_uint );
|
||||
|
||||
// the exception for the minimal value
|
||||
if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT )
|
||||
if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT )
|
||||
return 0;
|
||||
|
||||
if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
||||
if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
||||
// the value is too big
|
||||
return 1;
|
||||
|
||||
if( IsSign() )
|
||||
result = -sint(result);
|
||||
result = -result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1337,7 +1596,6 @@ 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
|
||||
|
@@ -618,6 +618,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void Abs(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
@@ -1030,6 +1031,133 @@ void Coth(int sindex, int amount_of_args, ValueType & result)
|
||||
}
|
||||
|
||||
|
||||
void Root(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 2 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::Root(stack[sindex].value, stack[sindex+2].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ASinh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::ASinh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void ACosh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::ACosh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void ATanh(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::ATanh(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void ACoth(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
ErrorCode err;
|
||||
result = ttmath::ACoth(stack[sindex].value, &err);
|
||||
|
||||
if( err != err_ok )
|
||||
Error( err );
|
||||
}
|
||||
|
||||
|
||||
void BitAnd(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 2 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
uint err;
|
||||
result = stack[sindex].value;
|
||||
err = result.BitAnd(stack[sindex+2].value);
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case 1:
|
||||
Error( err_overflow );
|
||||
break;
|
||||
case 2:
|
||||
Error( err_improper_argument );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BitOr(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 2 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
uint err;
|
||||
result = stack[sindex].value;
|
||||
err = result.BitOr(stack[sindex+2].value);
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case 1:
|
||||
Error( err_overflow );
|
||||
break;
|
||||
case 2:
|
||||
Error( err_improper_argument );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BitXor(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 2 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
uint err;
|
||||
result = stack[sindex].value;
|
||||
err = result.BitXor(stack[sindex+2].value);
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case 1:
|
||||
Error( err_overflow );
|
||||
break;
|
||||
case 2:
|
||||
Error( err_improper_argument );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
this method returns the value from a user-defined function
|
||||
|
||||
@@ -1178,6 +1306,19 @@ void CreateFunctionsTable()
|
||||
InsertFunctionToTable(std::string("tgh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(std::string("ctgh"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(std::string("root"), &Parser<ValueType>::Root);
|
||||
InsertFunctionToTable(std::string("asinh"), &Parser<ValueType>::ASinh);
|
||||
InsertFunctionToTable(std::string("acosh"), &Parser<ValueType>::ACosh);
|
||||
InsertFunctionToTable(std::string("atanh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(std::string("atgh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(std::string("acoth"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(std::string("actgh"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(std::string("bitand"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(std::string("bitor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(std::string("bitxor"), &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable(std::string("band"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(std::string("bor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(std::string("bxor"), &Parser<ValueType>::BitXor);
|
||||
}
|
||||
|
||||
|
||||
@@ -1478,13 +1619,22 @@ void CreateMathematicalOperatorsTable()
|
||||
}
|
||||
|
||||
|
||||
bool CanBeMathematicalOperator(unsigned char c)
|
||||
{
|
||||
if( c=='|' || c=='&' || c=='!' || c=='=' || c=='<' || c=='>' ||
|
||||
c=='*' || c=='/' || c=='+' || c=='-' || c=='^' )
|
||||
return true;
|
||||
/*!
|
||||
returns true if 'str2' is the substring of str1
|
||||
|
||||
return false;
|
||||
e.g.
|
||||
true when str1="test" and str2="te"
|
||||
*/
|
||||
bool IsSubstring(const std::string & str1, const std::string & str2)
|
||||
{
|
||||
if( str2.length() > str1.length() )
|
||||
return false;
|
||||
|
||||
for(std::string::size_type i=0 ; i<str2.length() ; ++i)
|
||||
if( str1[i] != str2[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1494,17 +1644,31 @@ return false;
|
||||
void ReadMathematicalOperator(Item & result)
|
||||
{
|
||||
std::string oper;
|
||||
typename OperatorsTable::iterator iter_old, iter_new;
|
||||
|
||||
for( ; CanBeMathematicalOperator(*pstring) ; ++pstring )
|
||||
iter_old = operators_table.end();
|
||||
|
||||
for( ; true ; ++pstring )
|
||||
{
|
||||
oper += *pstring;
|
||||
iter_new = operators_table.lower_bound(oper);
|
||||
|
||||
if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) )
|
||||
{
|
||||
oper.erase( --oper.end() ); // we've got mininum one element
|
||||
|
||||
typename OperatorsTable::iterator iter = operators_table.find(oper);
|
||||
|
||||
if( iter == operators_table.end() )
|
||||
Error( err_unknown_operator );
|
||||
|
||||
result.type = Item::mat_operator;
|
||||
result.moperator.SetType( iter->second );
|
||||
if( iter_old != operators_table.end() && iter_old->first == oper )
|
||||
{
|
||||
result.type = Item::mat_operator;
|
||||
result.moperator.SetType( iter_old->second );
|
||||
break;
|
||||
}
|
||||
|
||||
Error( err_unknown_operator );
|
||||
}
|
||||
|
||||
iter_old = iter_new;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1535,10 +1699,7 @@ int ReadOperator(Item & result)
|
||||
++pstring;
|
||||
}
|
||||
else
|
||||
if( CanBeMathematicalOperator(*pstring) )
|
||||
ReadMathematicalOperator(result);
|
||||
else
|
||||
Error( err_unknown_character );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2113,7 +2274,6 @@ ErrorCode Parse(const char * str)
|
||||
|
||||
stack.resize( default_stack_size );
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
Parse();
|
||||
|
@@ -58,10 +58,14 @@
|
||||
|
||||
/*!
|
||||
the version of the library
|
||||
|
||||
TTMATH_PRERELEASE_VER is either zero or one
|
||||
if zero that means this is the release version of the library
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 8
|
||||
#define TTMATH_REVISION_VER 0
|
||||
#define TTMATH_REVISION_VER 1
|
||||
#define TTMATH_PRERELEASE_VER 0
|
||||
|
||||
|
||||
/*!
|
||||
|
@@ -819,7 +819,7 @@ public:
|
||||
|
||||
"leal (%%ebx,%%edx,4), %%ebx \n"
|
||||
|
||||
"movl %%esi, %%edx \n"
|
||||
"movl %%esi, %%edx \n"
|
||||
"clc \n"
|
||||
"1: \n"
|
||||
|
||||
@@ -878,18 +878,31 @@ public:
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
||||
/*!
|
||||
this method moving once all bits into the left side
|
||||
return value <- this <- C
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
|
||||
the lowest bit will hold value of 'c' and
|
||||
function returns the highest bit
|
||||
the lowest *bits* will be held the 'c' and
|
||||
the state of one additional bit (on the left hand side)
|
||||
will be returned
|
||||
|
||||
for example:
|
||||
let this is 001010000
|
||||
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||
*/
|
||||
uint Rcl(uint c=0)
|
||||
uint Rcl2(uint bits, uint c)
|
||||
{
|
||||
if( bits == 0 )
|
||||
return 0;
|
||||
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
|
||||
@@ -900,12 +913,16 @@ public:
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx,[b]
|
||||
mov ebx,[p1]
|
||||
mov edx, [bits]
|
||||
|
||||
a:
|
||||
xor eax, eax
|
||||
sub eax, [c]
|
||||
|
||||
mov eax,0
|
||||
sub eax,[c]
|
||||
mov ecx, [b]
|
||||
mov ebx, [p1]
|
||||
|
||||
p:
|
||||
rcl dword ptr[ebx],1
|
||||
@@ -917,10 +934,15 @@ public:
|
||||
|
||||
loop p
|
||||
|
||||
dec edx
|
||||
|
||||
jnz a
|
||||
|
||||
mov eax,0
|
||||
adc eax,eax
|
||||
mov [c],eax
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
@@ -931,12 +953,16 @@ public:
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%esi \n"
|
||||
|
||||
"2: \n"
|
||||
|
||||
"xorl %%eax,%%eax \n"
|
||||
"subl %%edx,%%eax \n"
|
||||
|
||||
"push %%ebx \n"
|
||||
"push %%ecx \n"
|
||||
|
||||
"movl $0,%%eax \n"
|
||||
"subl %%edx,%%eax \n"
|
||||
|
||||
|
||||
"1: \n"
|
||||
"rcll $1,(%%ebx) \n"
|
||||
|
||||
@@ -947,14 +973,20 @@ public:
|
||||
|
||||
"loop 1b \n"
|
||||
|
||||
"movl $0, %%edx \n"
|
||||
"adcl %%edx,%%edx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
"pop %%ebx \n"
|
||||
|
||||
"decl %%esi \n"
|
||||
|
||||
"jnz 2b \n"
|
||||
|
||||
"movl $0, %%edx \n"
|
||||
"adcl %%edx, %%edx \n"
|
||||
|
||||
"pop %%esi \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||
: "%eax", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
@@ -965,14 +997,24 @@ public:
|
||||
|
||||
|
||||
/*!
|
||||
this method moving once all bits into the right side
|
||||
C -> *this -> return value
|
||||
this method moves all bits into the right hand side
|
||||
C -> this -> return value
|
||||
|
||||
the highest bit will be held value of 'c' and
|
||||
function returns the lowest bit
|
||||
the highest *bits* will be held the 'c' and
|
||||
the state of one additional bit (on the right hand side)
|
||||
will be returned
|
||||
|
||||
for example:
|
||||
let this is 000000010
|
||||
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||
*/
|
||||
uint Rcr(uint c=0)
|
||||
uint Rcr2(uint bits, uint c)
|
||||
{
|
||||
if( bits == 0 )
|
||||
return 0;
|
||||
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
|
||||
@@ -983,15 +1025,19 @@ public:
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov edx,[bits]
|
||||
|
||||
a:
|
||||
|
||||
xor eax,eax
|
||||
sub eax,[c]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov ecx,[b]
|
||||
|
||||
lea ebx,[ebx+4*ecx]
|
||||
|
||||
mov eax,0
|
||||
sub eax,[c]
|
||||
|
||||
p:
|
||||
dec ebx
|
||||
dec ebx
|
||||
@@ -1001,11 +1047,16 @@ public:
|
||||
rcr dword ptr [ebx],1
|
||||
|
||||
loop p
|
||||
|
||||
dec edx
|
||||
|
||||
jnz a
|
||||
|
||||
mov eax,0
|
||||
adc eax,eax
|
||||
mov [c],eax
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
@@ -1016,12 +1067,17 @@ public:
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%esi \n"
|
||||
|
||||
|
||||
"2: \n"
|
||||
|
||||
"push %%ebx \n"
|
||||
"push %%ecx \n"
|
||||
|
||||
"leal (%%ebx,%%ecx,4),%%ebx \n"
|
||||
|
||||
"movl $0, %%eax \n"
|
||||
"xorl %%eax, %%eax \n"
|
||||
"subl %%edx, %%eax \n"
|
||||
|
||||
"1: \n"
|
||||
@@ -1034,14 +1090,20 @@ public:
|
||||
|
||||
"loop 1b \n"
|
||||
|
||||
"movl $0, %%edx \n"
|
||||
"adcl %%edx,%%edx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
"pop %%ebx \n"
|
||||
|
||||
"decl %%esi \n"
|
||||
|
||||
"jnz 2b \n"
|
||||
|
||||
"movl $0, %%edx \n"
|
||||
"adcl %%edx, %%edx \n"
|
||||
|
||||
"pop %%esi \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||
: "%eax", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
@@ -1052,6 +1114,47 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for moving bits into the left hand side
|
||||
|
||||
this method moves only words
|
||||
*/
|
||||
void RclMoveAllWords( sint & all_words, uint & rest_bits, uint & last_c,
|
||||
uint bits, uint c)
|
||||
{
|
||||
rest_bits = sint(bits % TTMATH_BITS_PER_UINT);
|
||||
all_words = sint(bits / TTMATH_BITS_PER_UINT);
|
||||
|
||||
if( all_words >= sint(value_size) )
|
||||
{
|
||||
if( all_words==value_size && rest_bits==0 )
|
||||
last_c = table[0] & 1;
|
||||
|
||||
all_words = value_size; // not value_size - 1
|
||||
rest_bits = 0;
|
||||
}
|
||||
|
||||
if( all_words > 0 )
|
||||
{
|
||||
sint first;
|
||||
sint second;
|
||||
|
||||
last_c = table[value_size - all_words] & 1; // all_words is greater than 0
|
||||
|
||||
// copying the first part of the value
|
||||
for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
|
||||
table[first] = table[second];
|
||||
|
||||
// sets the rest bits of value into 'c'
|
||||
uint mask = c ? TTMATH_UINT_MAX_VALUE : 0;
|
||||
for( ; first>=0 ; --first )
|
||||
table[first] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
this method moving all bits into the left side 'bits' times
|
||||
return value <- this <- C
|
||||
@@ -1062,39 +1165,92 @@ public:
|
||||
the value c will be set into the lowest bits
|
||||
and the method returns state of the last moved bit
|
||||
*/
|
||||
uint Rcl(uint bits, uint c)
|
||||
uint Rcl(uint bits, uint c=0)
|
||||
{
|
||||
sint first;
|
||||
sint second;
|
||||
uint last_c = 0;
|
||||
|
||||
if( bits > value_size*TTMATH_BITS_PER_UINT )
|
||||
bits = value_size*TTMATH_BITS_PER_UINT;
|
||||
sint all_words = 0;
|
||||
uint rest_bits = bits;
|
||||
|
||||
sint all_words = sint(bits) / sint(TTMATH_BITS_PER_UINT);
|
||||
if( bits >= TTMATH_BITS_PER_UINT )
|
||||
RclMoveAllWords(all_words, rest_bits, last_c, bits, c);
|
||||
|
||||
if( all_words > 0 )
|
||||
|
||||
// rest_bits is from 0 to TTMATH_BITS_PER_UINT-1 now
|
||||
if( rest_bits > 0 )
|
||||
{
|
||||
// copying the first part of the value
|
||||
for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
|
||||
// if rest_bits is greater than a half of TTMATH_BITS_PER_UINT
|
||||
// we're moving bits into the right hand side
|
||||
// (TTMATH_BITS_PER_UINT-rest_bits) times
|
||||
// and then we're moving one word into left
|
||||
if( rest_bits > TTMATH_BITS_PER_UINT/2 + 1 )
|
||||
{
|
||||
last_c = table[first] & 1;
|
||||
table[first] = table[second];
|
||||
uint temp = table[0];
|
||||
Rcr2(TTMATH_BITS_PER_UINT-rest_bits,0);
|
||||
last_c = table[value_size-1] & 1;
|
||||
|
||||
for(uint i=value_size-1 ; i>0 ; --i)
|
||||
table[i] = table[i-1];
|
||||
|
||||
table[0] = temp << rest_bits;
|
||||
|
||||
if( c )
|
||||
{
|
||||
uint mask = TTMATH_UINT_MAX_VALUE << rest_bits;
|
||||
table[0] |= ~mask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_c = Rcl2(rest_bits, c);
|
||||
}
|
||||
|
||||
// sets the rest bits of value into 'c'
|
||||
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
|
||||
for( ; first>=0 ; --first )
|
||||
table[first] = mask;
|
||||
}
|
||||
|
||||
sint rest_bits = sint(bits) % sint(TTMATH_BITS_PER_UINT);
|
||||
for( ; rest_bits > 0 ; --rest_bits )
|
||||
last_c = Rcl(c);
|
||||
|
||||
return last_c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
an auxiliary method for moving bits into the right hand side
|
||||
|
||||
this method moves only words
|
||||
*/
|
||||
void RcrMoveAllWords( sint & all_words, uint & rest_bits, uint & last_c,
|
||||
uint bits, uint c)
|
||||
{
|
||||
rest_bits = sint(bits % TTMATH_BITS_PER_UINT);
|
||||
all_words = sint(bits / TTMATH_BITS_PER_UINT);
|
||||
|
||||
if( all_words >= sint(value_size) )
|
||||
{
|
||||
if( all_words==value_size && rest_bits==0 )
|
||||
last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||
|
||||
all_words = value_size; // not value_size - 1
|
||||
rest_bits = 0;
|
||||
}
|
||||
|
||||
|
||||
if( all_words > 0 )
|
||||
{
|
||||
uint first;
|
||||
uint second;
|
||||
|
||||
last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0
|
||||
|
||||
// copying the first part of the value
|
||||
for(first=0, second=all_words ; second<value_size ; ++first, ++second)
|
||||
table[first] = table[second];
|
||||
|
||||
// sets the rest bits of value into 'c'
|
||||
uint mask = c ? TTMATH_UINT_MAX_VALUE : 0;
|
||||
for( ; first<value_size ; ++first )
|
||||
table[first] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
this method moving all bits into the right side 'bits' times
|
||||
@@ -1106,39 +1262,42 @@ public:
|
||||
the value c will be set into the highest bits
|
||||
and the method returns state of the last moved bit
|
||||
*/
|
||||
uint Rcr(uint bits, uint c)
|
||||
uint Rcr(uint bits, uint c=0)
|
||||
{
|
||||
sint first;
|
||||
sint second;
|
||||
sint last_c = 0;
|
||||
uint last_c = 0;
|
||||
sint all_words = 0;
|
||||
uint rest_bits = bits;
|
||||
|
||||
if( bits > value_size*TTMATH_BITS_PER_UINT )
|
||||
bits = value_size*TTMATH_BITS_PER_UINT;
|
||||
if( bits >= TTMATH_BITS_PER_UINT )
|
||||
RcrMoveAllWords(all_words, rest_bits, last_c, bits, c);
|
||||
|
||||
sint all_words = sint(bits) / sint(TTMATH_BITS_PER_UINT);
|
||||
|
||||
if( all_words > 0 )
|
||||
// rest_bits is from 0 to TTMATH_BITS_PER_UINT-1 now
|
||||
if( rest_bits > 0 )
|
||||
{
|
||||
// copying the first part of the value
|
||||
for(first=0, second=all_words ; second<sint(value_size) ; ++first, ++second)
|
||||
if( rest_bits > TTMATH_BITS_PER_UINT/2 + 1 )
|
||||
{
|
||||
last_c = table[first] & TTMATH_UINT_HIGHEST_BIT;
|
||||
table[first] = table[second];
|
||||
uint temp = table[value_size-1];
|
||||
Rcl2(TTMATH_BITS_PER_UINT-rest_bits,0);
|
||||
last_c = (table[0] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||
|
||||
for(uint i=0 ; i<value_size-1 ; ++i)
|
||||
table[i] = table[i+1];
|
||||
|
||||
table[value_size-1] = temp >> rest_bits;
|
||||
|
||||
if( c )
|
||||
{
|
||||
uint mask = TTMATH_UINT_MAX_VALUE >> rest_bits;
|
||||
table[value_size-1] |= ~mask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_c = Rcr2(rest_bits, c);
|
||||
}
|
||||
|
||||
if( last_c )
|
||||
last_c = 1;
|
||||
|
||||
// sets the rest bits of value into 'c'
|
||||
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
|
||||
for( ; first<sint(value_size) ; ++first )
|
||||
table[first] = mask;
|
||||
}
|
||||
|
||||
sint rest_bits = sint(bits) % sint(TTMATH_BITS_PER_UINT);
|
||||
for( ; rest_bits > 0 ; --rest_bits )
|
||||
last_c = Rcr(c);
|
||||
|
||||
return last_c;
|
||||
}
|
||||
|
||||
@@ -1175,14 +1334,14 @@ public:
|
||||
table[i] = 0;
|
||||
}
|
||||
|
||||
// moving the rest bits (max TTMATH_BITS_PER_UINT -- only one word)
|
||||
while( !IsTheHighestBitSet() )
|
||||
{
|
||||
Rcl();
|
||||
++moving;
|
||||
}
|
||||
uint moving2 = FindLeadingBitInWord( table[value_size-1] );
|
||||
// moving2 is different from -1 because the value table[value_size-1]
|
||||
// is not zero
|
||||
|
||||
return moving;
|
||||
moving2 = TTMATH_BITS_PER_UINT - moving2 - 1;
|
||||
Rcl(moving2);
|
||||
|
||||
return moving + moving2;
|
||||
}
|
||||
|
||||
|
||||
@@ -1330,6 +1489,48 @@ public:
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method performs a bitwise operation AND
|
||||
*/
|
||||
void BitAnd(const UInt<value_size> & ss2)
|
||||
{
|
||||
for(uint x=0 ; x<value_size ; ++x)
|
||||
table[x] &= ss2.table[x];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method performs a bitwise operation OR
|
||||
*/
|
||||
void BitOr(const UInt<value_size> & ss2)
|
||||
{
|
||||
for(uint x=0 ; x<value_size ; ++x)
|
||||
table[x] |= ss2.table[x];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method performs a bitwise operation XOR
|
||||
*/
|
||||
void BitXor(const UInt<value_size> & ss2)
|
||||
{
|
||||
for(uint x=0 ; x<value_size ; ++x)
|
||||
table[x] ^= ss2.table[x];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method performs a bitwise operation NOT
|
||||
*/
|
||||
void BitNot()
|
||||
{
|
||||
for(uint x=0 ; x<value_size ; ++x)
|
||||
table[x] = ~table[x];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
* Multiplication
|
||||
@@ -1340,7 +1541,7 @@ public:
|
||||
public:
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
||||
@@ -1442,6 +1643,47 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
multiplication: result = this * ss2
|
||||
|
||||
we're using this method only when result_size is greater than value_size
|
||||
if so there will not be a carry
|
||||
*/
|
||||
template<uint result_size>
|
||||
uint MulInt(uint ss2, UInt<result_size> & result)
|
||||
{
|
||||
uint r2,r1;
|
||||
uint x1size=value_size;
|
||||
uint x1start=0;
|
||||
|
||||
if( value_size >= result_size )
|
||||
return 1;
|
||||
|
||||
result.SetZero();
|
||||
|
||||
if( value_size > 2 )
|
||||
{
|
||||
// if the value_size is smaller than or equal to 2
|
||||
// there is no sense to set x1size and x1start to another values
|
||||
|
||||
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||
|
||||
if( x1size==0 )
|
||||
return 0;
|
||||
|
||||
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||
}
|
||||
|
||||
for(uint x1=x1start ; x1<x1size ; ++x1)
|
||||
{
|
||||
MulTwoWords(table[x1], ss2, &r2, &r1 );
|
||||
result.AddTwoInts(r2,r1,x1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
the multiplication 'this' = 'this' * ss2
|
||||
@@ -1504,7 +1746,7 @@ public:
|
||||
if( Add(*this) )
|
||||
return 1;
|
||||
|
||||
if( ss1.Rcl() )
|
||||
if( ss1.Rcl(1) )
|
||||
if( Add(ss2) )
|
||||
return 1;
|
||||
}
|
||||
@@ -1893,7 +2135,7 @@ private:
|
||||
|
||||
|
||||
div_a:
|
||||
c = Rcl(c);
|
||||
c = Rcl(1, c);
|
||||
c = rest.Add(rest,c);
|
||||
c = rest.Sub(divisor,c);
|
||||
|
||||
@@ -1908,12 +2150,12 @@ private:
|
||||
if(loop)
|
||||
goto div_a;
|
||||
|
||||
c = Rcl(c);
|
||||
c = Rcl(1, c);
|
||||
return 0;
|
||||
|
||||
|
||||
div_c:
|
||||
c = Rcl(c);
|
||||
c = Rcl(1, c);
|
||||
c = rest.Add(rest,c);
|
||||
c = rest.Add(divisor);
|
||||
|
||||
@@ -1926,7 +2168,7 @@ private:
|
||||
if(loop)
|
||||
goto div_c;
|
||||
|
||||
c = Rcl(c);
|
||||
c = Rcl(1, c);
|
||||
c = rest.Add(divisor);
|
||||
|
||||
return 0;
|
||||
@@ -2007,7 +2249,7 @@ private:
|
||||
|
||||
if( CmpSmaller(divisor_copy, table_id) )
|
||||
{
|
||||
divisor_copy.Rcr();
|
||||
divisor_copy.Rcr(1);
|
||||
--bits_diff;
|
||||
}
|
||||
|
||||
@@ -2283,16 +2525,17 @@ private:
|
||||
{
|
||||
uint c = 0;
|
||||
|
||||
// !!!!!!!!! change
|
||||
for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
|
||||
{
|
||||
// we can move the bits only to the 'n-1' index but at the moment
|
||||
// we don't have such method
|
||||
// maybe it's time to write it now?
|
||||
v.Rcl(0);
|
||||
v.Rcl(1, 0);
|
||||
|
||||
c <<= 1;
|
||||
|
||||
if( Rcl(0) )
|
||||
if( Rcl(1, 0) )
|
||||
c += 1;
|
||||
}
|
||||
|
||||
@@ -3183,6 +3426,11 @@ public:
|
||||
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
private:
|
||||
uint Rcl2(uint bits, uint c);
|
||||
uint Rcr2(uint bits, uint c);
|
||||
|
||||
public:
|
||||
// these methods are for 64bit processors and are defined in 'ttmathuint64.h'
|
||||
UInt<value_size> & operator=(unsigned int i);
|
||||
UInt(unsigned int i);
|
||||
@@ -3194,8 +3442,6 @@ public:
|
||||
uint AddTwoInts(uint x2, uint x1, uint index);
|
||||
uint Sub(const UInt<value_size> & ss2, uint c=0);
|
||||
uint SubInt(uint value, uint index = 0);
|
||||
uint Rcl(uint c=0);
|
||||
uint Rcr(uint c=0);
|
||||
static sint FindLeadingBitInWord(uint x);
|
||||
static uint SetBitInWord(uint value, uint bit);
|
||||
static void MulTwoWords(uint a, uint b, uint * result2, uint * result1);
|
||||
|
@@ -416,7 +416,7 @@ namespace ttmath
|
||||
"movq $0, %%rdx \n"
|
||||
|
||||
"movq (%%rbx), %%rax \n"
|
||||
"addq %%rsi, %%rax \n"
|
||||
"addq %%rsi, %%rax \n"
|
||||
"movq %%rax, (%%rbx) \n"
|
||||
|
||||
"inc %%rbx \n"
|
||||
@@ -429,7 +429,7 @@ namespace ttmath
|
||||
"inc %%rbx \n"
|
||||
|
||||
"movq (%%rbx), %%rax \n"
|
||||
"adcq %%rdi, %%rax \n"
|
||||
"adcq %%rdi, %%rax \n"
|
||||
"movq %%rax, (%%rbx) \n"
|
||||
"jnc 2f \n"
|
||||
|
||||
@@ -638,17 +638,27 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this method moving once all bits into the left side
|
||||
return value <- this <- C
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
|
||||
the lowest *bits* will be held the 'c' and
|
||||
the state of one additional bit (on the left hand side)
|
||||
will be returned
|
||||
|
||||
for example:
|
||||
let this is 001010000
|
||||
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||
|
||||
***this method is created only on a 64bit platform***
|
||||
|
||||
the lowest bit will hold value of 'c' and
|
||||
function returns the highest bit
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::Rcl(uint c)
|
||||
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
||||
{
|
||||
if( bits == 0 )
|
||||
return 0;
|
||||
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
|
||||
@@ -659,12 +669,17 @@ namespace ttmath
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%rsi \n"
|
||||
|
||||
|
||||
"2: \n"
|
||||
|
||||
"xorq %%rax,%%rax \n"
|
||||
"subq %%rdx,%%rax \n"
|
||||
|
||||
"push %%rbx \n"
|
||||
"push %%rcx \n"
|
||||
|
||||
"movq $0,%%rax \n"
|
||||
"subq %%rdx,%%rax \n"
|
||||
|
||||
|
||||
"1: \n"
|
||||
"rclq $1,(%%rbx) \n"
|
||||
|
||||
@@ -679,14 +694,20 @@ namespace ttmath
|
||||
|
||||
"loop 1b \n"
|
||||
|
||||
"movq $0, %%rdx \n"
|
||||
"adcq %%rdx,%%rdx \n"
|
||||
|
||||
"pop %%rcx \n"
|
||||
"pop %%rbx \n"
|
||||
|
||||
"decq %%rsi \n"
|
||||
|
||||
"jnz 2b \n"
|
||||
|
||||
"movq $0, %%rdx \n"
|
||||
"adcq %%rdx, %%rdx \n"
|
||||
|
||||
"pop %%rsi \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||
: "%rax", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
@@ -697,17 +718,27 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
this method moving once all bits into the right side
|
||||
C -> *this -> return value
|
||||
this method moves all bits into the right hand side
|
||||
C -> this -> return value
|
||||
|
||||
the highest *bits* will be held the 'c' and
|
||||
the state of one additional bit (on the right hand side)
|
||||
will be returned
|
||||
|
||||
for example:
|
||||
let this is 000000010
|
||||
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||
|
||||
***this method is created only on a 64bit platform***
|
||||
|
||||
the highest bit will be held value of 'c' and
|
||||
function returns the lowest bit
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::Rcr(uint c)
|
||||
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
||||
{
|
||||
if( bits == 0 )
|
||||
return 0;
|
||||
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
|
||||
@@ -720,12 +751,18 @@ namespace ttmath
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%rsi \n"
|
||||
|
||||
|
||||
"2: \n"
|
||||
|
||||
|
||||
"push %%rbx \n"
|
||||
"push %%rcx \n"
|
||||
|
||||
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
||||
|
||||
"movq $0, %%rax \n"
|
||||
|
||||
"xorq %%rax, %%rax \n"
|
||||
"subq %%rdx, %%rax \n"
|
||||
|
||||
"1: \n"
|
||||
@@ -742,14 +779,20 @@ namespace ttmath
|
||||
|
||||
"loop 1b \n"
|
||||
|
||||
"movq $0, %%rdx \n"
|
||||
"adcq %%rdx,%%rdx \n"
|
||||
|
||||
"pop %%rcx \n"
|
||||
"pop %%rbx \n"
|
||||
|
||||
"decq %%rsi \n"
|
||||
|
||||
"jnz 2b \n"
|
||||
|
||||
"movq $0, %%rdx \n"
|
||||
"adcq %%rdx,%%rdx \n"
|
||||
|
||||
"pop %%rsi \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||
: "%rax", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user