fixed: there was a TTMATH_REREFENCE_ASSERT error in Big::PowUInt() caused by: start.Mul(start)

fixed:   Big::Add incorrectly rounded 'this' when both exponents were equal
         it caused that sometimes when adding a zero the result has changed
         this had impact among other things on FromString() method
         "0,8" had different binary representation from "0,80"
changed: renamed: Big::PowUInt(UInt<pow_size> pow) -> Big::Pow(UInt<pow_size> pow)
         it returns 2 when there is: 0^0
changed: renamed: Big::PowInt(Int<pow_size> pow) -> Big::Pow(Int<pow_size> pow)
         it returns 2 when there is: 0^0 or 0^(-something)
changed: renamed: Big::PowBUInt() -> PowUInt(), Big::PowBInt() -> Big::PowInt()
         they return 2 when the arguments are incorrect (like above)
changed: UInt::SetBitInWord(uint & value, uint bit) is taking the first argument by a reference now,
         the specific bit is set in the 'value' and the method returns the last state of the bit (zero or one)
added:   UInt::GetBit(uint bit_index) - returning the state of the specific bit
changed: UInt::SetBit(uint bit_index) - it's using TTMATH_ASSERT now
changed: Big::Mod2() - it's using mantissa.GetBit() now
added:   Big::operator=(double) and Big::Big(double)
added:   TTMATH_ASSERT somewhere in ttmathuint64.h
added:   UInt::Pow(UInt<value_size> pow) and Int::Pow(Int<value_size> pow)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@104 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2009-03-11 19:05:13 +00:00
parent 404727f3de
commit 978815f12d
8 changed files with 337 additions and 107 deletions

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -59,7 +59,52 @@ void test_uint()
int main() int main()
{ {
using namespace ttmath; using namespace ttmath;
/*
Int<300> uu, oo;
uu = -2;
oo = 5;
uint ccc = uu.Pow(oo);
if( ccc )
std::cout << "carry: " << ccc << std::endl;
else
std::cout << uu << std::endl;
return 0;
*/
/*
UInt<2> w = 100;
w.GetBit(64);
std::cout << w << std::endl;
return 0;
*/
/*
uint q = 100;
uint last = UInt<3>::SetBitInWord(q, 3);
std::cout << "nowa wartosc: " << q << ", wczesniejszy bit: " << last << std::endl;
return 0;
*/
/*
Big<1, 3> a = -26;
Int<3> b = -8;
uint c = a.Pow(b);
if ( c )
std::cout << "carry: " << c << std::endl;
else
std::cout << a << std::endl;
return 0;
*/
test_uint(); test_uint();

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -561,9 +561,9 @@ public:
} }
if( exp_offset > mantissa_size_in_bits ) if( exp_offset >= mantissa_size_in_bits )
{ {
// the second value is too short for taking into consideration in the sum // the second value is too small for taking into consideration in the sum
return 0; return 0;
} }
else else
@ -572,13 +572,6 @@ public:
// (2) moving 'exp_offset' times // (2) moving 'exp_offset' times
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
} }
else
{
// (3)
// exp_offset == mantissa_size_in_bits
// we're rounding 'this' about one (up or down depending on a ss2 sign)
ss2.mantissa.SetOne();
}
if( IsSign() == ss2.IsSign() ) if( IsSign() == ss2.IsSign() )
@ -594,8 +587,8 @@ public:
{ {
// values have different signs // values have different signs
// there shouldn't be a carry here because // there shouldn't be a carry here because
// (1) (2) and (3) guarantee that the mantissa of this // (1) (2) guarantee that the mantissa of this
// is greater than the mantissa of the ss2 // is greater than or equal to the mantissa of the ss2
uint c_temp = mantissa.Sub(ss2.mantissa); uint c_temp = mantissa.Sub(ss2.mantissa);
TTMATH_ASSERT( c_temp == 0 ) TTMATH_ASSERT( c_temp == 0 )
@ -653,7 +646,7 @@ public:
if( exp_offset >= mantissa_size_in_bits ) if( exp_offset >= mantissa_size_in_bits )
{ {
// the second value is too short // the second value is too small
SetZero(); SetZero();
return 0; return 0;
} }
@ -700,7 +693,7 @@ public:
} }
if( exp_offset >= mantissa_size_in_bits ) if( exp_offset >= mantissa_size_in_bits )
// the second value is too short // the second value is too small
return 0; return 0;
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
@ -745,7 +738,7 @@ public:
} }
if( exp_offset >= mantissa_size_in_bits ) if( exp_offset >= mantissa_size_in_bits )
// the second value is too short // the second value is too small
return 0; return 0;
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
@ -966,18 +959,23 @@ public:
/*! /*!
power this = this ^ pow power this = this ^ pow
pow without a sign (pow without a sign)
binary algorithm (r-to-l) binary algorithm (r-to-l)
return values:
0 - ok
1 - carry
2 - incorrect arguments (0^0)
*/ */
template<uint pow_size> template<uint pow_size>
uint PowUInt(UInt<pow_size> pow) uint Pow(UInt<pow_size> pow)
{ {
if(pow.IsZero() && IsZero()) if(pow.IsZero() && IsZero())
// we don't define zero^zero // we don't define zero^zero
return 1; return 2;
Big<exp, man> start(*this); Big<exp, man> start(*this), start_temp;
Big<exp, man> result; Big<exp, man> result;
result.SetOne(); result.SetOne();
@ -987,7 +985,8 @@ public:
if( result.Mul(start) ) if( result.Mul(start) )
return 1; return 1;
if( start.Mul(start) ) start_temp = start;
if( start.Mul(start_temp) )
return 1; return 1;
pow.Rcr(1); pow.Rcr(1);
@ -1001,27 +1000,31 @@ public:
/*! /*!
power this = this ^ pow power this = this ^ pow
p can be with a sign
p can be negative p can be negative
return values:
0 - ok
1 - carry
2 - incorrect arguments 0^0 or 0^(-something)
*/ */
template<uint pow_size> template<uint pow_size>
uint PowInt(Int<pow_size> pow) uint Pow(Int<pow_size> pow)
{ {
if( !pow.IsSign() ) if( !pow.IsSign() )
return PowUInt(pow); return Pow( UInt<pow_size>(pow) );
if( IsZero() ) if( IsZero() )
// if 'p' is negative then // if 'p' is negative then
// 'this' must be different from zero // 'this' must be different from zero
return 1; return 2;
if( pow.ChangeSign() ) if( pow.ChangeSign() )
return 1; return 1;
Big<exp, man> t(*this); Big<exp, man> t(*this);
if( t.PowUInt(pow) ) uint c_temp = t.Pow( UInt<pow_size>(pow) );
return 1; if( c_temp > 0 )
return c_temp;
SetOne(); SetOne();
if( Div(t) ) if( Div(t) )
@ -1032,33 +1035,40 @@ public:
/*! /*!
this method returns true if 'this' mod 2 is equal one this method returns: 'this' mod 2
(either zero or one)
this method is much faster than using Mod( object_with_value_two )
*/ */
bool Mod2() const uint Mod2() const
{ {
if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) ) if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
return false; return 0;
sint exp_int = exponent.ToInt(); sint exp_int = exponent.ToInt();
// 'exp_int' is negative (or zero), we set its as positive // 'exp_int' is negative (or zero), we set it as positive
exp_int = -exp_int; exp_int = -exp_int;
// !!! here we'll use a new method (method for testing a bit) return mantissa.GetBit(exp_int);
uint value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
value >>= (uint(exp_int) % TTMATH_BITS_PER_UINT);
return bool(value & 1);
} }
/*! /*!
power this = this ^ abs([pow]) power this = this ^ abs([pow])
pow without a sign and without a fraction pow is treated as a value without a sign and without a fraction
if pow has a sign then the method pow.Abs() is used
if pow has a fraction the fraction is skipped (not used in calculation)
return values:
0 - ok
1 - carry
2 - incorrect arguments (0^0)
*/ */
uint PowBUInt(Big<exp, man> pow) uint PowUInt(Big<exp, man> pow)
{ {
if( pow.IsZero() && IsZero() ) if( pow.IsZero() && IsZero() )
return 1; return 2;
if( pow.IsSign() ) if( pow.IsSign() )
pow.Abs(); pow.Abs();
@ -1070,7 +1080,7 @@ public:
e_one.SetOne(); e_one.SetOne();
one.SetOne(); one.SetOne();
result.SetOne(); result = one;
while( pow >= one ) while( pow >= one )
{ {
@ -1093,24 +1103,30 @@ public:
/*! /*!
power this = this ^ [pow] power this = this ^ [pow]
pow without a fraction pow is treated as a value without a fraction
pow can be negative pow can be negative
return values:
0 - ok
1 - carry
2 - incorrect arguments 0^0 or 0^(-something)
*/ */
uint PowBInt(const Big<exp, man> & pow) uint PowInt(const Big<exp, man> & pow)
{ {
TTMATH_REFERENCE_ASSERT( pow ) TTMATH_REFERENCE_ASSERT( pow )
if( !pow.IsSign() ) if( !pow.IsSign() )
return PowBUInt(pow); return PowUInt(pow);
if( IsZero() ) if( IsZero() )
// if 'pow' is negative then // if 'pow' is negative then
// 'this' must be different from zero // 'this' must be different from zero
return 1; return 2;
Big<exp, man> temp(*this); Big<exp, man> temp(*this);
if( temp.PowBUInt(pow) ) uint c_temp = temp.PowUInt(pow);
return 1; if( c_temp > 0 )
return c_temp;
SetOne(); SetOne();
if( Div(temp) ) if( Div(temp) )
@ -1122,13 +1138,13 @@ public:
/*! /*!
power this = this ^ pow power this = this ^ pow
this *must* be greater than zero (this > 0) this must be greater than zero (this > 0)
pow can be negative and with fraction pow can be negative and with fraction
return values: return values:
0 - ok 0 - ok
1 - carry 1 - carry
2 - incorrect argument ('this') 2 - incorrect argument ('this' <= 0)
*/ */
uint PowFrac(const Big<exp, man> & pow) uint PowFrac(const Big<exp, man> & pow)
{ {
@ -1147,6 +1163,7 @@ public:
} }
/*! /*!
power this = this ^ pow power this = this ^ pow
pow can be negative and with fraction pow can be negative and with fraction
@ -1175,7 +1192,7 @@ public:
pow_frac.RemainFraction(); pow_frac.RemainFraction();
if( pow_frac.IsZero() ) if( pow_frac.IsZero() )
return PowBInt( pow ); return PowInt( pow );
// pow is with fraction (not integer) // pow is with fraction (not integer)
// result = e^(pow * ln(this) ) where 'this' must be greater than 0 // result = e^(pow * ln(this) ) where 'this' must be greater than 0
@ -1318,7 +1335,7 @@ public:
else else
{ {
ExpSurrounding0(m); ExpSurrounding0(m);
c += PowBUInt(e_); c += PowUInt(e_);
} }
return (c==0)? 0 : 1; return (c==0)? 0 : 1;
@ -1793,7 +1810,7 @@ public:
// where "1.F" is intended to represent the binary number // where "1.F" is intended to represent the binary number
// created by prefixing F with an implicit leading 1 and a binary point. // created by prefixing F with an implicit leading 1 and a binary point.
FromDouble_SetExpAndMan(bool(temp.u[1] & 0x80000000u), FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u, e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
m1, m2); m1, m2);
@ -1815,7 +1832,7 @@ public:
m.table[0] = m2; m.table[0] = m2;
uint moved = m.CompensationToLeft(); uint moved = m.CompensationToLeft();
FromDouble_SetExpAndMan(bool(temp.u[1] & 0x80000000u), FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0, e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
m.table[1], m.table[2]); m.table[1], m.table[2]);
} }
@ -1906,7 +1923,7 @@ public:
// where "1.F" is intended to represent the binary number // where "1.F" is intended to represent the binary number
// created by prefixing F with an implicit leading 1 and a binary point. // created by prefixing F with an implicit leading 1 and a binary point.
FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul), FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
e - 1023 - man*TTMATH_BITS_PER_UINT + 1, e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
0x8000000000000000ul, m); 0x8000000000000000ul, m);
@ -2118,6 +2135,17 @@ public:
} }
/*!
an operator= for converting 'double' to this class
*/
Big<exp, man> & operator=(double value)
{
FromDouble(value);
return *this;
}
/*! /*!
a constructor for converting 'sint' to this class a constructor for converting 'sint' to this class
*/ */
@ -2135,6 +2163,15 @@ public:
} }
/*!
a constructor for converting 'double' to this class
*/
Big(double value)
{
FromDouble(value);
}
#ifdef TTMATH_PLATFORM64 #ifdef TTMATH_PLATFORM64
/*! /*!
@ -3324,7 +3361,7 @@ private:
new_exponent.ChangeSign(); new_exponent.ChangeSign();
temp = 10; temp = 10;
c += temp.PowBInt( new_exponent ); c += temp.PowInt( new_exponent );
c += Mul(temp); c += Mul(temp);
return (c==0)? 0 : 1; return (c==0)? 0 : 1;

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -469,6 +469,70 @@ public:
private:
/*!
power this = this ^ pow
this can be negative
pow is >= 0
*/
uint Pow2(const Int<value_size> & pow)
{
bool was_sign = IsSign();
uint c = 0;
if( was_sign )
c += Abs();
uint c_temp = UInt<value_size>::Pow(pow);
if( c_temp > 0 )
return c_temp; // c_temp can be: 0, 1 or 2
if( was_sign && (pow.table[0] & 1) == 1 )
// negative value to the power of odd number is negative
c += ChangeSign();
return (c==0)? 0 : 1;
}
public:
/*!
power this = this ^ pow
return values:
0 - ok
1 - carry
2 - incorrect arguments 0^0 or 0^(-something)
*/
uint Pow(Int<value_size> pow)
{
if( !pow.IsSign() )
return Pow2(pow);
if( UInt<value_size>::IsZero() )
// if 'p' is negative then
// 'this' must be different from zero
return 2;
if( pow.ChangeSign() )
return 1;
Int<value_size> t(*this);
uint c_temp = t.Pow2(pow);
if( c_temp > 0 )
return c_temp;
UInt<value_size>::SetOne();
if( Div(t) )
return 1;
return 0;
}
/*! /*!
* *

View File

@ -64,8 +64,8 @@
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 2 #define TTMATH_REVISION_VER 3
#define TTMATH_PRERELEASE_VER 0 #define TTMATH_PRERELEASE_VER 1
/*! /*!

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -950,9 +950,6 @@ private:
*/ */
uint Rcl2(uint bits, uint c) uint Rcl2(uint bits, uint c)
{ {
if( bits == 0 )
return 0;
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT ) TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
register sint b = value_size; register sint b = value_size;
@ -1078,9 +1075,6 @@ private:
*/ */
uint Rcr2(uint bits, uint c) uint Rcr2(uint bits, uint c)
{ {
if( bits == 0 )
return 0;
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT ) TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
register sint b = value_size; register sint b = value_size;
@ -1503,30 +1497,40 @@ public:
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
/*! /*!
this method sets a special bit in the 'value' this method sets a special bit in the 'value'
and returns the result and returns the last state of the bit (zero or one)
bit is from <0,31> bit is from <0,31>
e.g. e.g.
SetBitInWord(0,0) = 1 uint x = 100;
SetBitInWord(0,2) = 4 uint bit = SetBitInWord(x, 3);
SetBitInWord(10, 8) = 266 now: x = 108 and bit = 0
*/ */
static uint SetBitInWord(uint value, uint bit) static uint SetBitInWord(uint & value, uint bit)
{ {
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
uint old_bit;
uint v = value;
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push ebx push ebx
push eax push eax
mov eax, [value]
mov eax, [v]
mov ebx, [bit] mov ebx, [bit]
bts eax, ebx bts eax, ebx
mov [value], eax mov [v], eax
setc bl
movzx ebx, bl
mov [old_bit], ebx
pop eax pop eax
pop ebx pop ebx
} }
@ -1536,15 +1540,20 @@ public:
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"btsl %2,%0 \n" "btsl %%ebx, %%eax \n"
: "=R" (value) "setc %%bl \n"
: "0" (value), "R" (bit) "movzx %%bl, %%ebx \n"
: "=a" (v), "=b" (old_bit)
: "0" (v), "1" (bit)
: "cc" ); : "cc" );
#endif #endif
return value; value = v;
return old_bit;
} }
#endif #endif
@ -1555,15 +1564,33 @@ public:
bit_index bigger or equal zero bit_index bigger or equal zero
*/ */
void SetBit(uint bit_index) uint GetBit(uint bit_index) const
{ {
TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
uint index = bit_index / TTMATH_BITS_PER_UINT; uint index = bit_index / TTMATH_BITS_PER_UINT;
if( index >= value_size ) uint bit = bit_index % TTMATH_BITS_PER_UINT;
return;
bit_index %= TTMATH_BITS_PER_UINT; uint temp = table[index];
return SetBitInWord(temp, bit);
}
table[index] = SetBitInWord(table[index], bit_index);
/*!
setting the 'bit_index' bit
and returning the last state of the bit
bit_index bigger or equal zero
*/
uint SetBit(uint bit_index)
{
TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT )
uint index = bit_index / TTMATH_BITS_PER_UINT;
uint bit = bit_index % TTMATH_BITS_PER_UINT;
return SetBitInWord(table[index], bit);
} }
@ -2736,6 +2763,47 @@ private:
public: public:
/*!
power this = this ^ pow
binary algorithm (r-to-l)
return values:
0 - ok
1 - carry or
2 - incorrect argument (0^0)
*/
uint Pow(UInt<value_size> pow)
{
if(pow.IsZero() && IsZero())
// we don't define zero^zero
return 2;
UInt<value_size> start(*this), start_temp;
UInt<value_size> result;
result.SetOne();
while( !pow.IsZero() )
{
if( pow.table[0] & 1 )
if( result.Mul(start) )
return 1;
start_temp = start;
// in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there)
if( start.Mul(start_temp) )
return 1;
pow.Rcr2_one(0);
}
*this = result;
return 0;
}
/*! /*!
this method sets n first bits to value zero this method sets n first bits to value zero
@ -3607,7 +3675,7 @@ public:
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);
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);
static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest);

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2008, Tomasz Sowa * Copyright (c) 2006-2009, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -210,10 +210,12 @@ namespace ttmath
register uint * p2 = const_cast<uint*>(ss2.table); register uint * p2 = const_cast<uint*>(ss2.table);
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
/* /*
@ -281,6 +283,8 @@ namespace ttmath
register uint * p1 = table; register uint * p1 = table;
register uint c; register uint c;
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
@ -361,6 +365,8 @@ namespace ttmath
register uint * p1 = table; register uint * p1 = table;
register uint c; register uint c;
TTMATH_ASSERT( index < value_size - 1 )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
@ -424,6 +430,9 @@ namespace ttmath
register uint * p1 = table; register uint * p1 = table;
register uint * p2 = const_cast<uint*>(ss2.table); register uint * p2 = const_cast<uint*>(ss2.table);
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
@ -489,6 +498,8 @@ namespace ttmath
register uint * p1 = table; register uint * p1 = table;
register uint c; register uint c;
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
@ -559,8 +570,8 @@ namespace ttmath
"push %%rdx \n" "push %%rdx \n"
"push %%rcx \n" "push %%rcx \n"
"xorq %%rdx, %%rdx \n" // edx=0 "xorq %%rdx, %%rdx \n" // rdx=0
"neg %%rax \n" // CF=1 if eax!=0 , CF=0 if eax==0 "neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rclq $1, (%%rbx, %%rdx, 8) \n" "rclq $1, (%%rbx, %%rdx, 8) \n"
@ -616,7 +627,7 @@ namespace ttmath
"push %%rcx \n" "push %%rcx \n"
"neg %%rax \n" // CF=1 if eax!=0 , CF=0 if eax==0 "neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n" "1: \n"
"rcrq $1, -8(%%rbx, %%rcx, 8) \n" "rcrq $1, -8(%%rbx, %%rcx, 8) \n"
@ -658,9 +669,6 @@ namespace ttmath
template<uint value_size> template<uint value_size>
uint UInt<value_size>::Rcl2(uint bits, 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 ) TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
register sint b = value_size; register sint b = value_size;
@ -739,9 +747,6 @@ namespace ttmath
template<uint value_size> template<uint value_size>
uint UInt<value_size>::Rcr2(uint bits, 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 ) TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
register sint b = value_size; register sint b = value_size;
@ -843,20 +848,26 @@ namespace ttmath
/*! /*!
this method sets a special bit in the 'value' this method sets a special bit in the 'value'
and returns the result and returns the last state of the bit (zero or one)
***this method is created only on a 64bit platform*** ***this method is created only on a 64bit platform***
bit is from <0,31> bit is from <0,63>
e.g. e.g.
SetBitInWord(0,0) = 1 uint x = 100;
SetBitInWord(0,2) = 4 uint bit = SetBitInWord(x, 3);
SetBitInWord(10, 8) = 266 now: x = 108 and bit = 0
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SetBitInWord(uint value, uint bit) uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
{ {
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
uint old_bit;
uint v = value;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
@ -864,15 +875,20 @@ namespace ttmath
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"btsq %%rbx,%%rax \n" "btsq %%rbx, %%rax \n"
: "=a" (value) "setc %%bl \n"
: "0" (value), "b" (bit) "movzx %%bl, %%rbx \n"
: "=a" (v), "=b" (old_bit)
: "0" (v), "1" (bit)
: "cc" ); : "cc" );
#endif #endif
return value; value = v;
return old_bit;
} }