initial import

git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@1 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2007-01-21 20:02:44 +00:00
commit ab42f75285
11 changed files with 9408 additions and 0 deletions

4
CHANGELOG Normal file
View File

@ -0,0 +1,4 @@
Version 0.6.2 (2007.01.10):
* New division algorithm (radix b) where b is 2^32

28
COPYRIGHT Normal file
View File

@ -0,0 +1,28 @@
Copyright (c) 2006-2007, Tomasz Sowa
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name Tomasz Sowa nor the names of contributors to this
project may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

2
README Normal file
View File

@ -0,0 +1,2 @@

7
TODO Normal file
View File

@ -0,0 +1,7 @@
TODO TTMath Library
===================

530
ttmath/ttmath.h Normal file
View File

@ -0,0 +1,530 @@
/*
* This file is part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2006-2007, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmathmathtt
#define headerfilettmathmathtt
/*!
\file ttmath.h
\brief Mathematics functions.
*/
#include "ttmathbig.h"
#include <string>
namespace ttmath
{
/*!
the factorial from given 'x'
e.g.
Factorial(4) = 4! = 1*2*3*4
*/
template<int exp,int man>
Big<exp, man> Factorial(const Big<exp, man> & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
{
Big<exp, man> result;
result.SetOne();
if( x.IsSign() )
{
if( err )
*err = err_improper_argument;
return result;
}
if( !x.exponent.IsSign() && !x.exponent.IsZero() )
{
// when x>0 there's no sense to calculate the formula
// (we can't add one into the x bacause
// we don't have enough bits in our mantissa)
if( err )
*err = err_overflow;
return result;
}
Big<exp, man> multipler;
Big<exp, man> one;
uint carry = 0;
one = result; // =1
multipler = result; // =1
while( !carry && multipler < x )
{
if( stop && stop->WasStopSignal() )
{
if( err )
*err = err_interrupt;
return result;
}
carry += multipler.Add(one);
carry += result.Mul(multipler);
}
if( err )
{
if( carry )
*err = err_overflow;
else
*err = err_ok;
}
return result;
}
/*!
absolute value of x
e.g. -2 = 2
2 = 2
*/
template<int exp,int man>
Big<exp, man> Abs(const Big<exp, man> & x)
{
Big<exp, man> result( x );
result.Abs();
return result;
}
/*!
this method skips the fraction from x
e.g 2.2 = 2
2.7 = 2
-2.2 = 2
-2.7 = 2
*/
template<int exp,int man>
Big<exp, man> SkipFraction(const Big<exp, man> & x)
{
Big<exp, man> result( x );
result.SkipFraction();
return result;
}
/*!
this method rounds to the nearest integer value
e.g 2.2 = 2
2.7 = 3
-2.2 = -2
-2.7 = -3
*/
template<int exp,int man>
Big<exp, man> Round(const Big<exp, man> & x)
{
Big<exp, man> result( x );
result.Round();
return result;
}
/*!
this method calculates the natural logarithm (logarithm with the base 'e')
*/
template<int exp,int man>
Big<exp, man> Ln(const Big<exp, man> & x, ErrorCode * err = 0)
{
Big<exp, man> result;
uint state = result.Ln(x);
if( err )
{
switch( state )
{
case 0:
*err = err_ok;
break;
case 1:
*err = err_overflow;
break;
case 2:
*err = err_improper_argument;
break;
default:
*err = err_internal_error;
break;
}
}
return result;
}
/*!
this method calculates the logarithm
*/
template<int exp,int man>
Big<exp, man> Log(const Big<exp, man> & base, const Big<exp, man> & x, ErrorCode * err = 0)
{
Big<exp, man> result;
uint state = result.Log(base,x);
if( err )
{
switch( state )
{
case 0:
*err = err_ok;
break;
case 1:
*err = err_overflow;
break;
case 2:
case 3:
*err = err_improper_argument;
break;
default:
*err = err_internal_error;
break;
}
}
return result;
}
/*!
this method calculates the expression e^x
*/
template<int exp,int man>
Big<exp, man> Exp(const Big<exp, man> & x, ErrorCode * err = 0)
{
Big<exp, man> result;
uint state = result.Exp(x);
if( err )
if( state!=0 )
*err = err_overflow;
else
*err = err_ok;
return result;
}
/*!
*
* trigonometric functions
*
*/
/*!
an auxiliary function for calculating the Sin
(you don't have to call this function)
*/
template<int exp,int man>
void PrepareSin(Big<exp,man> & x, bool & change_sign)
{
Big<exp,man> temp;
change_sign = false;
if( x.IsSign() )
{
// we're using the formula 'sin(-x) = -sin(x)'
change_sign = !change_sign;
x.ChangeSign();
}
// we're reducing the period 2*PI
// (for big values there'll always be zero)
temp.Set2Pi();
if( x > temp )
{
x.Div( temp );
x.RemainFraction();
x.Mul( temp );
}
// we're setting 'x' as being in the range of <0, 0.5PI>
temp.SetPi();
if( x > temp )
{
// x is in (pi, 2*pi>
x.Sub( temp );
change_sign = !change_sign;
}
temp.Set05Pi();
if( x > temp )
{
// x is in (0.5pi, pi>
x.Sub( temp );
x = temp - x;
}
}
/*!
an auxiliary function for calculating the Sin
(you don't have to call this function)
it returns Sin(x) where 'x' is from <0, PI/2>
we're calculating the Sin with using Taylor series in zero or PI/2
(depending on which point of these two points is nearer to the 'x')
Taylor series:
sin(x) = sin(a) + cos(a)*(x-a)/(1!)
- sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!)
+ sin(a)*((x-a)^4)/(4!) + ...
when a=0 it'll be:
sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ...
and when a=PI/2:
sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ...
*/
template<int exp,int man>
Big<exp,man> Sin0pi05(const Big<exp,man> & x)
{
Big<exp,man> result;
Big<exp,man> numerator, denominator;
Big<exp,man> d_numerator, d_denominator;
Big<exp,man> one, temp, old_result;
// temp = pi/4
temp.Set05Pi();
temp.exponent.SubOne();
one.SetOne();
if( x < temp )
{
// we're using the Taylor series with a=0
result = x;
numerator = x;
denominator = one;
// d_numerator = x^2
d_numerator = x;
d_numerator.Mul(x);
d_denominator = 2;
}
else
{
// we're using the Taylor series with a=PI/2
result = one;
numerator = one;
denominator = one;
// d_numerator = (x-pi/2)^2
Big<exp,man> pi05;
pi05.Set05Pi();
temp = x;
temp.Sub( pi05 );
d_numerator = temp;
d_numerator.Mul( temp );
d_denominator = one;
}
int c = 0;
bool addition = false;
old_result = result;
for(int i=1 ; i<5000 ; ++i)
{
// we're starting from a second part of the formula
c += numerator. Mul( d_numerator );
c += denominator. Mul( d_denominator );
c += d_denominator.Add( one );
c += denominator. Mul( d_denominator );
c += d_denominator.Add( one );
temp = numerator;
c += temp.Div(denominator);
if( c )
// Sin is from <-1,1> and cannot make an overflow
// but the carry can be from the Taylor series
// (then we only breaks our calculations)
break;
if( addition )
result.Add( temp );
else
result.Sub( temp );
addition = !addition;
// we're testing whether the result has changed after adding
// the next part of the Taylor formula, if not we end the loop
// (it means 'x' is zero or 'x' is PI/2 or this part of the formula
// is too small)
if( result == old_result )
break;
old_result = result;
}
return result;
}
/*!
this function calulates the Sin
*/
template<int exp,int man>
Big<exp,man> Sin(Big<exp,man> x)
{
Big<exp,man> one;
bool change_sign;
PrepareSin( x, change_sign );
Big<exp,man> result = Sin0pi05( x );
one.SetOne();
if( result > one )
result = one;
else
if( result.IsSign() )
result.SetZero();
if( change_sign )
result.ChangeSign();
return result;
}
/*!
this function calulates the Cos
we're using the formula cos(x) = sin(x + PI/2)
*/
template<int exp,int man>
Big<exp,man> Cos(Big<exp,man> x)
{
Big<exp,man> pi05;
pi05.Set05Pi();
x.Add( pi05 );
return Sin(x);
}
/*!
this function calulates the Tan
we're using the formula tan(x) = sin(x) / cos(x)
it takes more time than calculating the Tan directly
from for example Taylor series but should be a bit precise
because Tan receives its values from -infinity to +infinity
and when we calculate it from any series then we can make
a small mistake than calculating 'sin/cos'
*/
template<int exp,int man>
Big<exp,man> Tan(const Big<exp,man> & x, ErrorCode * err = 0)
{
Big<exp,man> result = Cos(x);
if( result.IsZero() )
{
if( err )
*err = err_improper_argument;
return result;
}
if( err )
*err = err_ok;
return Sin(x) / result;
}
/*!
this function calulates the CTan
we're using the formula tan(x) = cos(x) / sin(x)
(why do we make it in this way?
look at the info in Tan() function)
*/
template<int exp,int man>
Big<exp,man> CTan(const Big<exp,man> & x, ErrorCode * err = 0)
{
Big<exp,man> result = Sin(x);
if( result.IsZero() )
{
if( err )
*err = err_improper_argument;
return result;
}
if( err )
*err = err_ok;
return Cos(x) / result;
}
} // namespace
#endif

2824
ttmath/ttmathbig.h Normal file

File diff suppressed because it is too large Load Diff

997
ttmath/ttmathint.h Normal file
View File

@ -0,0 +1,997 @@
/*
* This file is part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2006-2007, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmathint
#define headerfilettmathint
/*!
\file ttmathint.h
\brief template class Int<uint>
*/
#include "ttmathuint.h"
namespace ttmath
{
/*!
\brief it implements the big integer value with the sign
value_size - how many bytes specify our value (value_size = 1 -> 4 bytes -> 32 bits)
value_size = 1,2,3,4,5,6....
*/
template<uint value_size>
class Int : public UInt<value_size>
{
public:
/*!
this method sets the max value which this class can hold
(all bits will be one besides the last one)
*/
void SetMaxValue()
{
UInt<value_size>::SetMaxValue();
UInt<value_size>::table[value_size-1] = ~uint_the_highest_bit;
}
/*!
this method sets the min value which this class can hold
(all bits will be zero besides the last one which is one)
*/
void SetMinValue()
{
UInt<value_size>::SetZero();
UInt<value_size>::table[value_size-1] = uint_the_highest_bit;
}
/*!
this method sets -1 as the value
(-1 is equal the max value in an unsigned type)
*/
void SetSignOne()
{
UInt<value_size>::SetMaxValue();
}
/*!
we change the sign of the value
if it isn't possible to change the sign this method returns 1
else return 0 and changing the sign
*/
uint ChangeSign()
{
Int<value_size> temp;
temp.SetMinValue();
/*
if the value is equal that one which has been returned from SetMinValue
that means we can't change sign because the value is too big (bigger about one)
e.g. when value_size = 1 and value is -2147483648 we can't change it to the
2147483648 because the max value which can be held is 2147483647
we don't change the value and we're using this fact somewhere in some methods
(if we look on our value without the sign we get the correct value
eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type)
*/
if( operator==(temp) )
return 1;
temp.SetZero();
temp.UInt<value_size>::Sub(*this);
operator=(temp);
return 0;
}
/*!
this method sets the sign
e.g. 1 -> -1
-2 -> -2
from a positive value we always make a negative value
*/
void SetSign()
{
if( IsSign() )
return;
ChangeSign();
}
/*!
this method returns true if there's the sign
(the highest bit will be converted to the bool)
*/
bool IsSign() const
{
return UInt<value_size>::IsTheHighestBitSet();
}
/*!
it returns the absolute value
it can return carry (1) (look on ChangeSign() for details)
*/
uint Abs()
{
if( !IsSign() )
return 0;
return ChangeSign();
}
/*!
*
* basic mathematic functions
*
*/
/*!
this method adds two value with sign and returns carry
we're using methods from the base class because values are stored with U2
we must only make the carry correction
this = p1(=this) + p2
when p1>=0 i p2>=0 carry is set when the highest bit of value is set
when p1<0 i p2<0 carry is set when the highest bit of value is clear
when p1>=0 i p2<0 carry will never be set
when p1<0 i p2>=0 carry will never be set
*/
uint Add(const Int<value_size> & ss2)
{
bool p1_is_sign = IsSign();
bool p2_is_sign = ss2.IsSign();
UInt<value_size>::Add(ss2);
if( !p1_is_sign && !p2_is_sign )
{
if( UInt<value_size>::IsTheHighestBitSet() )
return 1;
}
if( p1_is_sign && p2_is_sign )
{
if( ! UInt<value_size>::IsTheHighestBitSet() )
return 1;
}
return 0;
}
/*!
this method subtracts two values with the sign
we don't use the previous Add because the method ChangeSign can
sometimes return carry
this = p1(=this) - p2
when p1>=0 i p2>=0 carry will never be set
when p1<0 i p2<0 carry will never be set
when p1>=0 i p2<0 carry is set when the highest bit of value is set
when p1<0 i p2>=0 carry is set when the highest bit of value is clear
*/
uint Sub(const Int<value_size> & ss2)
{
bool p1_is_sign = IsSign();
bool p2_is_sign = ss2.IsSign();
UInt<value_size>::Sub(ss2);
if( !p1_is_sign && p2_is_sign )
{
if( UInt<value_size>::IsTheHighestBitSet() )
return 1;
}
if( p1_is_sign && !p2_is_sign )
{
if( ! UInt<value_size>::IsTheHighestBitSet() )
return 1;
}
return 0;
}
/*!
this method adds one to the value and returns carry
*/
uint AddOne()
{
Int<value_size> temp;
temp.SetOne();
return Add(temp);
}
/*!
this method subtracts one from the value and returns carry
*/
uint SubOne()
{
Int<value_size> temp;
temp.SetOne();
return Sub(temp);
}
/*!
multiplication this = this * ss2
it returns carry if the result is too big
(we're using the method from the base class but we have to make
one correction in account of signs)
*/
uint Mul(Int<value_size> ss2)
{
bool ss1_is_sign, ss2_is_sign;
ss1_is_sign = IsSign();
ss2_is_sign = ss2.IsSign();
/*
we don't have to check the carry from Abs (values will be correct
because next we're using the method Mul from the base class UInt
which is without a sign)
*/
Abs();
ss2.Abs();
if( UInt<value_size>::Mul(ss2) )
return 1;
/*
we have to examine the sign of result now
but if the result is with the sign then:
1. if the signs were the same that means the result is too big
(the result must be without a sign)
2. if the signs were diffrent that means if the result
is different from that one which has been returned from SetMinValue()
that is carry (result too big) but if the result is equal SetMinValue()
there'll be ok (and the next SetSign will has no effect because
the value is actually negative -- look at description of that case
in ChangeSign())
*/
if( IsSign() )
{
/*
there can be one case where signs are different and
the result will be equal the value from SetMinValue()
(there is ok situation)
*/
if( ss1_is_sign != ss2_is_sign )
{
Int<value_size> temp;
temp.SetMinValue();
if( operator!=(temp) )
/*
the result is too big
*/
return 1;
}
else
{
/*
the result is too big
*/
return 1;
}
}
if( ss1_is_sign != ss2_is_sign )
SetSign();
return 0;
}
/*!
division this = this / ss2
function returns the remainder
for example: (result means this)
20 / 3 --> result: 6 remainder: 2
-20 / 3 --> result: -6 remainder: -2
20 / -3 --> result: -6 remainder: 2
-20 / -3 --> result: 6 remainder: -2
in other words: this(old) = result * this(new) + remainder
*/
Int<value_size> Div(Int<value_size> ss2)
{
bool ss1_is_sign, ss2_is_sign;
Int<value_size> remainder;
ss1_is_sign = IsSign();
ss2_is_sign = ss2.IsSign();
/*
we don't have to test the carry from Abs as well as in Mul
*/
Abs();
ss2.Abs();
remainder = UInt<value_size>::Div(ss2);
if( ss1_is_sign != ss2_is_sign )
SetSign();
if( ss1_is_sign )
remainder.SetSign();
return remainder;
}
/*!
*
* convertion methods
*
*/
/*!
this method convert an UInt<another_size> type to this class
this operation has mainly sense if the value from p
can be held in this type
it returns a carry if the value 'p' is too big
*/
template<uint argument_size>
uint FromInt(const Int<argument_size> & p)
{
uint min_size = (value_size < argument_size)? value_size : argument_size;
uint i;
for(i=0 ; i<min_size ; ++i)
UInt<value_size>::table[i] = p.table[i];
if( i < value_size )
{
uint fill = (p.table[argument_size-1] & uint_the_highest_bit)? uint_max_value : 0;
for( ; i<value_size ; ++i)
UInt<value_size>::table[i] = fill;
}
else
{
uint test = (UInt<value_size>::table[value_size-1] & uint_the_highest_bit)? uint_max_value : 0;
for( ; i<argument_size ; ++i)
if( p.table[i] != test )
return 1;
}
return 0;
}
/*!
this operator convert an UInt<another_size> type to this class
it doesn't return a carry
*/
template<uint argument_size>
Int<value_size> & operator=(const Int<argument_size> & p)
{
FromInt(p);
return *this;
}
/*!
the default assignment operator
*/
Int<value_size> & operator=(const Int<value_size> & p)
{
FromInt(p);
return *this;
}
/*!
this method convert an int type to this class
*/
Int<value_size> & operator=(int i)
{
if(i<0)
SetSignOne();
else
UInt<value_size>::SetZero();
UInt<value_size>::table[0] = uint(i);
return *this;
}
/*!
constructor for converting an uint to this class
*/
Int(int i)
{
operator=(i);
}
/*!
constructor for converting string to this class (with base=10)
*/
Int(const char * s)
{
FromString(s);
}
/*!
constructor for converting string to this class (with base=10)
*/
Int(const std::string & s)
{
FromString( s.c_str() );
}
/*!
default constructor
we don't clear table etc.
*/
Int()
{
}
/*!
the copying constructor
*/
template<uint argument_size>
Int(const Int<argument_size> & u) : UInt<value_size>::size(value_size)
{
// look that 'size' we still set as 'value_size' and not as u.value_size
operator=(u);
}
/*!
a destructor
*/
virtual ~Int()
{
}
/*!
this method returns the lowest value from table with the sign
we must be sure when we using this method whether the value
will hold in an int type or not (the rest value from table must be zero or -1)
*/
int ToInt() const
{
return int( UInt<value_size>::table[0] );
}
/*!
this method converts the value to a string with a base equal 'b'
*/
void ToString(std::string & result, uint b = 10) const
{
if( IsSign() )
{
Int<value_size> temp(*this);
temp.Abs();
temp.UInt<value_size>::ToString(result, b);
result.insert(result.begin(), '-');
}
else
{
UInt<value_size>::ToString(result, b);
}
}
/*!
this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
string is ended with a non-digit value, for example:
"-12" will be translated to -12
as well as:
"- 12foo" will be translated to 12 too
existing first white characters will be ommited
(between '-' and a first digit can be white characters too)
*/
uint FromString(const char * s, uint b = 10)
{
bool is_sign = false;
UInt<value_size>::SkipWhiteCharacters(s);
if( *s == '-' )
{
is_sign = true;
UInt<value_size>::SkipWhiteCharacters(++s);
}
else
if( *s == '+' )
{
UInt<value_size>::SkipWhiteCharacters(++s);
}
if( UInt<value_size>::FromString(s,b) )
return 1;
if( is_sign )
{
Int<value_size> mmin;
mmin.SetMinValue();
/*
the reference to mmin will be automatically converted to the reference
to a UInt type
(this value can be equal mmin -- look at a description in ChangeSign())
*/
if( UInt<value_size>::operator>( mmin ) )
return 1;
ChangeSign();
}
else
{
Int<value_size> mmax;
mmax.SetMaxValue();
if( UInt<value_size>::operator>( mmax ) )
return 1;
}
return 0;
}
/*!
this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
*/
uint FromString(const std::string & s, uint b = 10)
{
return FromString( s.c_str() );
}
/*!
this operator converts a string into its value (with base = 10)
*/
Int<value_size> & operator=(const char * s)
{
FromString(s);
return *this;
}
/*!
this operator converts a string into its value (with base = 10)
*/
Int<value_size> & operator=(const std::string & s)
{
FromString( s.c_str() );
return *this;
}
/*!
*
* methods for comparing
*
* operators == and != will be the same as in the base class (UInt<value_size>)
*
*/
bool operator<(const Int<value_size> & l) const
{
int i=value_size-1;
int a1 = int(UInt<value_size>::table[i]);
int a2 = int(l.table[i]);
if( a1 != a2 )
return a1 < a2;
// comparison as int
// if( int(UInt<value_size>::table[i]) != int(l.table[i]) )
// return int(UInt<value_size>::table[i]) < int(l.table[i]);
for(--i ; i>=0 ; --i)
{
if( UInt<value_size>::table[i] != l.table[i] )
// comparison as unsigned int
return UInt<value_size>::table[i] < l.table[i];
}
// they're equal
return false;
}
bool operator>(const Int<value_size> & l) const
{
int i=value_size-1;
int a1 = int(UInt<value_size>::table[i]);
int a2 = int(l.table[i]);
if( a1 != a2 )
return a1 > a2;
// comparison as int
// if( int(UInt<value_size>::table[i]) != int(l.table[i]) )
// return int(UInt<value_size>::table[i]) > int(l.table[i]);
for(--i ; i>=0 ; --i)
{
if( UInt<value_size>::table[i] != l.table[i] )
// comparison as unsigned int
return UInt<value_size>::table[i] > l.table[i];
}
// they're equal
return false;
}
bool operator<=(const Int<value_size> & l) const
{
int i=value_size-1;
int a1 = int(UInt<value_size>::table[i]);
int a2 = int(l.table[i]);
if( a1 != a2 )
return a1 < a2;
// comparison as int
// if( int(UInt<value_size>::table[i]) != int(l.table[i]) )
// return int(UInt<value_size>::table[i]) < int(l.table[i]);
for(--i ; i>=0 ; --i)
{
if( UInt<value_size>::table[i] != l.table[i] )
// comparison as unsigned int
return UInt<value_size>::table[i] < l.table[i];
}
// they're equal
return true;
}
bool operator>=(const Int<value_size> & l) const
{
int i=value_size-1;
int a1 = int(UInt<value_size>::table[i]);
int a2 = int(l.table[i]);
if( a1 != a2 )
return a1 > a2;
// comparison as int
// if( int(UInt<value_size>::table[i]) != int(l.table[i]) )
// return int(UInt<value_size>::table[i]) > int(l.table[i]);
for(--i ; i>=0 ; --i)
{
if( UInt<value_size>::table[i] != l.table[i] )
// comparison as unsigned int
return UInt<value_size>::table[i] > l.table[i];
}
// they're equal
return true;
}
/*!
*
* standard mathematical operators
*
*/
/*!
an operator for changing the sign
it's not changing 'this' but the changed value will be returned
*/
Int<value_size> operator-() const
{
Int<value_size> temp(*this);
temp.ChangeSign();
return temp;
}
Int<value_size> operator-(const Int<value_size> & p2) const
{
Int<value_size> temp(*this);
temp.Sub(p2);
return temp;
}
Int<value_size> & operator-=(const Int<value_size> & p2)
{
Sub(p2);
return *this;
}
Int<value_size> operator+(const Int<value_size> & p2) const
{
Int<value_size> temp(*this);
temp.Add(p2);
return temp;
}
Int<value_size> & operator+=(const Int<value_size> & p2)
{
Add(p2);
return *this;
}
Int<value_size> operator*(const Int<value_size> & p2) const
{
Int<value_size> temp(*this);
temp.Mul(p2);
return temp;
}
Int<value_size> & operator*=(const Int<value_size> & p2)
{
Mul(p2);
return *this;
}
Int<value_size> operator/(const Int<value_size> & p2) const
{
Int<value_size> temp(*this);
temp.Div(p2);
return temp;
}
Int<value_size> & operator/=(const Int<value_size> & p2)
{
Div(p2);
return *this;
}
Int<value_size> operator%(const Int<value_size> & p2) const
{
Int<value_size> temp(*this);
Int<value_size> remainder = temp.Div( p2 );
return remainder;
}
Int<value_size> & operator%=(const Int<value_size> & p2)
{
Int<value_size> temp(*this);
Int<value_size> remainder = temp.Div( p2 );
operator=(remainder);
return *this;
}
/*!
Prefix operator e.g ++variable
*/
UInt<value_size> & operator++()
{
AddOne();
return *this;
}
/*!
Postfix operator e.g variable++
*/
UInt<value_size> operator++(int)
{
UInt<value_size> temp( *this );
AddOne();
return temp;
}
UInt<value_size> & operator--()
{
AddOne();
return *this;
}
UInt<value_size> operator--(int)
{
UInt<value_size> temp( *this );
SubOne();
return temp;
}
/*!
*
* input/output operators for standard streams
*
*/
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
{
std::string ss;
l.ToString(ss);
s << ss;
return s;
}
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
{
std::string ss;
// char for operator>>
unsigned char z;
// operator>> omits white characters if they're set for ommiting
s >> z;
if( z=='-' || z=='+' )
{
ss += z;
s >> z; // we're reading a next character (white characters can be ommited)
}
// we're reading only digits (base=10)
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
{
ss += z;
z = s.get();
}
// we're leaving the last readed character
// (it's not belonging to the value)
s.unget();
l.FromString(ss);
return s;
}
};
} // namespace
#endif

181
ttmath/ttmathobjects.h Normal file
View File

@ -0,0 +1,181 @@
/*
* This file is part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2006-2007, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmathobject
#define headerfilettmathobject
#include "ttmathtypes.h"
#include <string>
#include <map>
#include <algorithm>
namespace ttmath
{
class Objects
{
public:
struct ObjectValue
{
std::string value;
int param;
ObjectValue() {}
ObjectValue(const std::string & v, int p) : value(v), param(p) {}
};
typedef std::map<std::string, ObjectValue> Table;
typedef Table::const_iterator CIterator;
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
{
Table::iterator i = table.find(name);
if( i != table.end() )
// we have this object in our table
return err_object_exists;
table.insert( std::make_pair(name, ObjectValue(value, param)) );
return err_ok;
}
bool Empty() const
{
return table.empty();
}
void Clear()
{
return table.clear();
}
CIterator Begin() const
{
return table.begin();
}
CIterator End() const
{
return table.end();
}
ErrorCode Edit(const std::string & name, const std::string & value, int param = 0)
{
Table::iterator i = table.find(name);
if( i == table.end() )
// we don't have this variable in our table
return err_unknown_object;
i->second.value = value;
i->second.param = param;
return err_ok;
}
ErrorCode Delete(const std::string & name)
{
Table::iterator i = table.find(name);
if( i == table.end() )
// we don't have this variable in our table
return err_unknown_object;
table.erase( i );
return err_ok;
}
ErrorCode GetValue(const std::string & name, const char * * value) const
{
Table::const_iterator i = table.find(name);
if( i == table.end() )
{
// we don't have this variable in our table
*value = 0;
return err_unknown_object;
}
*value = i->second.value.c_str();
return err_ok;
}
ErrorCode GetValueParam(const std::string & name, const char * * value, int * param) const
{
Table::const_iterator i = table.find(name);
if( i == table.end() )
{
// we don't have this variable in our table
*value = 0;
return err_unknown_object;
}
*value = i->second.value.c_str();
*param = i->second.param;
return err_ok;
}
Table * GetTable()
{
return &table;
}
private:
Table table;
};
} // namespace
#endif

1705
ttmath/ttmathparser.h Normal file

File diff suppressed because it is too large Load Diff

284
ttmath/ttmathtypes.h Normal file
View File

@ -0,0 +1,284 @@
/*
* This file is part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2006-2007, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfilettmathtypes
#define headerfilettmathtypes
/*!
\file ttmathtypes.h
\brief A Documented file.
Details.
*/
#include <exception>
#include <string>
#include <iostream>
#include <map>
/*!
the version of the library
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 6
#define TTMATH_REVISION_VER 2
/*!
this macro enables further testing during writing your code
you don't have to define it in a release mode
if this macro is set then macro MATHTT_ASSERT is set as well
and MATHTT_ASSERT can throw an exception if a condition is not fulfilled
(look at the definition of MATHTT_ASSERT)
if you don't want any further testing put two characters '//' before this macro
e.g.
// #define MATHTT_DEBUG
*/
#define MATHTT_DEBUG
/*!
32 bit integer value without a sign
(the same on 64 bits platform (amd))
*/
typedef unsigned int uint;
/*!
how many bits there are in the uint type
*/
#define BITS_PER_UINT 32u
/*!
the mask for the highest bit in the unsigned 32bits word (2^31)
*/
#define uint_the_highest_bit 2147483648u
/*!
the max value of the unsigned 32bits word (2^32 - 1)
(all bits equal one)
*/
#define uint_max_value 4294967295u
/*!
if you define this macro that means the version one of the multiplication algorithm
will be used in the UInt class
*/
//#define UINT_MUL_VERSION_1
/*!
if you define this macro that means the version two of the multiplication algorithm
will be used in the UInt class
this algorithm is much faster than previous
you can't use both these macros together, you must use either UINT_MUL_VERSION_1
or UINT_MUL_VERSION_2
*/
#define UINT_MUL_VERSION_2
/*!
characters which represent the comma operator
MATHTT_COMMA_CHARACTER_1 is used in reading (parsing) and in writing
MATHTT_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
that means you can input values for example 1.2345 and 1,2345 as well
if you don't want it just put 0 there eg.
#define MATHTT_COMMA_CHARACTER_2 0
then only MATHTT_COMMA_CHARACTER_1 will be used
don't put here any special character which is used by the parser
(for example a semicolon ';' shouldn't be here)
*/
#define MATHTT_COMMA_CHARACTER_1 '.'
#define MATHTT_COMMA_CHARACTER_2 ','
////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//// odwrocic nazwy ma byc TTMATH
namespace ttmath
{
/*!
error codes
*/
enum ErrorCode
{
err_ok = 0,
err_nothing_has_read = 1,
err_unknown_character = 2,
err_unexpected_final_bracket = 4,
err_stack_not_clear = 6,
err_unknown_variable = 8,
err_division_by_zero = 9,
err_interrupt = 10,
err_overflow = 11,
err_unknown_function = 12,
err_unexpected_semicolon_operator = 18,
err_improper_amount_of_arguments = 19,
err_improper_argument = 20,
err_unexpected_end = 21,
err_internal_error = 100,
err_incorrect_name,
err_incorrect_value,
err_variable_exists,
err_variable_loop,
err_functions_loop,
err_must_be_only_one_value,
err_object_exists,
err_unknown_object,
err_this_cant_be_used = 200
};
class StopCalculating
{
public:
virtual bool WasStopSignal() const volatile { return false; }
virtual ~StopCalculating(){}
};
// moze tutaj z runtime dziedziczyc?
//zmienic nazwe na TTMathError
class MathTTError : public std::exception
{
ErrorCode code;
public:
MathTTError(ErrorCode c) : code(c) {}
const char* what() const throw()
{
switch( code )
{
case err_this_cant_be_used:
return "You've used 'this' somewhere in your code but you can't use it there";
// dac tu jakis lepszy komunikat w stylu
// 'uzyles referencji do samego siebie ale w tym miejscu nie mozesz tego zrobic'
default:
return ":)"; // temporary
}
return "Unnamed";
}
};
#ifdef MATHTT_DEBUG
#define MATHTT_ASSERT(expression, c) \
if( !(expression) ) throw MathTTError(c);
#else
#define MATHTT_ASSERT(expression, c)
#endif
#define MATHTT_THIS_ASSERT(expression) \
MATHTT_ASSERT( &expression != this, err_this_cant_be_used)
/*
template<class ValueType>
class ValuesHistory
{
typedef std::map<ValueType, ValueType> buffer_type;
buffer_type buffer;
public:
void AddValue(const ValueType & key, const ValueType & result)
{
buffer.insert( std::make_pair(key, result) );
}
bool GetValue(const ValueType & key, ValueType & result) const
{
buffer_type::iterator i = buffer.find( key );
if( i == buffer.end() )
return false;
result = *i;
return true;
}
uint Size() const
{
return static_cast<uint>( buffer.size() );
}
};
*/
} // namespace
#endif

2846
ttmath/ttmathuint.h Normal file

File diff suppressed because it is too large Load Diff