15 Commits
0.9.0 ... 0.9.1

Author SHA1 Message Date
aeadb8a04a changed: version of the library: 0.9.1 now
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@286 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-07 18:17:24 +00:00
053861655d added: to samples: big2.cpp with TTMATH_BITS() macro
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@285 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-07 13:36:39 +00:00
35f2a8a28b the half-to-even rounding was turned off (some 'return' statement left)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@284 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-02 21:05:08 +00:00
d5a5ea1a7d removed: from Big::ToString() the feature with calculating how many valid digits there are
after the comma operator
         this was not correctly calculated - sometimes gives unexpected results,
         e.g. 0.5/2/2=0.125 (only one bit in the mantissa) gives 0.1 as the result
changed: cosmetic changes in Big::Add()




git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@283 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-02 21:02:10 +00:00
32b8c7a957 removed: from parser: SetSmallToZero(bool zero)
this was actually a bad feature


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@277 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-06 00:54:01 +00:00
e727eacce0 added: static sint UInt<value_size>::FindLowestBitInWord(uint x)
(asm_vc_32, asm_gcc_32, no_asm, and intrinsic for vc64)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@275 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-03 01:10:37 +00:00
39db6fc469 fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula:
new_exp_ = [log base (2^exponent)] + 1
       now the part '+ 1' is only made when the logarithm is positive and with fraction
       if the value is negative we can only skip the fraction, previously
       we lost some last digits from the new mantissa
       
       Consider this binary value (32 bit mantissa):
       (bin)1.0000000000000000000000000000011
       previously ToString() gave 1, now we have: 1.000000001



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@274 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-28 15:41:28 +00:00
0ada20b4cb fixed: added in the parser: operator's associativity
operator ^ (powering) is right-associative:
        sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24
        previously was: 2^3^4 = (2^3)^4 = 4096



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@273 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-25 22:06:49 +00:00
31563ce343 fixed: I have forgotten to remove rounding down from division (Big::div)
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@264 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-14 15:54:23 +00:00
418db51f46 added: to Big::Add Big::Sub Big::Mul Big::Div
second parameter 'bool round = true'
         the rounding is made if it is true
changed: in Big::ToString_CreateNewMantissaAndExponent()
         we should use dividing without rounding
         consider this 32 bit binary value:
         1.1111111111111111111111111111111
         previous the result from converting (to the base 10) was equal 2
         now is 1.999999
      



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@263 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-14 12:16:32 +00:00
82711f4441 fixed: Big::Add() should make the half-to-even rounding
by analizing the old ss2 parameter,
        and when it does substraction too
added:  UInt::AreFirstBitsZero(uint bits)
        returning true if first bits are cleared


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@262 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-12 20:45:18 +00:00
e5fc7a52e8 fixed: base rounding in Big::ToString
if the result were integer we shoud not round the value
          3.0001 should be 3.0001 and
          2.9999 should be 2.9999



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@259 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-06 23:18:05 +00:00
357524ae13 added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
floating point algorithms:
         Big::Add
         Big::Sub
         Big::Mul
         Big::Div



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@258 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-06 01:09:55 +00:00
72052420dd fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
         (this bug was introduced in 0.9.0)
added:   to Big::ToString() - additional rounding when conv.base_round is used
         if the value is not an integer we calculate how many valid digits there are
         after the comma operator (in conv.base radix) and then we skipped the rest
         digits, after skipping the base-rounding is made
         this helps to print values which have some last clear bits in the mantissa
         consider this 32 bit value:
         (binary)0.00011100001010001111010111000000000
         which has mantissa equal: (binary)11100001010001111010111000000000 (32 bits)
         previous the ToString() method gave: (decimal)0.10999999[...] 
         now we have: (decimal)0.11
