diff --git a/CHANGELOG b/CHANGELOG index 1f90bbb..e83b27e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,8 +34,10 @@ Version 0.9.1 prerelease (2009.12.28): - and the exponent is smaller than about 2 times the number of bits from the mantissa this helps to correctly calculate expressions such as: "0.80-3*0.34+0.22" now the parser gives zero (previous there was a value very closed to zero) + * added: static sint UInt::FindLowestBitInWord(uint x) + this method is looking for the lowest set bit in a word * added: UInt::FindLowestBit(uint & table_id, uint & index) - /temporarily version - asm version is missing / + this method is looking for the lowest set bit Version 0.9.0 (2009.11.25): diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index 52d662c..5f3e3e2 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -672,27 +672,14 @@ public: if( table_id >= value_size ) { // is zero - index = 0; + index = 0; table_id = 0; return false; } // table[table_id] is different from 0 - - // !! need asm version: - // index = FindSmallestBitInWord( table[table_id] ); - - index = 0; - uint temp = table[table_id]; - - while( (temp & 1) == 0 ) - { - index += 1; - temp >>= 1; - } - - // !! + index = FindLowestBitInWord( table[table_id] ); return true; } @@ -3498,6 +3485,7 @@ public: uint SubInt(uint value, uint index = 0); static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); static sint FindLeadingBitInWord(uint x); + static sint FindLowestBitInWord(uint x); static uint SetBitInWord(uint & value, uint bit); static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); diff --git a/ttmath/ttmathuint_noasm.h b/ttmath/ttmathuint_noasm.h index 9bda34e..ed3c180 100644 --- a/ttmath/ttmathuint_noasm.h +++ b/ttmath/ttmathuint_noasm.h @@ -588,6 +588,27 @@ namespace ttmath + /*! + this method returns the number of the highest set bit in x + if the 'x' is zero this method returns '-1' + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + if( x == 0 ) + return -1; + + uint bit = 0; + + while( (x & 1) == 0 ) + { + x = x >> 1; + ++bit; + } + + return bit; + } + /*! diff --git a/ttmath/ttmathuint_x86.h b/ttmath/ttmathuint_x86.h index 1b91ce4..1dd087f 100644 --- a/ttmath/ttmathuint_x86.h +++ b/ttmath/ttmathuint_x86.h @@ -1353,6 +1353,50 @@ namespace ttmath + /* + this method returns the number of the smallest set bit in one 32-bit word + if the 'x' is zero this method returns '-1' + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + sint result; + + #ifndef __GNUC__ + __asm + { + push eax + push edx + + mov edx,-1 + bsf eax,[x] + cmovz eax,edx + mov [result], eax + + pop edx + pop eax + } + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movl $-1, %1 \n" + "bsfl %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + return result; + } + /*! diff --git a/ttmath/ttmathuint_x86_64.h b/ttmath/ttmathuint_x86_64.h index 7660b20..2fedb70 100644 --- a/ttmath/ttmathuint_x86_64.h +++ b/ttmath/ttmathuint_x86_64.h @@ -987,6 +987,55 @@ namespace ttmath } + /* + this method returns the number of the highest set bit in one 64-bit word + if the 'x' is zero this method returns '-1' + + ***this method is created only on a 64bit platform*** + */ + template + sint UInt::FindLowestBitInWord(uint x) + { + sint result; + + + #if !defined(__GNUC__) && !defined(_MSC_VER) + #error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" + #endif + + + #ifdef _MSC_VER + + unsigned long nIndex = 0; + + if( _BitScanForward64(&nIndex,x) == 0 ) + result = -1; + else + result = nIndex; + + #endif + + + #ifdef __GNUC__ + uint dummy; + + __asm__ ( + + "movq $-1, %1 \n" + "bsfq %2, %0 \n" + "cmovz %1, %0 \n" + + : "=r" (result), "=&r" (dummy) + : "r" (x) + : "cc" ); + + #endif + + + return result; + } + + /*! this method sets a special bit in the 'value' and returns the last state of the bit (zero or one)