6 Commits
0.8.0 ... 0.8.1

Author SHA1 Message Date
bb16c871c9 changed: the way of parsing operators in the mathematical parser
(the parser is not too much greedy now)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@38 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-17 13:42:19 +00:00
2116418f08 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()/


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@36 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-13 18:14:11 +00:00
062881900a changed: small changes in: Big::SetPi(), Big::Set05Pi(), Big::Set2Pi(),
Big::ChangeSign()
added:   ASinh(), ACosh(), ATanh() /ATgh()/, ACoth() /ACtgh()/
         and to the parser as well


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@35 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-12 17:17:22 +00:00
0170572f84 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


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@34 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-11 22:14:17 +00:00
e40ed603c6 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)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@33 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-07 22:21:31 +00:00
c97ebf282f 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)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@32 e52654a7-88a9-db11-a3e9-0013d4bc506e
2007-04-05 19:08:15 +00:00
10 changed files with 2628 additions and 211 deletions

View File

@@ -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): Version 0.8.0 (2007.03.28):
* added: into the parser: SetFactorialMax() * added: into the parser: SetFactorialMax()
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec), * added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),

2
README
View File

@@ -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. values can be is set directly in the source code by the programmer.
Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl> Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl>
Home page: http://sourceforge.net/projects/ttmath Project page: http://sourceforge.net/projects/ttmath

4
TODO
View File

@@ -1,7 +1,5 @@
TODO TTMath Library TODO TTMath Library
=================== ===================
* Add bitwise operators (or functions) and, or, xor
* Add functions for generating random values * Add functions for generating random values
* Add something like NaN to the Big<> type

1257
doxygen.cfg Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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' the factorial from given 'x'
e.g. e.g.
@@ -1350,6 +1777,8 @@ namespace ttmath
template<class ValueType> template<class ValueType>
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
{ {
using namespace auxiliaryfunctions;
static History<ValueType> history; static History<ValueType> history;
ValueType result; ValueType result;
@@ -1384,33 +1813,17 @@ namespace ttmath
return result; return result;
} }
ValueType multipler; uint status = FactorialInt(x, err, stop, result);
ValueType one; if( status == 0 )
uint carry = 0; status = FactorialMore(x, err, stop, result);
one = result; // =1
multipler = result; // =1
while( !carry && multipler < x )
{
if( stop && stop->WasStopSignal() )
{
if( err )
*err = err_interrupt;
if( status == 2 )
// the calculation has been interrupted
return result; return result;
}
carry += multipler.Add(one); err_tmp = status==1 ? err_overflow : err_ok;
carry += result.Mul(multipler);
}
err_tmp = carry ? err_overflow : err_ok;
history.Add(x, result, err_tmp); history.Add(x, result, err_tmp);
if( err )
*err = carry ? err_overflow : err_ok;
return result; return result;
} }
@@ -1432,7 +1845,7 @@ namespace ttmath
/*! /*!
it returns the sign of the value it returns the sign of the value
e.g. -2 = 1 e.g. -2 = -1
0 = 0 0 = 0
10 = 1 10 = 1
*/ */

View File

