Merged against the current original ttmath trunk
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@170 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
commit
de64608eba
29
CHANGELOG
29
CHANGELOG
|
@ -1,4 +1,4 @@
|
|||
Version 0.8.5 prerelease (2009.05.15):
|
||||
Version 0.8.5 (2009.06.16):
|
||||
* fixed: Big::Mod(x) didn't correctly return a carry
|
||||
and the result was sometimes very big (even greater than x)
|
||||
* fixed: global function Mod(x) didn't set an ErrorCode object
|
||||
|
@ -7,7 +7,7 @@ Version 0.8.5 prerelease (2009.05.15):
|
|||
* changed: function Sin(x) to Sin(x, ErrorCode * err=0)
|
||||
when x was very big the function returns zero
|
||||
now it sets ErrorCode object to err_overflow
|
||||
and the result is undefined
|
||||
and the result has a NaN flag set
|
||||
the same is to Cos() function
|
||||
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
|
||||
should be a little accurate especially on a very big 'x'
|
||||
|
@ -29,6 +29,31 @@ Version 0.8.5 prerelease (2009.05.15):
|
|||
uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
three forms: asm x86, asm x86_64, no-asm
|
||||
those methods are used by the Karatsuba multiplication algorithm
|
||||
* added: to Big<> class: support for NaN flag (Not a Number)
|
||||
bool Big::IsNan() - returns true if the NaN flag is set
|
||||
void Big::SetNan() - sets the NaN flag
|
||||
The NaN flag is set by default after creating an object:
|
||||
Big<1, 2> a; // NaN is set (it means the object has not a valid number)
|
||||
std::cout << a; // cout gives "NaN"
|
||||
a = 123; // now NaN is not set
|
||||
std::cout << a; // cout gives "123"
|
||||
The NaN is set if there was a carry during calculations
|
||||
a.Mul(very_big_value); // a will have a NaN set
|
||||
The NaN is set if an argument is NaN too
|
||||
b.SetNan();
|
||||
a.Add(b); // a will have NaN because b has NaN too
|
||||
If you try to do something on a NaN object, the result is a NaN too
|
||||
a.SetNan();
|
||||
a.Add(2); // a is still a NaN
|
||||
The NaN is set if you use incorrect arguments
|
||||
a.Ln(-10); // a will have the NaN flag
|
||||
The only way to clear the NaN flag is to assign a correct value or other correct object,
|
||||
supposing 'a' has NaN flag, to remove the flag you can either:
|
||||
a = 10;
|
||||
a.FromInt(30);
|
||||
a.SetOne();
|
||||
a.FromBig(other_object_without_nan);
|
||||
etc.
|
||||
|
||||
|
||||
Version 0.8.4 (2009.05.08):
|
||||
|
|
257
ttmath/ttmath.h
257
ttmath/ttmath.h
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
|
@ -46,7 +45,7 @@
|
|||
\brief Mathematics functions.
|
||||
*/
|
||||
|
||||
#include "ttmathconfig.h"
|
||||
#include "ttmathconfig.h"
|
||||
#include "ttmathbig.h"
|
||||
#include "ttmathobjects.h"
|
||||
|
||||
|
@ -99,6 +98,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Round(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result( x );
|
||||
uint c = result.Round();
|
||||
|
||||
|
@ -124,6 +131,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Ceil(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result(x);
|
||||
uint c = 0;
|
||||
|
||||
|
@ -163,6 +178,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Floor(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result(x);
|
||||
uint c = 0;
|
||||
|
||||
|
@ -203,8 +226,15 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Ln(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
|
||||
uint state = result.Ln(x);
|
||||
|
||||
if( err )
|
||||
|
@ -237,8 +267,15 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() || base.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return ValueType(); // default NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
|
||||
uint state = result.Log(x, base);
|
||||
|
||||
if( err )
|
||||
|
@ -271,8 +308,15 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Exp(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
|
||||
uint c = result.Exp(x);
|
||||
|
||||
if( err )
|
||||
|
@ -468,6 +512,14 @@ namespace ttmath
|
|||
ValueType one, result;
|
||||
bool change_sign;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
|
@ -479,7 +531,7 @@ namespace ttmath
|
|||
// result has NaN flag set by default
|
||||
|
||||
if( err )
|
||||
*err = err_overflow; // maybe another error code?
|
||||
*err = err_overflow; // maybe another error code? err_improper_argument?
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
@ -511,6 +563,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Cos(ValueType x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType pi05;
|
||||
pi05.Set05Pi();
|
||||
|
||||
|
@ -783,6 +843,14 @@ namespace ttmath
|
|||
one.SetOne();
|
||||
bool change_sign = false;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
if( x.GreaterWithoutSignThan(one) )
|
||||
{
|
||||
if( err )
|
||||
|
@ -1005,6 +1073,9 @@ namespace ttmath
|
|||
one.SetOne();
|
||||
bool change_sign = false;
|
||||
|
||||
if( x.IsNan() )
|
||||
return result; // NaN is set by default
|
||||
|
||||
// if x is negative we're using the formula:
|
||||
// atan(-x) = -atan(x)
|
||||
if( x.IsSign() )
|
||||
|
@ -1085,6 +1156,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Sinh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType ex, emx;
|
||||
uint c = 0;
|
||||
|
||||
|
@ -1109,6 +1188,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Cosh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType ex, emx;
|
||||
uint c = 0;
|
||||
|
||||
|
@ -1133,6 +1220,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Tanh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType ex, emx, nominator, denominator;
|
||||
uint c = 0;
|
||||
|
||||
|
@ -1173,6 +1268,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Coth(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
if( x.IsZero() )
|
||||
{
|
||||
if( err )
|
||||
|
@ -1230,6 +1333,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType ASinh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType xx(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
@ -1258,6 +1369,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType ACosh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType xx(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
@ -1299,6 +1418,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType ATanh(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType nominator(x), denominator, one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
@ -1344,6 +1471,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType ACoth(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType nominator(x), denominator(x), one, result;
|
||||
uint c = 0;
|
||||
one.SetOne();
|
||||
|
@ -1402,6 +1537,14 @@ namespace ttmath
|
|||
ValueType result, temp;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
|
||||
// it is better to make division first and then multiplication
|
||||
|
@ -1430,6 +1573,14 @@ namespace ttmath
|
|||
ValueType result, delimiter;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = 180;
|
||||
c += result.Mul(x);
|
||||
|
||||
|
@ -1467,7 +1618,7 @@ namespace ttmath
|
|||
ValueType delimiter, multipler;
|
||||
uint c = 0;
|
||||
|
||||
if( m.IsSign() || s.IsSign() )
|
||||
if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
@ -1521,6 +1672,14 @@ namespace ttmath
|
|||
ValueType result, temp;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
|
||||
// it is better to make division first and then multiplication
|
||||
|
@ -1549,6 +1708,14 @@ namespace ttmath
|
|||
ValueType result, delimiter;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = 200;
|
||||
c += result.Mul(x);
|
||||
|
||||
|
@ -1573,6 +1740,14 @@ namespace ttmath
|
|||
ValueType result, temp;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
|
||||
temp = 200;
|
||||
|
@ -1615,6 +1790,14 @@ namespace ttmath
|
|||
ValueType result, temp;
|
||||
uint c = 0;
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
|
||||
temp = 180;
|
||||
|
@ -1648,7 +1831,7 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Sqrt(ValueType x, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsSign() )
|
||||
if( x.IsNan() || x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
@ -1730,7 +1913,7 @@ namespace ttmath
|
|||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
ValueType one;
|
||||
one.SetOne();
|
||||
|
@ -1772,11 +1955,12 @@ namespace ttmath
|
|||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
bool RootCheckXZero(ValueType & x, ErrorCode * err)
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// root(0;index) is zero (if index!=0)
|
||||
// RootCheckIndexZero() must be called beforehand
|
||||
x.SetZero();
|
||||
|
||||
if( err )
|
||||
|
@ -1843,11 +2027,19 @@ namespace ttmath
|
|||
{
|
||||
using namespace auxiliaryfunctions;
|
||||
|
||||
if( x.IsNan() || index.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return ValueType(); // NaN is set by default
|
||||
}
|
||||
|
||||
if( RootCheckIndexSign(x, index, err) ) return x;
|
||||
if( RootCheckIndexZero(x, index, err) ) return x;
|
||||
if( RootCheckIndexOne (x, index, err) ) return x;
|
||||
if( RootCheckIndexOne ( index, err) ) return x;
|
||||
if( RootCheckIndexFrac(x, index, err) ) return x;
|
||||
if( RootCheckXZero(x, index, err) ) return x;
|
||||
if( RootCheckXZero (x, err) ) return x;
|
||||
|
||||
// index integer and index!=0
|
||||
// x!=0
|
||||
|
@ -1898,14 +2090,17 @@ namespace ttmath
|
|||
|
||||
while( !carry && multipler<maxvalue )
|
||||
{
|
||||
// !! the test here we don't have to make in all iterations (performance)
|
||||
if( stop && stop->WasStopSignal() )
|
||||
if( stop && (multipler & 127)==0 ) // it means 'stop && (multipler % 128)==0'
|
||||
{
|
||||
// after each 128 iterations we make a test
|
||||
if( stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
++multipler;
|
||||
carry += result.MulUInt(multipler);
|
||||
|
@ -1928,20 +2123,25 @@ namespace ttmath
|
|||
|
||||
one.SetOne();
|
||||
uint carry = 0;
|
||||
uint iter = 1; // only for testing the stop object
|
||||
|
||||
while( !carry && multipler < x )
|
||||
{
|
||||
// !! the test here we don't have to make in all iterations (performance)
|
||||
if( stop && stop->WasStopSignal() )
|
||||
if( stop && (iter & 31)==0 ) // it means 'stop && (iter % 32)==0'
|
||||
{
|
||||
// after each 32 iterations we make a test
|
||||
if( stop->WasStopSignal() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_interrupt;
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
carry += multipler.Add(one);
|
||||
carry += result.Mul(multipler);
|
||||
++iter;
|
||||
}
|
||||
|
||||
if( err )
|
||||
|
@ -1968,18 +2168,16 @@ namespace ttmath
|
|||
static History<ValueType> history;
|
||||
ValueType result;
|
||||
|
||||
result.SetOne();
|
||||
|
||||
if( x.IsSign() )
|
||||
if( x.IsNan() || x.IsSign() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
result.SetNan();
|
||||
|
||||
return result;
|
||||
return result; // NaN set by default
|
||||
}
|
||||
|
||||
result.SetOne();
|
||||
|
||||
if( !x.exponent.IsSign() && !x.exponent.IsZero() )
|
||||
{
|
||||
// when x.exponent>0 there's no sense to calculate the formula
|
||||
|
@ -2065,6 +2263,14 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0)
|
||||
{
|
||||
if( a.IsNan() || b.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return ValueType(); // NaN is set by default
|
||||
}
|
||||
|
||||
uint c = a.Mod(b);
|
||||
|
||||
if( err )
|
||||
|
@ -2084,4 +2290,11 @@ namespace ttmath
|
|||
*/
|
||||
#include "ttmathparser.h"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( default: 4127 )
|
||||
//warning C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -143,9 +143,8 @@ public:
|
|||
return 0;
|
||||
|
||||
uint comp = mantissa.CompensationToLeft();
|
||||
uint c = exponent.Sub( comp );
|
||||
|
||||
return CheckCarry(c);
|
||||
return exponent.Sub( comp );
|
||||
}
|
||||
|
||||
|
||||
|
@ -540,6 +539,7 @@ public:
|
|||
/*
|
||||
we only have to test the mantissa
|
||||
also we don't check the NaN flag
|
||||
(maybe this method should return false if there is NaN flag set?)
|
||||
*/
|
||||
return mantissa.IsZero();
|
||||
}
|
||||
|
@ -587,6 +587,7 @@ public:
|
|||
*/
|
||||
void Sgn()
|
||||
{
|
||||
// we have to check the NaN flag, because the next SetOne() method would clear it
|
||||
if( IsNan() )
|
||||
return;
|
||||
|
||||
|
@ -622,6 +623,7 @@ public:
|
|||
|
||||
/*!
|
||||
this method changes the sign
|
||||
when there is a value of zero then the sign is not changed
|
||||
|
||||
e.g.
|
||||
-1 -> 1
|
||||
|
@ -629,6 +631,8 @@ public:
|
|||
*/
|
||||
void ChangeSign()
|
||||
{
|
||||
// we don't have to check the NaN flag here
|
||||
|
||||
if( info & TTMATH_BIG_SIGN )
|
||||
{
|
||||
info &= ~TTMATH_BIG_SIGN;
|
||||
|
@ -708,7 +712,14 @@ public:
|
|||
// there shouldn't be a carry here because
|
||||
// (1) (2) guarantee that the mantissa of this
|
||||
// is greater than or equal to the mantissa of the ss2
|
||||
TTMATH_VERIFY( mantissa.Sub(ss2.mantissa) >= 0 )
|
||||
|
||||
#ifdef TTMATH_DEBUG
|
||||
// this is to get rid of a warning saying that c_temp is not used
|
||||
uint c_temp = /* mantissa.Sub(ss2.mantissa); */
|
||||
#endif
|
||||
mantissa.Sub(ss2.mantissa);
|
||||
|
||||
TTMATH_ASSERT( c_temp == 0 )
|
||||
}
|
||||
|
||||
c += Standardizing();
|
||||
|
@ -1393,19 +1404,17 @@ public:
|
|||
denominator.SetOne();
|
||||
denominator_i.SetOne();
|
||||
|
||||
// every 'step_test' times we make a test
|
||||
const uint step_test = 5;
|
||||
uint i;
|
||||
old_value = *this;
|
||||
|
||||
// we begin from 1 in order to not testing at the beginning
|
||||
// we begin from 1 in order to not test at the beginning
|
||||
#ifdef TTMATH_CONSTANTSGENERATOR
|
||||
for(i=1 ; true ; ++i)
|
||||
#else
|
||||
for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
||||
#endif
|
||||
{
|
||||
bool testing = ((i % step_test) == 0);
|
||||
bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
|
||||
|
||||
next_part = numerator;
|
||||
|
||||
|
@ -1418,13 +1427,15 @@ public:
|
|||
// there shouldn't be a carry here
|
||||
Add( next_part );
|
||||
|
||||
if( testing && old_value==*this )
|
||||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next few parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
|
||||
}
|
||||
|
||||
// we set the denominator and the numerator for a next part of the formula
|
||||
if( denominator_i.Add(one) )
|
||||
|
@ -1559,20 +1570,17 @@ public:
|
|||
SetZero();
|
||||
|
||||
old_value = *this;
|
||||
|
||||
// every 'step_test' times we make a test
|
||||
const uint step_test = 5;
|
||||
uint i;
|
||||
|
||||
|
||||
#ifdef TTMATH_CONSTANTSGENERATOR
|
||||
for(i=1 ; true ; ++i)
|
||||
#else
|
||||
// we begin from 1 in order to not testing at the beginning
|
||||
// we begin from 1 in order to not test at the beginning
|
||||
for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
||||
#endif
|
||||
{
|
||||
bool testing = ((i % step_test) == 0);
|
||||
bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
|
||||
|
||||
next_part = x1;
|
||||
|
||||
|
@ -1585,12 +1593,15 @@ public:
|
|||
// there shouldn't be a carry here
|
||||
Add(next_part);
|
||||
|
||||
if( testing && old_value == *this )
|
||||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next (step_test) parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
}
|
||||
|
||||
if( x1.Mul(x2) )
|
||||
// if there is a carry here the result we return as good
|
||||
|
@ -2021,9 +2032,10 @@ public:
|
|||
// If E=2047 and F is zero and S is 1, then V=-Infinity
|
||||
// If E=2047 and F is zero and S is 0, then V=Infinity
|
||||
|
||||
// at the moment we do not support NaN, -Infinity and +Infinity
|
||||
// we do not support -Infinity and +Infinity
|
||||
// we assume that there is always NaN
|
||||
|
||||
SetZero();
|
||||
SetNan();
|
||||
}
|
||||
else
|
||||
if( e > 0 )
|
||||
|
@ -2134,9 +2146,10 @@ public:
|
|||
// If E=2047 and F is zero and S is 1, then V=-Infinity
|
||||
// If E=2047 and F is zero and S is 0, then V=Infinity
|
||||
|
||||
// at the moment we do not support NaN, -Infinity and +Infinity
|
||||
// we do not support -Infinity and +Infinity
|
||||
// we assume that there is always NaN
|
||||
|
||||
SetZero();
|
||||
SetNan();
|
||||
}
|
||||
else
|
||||
if( e > 0 )
|
||||
|
@ -2226,12 +2239,19 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
if( IsNan() )
|
||||
{
|
||||
result = ToDouble_SetDouble( false, 2047, 0, false, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1;
|
||||
|
||||
if( exponent >= 1024 - e_correction )
|
||||
{
|
||||
// +/- infinity
|
||||
result = ToDouble_SetDouble( IsSign(), 2047, 0, true);
|
||||
result = ToDouble_SetDouble( 0, 2047, 0, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -2266,7 +2286,7 @@ private:
|
|||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
// 32bit platforms
|
||||
double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false) const
|
||||
double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
|
||||
{
|
||||
union
|
||||
{
|
||||
|
@ -2281,6 +2301,12 @@ private:
|
|||
|
||||
temp.u[1] |= (e << 20) & 0x7FF00000u;
|
||||
|
||||
if( nan )
|
||||
{
|
||||
temp.u[0] |= 1;
|
||||
return temp.d;
|
||||
}
|
||||
|
||||
if( infinity )
|
||||
return temp.d;
|
||||
|
||||
|
@ -2303,7 +2329,7 @@ private:
|
|||
#else
|
||||
|
||||
// 64bit platforms
|
||||
double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false) const
|
||||
double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
|
||||
{
|
||||
union
|
||||
{
|
||||
|
@ -2318,6 +2344,12 @@ private:
|
|||
|
||||
temp.u |= (e << 52) & 0x7FF0000000000000ul;
|
||||
|
||||
if( nan )
|
||||
{
|
||||
temp.u |= 1;
|
||||
return temp.d;
|
||||
}
|
||||
|
||||
if( infinity )
|
||||
return temp.d;
|
||||
|
||||
|
@ -2600,7 +2632,12 @@ public:
|
|||
*/
|
||||
Big()
|
||||
{
|
||||
SetNan();
|
||||
info = TTMATH_BIG_NAN;
|
||||
|
||||
/*
|
||||
we're directly setting 'info' (instead of calling SetNan())
|
||||
in order to get rid of a warning saying that 'info' is uninitialized
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -2682,7 +2719,8 @@ public:
|
|||
output:
|
||||
return value:
|
||||
0 - ok and 'result' will be an object of type tstr_t which holds the value
|
||||
1 - if there was a carry
|
||||
1 - if there was a carry (shoudn't be in a normal situation - if is that means there
|
||||
is somewhere an error in the library)
|
||||
*/
|
||||
uint ToString( tstr_t & result,
|
||||
uint base = 10,
|
||||
|
@ -3100,7 +3138,7 @@ private:
|
|||
else
|
||||
was_carry = false;
|
||||
|
||||
new_man[i] = UInt<man>::DigitToChar( digit );
|
||||
new_man[i] = static_cast<char>( UInt<man>::DigitToChar(digit) );
|
||||
}
|
||||
|
||||
if( i<0 && was_carry )
|
||||
|
@ -3826,6 +3864,25 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsNearZero() const
|
||||
{
|
||||
// we should check the mantissas beforehand because sometimes we can have
|
||||
// a mantissa set to zero but in the exponent something another value
|
||||
// (maybe we've forgotten about calling CorrectZero() ?)
|
||||
if( mantissa.IsZero() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt<man> m(mantissa);
|
||||
|
||||
m.Rcr(man*3); // pi * thumb rule...
|
||||
|
||||
return(m.IsZero());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool operator<(const Big<exp,man> & ss2) const
|
||||
{
|
||||
|
@ -3857,6 +3914,14 @@ public:
|
|||
}
|
||||
|
||||
|
||||
bool operator^=(const Big<exp,man> & ss2) const
|
||||
{
|
||||
if( IsSign() != ss2.IsSign() )
|
||||
return false;
|
||||
|
||||
return AboutEqualWithoutSign( ss2 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool operator>(const Big<exp,man> & ss2) const
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* This file is a part of TTMath Mathematical Library
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||
*/
|
||||
|
@ -973,7 +973,7 @@ void Not(int sindex, int amount_of_args, ValueType & result)
|
|||
|
||||
void DegToRad(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
ErrorCode err;
|
||||
ErrorCode err = err_ok;
|
||||
|
||||
if( amount_of_args == 1 )
|
||||
{
|
||||
|
@ -1052,7 +1052,7 @@ void RadToGrad(int sindex, int amount_of_args, ValueType & result)
|
|||
|
||||
void DegToGrad(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
ErrorCode err;
|
||||
ErrorCode err = err_ok;
|
||||
|
||||
if( amount_of_args == 1 )
|
||||
{
|
||||
|
@ -1555,7 +1555,7 @@ int character;
|
|||
|
||||
do
|
||||
{
|
||||
result += character;
|
||||
result += static_cast<char>( character );
|
||||
character = * ++pstring;
|
||||
}
|
||||
while( (character>='a' && character<='z') ||
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 8
|
||||
#define TTMATH_REVISION_VER 4
|
||||
#define TTMATH_PRERELEASE_VER 1
|
||||
#define TTMATH_REVISION_VER 5
|
||||
#define TTMATH_PRERELEASE_VER 0
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -232,6 +232,16 @@ namespace ttmath
|
|||
|
||||
|
||||
|
||||
/*!
|
||||
this is a limit when calculating Karatsuba multiplication
|
||||
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
|
||||
the Karatsuba algorithm will use standard schoolbook multiplication
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#else
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||
#endif
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -75,9 +75,9 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
||||
{
|
||||
register uint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint * p2 = const_cast<uint*>(ss2.table);
|
||||
|
||||
// we don't have to use TTMATH_REFERENCE_ASSERT here
|
||||
// this algorithm doesn't require it
|
||||
|
@ -96,13 +96,13 @@ namespace ttmath
|
|||
sub eax,[c] // CF=c
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4+0]
|
||||
adc [ebx+edx*4+0],eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
|
@ -112,34 +112,27 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
uint dummy, dummy2;
|
||||
// this part should be compiled with gcc
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%ecx \n"
|
||||
|
||||
"xorl %%eax, %%eax \n"
|
||||
"movl %%eax, %%edx \n"
|
||||
"subl %%edi, %%eax \n"
|
||||
|
||||
"xorl %%edx, %%edx \n"
|
||||
"negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
|
||||
"1: \n"
|
||||
"movl (%%esi,%%edx,4),%%eax \n"
|
||||
"movl (%%esi,%%edx,4), %%eax \n"
|
||||
"adcl %%eax, (%%ebx,%%edx,4) \n"
|
||||
|
||||
"incl %%edx \n"
|
||||
"decl %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"setc %%al \n"
|
||||
"movzx %%al,%%edx \n"
|
||||
"adc %%ecx, %%ecx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "D" (c), "c" (b), "b" (p1), "S" (p2)
|
||||
: "%eax", "cc", "memory" );
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
@ -189,16 +182,16 @@ namespace ttmath
|
|||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
add [ebx+edx*4], eax
|
||||
jnc end
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
end:
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
|
@ -207,11 +200,10 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%eax \n"
|
||||
"push %%ecx \n"
|
||||
|
||||
"subl %%edx, %%ecx \n"
|
||||
|
||||
"1: \n"
|
||||
|
@ -227,12 +219,10 @@ namespace ttmath
|
|||
"setc %%al \n"
|
||||
"movzx %%al, %%edx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
"pop %%eax \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "a" (value), "c" (b), "0" (index), "b" (p1)
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "0" (index), "1" (value), "2" (b), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
@ -297,16 +287,16 @@ namespace ttmath
|
|||
mov eax, [x2]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
adc [ebx+edx*4+4], eax
|
||||
jnc end
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 0
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
end:
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
|
@ -338,12 +328,10 @@ namespace ttmath
|
|||
"setc %%al \n"
|
||||
"movzx %%al, %%eax \n"
|
||||
|
||||
"pop %%edx \n"
|
||||
"pop %%ecx \n"
|
||||
|
||||
: "=a" (c)
|
||||
: "c" (b), "d" (index), "b" (p1), "S" (x1), "0" (x2)
|
||||
: "=a" (c), "=c" (dummy), "=d" (dummy2)
|
||||
: "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
@ -353,6 +341,131 @@ namespace ttmath
|
|||
|
||||
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// this part might be compiled with for example visual c
|
||||
__asm
|
||||
{
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
||||
mov esi, [ss1]
|
||||
mov ebx, [ss2]
|
||||
mov edi, [result]
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
adc eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx // ecx has the cf state
|
||||
|
||||
mov ebx, [rest]
|
||||
or ebx, ebx
|
||||
jz ttmath_end
|
||||
|
||||
xor ebx, ebx // ebx = 0
|
||||
neg ecx // setting cf from ecx
|
||||
mov ecx, [rest] // ecx is != 0
|
||||
|
||||
ttmath_loop2:
|
||||
mov eax, [esi+edx*4]
|
||||
adc eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
adc ecx, ecx
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
// this part should be compiled with gcc
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"push %%edx \n"
|
||||
"xor %%edx, %%edx \n" // edx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%esi,%%edx,4), %%eax \n"
|
||||
"adc (%%ebx,%%edx,4), %%eax \n"
|
||||
"mov %%eax, (%%edi,%%edx,4) \n"
|
||||
|
||||
"inc %%edx \n"
|
||||
"dec %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%ecx, %%ecx \n" // ecx has the cf state
|
||||
"pop %%eax \n" // eax = rest
|
||||
|
||||
"or %%eax, %%eax \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%ebx, %%ebx \n" // ebx = 0
|
||||
"neg %%ecx \n" // setting cf from ecx
|
||||
"mov %%eax, %%ecx \n" // ecx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%esi, %%edx, 4), %%eax \n"
|
||||
"adc %%ebx, %%eax \n"
|
||||
"mov %%eax, (%%edi, %%edx, 4) \n"
|
||||
|
||||
"inc %%edx \n"
|
||||
"dec %%ecx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%ecx, %%ecx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -366,9 +479,9 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
||||
{
|
||||
register uint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint * p2 = const_cast<uint*>(ss2.table);
|
||||
|
||||
// we don't have to use TTMATH_REFERENCE_ASSERT here
|
||||
// this algorithm doesn't require it
|
||||
|
@ -387,13 +500,13 @@ namespace ttmath
|
|||
sub eax, [c]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
sbb [ebx+edx*4], eax
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
|
@ -404,30 +517,26 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
"push %%ecx \n"
|
||||
|
||||
"xorl %%eax, %%eax \n"
|
||||
"movl %%eax, %%edx \n"
|
||||
"subl %%edi, %%eax \n"
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"xorl %%edx, %%edx \n"
|
||||
"negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
|
||||
"1: \n"
|
||||
"movl (%%esi,%%edx,4),%%eax \n"
|
||||
"movl (%%esi,%%edx,4), %%eax \n"
|
||||
"sbbl %%eax, (%%ebx,%%edx,4) \n"
|
||||
|
||||
"incl %%edx \n"
|
||||
"decl %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"setc %%al \n"
|
||||
"movzx %%al,%%edx \n"
|
||||
"adc %%ecx, %%ecx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "D" (c), "c" (b), "b" (p1), "S" (p2)
|
||||
: "%eax", "cc", "memory" );
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -479,16 +588,16 @@ namespace ttmath
|
|||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
sub [ebx+edx*4], eax
|
||||
jnc end
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
end:
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
|
@ -497,11 +606,10 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%eax \n"
|
||||
"push %%ecx \n"
|
||||
|
||||
"subl %%edx, %%ecx \n"
|
||||
|
||||
"1: \n"
|
||||
|
@ -517,12 +625,10 @@ namespace ttmath
|
|||
"setc %%al \n"
|
||||
"movzx %%al, %%edx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
"pop %%eax \n"
|
||||
|
||||
: "=d" (c)
|
||||
: "a" (value), "c" (b), "0" (index), "b" (p1)
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "0" (index), "1" (value), "2" (b), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubInt")
|
||||
|
@ -532,6 +638,141 @@ namespace ttmath
|
|||
|
||||
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// this part might be compiled with for example visual c
|
||||
|
||||
/*
|
||||
the asm code is nearly the same as in AddVector
|
||||
only two instructions 'adc' are changed to 'sbb'
|
||||
*/
|
||||
__asm
|
||||
{
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
||||
mov esi, [ss1]
|
||||
mov ebx, [ss2]
|
||||
mov edi, [result]
|
||||
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
sbb eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx // ecx has the cf state
|
||||
|
||||
mov ebx, [rest]
|
||||
or ebx, ebx
|
||||
jz ttmath_end
|
||||
|
||||
xor ebx, ebx // ebx = 0
|
||||
neg ecx // setting cf from ecx
|
||||
mov ecx, [rest] // ecx is != 0
|
||||
|
||||
ttmath_loop2:
|
||||
mov eax, [esi+edx*4]
|
||||
sbb eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
adc ecx, ecx
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
// this part should be compiled with gcc
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"push %%edx \n"
|
||||
"xor %%edx, %%edx \n" // edx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%esi,%%edx,4), %%eax \n"
|
||||
"sbb (%%ebx,%%edx,4), %%eax \n"
|
||||
"mov %%eax, (%%edi,%%edx,4) \n"
|
||||
|
||||
"inc %%edx \n"
|
||||
"dec %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%ecx, %%ecx \n" // ecx has the cf state
|
||||
"pop %%eax \n" // eax = rest
|
||||
|
||||
"or %%eax, %%eax \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%ebx, %%ebx \n" // ebx = 0
|
||||
"neg %%ecx \n" // setting cf from ecx
|
||||
"mov %%eax, %%ecx \n" // ecx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%esi, %%edx, 4), %%eax \n"
|
||||
"sbb %%ebx, %%eax \n"
|
||||
"mov %%eax, (%%edi, %%edx, 4) \n"
|
||||
|
||||
"inc %%edx \n"
|
||||
"dec %%ecx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%ecx, %%ecx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
|
@ -547,8 +788,8 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
uint UInt<value_size>::Rcl2_one(uint c)
|
||||
{
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
|
@ -562,12 +803,12 @@ namespace ttmath
|
|||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
rcl dword ptr [ebx+edx*4], 1
|
||||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
|
@ -577,13 +818,12 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%edx \n"
|
||||
"push %%ecx \n"
|
||||
|
||||
"xorl %%edx, %%edx \n" // edx=0
|
||||
"neg %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0
|
||||
"negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0
|
||||
|
||||
"1: \n"
|
||||
"rcll $1, (%%ebx, %%edx, 4) \n"
|
||||
|
@ -592,15 +832,12 @@ namespace ttmath
|
|||
"decl %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"setc %%al \n"
|
||||
"movzx %%al, %%eax \n"
|
||||
"adcl %%ecx, %%ecx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
"pop %%edx \n"
|
||||
|
||||
: "=a" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Rcl2_one")
|
||||
|
@ -625,8 +862,8 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
uint UInt<value_size>::Rcr2_one(uint c)
|
||||
{
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
|
@ -638,11 +875,11 @@ namespace ttmath
|
|||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
rcr dword ptr [ebx+ecx*4-4], 1
|
||||
|
||||
dec ecx
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
|
@ -652,11 +889,11 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%ecx \n"
|
||||
|
||||
"neg %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0
|
||||
"negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0
|
||||
|
||||
"1: \n"
|
||||
"rcrl $1, -4(%%ebx, %%ecx, 4) \n"
|
||||
|
@ -664,14 +901,12 @@ namespace ttmath
|
|||
"decl %%ecx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"setc %%al \n"
|
||||
"movzx %%al, %%eax \n"
|
||||
"adcl %%ecx, %%ecx \n"
|
||||
|
||||
"pop %%ecx \n"
|
||||
|
||||
: "=a" (c)
|
||||
: "0" (c), "c" (b), "b" (p1)
|
||||
: "=c" (c), "=a" (dummy)
|
||||
: "0" (b), "1" (c), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Rcr2_one")
|
||||
|
@ -724,7 +959,7 @@ namespace ttmath
|
|||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
rol dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
|
@ -735,7 +970,7 @@ namespace ttmath
|
|||
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec edi
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
and eax, 1
|
||||
mov dword ptr [c], eax
|
||||
|
@ -744,31 +979,30 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%edx \n"
|
||||
"push %%esi \n"
|
||||
"push %%edi \n"
|
||||
"push %%ebp \n"
|
||||
|
||||
"movl %%ecx, %%esi \n"
|
||||
"movl $32, %%ecx \n"
|
||||
"subl %%esi, %%ecx \n"
|
||||
"movl $-1, %%edx \n"
|
||||
"shrl %%cl, %%edx \n"
|
||||
"movl %%edx, %[amask] \n"
|
||||
"subl %%esi, %%ecx \n" // ecx = 32 - bits
|
||||
"movl $-1, %%edx \n" // edx = -1 (all bits set to one)
|
||||
"shrl %%cl, %%edx \n" // shifting (0 -> edx -> cf) (cl times)
|
||||
"movl %%edx, %%ebp \n" // ebp = edx = mask
|
||||
"movl %%esi, %%ecx \n"
|
||||
|
||||
"xorl %%edx, %%edx \n"
|
||||
"movl %%edx, %%esi \n"
|
||||
|
||||
"orl %%eax, %%eax \n"
|
||||
"cmovnz %[amask], %%esi \n"
|
||||
"cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0
|
||||
|
||||
"1: \n"
|
||||
"roll %%cl, (%%ebx,%%edx,4) \n"
|
||||
|
||||
"movl (%%ebx,%%edx,4), %%eax \n"
|
||||
"andl %[amask], %%eax \n"
|
||||
"andl %%ebp, %%eax \n"
|
||||
"xorl %%eax, (%%ebx,%%edx,4) \n"
|
||||
"orl %%esi, (%%ebx,%%edx,4) \n"
|
||||
"movl %%eax, %%esi \n"
|
||||
|
@ -779,13 +1013,12 @@ namespace ttmath
|
|||
|
||||
"and $1, %%eax \n"
|
||||
|
||||
"pop %%edi \n"
|
||||
"pop %%esi \n"
|
||||
"pop %%edx \n"
|
||||
"pop %%ebp \n"
|
||||
|
||||
: "=a" (c)
|
||||
: "0" (c), "D" (b), "b" (p1), "c" (bits), [amask] "m" (mask)
|
||||
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
@ -813,9 +1046,9 @@ namespace ttmath
|
|||
{
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint mask;
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
|
@ -841,7 +1074,7 @@ namespace ttmath
|
|||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
p:
|
||||
ttmath_loop:
|
||||
ror dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
|
@ -852,7 +1085,7 @@ namespace ttmath
|
|||
|
||||
dec edx
|
||||
dec edi
|
||||
jnz p
|
||||
jnz ttmath_loop
|
||||
|
||||
rol eax, 1 // bit 31 will be bit 0
|
||||
and eax, 1
|
||||
|
@ -863,33 +1096,32 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%edx \n"
|
||||
"push %%esi \n"
|
||||
"push %%edi \n"
|
||||
"push %%ebp \n"
|
||||
|
||||
"movl %%ecx, %%esi \n"
|
||||
"movl $32, %%ecx \n"
|
||||
"subl %%esi, %%ecx \n"
|
||||
"movl $-1, %%edx \n"
|
||||
"shll %%cl, %%edx \n"
|
||||
"movl %%edx, %[amask] \n"
|
||||
"subl %%esi, %%ecx \n" // ecx = 32 - bits
|
||||
"movl $-1, %%edx \n" // edx = -1 (all bits set to one)
|
||||
"shll %%cl, %%edx \n" // shifting (cf <- edx <- 0) (cl times)
|
||||
"movl %%edx, %%ebp \n" // ebp = edx = mask
|
||||
"movl %%esi, %%ecx \n"
|
||||
|
||||
"xorl %%edx, %%edx \n"
|
||||
"movl %%edx, %%esi \n"
|
||||
"addl %%edi, %%edx \n"
|
||||
"decl %%edx \n"
|
||||
|
||||
"decl %%edx \n" // edx is pointing at the end of the table (on last word)
|
||||
"orl %%eax, %%eax \n"
|
||||
"cmovnz %[amask], %%esi \n"
|
||||
"cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0
|
||||
|
||||
"1: \n"
|
||||
"rorl %%cl, (%%ebx,%%edx,4) \n"
|
||||
|
||||
"movl (%%ebx,%%edx,4), %%eax \n"
|
||||
"andl %[amask], %%eax \n"
|
||||
"andl %%ebp, %%eax \n"
|
||||
"xorl %%eax, (%%ebx,%%edx,4) \n"
|
||||
"orl %%esi, (%%ebx,%%edx,4) \n"
|
||||
"movl %%eax, %%esi \n"
|
||||
|
@ -901,13 +1133,12 @@ namespace ttmath
|
|||
"roll $1, %%eax \n"
|
||||
"andl $1, %%eax \n"
|
||||
|
||||
"pop %%edi \n"
|
||||
"pop %%esi \n"
|
||||
"pop %%edx \n"
|
||||
"pop %%ebp \n"
|
||||
|
||||
: "=a" (c)
|
||||
: "0" (c), "D" (b), "b" (p1), "c" (bits), [amask] "m" (mask)
|
||||
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
@ -939,16 +1170,17 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
__asm__ __volatile__(
|
||||
uint dummy;
|
||||
|
||||
"bsrl %1, %0 \n"
|
||||
"jnz 1f \n"
|
||||
"movl $-1, %0 \n"
|
||||
"1: \n"
|
||||
__asm__ (
|
||||
|
||||
: "=R" (result)
|
||||
: "R" (x)
|
||||
: "cc" );
|
||||
"movl $-1, %1 \n"
|
||||
"bsrl %2, %0 \n"
|
||||
"cmovz %1, %0 \n"
|
||||
|
||||
: "=r" (result), "=&r" (dummy)
|
||||
: "r" (x)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -974,8 +1206,8 @@ namespace ttmath
|
|||
{
|
||||
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
|
||||
|
||||
uint v = value;
|
||||
uint old_bit;
|
||||
uint v = value;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
|
@ -993,17 +1225,16 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ __volatile__(
|
||||
__asm__ (
|
||||
|
||||
"btsl %%ebx, %%eax \n"
|
||||
|
||||
"setc %%bl \n"
|
||||
"movzx %%bl, %%ebx \n"
|
||||
|
||||
: "=a" (v), "=b" (old_bit)
|
||||
: "0" (v), "1" (bit)
|
||||
: "0" (v), "1" (bit)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
||||
value = v;
|
||||
|
@ -1031,8 +1262,8 @@ namespace ttmath
|
|||
this has no effect in visual studio but it's useful when
|
||||
using gcc and options like -Ox
|
||||
*/
|
||||
register uint result1_;
|
||||
register uint result2_;
|
||||
uint result1_;
|
||||
uint result2_;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
|
@ -1050,12 +1281,12 @@ namespace ttmath
|
|||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ __volatile__(
|
||||
__asm__ (
|
||||
|
||||
"mull %%edx \n"
|
||||
|
||||
: "=a" (result1_), "=d" (result2_)
|
||||
: "0" (a), "1" (b)
|
||||
: "0" (a), "1" (b)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
@ -1093,8 +1324,8 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
|
||||
{
|
||||
register uint r_;
|
||||
register uint rest_;
|
||||
uint r_;
|
||||
uint rest_;
|
||||
/*
|
||||
these variables have similar meaning like those in
|
||||
the multiplication algorithm MulTwoWords
|
||||
|
@ -1117,12 +1348,12 @@ namespace ttmath
|
|||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ __volatile__(
|
||||
__asm__ (
|
||||
|
||||
"divl %%ecx \n"
|
||||
|
||||
: "=a" (r_), "=d" (rest_)
|
||||
: "d" (a), "a" (b), "c" (c)
|
||||
: "0" (b), "1" (a), "c" (c)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -911,6 +911,131 @@ namespace ttmath
|
|||
*rest = rest_;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
uint temp;
|
||||
|
||||
if( carry == 0 )
|
||||
{
|
||||
temp = a + b;
|
||||
|
||||
if( temp < a )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
temp = a + b + carry;
|
||||
|
||||
if( temp > a ) // !(temp<=a)
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
*result = temp;
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
if( carry == 0 )
|
||||
{
|
||||
*result = a - b;
|
||||
|
||||
if( a < b )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
*result = a - b - carry;
|
||||
|
||||
if( a > b ) // !(a <= b )
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
|
|
Loading…
Reference in New Issue