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):
|
Version 0.9.0 (2009.11.25):
|
||||||
* added: support for wide characters (wchar_t, std::wstring)
|
* added: support for wide characters (wchar_t, std::wstring)
|
||||||
* added: Big::IsInteger()
|
* added: Big::IsInteger()
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2006-2009, Tomasz Sowa
|
Copyright (c) 2006-2010, 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
|
||||||
|
@@ -8,7 +8,7 @@ CFLAGS = -Wall -pedantic -s -O2 -I..
|
|||||||
$(CC) -c $(CFLAGS) $<
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
all: uint int big parser
|
all: uint int big big2 parser
|
||||||
|
|
||||||
|
|
||||||
uint: uint.o
|
uint: uint.o
|
||||||
@@ -20,6 +20,9 @@ int: int.o
|
|||||||
big: big.o
|
big: big.o
|
||||||
$(CC) -o big $(CFLAGS) big.o
|
$(CC) -o big $(CFLAGS) big.o
|
||||||
|
|
||||||
|
big2: big2.o
|
||||||
|
$(CC) -o big2 $(CFLAGS) big2.o
|
||||||
|
|
||||||
parser: parser.o
|
parser: parser.o
|
||||||
$(CC) -o parser $(CFLAGS) parser.o
|
$(CC) -o parser $(CFLAGS) parser.o
|
||||||
|
|
||||||
@@ -27,6 +30,7 @@ parser: parser.o
|
|||||||
uint.o: uint.cpp
|
uint.o: uint.cpp
|
||||||
int.o: int.cpp
|
int.o: int.cpp
|
||||||
big.o: big.cpp
|
big.o: big.cpp
|
||||||
|
big2.o: big2.cpp
|
||||||
parser.o: parser.cpp
|
parser.o: parser.cpp
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +40,7 @@ clean:
|
|||||||
rm -f uint
|
rm -f uint
|
||||||
rm -f int
|
rm -f int
|
||||||
rm -f big
|
rm -f big
|
||||||
|
rm -f big2
|
||||||
rm -f parser
|
rm -f parser
|
||||||
# on MS Windows can automatically be added suffixes .exe to the names of output programs
|
# on MS Windows can automatically be added suffixes .exe to the names of output programs
|
||||||
rm -f *.exe
|
rm -f *.exe
|
||||||
|
@@ -5,8 +5,10 @@
|
|||||||
// this type has 2 words for its mantissa and 1 word for its exponent
|
// 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,
|
// (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)
|
// and on a 64bit platform one word means a word of 64 bits)
|
||||||
|
|
||||||
|
// Big<exponent, mantissa>
|
||||||
typedef ttmath::Big<1,2> MyBig;
|
typedef ttmath::Big<1,2> MyBig;
|
||||||
|
|
||||||
|
|
||||||
void SimpleCalculating(const MyBig & a, const MyBig & b)
|
void SimpleCalculating(const MyBig & a, const MyBig & b)
|
||||||
{
|
{
|
||||||
@@ -56,6 +58,7 @@ MyBig atemp;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
MyBig a,b;
|
MyBig a,b;
|
||||||
@@ -86,12 +89,12 @@ b = 98767878.124322
|
|||||||
a + b = 98891334.667778
|
a + b = 98891334.667778
|
||||||
a - b = -98644421.580866
|
a - b = -98644421.580866
|
||||||
a * b = 12193540837712.2708
|
a * b = 12193540837712.2708
|
||||||
a / b = 0.0012499665458095765
|
a / b = 0.00124996654580957646
|
||||||
Calculating with a carry
|
Calculating with a carry
|
||||||
a = 1.624801256070839555e+646457012
|
a = 1.624801256066640878e+646457012
|
||||||
b = 456.31999999999999
|
b = 456.319999999999993
|
||||||
a + b = 1.624801256070839555e+646457012
|
a + b = 1.624801256066640878e+646457012
|
||||||
a - b = 1.624801256070839555e+646457012
|
a - b = 1.624801256066640878e+646457012
|
||||||
a * b = (carry)
|
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):
|
the result (on 32 bit platform):
|
||||||
|
|
||||||
-897705014.52573107
|
-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)
|
// 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);
|
Gamma(x, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
* Copyright (c) 2006-2010, 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
|
||||||
@@ -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
|
an auxiliary method for adding
|
||||||
|
|
||||||
it returns carry if the sum is too big
|
|
||||||
*/
|
*/
|
||||||
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 );
|
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||||
|
|
||||||
uint c = 0;
|
if( exp_offset == mantissa_size_in_bits )
|
||||||
|
|
||||||
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) )
|
|
||||||
{
|
{
|
||||||
Big<exp, man> temp(ss2);
|
last_bit_set = ss2.mantissa.IsTheHighestBitSet();
|
||||||
|
rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1);
|
||||||
ss2 = *this;
|
do_rounding = true; // we'are only rounding
|
||||||
*this = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( exp_offset >= mantissa_size_in_bits )
|
|
||||||
{
|
|
||||||
// the second value is too small for taking into consideration in the sum
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( exp_offset < mantissa_size_in_bits )
|
if( exp_offset < mantissa_size_in_bits )
|
||||||
{
|
{
|
||||||
// (2) moving 'exp_offset' times
|
uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa
|
||||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
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(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() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
{
|
{
|
||||||
// values have the same signs
|
// values have the same signs
|
||||||
if( mantissa.Add(ss2.mantissa) )
|
if( mantissa.Add(ss2.mantissa) )
|
||||||
{
|
{
|
||||||
mantissa.Rcr(1,1);
|
// we have one bit more from addition (carry)
|
||||||
c = exponent.AddOne();
|
// 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
|
else
|
||||||
{
|
{
|
||||||
@@ -782,32 +844,82 @@ public:
|
|||||||
// there shouldn't be a carry here because
|
// there shouldn't be a carry here because
|
||||||
// (1) (2) guarantee that the mantissa of this
|
// (1) (2) guarantee that the mantissa of this
|
||||||
// is greater than or equal to the mantissa of the ss2
|
// is greater than or equal to the mantissa of the ss2
|
||||||
|
|
||||||
#ifdef TTMATH_DEBUG
|
#ifdef TTMATH_DEBUG
|
||||||
// this is to get rid of a warning saying that c_temp is not used
|
uint c_temp =
|
||||||
uint c_temp = /* mantissa.Sub(ss2.mantissa); */
|
|
||||||
#endif
|
#endif
|
||||||
mantissa.Sub(ss2.mantissa);
|
mantissa.Sub(ss2.mantissa);
|
||||||
|
|
||||||
TTMATH_ASSERT( c_temp == 0 )
|
TTMATH_ASSERT( c_temp == 0 )
|
||||||
}
|
}
|
||||||
|
|
||||||
c += Standardizing();
|
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);
|
return CheckCarry(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Subtraction this = this - ss2
|
Subtraction this = this - ss2
|
||||||
|
|
||||||
it returns carry if the result is too big
|
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();
|
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
|
multiplication this = this * ss2
|
||||||
this method returns a carry
|
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 )
|
TTMATH_REFERENCE_ASSERT( ss2 )
|
||||||
|
|
||||||
UInt<man*2> man_result;
|
UInt<man*2> man_result;
|
||||||
uint i,c;
|
uint c = 0;
|
||||||
|
uint i;
|
||||||
|
|
||||||
if( IsNan() || ss2.IsNan() )
|
if( IsNan() || ss2.IsNan() )
|
||||||
return CheckCarry(1);
|
return CheckCarry(1);
|
||||||
@@ -1110,13 +1258,22 @@ public:
|
|||||||
// if there is a zero value in man_result the method CompensationToLeft()
|
// 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)
|
// returns 0 but we'll correct this at the end in Standardizing() method)
|
||||||
i = man_result.CompensationToLeft();
|
i = man_result.CompensationToLeft();
|
||||||
|
uint exp_add = man * TTMATH_BITS_PER_UINT - i;
|
||||||
c = exponent.Add( man * TTMATH_BITS_PER_UINT - i );
|
|
||||||
|
if( exp_add )
|
||||||
|
c += exponent.Add( exp_add );
|
||||||
|
|
||||||
c += exponent.Add( ss2.exponent );
|
c += exponent.Add( ss2.exponent );
|
||||||
|
|
||||||
for(i=0 ; i<man ; ++i)
|
for(i=0 ; i<man ; ++i)
|
||||||
mantissa.table[i] = man_result.table[i+man];
|
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() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
{
|
{
|
||||||
// the signs are the same, the result is positive
|
// the signs are the same, the result is positive
|
||||||
@@ -1143,7 +1300,7 @@ public:
|
|||||||
1 - carry (in a division carry can be as well)
|
1 - carry (in a division carry can be as well)
|
||||||
2 - improper argument (ss2 is zero)
|
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 )
|
TTMATH_REFERENCE_ASSERT( ss2 )
|
||||||
|
|
||||||
@@ -1187,6 +1344,12 @@ public:
|
|||||||
for(i=0 ; i<man ; ++i)
|
for(i=0 ; i<man ; ++i)
|
||||||
mantissa.table[i] = man1.table[i+man];
|
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() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
Abs();
|
Abs();
|
||||||
else
|
else
|
||||||
@@ -1408,7 +1571,7 @@ public:
|
|||||||
if( pow.Mod2() )
|
if( pow.Mod2() )
|
||||||
c += result.Mul(start);
|
c += result.Mul(start);
|
||||||
|
|
||||||
c += pow.exponent.Sub( e_one );
|
c += pow.exponent.Sub( e_one ); // !! may use SubOne() here?
|
||||||
|
|
||||||
if( pow < one )
|
if( pow < one )
|
||||||
break;
|
break;
|
||||||
@@ -3058,23 +3221,13 @@ private:
|
|||||||
*/
|
*/
|
||||||
Int<exp+1> new_exp;
|
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);
|
Misc::AssignString(result, error_overflow_msg);
|
||||||
return 1;
|
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) )
|
if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
|
||||||
{
|
{
|
||||||
Misc::AssignString(result, error_overflow_msg);
|
Misc::AssignString(result, error_overflow_msg);
|
||||||
@@ -3084,6 +3237,7 @@ private:
|
|||||||
if( IsSign() )
|
if( IsSign() )
|
||||||
result.insert(result.begin(), '-');
|
result.insert(result.begin(), '-');
|
||||||
|
|
||||||
|
|
||||||
// converted successfully
|
// converted successfully
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3143,7 +3297,7 @@ private:
|
|||||||
M = mm * 2^ee where ee will be <= 0
|
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
|
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:
|
then we'll have:
|
||||||
M = mmm * 2^0
|
M = mmm * 2^0
|
||||||
@@ -3154,10 +3308,13 @@ private:
|
|||||||
2^exponent <= base^new_exp
|
2^exponent <= base^new_exp
|
||||||
new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
|
new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
|
||||||
|
|
||||||
but we need 'new'exp' as integer then we take:
|
but we need new_exp as integer then we test:
|
||||||
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
|
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,
|
uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
|
||||||
Int<exp+1> & new_exp) const
|
Int<exp+1> & new_exp) const
|
||||||
{
|
{
|
||||||
@@ -3193,12 +3350,26 @@ private:
|
|||||||
temp.mantissa.SetOne();
|
temp.mantissa.SetOne();
|
||||||
c += temp.Standardizing();
|
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_;
|
Big<exp+1,man> new_exp_;
|
||||||
c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
|
c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
|
||||||
|
|
||||||
|
// 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();
|
new_exp_.SkipFraction();
|
||||||
temp.SetOne();
|
|
||||||
c += new_exp_.Add( temp );
|
|
||||||
|
|
||||||
// because 'base^new_exp' is >= '2^exponent' then
|
// because 'base^new_exp' is >= '2^exponent' then
|
||||||
// because base is >= 2 then we've got:
|
// because base is >= 2 then we've got:
|
||||||
@@ -3219,7 +3390,7 @@ private:
|
|||||||
// the sign don't interest us here
|
// the sign don't interest us here
|
||||||
temp.mantissa = mantissa;
|
temp.mantissa = mantissa;
|
||||||
temp.exponent = exponent;
|
temp.exponent = exponent;
|
||||||
c += temp.Div( base_ );
|
c += temp.Div(base_, false); // dividing without rounding
|
||||||
|
|
||||||
// moving all bits of the mantissa into the right
|
// moving all bits of the mantissa into the right
|
||||||
// (how many times to move depend on the exponent)
|
// (how many times to move depend on the exponent)
|
||||||
@@ -3232,9 +3403,9 @@ private:
|
|||||||
// maximum valid bits
|
// maximum valid bits
|
||||||
temp.mantissa.ToString(new_man, conv.base);
|
temp.mantissa.ToString(new_man, conv.base);
|
||||||
|
|
||||||
// because we had used a bigger type for calculating I think we
|
// base rounding
|
||||||
// shouldn't have had a carry
|
if( conv.base_round )
|
||||||
// (in the future this can be changed)
|
c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp);
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
}
|
}
|
||||||
@@ -3569,21 +3740,68 @@ private:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
an auxiliary method for converting into the string
|
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>
|
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
|
// we must have minimum two characters
|
||||||
if( new_man.length() < 2 )
|
if( new_man.size() < 2 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// the rounding is only made when new_exp is less than zero
|
// assert that there will not be an integer after rounding
|
||||||
// if new_exp is greater or equal zero then the value is integer and
|
if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) )
|
||||||
// don't have to be rounded
|
|
||||||
if( !new_exp.IsSign() )
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
typename string_type::size_type i = new_man.length() - 1;
|
typename string_type::size_type i = new_man.length() - 1;
|
||||||
@@ -3591,14 +3809,14 @@ private:
|
|||||||
// we're erasing the last character
|
// we're erasing the last character
|
||||||
uint digit = Misc::CharToDigit( new_man[i] );
|
uint digit = Misc::CharToDigit( new_man[i] );
|
||||||
new_man.erase(i, 1);
|
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'
|
// 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 )
|
if( digit >= conv.base / 2 )
|
||||||
ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
|
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
|
an auxiliary method for converting into the string
|
||||||
|
|
||||||
@@ -3767,9 +3986,12 @@ private:
|
|||||||
if( new_man.empty() )
|
if( new_man.empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
|
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_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
|
|
||||||
ToString_Group_man<string_type, char_type>(new_man, conv);
|
ToString_Group_man<string_type, char_type>(new_man, conv);
|
||||||
|
|
||||||
if( conv.base == 10 )
|
if( conv.base == 10 )
|
||||||
@@ -4194,7 +4416,7 @@ private:
|
|||||||
{
|
{
|
||||||
sint character;
|
sint character;
|
||||||
uint c = 0, index = 1;
|
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
|
// we don't remove any white characters here
|
||||||
|
|
||||||
@@ -4203,6 +4425,7 @@ private:
|
|||||||
old_value.SetZero();
|
old_value.SetZero();
|
||||||
|
|
||||||
power.SetOne();
|
power.SetOne();
|
||||||
|
sum.SetZero();
|
||||||
|
|
||||||
for( ; true ; ++source, ++index )
|
for( ; true ; ++source, ++index )
|
||||||
{
|
{
|
||||||
@@ -4231,12 +4454,12 @@ private:
|
|||||||
bool testing = (character != 0 && (index % 5) == 0);
|
bool testing = (character != 0 && (index % 5) == 0);
|
||||||
|
|
||||||
if( testing )
|
if( testing )
|
||||||
old_value = *this;
|
old_value = sum;
|
||||||
|
|
||||||
// there actually shouldn't be a carry here
|
// 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
|
// after adding 'part' the value has not been changed
|
||||||
// there's no sense to add any next parts
|
// there's no sense to add any next parts
|
||||||
break;
|
break;
|
||||||
@@ -4247,6 +4470,8 @@ private:
|
|||||||
// we should set a correct value of 'source' now
|
// we should set a correct value of 'source' now
|
||||||
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
|
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
|
||||||
|
|
||||||
|
c += Add(sum);
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4864,9 +5089,7 @@ public:
|
|||||||
return CheckCarry(c);
|
return CheckCarry(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
* Copyright (c) 2006-2010, 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
|
||||||
@@ -159,14 +159,20 @@ private:
|
|||||||
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
|
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; }
|
Type GetType() const { return type; }
|
||||||
int GetPriority() const { return priority; }
|
int GetPriority() const { return priority; }
|
||||||
|
Assoc GetAssoc() const { return assoc; }
|
||||||
|
|
||||||
void SetType(Type t)
|
void SetType(Type t)
|
||||||
{
|
{
|
||||||
type = t;
|
type = t;
|
||||||
|
assoc = non_right;
|
||||||
|
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
@@ -200,6 +206,7 @@ private:
|
|||||||
|
|
||||||
case pow:
|
case pow:
|
||||||
priority = 14;
|
priority = 14;
|
||||||
|
assoc = right;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -208,15 +215,15 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MatOperator(): type(none), priority(0)
|
MatOperator(): type(none), priority(0), assoc(non_right)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
int priority;
|
int priority;
|
||||||
|
Assoc assoc;
|
||||||
}; // end of MatOperator class
|
}; // end of MatOperator class
|
||||||
|
|
||||||
|
|
||||||
@@ -464,6 +471,8 @@ int param_sep;
|
|||||||
*/
|
*/
|
||||||
bool calculated;
|
bool calculated;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
we're using this method for reporting an error
|
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
|
we're reading a numerical value directly from the string
|
||||||
*/
|
*/
|
||||||
@@ -1746,7 +1757,7 @@ const char * new_stack_pointer;
|
|||||||
bool value_read;
|
bool value_read;
|
||||||
Conv conv;
|
Conv conv;
|
||||||
|
|
||||||
conv.base = base;
|
conv.base = reading_base;
|
||||||
conv.comma = comma;
|
conv.comma = comma;
|
||||||
conv.comma2 = comma2;
|
conv.comma2 = comma2;
|
||||||
conv.group = group;
|
conv.group = group;
|
||||||
@@ -1884,13 +1895,13 @@ int character;
|
|||||||
this value is from a variable or directly from the string
|
this value is from a variable or directly from the string
|
||||||
*/
|
*/
|
||||||
result.type = Item::numerical_value;
|
result.type = Item::numerical_value;
|
||||||
|
|
||||||
if( result.sign )
|
if( result.sign )
|
||||||
{
|
{
|
||||||
result.value.ChangeSign();
|
result.value.ChangeSign();
|
||||||
result.sign = false;
|
result.sign = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2149,10 +2160,20 @@ void TryRollingUpStackWithOperatorPriority()
|
|||||||
{
|
{
|
||||||
while( stack_index>=4 &&
|
while( stack_index>=4 &&
|
||||||
stack[stack_index-4].type == Item::numerical_value &&
|
stack[stack_index-4].type == Item::numerical_value &&
|
||||||
stack[stack_index-3].type == Item::mat_operator &&
|
stack[stack_index-3].type == Item::mat_operator &&
|
||||||
stack[stack_index-2].type == Item::numerical_value &&
|
stack[stack_index-2].type == Item::numerical_value &&
|
||||||
stack[stack_index-1].type == Item::mat_operator &&
|
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,
|
MakeStandardMathematicOperation(stack[stack_index-4].value,
|
||||||
@@ -2335,7 +2356,7 @@ int index;
|
|||||||
stack[index-1].value.ChangeSign();
|
stack[index-1].value.ChangeSign();
|
||||||
|
|
||||||
stack[index-1].type = Item::numerical_value;
|
stack[index-1].type = Item::numerical_value;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
the pointer of the stack will be pointing on the next (non-existing now) element
|
the pointer of the stack will be pointing on the next (non-existing now) element
|
||||||
@@ -2710,7 +2731,7 @@ ErrorCode Parse(const std::wstring & str)
|
|||||||
/*!
|
/*!
|
||||||
this method returns true is something was calculated
|
this method returns true is something was calculated
|
||||||
(at least one mathematical operator was used or a function or variable)
|
(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"
|
"1+1"
|
||||||
"2*3"
|
"2*3"
|
||||||
"sin(5)"
|
"sin(5)"
|
||||||
@@ -2722,6 +2743,7 @@ bool Calculated()
|
|||||||
return calculated;
|
return calculated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
* Copyright (c) 2006-2010, 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
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 9
|
#define TTMATH_MINOR_VER 9
|
||||||
#define TTMATH_REVISION_VER 0
|
#define TTMATH_REVISION_VER 1
|
||||||
#define TTMATH_PRERELEASE_VER 0
|
#define TTMATH_PRERELEASE_VER 0
|
||||||
|
|
||||||
|
|
||||||
|
@@ -627,7 +627,7 @@ public:
|
|||||||
if 'this' is not zero:
|
if 'this' is not zero:
|
||||||
return value - true
|
return value - true
|
||||||
'table_id' - the index of a word <0..value_size-1>
|
'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:
|
if 'this' is zero:
|
||||||
return value - false
|
return value - false
|
||||||
@@ -645,7 +645,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// table[table_id] != 0
|
// table[table_id] is different from 0
|
||||||
index = FindLeadingBitInWord( table[table_id] );
|
index = FindLeadingBitInWord( table[table_id] );
|
||||||
|
|
||||||
return true;
|
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
|
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);
|
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 uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
|
||||||
static sint FindLeadingBitInWord(uint x);
|
static sint FindLeadingBitInWord(uint x);
|
||||||
|
static sint FindLowestBitInWord(uint x);
|
||||||
static uint SetBitInWord(uint & value, uint bit);
|
static uint SetBitInWord(uint & value, uint bit);
|
||||||
static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
|
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);
|
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'
|
this method sets a special bit in the 'value'
|
||||||
and returns the last state of the bit (zero or one)
|
and returns the last state of the bit (zero or one)
|
||||||
|
Reference in New Issue
Block a user