initial import
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@1 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
commit
ab42f75285
|
@ -0,0 +1,4 @@
|
|||
Version 0.6.2 (2007.01.10):
|
||||
* New division algorithm (radix b) where b is 2^32
|
||||
|
||||
|
|
@ -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.
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue