Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
aeadb8a04a | |||
053861655d | |||
35f2a8a28b | |||
d5a5ea1a7d | |||
32b8c7a957 | |||
e727eacce0 | |||
39db6fc469 | |||
0ada20b4cb | |||
31563ce343 | |||
418db51f46 | |||
82711f4441 | |||
e5fc7a52e8 | |||
357524ae13 | |||
72052420dd | |||
321953e833 |
27
CHANGELOG
27
CHANGELOG
@@ -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()
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
113
samples/big2.cpp
Normal 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
|
||||
*/
|
@@ -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
|
||||
*/
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user