@@ -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) // this is a static table which represents the value Pi (mantissa of it)
// (first is the highest word) // (first is the highest word)
@@ -223,8 +226,19 @@ public:
// and on 64bit platform value 64 (128/2=64)) // and on 64bit platform value 64 (128/2=64))
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); 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; info = 0;
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
} }
@@ -233,7 +247,8 @@ public:
*/ */
void Set05Pi() void Set05Pi()
{ {
SetPi(); SetMantissaPi();
info = 0;
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1; exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
} }
@@ -243,7 +258,8 @@ public:
*/ */
void Set2Pi() void Set2Pi()
{ {
SetPi(); SetMantissaPi();
info = 0;
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3; exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
} }
@@ -450,7 +466,7 @@ public:
/*! /*!
it remains the 'sign' of the value it remains the 'sign' of the value
e.g. -2 = 1 e.g. -2 = -1
0 = 0 0 = 0
10 = 1 10 = 1
*/ */
@@ -495,10 +511,16 @@ public:
*/ */
void ChangeSign() void ChangeSign()
{ {
if( info & TTMATH_BIG_SIGN )
{
info &= ~TTMATH_BIG_SIGN;
return;
}
if( IsZero() ) if( IsZero() )
return; 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.Sub( ss2.exponent );
exp_offset.Abs(); exp_offset.Abs();
// abs(this) will be >= abs(ss2) // (1) abs(this) will be >= abs(ss2)
if( SmallerWithoutSignThan(ss2) ) if( SmallerWithoutSignThan(ss2) )
{ {
Big<exp, man> temp(ss2); Big<exp, man> temp(ss2);
@@ -545,11 +567,12 @@ public:
else else
if( exp_offset < mantissa_size_in_bits ) if( exp_offset < mantissa_size_in_bits )
{ {
// moving 'exp_offset' times // (2) moving 'exp_offset' times
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
} }
else else
{ {
// (3)
// exp_offset == mantissa_size_in_bits // exp_offset == mantissa_size_in_bits
// we're rounding 'this' about one (up or down depending on a ss2 sign) // we're rounding 'this' about one (up or down depending on a ss2 sign)
ss2.mantissa.SetOne(); ss2.mantissa.SetOne();
@@ -561,18 +584,19 @@ public:
// values have the same signs // values have the same signs
if( mantissa.Add(ss2.mantissa) ) if( mantissa.Add(ss2.mantissa) )
{ {
mantissa.Rcr(1); mantissa.Rcr(1,1);
c = exponent.AddOne(); c = exponent.AddOne();
} }
} }
else else
{ {
// values have different signs // values have different signs
if( mantissa.Sub(ss2.mantissa) ) // there shouldn't be a carry here because
{ // (1) (2) and (3) guarantee that the mantissa of this
mantissa.Rcl(1); // is greater than the mantissa of the ss2
c = exponent.SubOne(); uint c_temp = mantissa.Sub(ss2.mantissa);
}
TTMATH_ASSERT( c_temp == 0 )
} }
c += Standardizing(); c += Standardizing();
@@ -594,6 +618,212 @@ public:
} }
/*!
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 multiplication this = this * ss2
this method returns carry this method returns carry
@@ -747,7 +977,7 @@ public:
if( start.Mul(start) ) if( start.Mul(start) )
return 1; return 1;
pow.Rcr(); pow.Rcr(1);
} }
*this = result; *this = result;
@@ -883,6 +1113,7 @@ public:
pow can be negative and with fraction pow can be negative and with fraction
return values: return values:
0 - ok
1 - carry 1 - carry
2 - incorrect argument ('this') 2 - incorrect argument ('this')
*/ */
@@ -892,6 +1123,10 @@ public:
Big<exp, man> temp; Big<exp, man> temp;
uint c = temp.Ln(*this); uint c = temp.Ln(*this);
if( c!= 0 )
return c;
c += temp.Mul(pow); c += temp.Mul(pow);
c += Exp(temp); c += Exp(temp);
@@ -904,6 +1139,7 @@ public:
pow can be negative and with fraction pow can be negative and with fraction
return values: return values:
0 - ok
1 - carry 1 - carry
2 - incorrect argument ('this' or 'pow') 2 - incorrect argument ('this' or 'pow')
*/ */
@@ -1269,19 +1505,22 @@ public:
* *
*/ */
/*! /*!
this method sets 'result' as the one word of type sint this method sets 'result' as the one word of type uint
if the value is too big this method returns a carry (1) if the value is too big this method returns a carry (1)
*/ */
uint ToInt(sint & result) const uint ToUInt(uint & result, bool test_sign = true) const
{ {
result = 0; result = 0;
if( IsZero() ) if( IsZero() )
return 0; return 0;
if( test_sign && IsSign() )
// the result should be positive
return 1;
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) ) if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
@@ -1290,30 +1529,50 @@ public:
return 1; return 1;
if( exponent <= maxbit ) if( exponent <= maxbit )
// our value is from range (-1,1) and we return zero // our value is from the range of (-1,1) and we return zero
return 0; return 0;
UInt<man> mantissa_temp(mantissa); UInt<man> mantissa_temp(mantissa);
// exponent is from a range of (-maxbit,0> // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
sint how_many_bits = exponent.ToInt(); sint how_many_bits = exponent.ToInt();
// how_many_bits is negative, we'll make it positive // how_many_bits is negative, we'll make it positive
how_many_bits = -how_many_bits; how_many_bits = -how_many_bits;
// we're taking into an account only the last word in a mantissa table // we're taking into account only the last word in a mantissa table
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
result = mantissa_temp.table[ man-1 ]; result = mantissa_temp.table[ man-1 ];
return 0;
}
/*!
this method sets 'result' as the one word of type sint
if the value is too big this method returns a carry (1)
*/
uint ToInt(sint & result) const
{
result = 0;
uint result_uint;
if( ToUInt(result_uint, false) )
return 1;
result = static_cast<sint>( result_uint );
// the exception for the minimal value // the exception for the minimal value
if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT ) if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT )
return 0; return 0;
if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 ) if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 )
// the value is too big // the value is too big
return 1; return 1;
if( IsSign() ) if( IsSign() )
result = -sint(result); result = -result;
return 0; 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) )
// if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed // 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) // into the 'Int<int_size>' type (it's too big)
return 1;
if( exponent <= maxbit ) if( exponent <= maxbit )
// our value is from range (-1,1) and we return zero // our value is from range (-1,1) and we return zero

View File

@@ -618,6 +618,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
Error( err ); Error( err );
} }
void Abs(int sindex, int amount_of_args, ValueType & result) void Abs(int sindex, int amount_of_args, ValueType & result)
{ {
if( amount_of_args != 1 ) 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 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("tgh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth); InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
InsertFunctionToTable(std::string("ctgh"), &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) /*!
{ returns true if 'str2' is the substring of str1
if( c=='|' || c=='&' || c=='!' || c=='=' || c=='<' || c=='>' ||
c=='*' || c=='/' || c=='+' || c=='-' || c=='^' )
return true;
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; 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) void ReadMathematicalOperator(Item & result)
{ {
std::string oper; std::string oper;
typename OperatorsTable::iterator iter_old, iter_new;
for( ; CanBeMathematicalOperator(*pstring) ; ++pstring ) iter_old = operators_table.end();
for( ; true ; ++pstring )
{
oper += *pstring; oper += *pstring;
iter_new = operators_table.lower_bound(oper);
typename OperatorsTable::iterator iter = operators_table.find(oper); if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) )
{
if( iter == operators_table.end() ) oper.erase( --oper.end() ); // we've got mininum one element
Error( err_unknown_operator );
if( iter_old != operators_table.end() && iter_old->first == oper )
{
result.type = Item::mat_operator; result.type = Item::mat_operator;
result.moperator.SetType( iter->second ); result.moperator.SetType( iter_old->second );
break;
}
Error( err_unknown_operator );
}
iter_old = iter_new;
}
} }
@@ -1535,10 +1699,7 @@ int ReadOperator(Item & result)
++pstring; ++pstring;
} }
else else
if( CanBeMathematicalOperator(*pstring) )
ReadMathematicalOperator(result); ReadMathematicalOperator(result);
else
Error( err_unknown_character );
return 0; return 0;
} }
@@ -2113,7 +2274,6 @@ ErrorCode Parse(const char * str)
stack.resize( default_stack_size ); stack.resize( default_stack_size );
try try
{ {
Parse(); Parse();

View File

@@ -58,10 +58,14 @@
/*! /*!
the version of the library 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_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 0 #define TTMATH_REVISION_VER 1
#define TTMATH_PRERELEASE_VER 0
/*! /*!

View File

@@ -878,18 +878,31 @@ public:
} }
private:
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
/*! /*!
this method moving once all bits into the left side this method moves all bits into the left hand side
return value <- this <- C return value <- this <- c
the lowest bit will hold value of 'c' and the lowest *bits* will be held the 'c' and
function returns the highest bit 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 sint b = value_size;
register uint * p1 = table; register uint * p1 = table;
@@ -900,13 +913,17 @@ public:
push eax push eax
push ebx push ebx
push ecx push ecx
push edx
mov edx, [bits]
a:
xor eax, eax
sub eax, [c]
mov ecx, [b] mov ecx, [b]
mov ebx, [p1] mov ebx, [p1]
mov eax,0
sub eax,[c]
p: p:
rcl dword ptr[ebx],1 rcl dword ptr[ebx],1
@@ -917,10 +934,15 @@ public:
loop p loop p
dec edx
jnz a
mov eax,0 mov eax,0
adc eax,eax adc eax,eax
mov [c],eax mov [c],eax
pop edx
pop ecx pop ecx
pop ebx pop ebx
pop eax pop eax
@@ -931,12 +953,16 @@ public:
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"push %%esi \n"
"2: \n"
"xorl %%eax,%%eax \n"
"subl %%edx,%%eax \n"
"push %%ebx \n" "push %%ebx \n"
"push %%ecx \n" "push %%ecx \n"
"movl $0,%%eax \n"
"subl %%edx,%%eax \n"
"1: \n" "1: \n"
"rcll $1,(%%ebx) \n" "rcll $1,(%%ebx) \n"
@@ -947,14 +973,20 @@ public:
"loop 1b \n" "loop 1b \n"
"movl $0, %%edx \n"
"adcl %%edx,%%edx \n"
"pop %%ecx \n" "pop %%ecx \n"
"pop %%ebx \n" "pop %%ebx \n"
"decl %%esi \n"
"jnz 2b \n"
"movl $0, %%edx \n"
"adcl %%edx, %%edx \n"
"pop %%esi \n"
: "=d" (c) : "=d" (c)
: "0" (c), "c" (b), "b" (p1) : "0" (c), "c" (b), "b" (p1), "S" (bits)
: "%eax", "cc", "memory" ); : "%eax", "cc", "memory" );
#endif #endif
@@ -965,14 +997,24 @@ public:
/*! /*!
this method moving once all bits into the right side this method moves all bits into the right hand side
C -> *this -> return value C -> this -> return value
the highest bit will be held value of 'c' and the highest *bits* will be held the 'c' and
function returns the lowest bit 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 sint b = value_size;
register uint * p1 = table; register uint * p1 = table;
@@ -983,15 +1025,19 @@ public:
push eax push eax
push ebx push ebx
push ecx push ecx
push edx
mov edx,[bits]
a:
xor eax,eax
sub eax,[c]
mov ebx,[p1] mov ebx,[p1]
mov ecx,[b] mov ecx,[b]
lea ebx,[ebx+4*ecx] lea ebx,[ebx+4*ecx]
mov eax,0
sub eax,[c]
p: p:
dec ebx dec ebx
dec ebx dec ebx
@@ -1002,10 +1048,15 @@ public:
loop p loop p
dec edx
jnz a
mov eax,0 mov eax,0
adc eax,eax adc eax,eax
mov [c],eax mov [c],eax
pop edx
pop ecx pop ecx
pop ebx pop ebx
pop eax pop eax
@@ -1016,12 +1067,17 @@ public:
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"push %%esi \n"
"2: \n"
"push %%ebx \n" "push %%ebx \n"
"push %%ecx \n" "push %%ecx \n"
"leal (%%ebx,%%ecx,4),%%ebx \n" "leal (%%ebx,%%ecx,4),%%ebx \n"
"movl $0, %%eax \n" "xorl %%eax, %%eax \n"
"subl %%edx, %%eax \n" "subl %%edx, %%eax \n"
"1: \n" "1: \n"
@@ -1034,14 +1090,20 @@ public:
"loop 1b \n" "loop 1b \n"
"movl $0, %%edx \n"
"adcl %%edx,%%edx \n"
"pop %%ecx \n" "pop %%ecx \n"
"pop %%ebx \n" "pop %%ebx \n"
"decl %%esi \n"
"jnz 2b \n"
"movl $0, %%edx \n"
"adcl %%edx, %%edx \n"
"pop %%esi \n"
: "=d" (c) : "=d" (c)
: "0" (c), "c" (b), "b" (p1) : "0" (c), "c" (b), "b" (p1), "S" (bits)
: "%eax", "cc", "memory" ); : "%eax", "cc", "memory" );
#endif #endif
@@ -1052,6 +1114,47 @@ public:
#endif #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 this method moving all bits into the left side 'bits' times
return value <- this <- C return value <- this <- C
@@ -1062,39 +1165,92 @@ public:
the value c will be set into the lowest bits the value c will be set into the lowest bits
and the method returns state of the last moved bit 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; uint last_c = 0;
sint all_words = 0;
uint rest_bits = bits;
if( bits > value_size*TTMATH_BITS_PER_UINT ) if( bits >= TTMATH_BITS_PER_UINT )
bits = value_size*TTMATH_BITS_PER_UINT; RclMoveAllWords(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 // if rest_bits is greater than a half of TTMATH_BITS_PER_UINT
for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) // 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; uint temp = table[0];
table[first] = table[second]; 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; 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 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 the value c will be set into the highest bits
and the method returns state of the last moved bit 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; uint last_c = 0;
sint second; sint all_words = 0;
sint last_c = 0; uint rest_bits = bits;
if( bits > value_size*TTMATH_BITS_PER_UINT ) if( bits >= TTMATH_BITS_PER_UINT )
bits = value_size*TTMATH_BITS_PER_UINT; RcrMoveAllWords(all_words, rest_bits, last_c, bits, c);
sint all_words = sint(bits) / sint(TTMATH_BITS_PER_UINT); // rest_bits is from 0 to TTMATH_BITS_PER_UINT-1 now
if( rest_bits > 0 )
if( all_words > 0 )
{ {
// copying the first part of the value if( rest_bits > TTMATH_BITS_PER_UINT/2 + 1 )
for(first=0, second=all_words ; second<sint(value_size) ; ++first, ++second)
{ {
last_c = table[first] & TTMATH_UINT_HIGHEST_BIT; uint temp = table[value_size-1];
table[first] = table[second]; 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; return last_c;
} }
@@ -1175,14 +1334,14 @@ public:
table[i] = 0; table[i] = 0;
} }
// moving the rest bits (max TTMATH_BITS_PER_UINT -- only one word) uint moving2 = FindLeadingBitInWord( table[value_size-1] );
while( !IsTheHighestBitSet() ) // moving2 is different from -1 because the value table[value_size-1]
{ // is not zero
Rcl();
++moving;
}
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 * Multiplication
@@ -1442,6 +1643,47 @@ public:
return 0; 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 the multiplication 'this' = 'this' * ss2
@@ -1504,7 +1746,7 @@ public:
if( Add(*this) ) if( Add(*this) )
return 1; return 1;
if( ss1.Rcl() ) if( ss1.Rcl(1) )
if( Add(ss2) ) if( Add(ss2) )
return 1; return 1;
} }
@@ -1893,7 +2135,7 @@ private:
div_a: div_a:
c = Rcl(c); c = Rcl(1, c);
c = rest.Add(rest,c); c = rest.Add(rest,c);
c = rest.Sub(divisor,c); c = rest.Sub(divisor,c);
@@ -1908,12 +2150,12 @@ private:
if(loop) if(loop)
goto div_a; goto div_a;
c = Rcl(c); c = Rcl(1, c);
return 0; return 0;
div_c: div_c:
c = Rcl(c); c = Rcl(1, c);
c = rest.Add(rest,c); c = rest.Add(rest,c);
c = rest.Add(divisor); c = rest.Add(divisor);
@@ -1926,7 +2168,7 @@ private:
if(loop) if(loop)
goto div_c; goto div_c;
c = Rcl(c); c = Rcl(1, c);
c = rest.Add(divisor); c = rest.Add(divisor);
return 0; return 0;
@@ -2007,7 +2249,7 @@ private:
if( CmpSmaller(divisor_copy, table_id) ) if( CmpSmaller(divisor_copy, table_id) )
{ {
divisor_copy.Rcr(); divisor_copy.Rcr(1);
--bits_diff; --bits_diff;
} }
@@ -2283,16 +2525,17 @@ private:
{ {
uint c = 0; uint c = 0;
// !!!!!!!!! change
for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) 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 can move the bits only to the 'n-1' index but at the moment
// we don't have such method // we don't have such method
// maybe it's time to write it now? // maybe it's time to write it now?
v.Rcl(0); v.Rcl(1, 0);
c <<= 1; c <<= 1;
if( Rcl(0) ) if( Rcl(1, 0) )
c += 1; c += 1;
} }
@@ -3183,6 +3426,11 @@ public:
#ifdef TTMATH_PLATFORM64 #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' // these methods are for 64bit processors and are defined in 'ttmathuint64.h'
UInt<value_size> & operator=(unsigned int i); UInt<value_size> & operator=(unsigned int i);
UInt(unsigned int i); UInt(unsigned int i);
@@ -3194,8 +3442,6 @@ public:
uint AddTwoInts(uint x2, uint x1, uint index); uint AddTwoInts(uint x2, uint x1, uint index);
uint Sub(const UInt<value_size> & ss2, uint c=0); uint Sub(const UInt<value_size> & ss2, uint c=0);
uint SubInt(uint value, uint index = 0); uint SubInt(uint value, uint index = 0);
uint Rcl(uint c=0);
uint Rcr(uint c=0);
static sint FindLeadingBitInWord(uint x); static sint FindLeadingBitInWord(uint x);
static uint SetBitInWord(uint value, uint bit); static uint SetBitInWord(uint value, uint bit);
static void MulTwoWords(uint a, uint b, uint * result2, uint * result1); static void MulTwoWords(uint a, uint b, uint * result2, uint * result1);

View File

@@ -638,17 +638,27 @@ namespace ttmath
/*! /*!
this method moving once all bits into the left side this method moves all bits into the left hand side
return value <- this <- C 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*** ***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> 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 sint b = value_size;
register uint * p1 = table; register uint * p1 = table;
@@ -659,12 +669,17 @@ namespace ttmath
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"push %%rsi \n"
"2: \n"
"xorq %%rax,%%rax \n"
"subq %%rdx,%%rax \n"
"push %%rbx \n" "push %%rbx \n"
"push %%rcx \n" "push %%rcx \n"
"movq $0,%%rax \n"
"subq %%rdx,%%rax \n"
"1: \n" "1: \n"
"rclq $1,(%%rbx) \n" "rclq $1,(%%rbx) \n"
@@ -679,14 +694,20 @@ namespace ttmath
"loop 1b \n" "loop 1b \n"
"movq $0, %%rdx \n"
"adcq %%rdx,%%rdx \n"
"pop %%rcx \n" "pop %%rcx \n"
"pop %%rbx \n" "pop %%rbx \n"
"decq %%rsi \n"
"jnz 2b \n"
"movq $0, %%rdx \n"
"adcq %%rdx, %%rdx \n"
"pop %%rsi \n"
: "=d" (c) : "=d" (c)
: "0" (c), "c" (b), "b" (p1) : "0" (c), "c" (b), "b" (p1), "S" (bits)
: "%rax", "cc", "memory" ); : "%rax", "cc", "memory" );
#endif #endif
@@ -697,17 +718,27 @@ namespace ttmath
/*! /*!
this method moving once all bits into the right side this method moves all bits into the right hand side
C -> *this -> return value 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*** ***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> 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 sint b = value_size;
register uint * p1 = table; register uint * p1 = table;
@@ -720,12 +751,18 @@ namespace ttmath
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"push %%rsi \n"
"2: \n"
"push %%rbx \n" "push %%rbx \n"
"push %%rcx \n" "push %%rcx \n"
"leaq (%%rbx,%%rcx,8),%%rbx \n" "leaq (%%rbx,%%rcx,8),%%rbx \n"
"movq $0, %%rax \n" "xorq %%rax, %%rax \n"
"subq %%rdx, %%rax \n" "subq %%rdx, %%rax \n"
"1: \n" "1: \n"
@@ -742,14 +779,20 @@ namespace ttmath
"loop 1b \n" "loop 1b \n"
"movq $0, %%rdx \n"
"adcq %%rdx,%%rdx \n"
"pop %%rcx \n" "pop %%rcx \n"
"pop %%rbx \n" "pop %%rbx \n"
"decq %%rsi \n"
"jnz 2b \n"
"movq $0, %%rdx \n"
"adcq %%rdx,%%rdx \n"
"pop %%rsi \n"
: "=d" (c) : "=d" (c)
: "0" (c), "c" (b), "b" (p1) : "0" (c), "c" (b), "b" (p1), "S" (bits)
: "%rax", "cc", "memory" ); : "%rax", "cc", "memory" );
#endif #endif