added:   Parser::SetSmallToZero(bool zero) (default true)
         if true then the parser changes small values into zero
         small value means:
         - if the mantissa of the value consists only of one, two or three set bits
         - and these bits are next to each other
         - 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:   UInt::FindLowestBit(uint & table_id, uint & index)
         /temporary version - asm version is missing /



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@256 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-05 18:13:53 +00:00
321953e833 fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
       (this bug was introduced in 0.9.0)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@255 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-02 11:38:17 +00:00
14 changed files with 690 additions and 123 deletions

View File

@@ -1,3 +1,30 @@
Version 0.9.1 (2010.02.07):
* fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
(this bug was introduced in 0.9.0)
* fixed: added in the parser: operator's associativity
operator ^ (powering) is right-associative:
sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24
previously was: 2^3^4 = (2^3)^4 = 4096
* fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula:
new_exp_ = [log base (2^exponent)] + 1
now the part '+ 1' is only made when the logarithm is positive and with fraction
if the value is negative we can only skip the fraction, previously
we lost some last digits from the new mantissa
Consider this binary value (32 bit mantissa):
(bin)1.0000000000000000000000000000011
previously ToString() gave 1, now we have: 1.000000001
* changed: in Big::ToString() the base rounding is made only if the result value
would not be an integer, e.g. if the value is 1.999999999999 then
the base rounding will not be done - because as the result would be 2
* added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
floating point algorithms: Big::Add, Big::Sub, Big::Mul, Big::Div
* added: static sint UInt<value_size>::FindLowestBitInWord(uint x)
this method is looking for the lowest set bit in a word
* added: UInt::FindLowestBit(uint & table_id, uint & index)
this method is looking for the lowest set bit
Version 0.9.0 (2009.11.25):
* added: support for wide characters (wchar_t, std::wstring)
* added: Big::IsInteger()

View File

@@ -1,4 +1,4 @@
Copyright (c) 2006-2009, Tomasz Sowa
Copyright (c) 2006-2010, Tomasz Sowa
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -8,7 +8,7 @@ CFLAGS = -Wall -pedantic -s -O2 -I..
$(CC) -c $(CFLAGS) $<
all: uint int big parser
all: uint int big big2 parser
uint: uint.o
@@ -20,6 +20,9 @@ int: int.o
big: big.o
$(CC) -o big $(CFLAGS) big.o
big2: big2.o
$(CC) -o big2 $(CFLAGS) big2.o
parser: parser.o
$(CC) -o parser $(CFLAGS) parser.o
@@ -27,6 +30,7 @@ parser: parser.o
uint.o: uint.cpp
int.o: int.cpp
big.o: big.cpp
big2.o: big2.cpp
parser.o: parser.cpp
@@ -36,6 +40,7 @@ clean:
rm -f uint
rm -f int
rm -f big
rm -f big2
rm -f parser
# on MS Windows can automatically be added suffixes .exe to the names of output programs
rm -f *.exe

View File

@@ -5,6 +5,8 @@
// this type has 2 words for its mantissa and 1 word for its exponent
// (on a 32bit platform one word means a word of 32 bits,
// and on a 64bit platform one word means a word of 64 bits)
// Big<exponent, mantissa>
typedef ttmath::Big<1,2> MyBig;
@@ -56,6 +58,7 @@ MyBig atemp;
}
int main()
{
MyBig a,b;
@@ -86,12 +89,12 @@ b = 98767878.124322
a + b = 98891334.667778
a - b = -98644421.580866
a * b = 12193540837712.2708
a / b = 0.0012499665458095765
a / b = 0.00124996654580957646
Calculating with a carry
a = 1.624801256070839555e+646457012
b = 456.31999999999999
a + b = 1.624801256070839555e+646457012
a - b = 1.624801256070839555e+646457012
a = 1.624801256066640878e+646457012
b = 456.319999999999993
a + b = 1.624801256066640878e+646457012
a - b = 1.624801256066640878e+646457012
a * b = (carry)
a / b = 3.56066193914542334e+646457009
a / b = 3.560661939136222174e+646457009
*/

113
samples/big2.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include <ttmath/ttmath.h>
#include <iostream>
// this is a similar example to big.cpp
// but now we're using TTMATH_BITS() macro
// this macro returns how many words we need to store
// the given number of bits
// TTMATH_BITS(64)
// on a 32bit platform the macro returns 2 (2*32=64)
// on a 64bit platform the macro returns 1
// TTMATH_BITS(128)
// on a 32bit platform the macro returns 4 (4*32=128)
// on a 64bit platform the macro returns 2 (2*64=128)
// Big<exponent, mantissa>
typedef ttmath::Big<TTMATH_BITS(64), TTMATH_BITS(128)> MyBig;
// consequently on a 32bit platform we define: Big<2, 4>
// and on a 64bit platform: Big<1, 2>
// and the calculations will be the same on both platforms
void SimpleCalculating(const MyBig & a, const MyBig & b)
{
std::cout << "Simple calculating" << std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
std::cout << "a + b = " << a+b << std::endl;
std::cout << "a - b = " << a-b << std::endl;
std::cout << "a * b = " << a*b << std::endl;
std::cout << "a / b = " << a/b << std::endl;
}
void CalculatingWithCarry(const MyBig & a, const MyBig & b)
{
MyBig atemp;
std::cout << "Calculating with a carry" << std::endl;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
atemp = a;
if( !atemp.Add(b) )
std::cout << "a + b = " << atemp << std::endl;
else
std::cout << "a + b = (carry)" << std::endl;
// it have no sense to print 'atemp' (it's undefined)
atemp = a;
if( !atemp.Sub(b) )
std::cout << "a - b = " << atemp << std::endl;
else
std::cout << "a - b = (carry)" << std::endl;
atemp = a;
if( !atemp.Mul(b) )
std::cout << "a * b = " << atemp << std::endl;
else
std::cout << "a * b = (carry)" << std::endl;
atemp = a;
if( !atemp.Div(b) )
std::cout << "a / b = " << atemp << std::endl;
else
std::cout << "a / b = (carry or division by zero) " << std::endl;
}
int main()
{
MyBig a,b;
// conversion from 'const char *'
a = "123456.543456";
b = "98767878.124322";
SimpleCalculating(a,b);
// 'a' will have the max value which can be held in this type
a.SetMax();
// conversion from double
b = 456.32;
// Look at the value 'a' and the product from a+b and a-b
// Don't worry this is the nature of floating point numbers
CalculatingWithCarry(a,b);
}
/*
the result (the same on a 32 or 64bit platform):
Simple calculating
a = 123456.543456
b = 98767878.124322
a + b = 98891334.667778
a - b = -98644421.580866
a * b = 12193540837712.270763536832
a / b = 0.001249966545809576460596448526166860913
Calculating with a carry
a = 2.3495345545711177736883282090959505003e+2776511644261678604
b = 456.3199999999999931787897367030382156
a + b = 2.3495345545711177736883282090959505003e+2776511644261678604
a - b = 2.3495345545711177736883282090959505003e+2776511644261678604
a * b = (carry)
a / b = 5.1488748127873374141170361292780486452e+2776511644261678601
*/

View File

@@ -29,6 +29,11 @@ const char equation[] = " (34 + 24) * 123 - 34.32 ^ 6 * sin(2.56) - atan(10)";
/*
the result (on 32 bit platform):
-897705014.52573107
*/
/*
the result (on 64 bit platform):
-897705014.5257310676097719585259773124
*/

View File

@@ -2807,7 +2807,7 @@ namespace ttmath
}
// the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1)
// when x is larger then less coefficients we need
// when x is larger then fewer coefficients we need
Gamma(x, *this);
}

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2006-2009, Tomasz Sowa
* Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -714,6 +714,51 @@ public:
private:
/*!
this method does the half-to-even rounding (banker's rounding)
if is_half is:
true - that means the rest was equal the half (0.5 decimal)
false - that means the rest was greater than a half (greater than 0.5 decimal)
if the rest was less than a half then don't call this method
(the rounding should does nothing then)
*/
uint RoundHalfToEven(bool is_half, bool rounding_up = true)
{
uint c = 0;
if( !is_half || mantissa.IsTheLowestBitSet() )
{
if( rounding_up )
{
if( mantissa.AddOne() )
{
mantissa.Rcr(1, 1);
c = exponent.AddOne();
}
}
else
{
#ifdef TTMATH_DEBUG
uint c_from_zero =
#endif
mantissa.SubOne();
// we're using rounding_up=false in Add() when the mantissas have different signs
// mantissa can be zero only when previous mantissa was equal to ss2.mantissa
// but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false
TTMATH_ASSERT( c_from_zero == 0 )
}
}
return c;
}
/*!
@@ -722,59 +767,76 @@ public:
*
*/
private:
/*!
Addition this = this + ss2
it returns carry if the sum is too big
an auxiliary method for adding
*/
uint Add(Big<exp, man> ss2)
void AddCheckExponents( Big<exp, man> & ss2,
Int<exp> & exp_offset,
bool & last_bit_set,
bool & rest_zero,
bool & do_adding,
bool & do_rounding)
{
Int<exp> exp_offset( exponent );
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
uint c = 0;
if( IsNan() || ss2.IsNan() )
return CheckCarry(1);
if( ss2.IsZero() )
return 0;
exp_offset.Sub( ss2.exponent );
exp_offset.Abs();
// (1) abs(this) will be >= abs(ss2)
if( SmallerWithoutSignThan(ss2) )
if( exp_offset == mantissa_size_in_bits )
{
Big<exp, man> temp(ss2);
ss2 = *this;
*this = temp;
}
if( exp_offset >= mantissa_size_in_bits )
{
// the second value is too small for taking into consideration in the sum
return 0;
last_bit_set = ss2.mantissa.IsTheHighestBitSet();
rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1);
do_rounding = true; // we'are only rounding
}
else
if( exp_offset < mantissa_size_in_bits )
{
uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa
rest_zero = true;
if( moved > 0 )
{
last_bit_set = static_cast<bool>( ss2.mantissa.GetBit(moved-1) );
if( moved > 1 )
rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1);
// (2) moving 'exp_offset' times
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
ss2.mantissa.Rcr(moved, 0);
}
do_adding = true;
do_rounding = true;
}
// if exp_offset is greater than mantissa_size_in_bits then we do nothing
// ss2 is too small for taking into consideration in the sum
}
/*!
an auxiliary method for adding
*/
uint AddMantissas( Big<exp, man> & ss2,
bool & last_bit_set,
bool & rest_zero,
bool & rounding_up)
{
uint c = 0;
if( IsSign() == ss2.IsSign() )
{
// values have the same signs
if( mantissa.Add(ss2.mantissa) )
{
mantissa.Rcr(1,1);
c = exponent.AddOne();
// we have one bit more from addition (carry)
// now rest_zero means the old rest_zero with the old last_bit_set
rest_zero = (!last_bit_set && rest_zero);
last_bit_set = mantissa.Rcr(1,1);
c += exponent.AddOne();
}
rounding_up = true;
}
else
{
@@ -784,30 +846,80 @@ public:
// is greater than or equal to the mantissa of the ss2
#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); */
uint c_temp =
#endif
mantissa.Sub(ss2.mantissa);
TTMATH_ASSERT( c_temp == 0 )
}
return c;
}
public:
/*!
Addition this = this + ss2
it returns carry if the sum is too big
*/
uint Add(Big<exp, man> ss2, bool round = true)
{
bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up;
Int<exp> exp_offset( exponent );
uint c = 0;
if( IsNan() || ss2.IsNan() )
return CheckCarry(1);
exp_offset.Sub( ss2.exponent );
exp_offset.Abs();
// (1) abs(this) will be >= abs(ss2)
if( SmallerWithoutSignThan(ss2) )
{
// !! use Swap here (not implemented yet)
Big<exp, man> temp(ss2);
ss2 = *this;
*this = temp;
}
if( ss2.IsZero() )
return 0;
last_bit_set = rest_zero = do_adding = do_rounding = rounding_up = false;
AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding);
if( do_adding )
c += AddMantissas(ss2, last_bit_set, rest_zero, rounding_up);
if( !round || !last_bit_set )
do_rounding = false;
if( do_rounding )
c += RoundHalfToEven(rest_zero, rounding_up);
if( do_adding || do_rounding )
c += Standardizing();
return CheckCarry(c);
}
/*!
Subtraction this = this - ss2
it returns carry if the result is too big
*/
uint Sub(Big<exp, man> ss2)
uint Sub(Big<exp, man> ss2, bool round = true)
{
ss2.ChangeSign();
return Add(ss2);
return Add(ss2, round);
}
@@ -1078,16 +1190,52 @@ public:
}
private:
/*!
this method checks whether a table pointed by 'tab' and 'len'
has the value 0.5 decimal
(it is treated as the comma operator would be before the highest bit)
call this method only if the highest bit is set - you have to test it beforehand
return:
true - tab was equal the half (0.5 decimal)
false - tab was greater than a half (greater than 0.5 decimal)
*/
bool CheckGreaterOrEqualHalf(uint * tab, uint len)
{
uint i;
TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 )
for(i=0 ; i<len-1 ; ++i)
if( tab[i] != 0 )
return false;
if( tab[i] != TTMATH_UINT_HIGHEST_BIT )
return false;
return true;
}
public:
/*!
multiplication this = this * ss2
this method returns a carry
*/
uint Mul(const Big<exp, man> & ss2)
uint Mul(const Big<exp, man> & ss2, bool round = true)
{
TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man_result;
uint i,c;
uint c = 0;
uint i;
if( IsNan() || ss2.IsNan() )
return CheckCarry(1);
@@ -1110,13 +1258,22 @@ public:
// if there is a zero value in man_result the method CompensationToLeft()
// returns 0 but we'll correct this at the end in Standardizing() method)
i = man_result.CompensationToLeft();
uint exp_add = man * TTMATH_BITS_PER_UINT - i;
if( exp_add )
c += exponent.Add( exp_add );
c = exponent.Add( man * TTMATH_BITS_PER_UINT - i );
c += exponent.Add( ss2.exponent );
for(i=0 ; i<man ; ++i)
mantissa.table[i] = man_result.table[i+man];
if( round && (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
{
bool is_half = CheckGreaterOrEqualHalf(man_result.table, man);
c += RoundHalfToEven(is_half);
}
if( IsSign() == ss2.IsSign() )
{
// the signs are the same, the result is positive
@@ -1143,7 +1300,7 @@ public:
1 - carry (in a division carry can be as well)
2 - improper argument (ss2 is zero)
*/
uint Div(const Big<exp, man> & ss2)
uint Div(const Big<exp, man> & ss2, bool round = true)
{
TTMATH_REFERENCE_ASSERT( ss2 )
@@ -1187,6 +1344,12 @@ public:
for(i=0 ; i<man ; ++i)
mantissa.table[i] = man1.table[i+man];
if( round && (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
{
bool is_half = CheckGreaterOrEqualHalf(man1.table, man);
c += RoundHalfToEven(is_half);
}
if( IsSign() == ss2.IsSign() )
Abs();
else
@@ -1408,7 +1571,7 @@ public:
if( pow.Mod2() )
c += result.Mul(start);
c += pow.exponent.Sub( e_one );
c += pow.exponent.Sub( e_one ); // !! may use SubOne() here?
if( pow < one )
break;
@@ -3058,22 +3221,12 @@ private:
*/
Int<exp+1> new_exp;
if( ToString_CreateNewMantissaAndExponent(result, conv, new_exp) )
if( ToString_CreateNewMantissaAndExponent<string_type, char_type>(result, conv, new_exp) )
{
Misc::AssignString(result, error_overflow_msg);
return 1;
}
/*
we're rounding the mantissa only if the base is different from 2,4,8 or 16
(this formula means that the number of bits in the base is greater than one)
*/
if( conv.base_round && conv.base!=2 && conv.base!=4 && conv.base!=8 && conv.base!=16 )
if( ToString_RoundMantissa<string_type, char_type>(result, conv, new_exp) )
{
Misc::AssignString(result, error_overflow_msg);
return 1;
}
if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
{
@@ -3084,6 +3237,7 @@ private:
if( IsSign() )
result.insert(result.begin(), '-');
// converted successfully
return 0;
}
@@ -3143,7 +3297,7 @@ private:
M = mm * 2^ee where ee will be <= 0
next we'll move all bits of mm into the right when ee is equal zero
abs(ee) must not to be too big that only few bits from mm we can leave
abs(ee) must not be too big that only few bits from mm we can leave
then we'll have:
M = mmm * 2^0
@@ -3154,10 +3308,13 @@ private:
2^exponent <= base^new_exp
new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
but we need 'new'exp' as integer then we take:
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
but we need new_exp as integer then we test:
if new_exp is greater than zero and with fraction we add one to new_exp
new_exp = new_exp + 1 (if new_exp>0 and with fraction)
and at the end we take the integer part:
new_exp = int(new_exp)
*/
template<class string_type>
template<class string_type, class char_type>
uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
Int<exp+1> & new_exp) const
{
@@ -3193,12 +3350,26 @@ private:
temp.mantissa.SetOne();
c += temp.Standardizing();
// new_exp_ = [log base (2^exponent)] + 1
// new_exp_ = log base (2^exponent)
// if new_exp_ is positive and with fraction then we add one
Big<exp+1,man> new_exp_;
c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
new_exp_.SkipFraction();
// adding some epsilon value (to get rid of some floating point errors)
temp.Set05();
temp.exponent.SubOne(); // temp = 0.5/2 = 0.25
c += new_exp_.Add(temp);
if( !new_exp_.IsSign() && !new_exp_.IsInteger() )
{
// new_exp_ > 0 and with fraction
temp.SetOne();
c += new_exp_.Add( temp );
}
// new_exp_ = int(new_exp_)
new_exp_.SkipFraction();
// because 'base^new_exp' is >= '2^exponent' then
// because base is >= 2 then we've got:
@@ -3219,7 +3390,7 @@ private:
// the sign don't interest us here
temp.mantissa = mantissa;
temp.exponent = exponent;
c += temp.Div( base_ );
c += temp.Div(base_, false); // dividing without rounding
// moving all bits of the mantissa into the right
// (how many times to move depend on the exponent)
@@ -3232,9 +3403,9 @@ private:
// maximum valid bits
temp.mantissa.ToString(new_man, conv.base);
// because we had used a bigger type for calculating I think we
// shouldn't have had a carry
// (in the future this can be changed)
// base rounding
if( conv.base_round )
c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp);
return (c==0)? 0 : 1;
}
@@ -3569,21 +3740,68 @@ private:
/*!
an auxiliary method for converting into the string
this method roundes the last character from the new mantissa
(it's used in systems where the base is different from 2)
*/
template<class string_type, class char_type>
uint ToString_RoundMantissa(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
{
// if new_exp is greater or equal to zero then we have an integer value,
// if new_exp is equal -1 then we have only one digit after the comma
// and after rounding it would be an integer value
if( !new_exp.IsSign() || new_exp == -1 )
return true;
if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 )
return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding
uint i = 0;
char_type digit;
if( new_exp >= -sint(new_man.size()) )
{
uint new_exp_abs = -new_exp.ToInt();
i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator
}
if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 )
{
if( new_exp < -sint(new_man.size()) )
{
// there are some zeroes after the comma operator
// (between the comma and the first digit from the mantissa)
// and the result value will never be an integer
return false;
}
digit = static_cast<char_type>( Misc::DigitToChar(conv.base-1) );
}
else
{
digit = '0';
}
for( ; i < new_man.size()-1 ; ++i)
if( new_man[i] != digit )
return false; // it will not be an integer
return true; // it will be integer after rounding
}
/*!
an auxiliary method for converting into the string
this method is used for base!=2, base!=4, base!=8 and base!=16
we do the rounding when the value has fraction (is not an integer)
*/
template<class string_type, class char_type>
uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
{
// we must have minimum two characters
if( new_man.length() < 2 )
if( new_man.size() < 2 )
return 0;
// the rounding is only made when new_exp is less than zero
// if new_exp is greater or equal zero then the value is integer and
// don't have to be rounded
if( !new_exp.IsSign() )
// assert that there will not be an integer after rounding
if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) )
return 0;
typename string_type::size_type i = new_man.length() - 1;
@@ -3591,14 +3809,14 @@ private:
// we're erasing the last character
uint digit = Misc::CharToDigit( new_man[i] );
new_man.erase(i, 1);
uint carry = new_exp.AddOne();
uint c = new_exp.AddOne();
// if the last character is greater or equal 'base/2'
// we'll add one into the new mantissa
// we are adding one into the new mantissa
if( digit >= conv.base / 2 )
ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
return carry;
return c;
}
@@ -3640,6 +3858,7 @@ private:
}
/*!
an auxiliary method for converting into the string
@@ -3767,9 +3986,12 @@ private:
if( new_man.empty() )
return;
if( new_man.size() > 1 )
{
new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
}
ToString_Group_man<string_type, char_type>(new_man, conv);
if( conv.base == 10 )
@@ -4194,7 +4416,7 @@ private:
{
sint character;
uint c = 0, index = 1;
Big<exp, man> part, power, old_value, base_( conv.base );
Big<exp, man> sum, part, power, old_value, base_( conv.base );
// we don't remove any white characters here
@@ -4203,6 +4425,7 @@ private:
old_value.SetZero();
power.SetOne();
sum.SetZero();
for( ; true ; ++source, ++index )
{
@@ -4231,12 +4454,12 @@ private:
bool testing = (character != 0 && (index % 5) == 0);
if( testing )
old_value = *this;
old_value = sum;
// there actually shouldn't be a carry here
c += Add( part );
c += sum.Add( part );
if( testing && old_value == *this )
if( testing && old_value == sum )
// after adding 'part' the value has not been changed
// there's no sense to add any next parts
break;
@@ -4247,6 +4470,8 @@ private:
// we should set a correct value of 'source' now
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
c += Add(sum);
return (c==0)? 0 : 1;
}
@@ -4866,8 +5091,6 @@ public:
/*!
*
* input/output operators for standard streams

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2006-2009, Tomasz Sowa
* Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -159,14 +159,20 @@ private:
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
};
enum Assoc
{
right, // right-associative
non_right // associative or left-associative
};
Type GetType() const { return type; }
int GetPriority() const { return priority; }
Assoc GetAssoc() const { return assoc; }
void SetType(Type t)
{
type = t;
assoc = non_right;
switch( type )
{
@@ -200,6 +206,7 @@ private:
case pow:
priority = 14;
assoc = right;
break;
default:
@@ -208,7 +215,7 @@ private:
}
}
MatOperator(): type(none), priority(0)
MatOperator(): type(none), priority(0), assoc(non_right)
{
}
@@ -216,7 +223,7 @@ private:
Type type;
int priority;
Assoc assoc;
}; // end of MatOperator class
@@ -464,6 +471,8 @@ int param_sep;
*/
bool calculated;
/*!
we're using this method for reporting an error
*/
@@ -1737,6 +1746,8 @@ return is_it_name_of_function;
}
/*!
we're reading a numerical value directly from the string
*/
@@ -1746,7 +1757,7 @@ const char * new_stack_pointer;
bool value_read;
Conv conv;
conv.base = base;
conv.base = reading_base;
conv.comma = comma;
conv.comma2 = comma2;
conv.group = group;
@@ -2152,7 +2163,17 @@ void TryRollingUpStackWithOperatorPriority()
stack[stack_index-3].type == Item::mat_operator &&
stack[stack_index-2].type == Item::numerical_value &&
stack[stack_index-1].type == Item::mat_operator &&
stack[stack_index-3].moperator.GetPriority() >= stack[stack_index-1].moperator.GetPriority()
(
(
// the first operator has greater priority
stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority()
) ||
(
// or both operators have the same priority and the first operator is not right associative
stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() &&
stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right
)
)
)
{
MakeStandardMathematicOperation(stack[stack_index-4].value,
@@ -2710,7 +2731,7 @@ ErrorCode Parse(const std::wstring & str)
/*!
this method returns true is something was calculated
(at least one mathematical operator was used or a function or variable)
e.g. the string to Parse() looked like this:
e.g. true if the string to Parse() looked like this:
"1+1"
"2*3"
"sin(5)"
@@ -2722,6 +2743,7 @@ bool Calculated()
return calculated;
}
};

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2006-2009, Tomasz Sowa
* Copyright (c) 2006-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,7 @@
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 9
#define TTMATH_REVISION_VER 0
#define TTMATH_REVISION_VER 1
#define TTMATH_PRERELEASE_VER 0

View File

@@ -627,7 +627,7 @@ public:
if 'this' is not zero:
return value - true
'table_id' - the index of a word <0..value_size-1>
'index' - the index of this set bit in the word <0..31>
'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
if 'this' is zero:
return value - false
@@ -645,7 +645,7 @@ public:
return false;
}
// table[table_id] != 0
// table[table_id] is different from 0
index = FindLeadingBitInWord( table[table_id] );
return true;
@@ -653,7 +653,40 @@ public:
/*!
setting the 'bit_index' bit
this method looks for the smallest set bit
result:
if 'this' is not zero:
return value - true
'table_id' - the index of a word <0..value_size-1>
'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT)
if 'this' is zero:
return value - false
both 'table_id' and 'index' are zero
*/
bool FindLowestBit(uint & table_id, uint & index) const
{
for(table_id=0 ; table_id<value_size && table[table_id]==0 ; ++table_id);
if( table_id >= value_size )
{
// is zero
index = 0;
table_id = 0;
return false;
}
// table[table_id] is different from 0
index = FindLowestBitInWord( table[table_id] );
return true;
}
/*!
getting the 'bit_index' bit
bit_index bigger or equal zero
*/
@@ -2370,7 +2403,28 @@ public:
}
/*!
returning true if first 'bits' bits are equal zero
*/
bool AreFirstBitsZero(uint bits) const
{
TTMATH_ASSERT( bits <= value_size * TTMATH_BITS_PER_UINT )
uint index = bits / TTMATH_BITS_PER_UINT;
uint rest = bits % TTMATH_BITS_PER_UINT;
uint i;
for(i=0 ; i<index ; ++i)
if(table[i] != 0 )
return false;
if( rest == 0 )
return true;
uint mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
return (table[i] & mask) == 0;
}
@@ -3431,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);

View File

@@ -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<uint value_size>
sint UInt<value_size>::FindLowestBitInWord(uint x)
{
if( x == 0 )
return -1;
uint bit = 0;
while( (x & 1) == 0 )
{
x = x >> 1;
++bit;
}
return bit;
}
/*!

View File

@@ -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<uint value_size>
sint UInt<value_size>::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;
}
/*!

View File

@@ -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<uint value_size>
sint UInt<value_size>::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)