Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
98c2379182 | |||
2933213a02 | |||
4d0241c9c9 | |||
4f3f05fa9d | |||
f139e6457c | |||
29bb4fb3f7 | |||
5002f435ae | |||
61886fc829 | |||
25f876762a | |||
692ff5406e | |||
669698c6d7 | |||
93ba8ce17d | |||
d27cabec93 | |||
bc9d528a75 | |||
bb16c871c9 | |||
2116418f08 | |||
062881900a | |||
0170572f84 | |||
e40ed603c6 | |||
c97ebf282f |
233
CHANGELOG
233
CHANGELOG
@@ -1,84 +1,171 @@
|
|||||||
|
Version 0.8.2 (2008.06.18):
|
||||||
|
* added: UInt::BitNot2() this method has been proposed by
|
||||||
|
Arek <kmicicc AnTispam users.sourceforge.net>
|
||||||
|
* changed: Int::FromInt(const Int<argument_size> & p),
|
||||||
|
Int::FromInt(sint value) (it returns zero now)
|
||||||
|
Int::operator=(uint i)
|
||||||
|
Int::Int(uint i)
|
||||||
|
* added: Int::FromUInt(const UInt<argument_size> & p),
|
||||||
|
Int::FromUInt(uint value)
|
||||||
|
and appropriate constructors and assignment
|
||||||
|
operators as well
|
||||||
|
* changed: Big::FromInt(Int<int_size> value),
|
||||||
|
* added: Big::FromUInt(UInt<int_size> value),
|
||||||
|
Big::operator=(const UInt<int_size> & value)
|
||||||
|
Big::Big(const UInt<int_size> & value)
|
||||||
|
* changed: the parser is allowed to recognize values which
|
||||||
|
begin with a dot, e.g '.5' is treated as '0.5'
|
||||||
|
* added: a method Big::FromDouble(double) which converts from
|
||||||
|
standard double into a Big
|
||||||
|
* added: uint Big::ToDouble(double&) - converting into double
|
||||||
|
* added: Big::FromBig() and an operator= and a contructor
|
||||||
|
for converting from another kind of a Big class
|
||||||
|
* added: to the parser: avg(), sum()
|
||||||
|
* added: 'decimal_point' parameter into Big::ToString(...)
|
||||||
|
* fixed: Big::operator>> didn't use TTMATH_COMMA_CHARACTER_2 macro
|
||||||
|
* added: a short form of multiplication (without the '*' character)
|
||||||
|
e.g. '5y', (it's used only if the second parameter
|
||||||
|
is a variable or function)
|
||||||
|
* changed: variables and functions are case-sensitive now
|
||||||
|
* added: variables and functions can have underline characters
|
||||||
|
in their names
|
||||||
|
* changed: 'max_digit_after_comma' in Big::ToString()
|
||||||
|
remove the -2 state
|
||||||
|
* added: 'remove_trailing_zeroes' in Big::ToString()
|
||||||
|
it's either true or false
|
||||||
|
* fixed/changed: the way of using Big::SetSign()
|
||||||
|
the method do not check whether there is a zero or not now
|
||||||
|
(even if there's a zero the method can set a sign bit)
|
||||||
|
I changed this due to some prior errors
|
||||||
|
(errors corrected in revision 17, 49 and 58)
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.1 (2007.04.17):
|
||||||
|
* fixed: Big::PowFrac(..) didn't return a correct error code
|
||||||
|
(when 'this' was negative)
|
||||||
|
* added: Root(x; index) (and to the parser as well)
|
||||||
|
* added: macro: TTMATH_PRERELEASE_VER (can be either zero or one)
|
||||||
|
* added: UInt::MulInt(int, UInt<int another_size>::&)
|
||||||
|
* added: Big::MulUInt(uint)
|
||||||
|
* changed: Big::MulInt(sint)
|
||||||
|
* added: Big::ToUInt(uint &)
|
||||||
|
* changed: Big::ToInt(sint&)
|
||||||
|
* changed: Factorial() it uses Big::MulUInt() at the beginning
|
||||||
|
(faster now especially more on a 32bit platform)
|
||||||
|
* added: doxygen.cfg for generating a documentation from the doxygen
|
||||||
|
* changed: UInt::Rcl(uint c=0) and UInt::Rcr(uint c=0) into
|
||||||
|
UInt::Rcl2(uint bits, uint c) and UInt::Rcr2(uint bits, uint c)
|
||||||
|
now they can move more than one bit and they are only private
|
||||||
|
* fixed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||||
|
didn't correctly return a carry if the 'bits' were equal
|
||||||
|
to 'value_size*TTMATH_BITS_PER_UINT'
|
||||||
|
* changed: UInt::Rcl(uint bits, uint c) and UInt::Rcr(uint bits, uint c)
|
||||||
|
into UInt::Rcl(uint bits, uint c=0) and
|
||||||
|
UInt::Rcr(uint bits, uint c=0)
|
||||||
|
they are faster now when the bits is greater than a half of
|
||||||
|
the TTMATH_BITS_PER_UINT
|
||||||
|
* changed: UInt::CompensationToLeft() it's faster now
|
||||||
|
* changed: more small changes where there were UInt::Rcl(uint c=0) and
|
||||||
|
UInt::Rcr(uint c=0) used
|
||||||
|
* changed: as the Big type uses UInt::Rcl() and UInt::Rcr() a lot then
|
||||||
|
it is much faster now (about 5-25%)
|
||||||
|
* added: ASinh(), ACosh(), ATanh() /ATgh()/, ACoth() /ACtgh()/
|
||||||
|
and to the parser as well
|
||||||
|
* added: UInt::BitAnd(), UInt::BitOr(), UInt::BitXor(), UInt::BitNot(),
|
||||||
|
Big::BitAnd(), Big::BitOr(), Big::BitXor()
|
||||||
|
* added: to the parser: bitand(), bitor(), bitxor()
|
||||||
|
/band(), bor(), bxor()/
|
||||||
|
* changed: the way of parsing operators in the mathematical parser
|
||||||
|
(the parser is not too much greedy now)
|
||||||
|
|
||||||
|
|
||||||
Version 0.8.0 (2007.03.28):
|
Version 0.8.0 (2007.03.28):
|
||||||
* added: into the parser: SetFactorialMax()
|
* added: into the parser: SetFactorialMax()
|
||||||
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
* added: DegToDeg(deg, min, sec), DegToRad(deg), DegToRad(deg, min, sec),
|
||||||
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x),
|
RadToDeg(rad), Ceil(x), Floor(x), Sqrt(x), Sinh(x), Cosh(x),
|
||||||
Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/
|
Tanh(x) /Tgh(x)/, Coth(x) /Ctgh(x)/
|
||||||
* changed: class Objects in ttmathobjects.h has been completely rewritten,
|
* changed: class Objects in ttmathobjects.h has been completely rewritten,
|
||||||
we can change the names of user-defined variables or functions, and the
|
we can change the names of user-defined variables or functions,
|
||||||
names are case-sensitive now
|
and the names are case-sensitive now
|
||||||
* added: class History which is used in functions which take a lot of time
|
* added: class History which is used in functions which take a lot of time
|
||||||
during calculating e.g. Factorial(x)
|
during calculating e.g. Factorial(x)
|
||||||
* added: Tg(x) a wrapper for Tan(x)
|
* added: Tg(x) a wrapper for Tan(x)
|
||||||
* changed: CTan(x) is Cot(x) now
|
* changed: CTan(x) is Cot(x) now
|
||||||
* added: Ctg(x) a wrapper for Cot(x)
|
* added: Ctg(x) a wrapper for Cot(x)
|
||||||
* added: ATg(x) a wrapper for ATan(x)
|
* added: ATg(x) a wrapper for ATan(x)
|
||||||
* changed: ACTan(x) is ACot(x) now
|
* changed: ACTan(x) is ACot(x) now
|
||||||
* added: ACtg(x) a wrapper for ACot(x)
|
* added: ACtg(x) a wrapper for ACot(x)
|
||||||
* added: UInt::PrintTable() (for debugging etc.)
|
* added: UInt::PrintTable() (for debugging etc.)
|
||||||
* changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have
|
* changed: the methods Big::SetPi() Big::SetE() and Big::SetLn2() have
|
||||||
been rewritten, now they have 128 32bit words (it's about 1232 valid
|
been rewritten, now they have 128 32bit words (it's about
|
||||||
decimal digits)
|
1232 valid decimal digits)
|
||||||
* fixed: previous values from Big::SetPi() Big::SetE() and
|
* fixed: previous values from Big::SetPi() Big::SetE() and
|
||||||
Big::SetLn2() were not too much accurate (last 2-3 words were wrong)
|
Big::SetLn2() were not too much accurate (last 2-3 words were wrong)
|
||||||
* added: Big::SetLn10() (128 32bit words as well)
|
* added: Big::SetLn10() (128 32bit words as well)
|
||||||
* added: macro: TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on
|
* added: macro TTMATH_BUILTIN_VARIABLES_SIZE which is equal 128u on
|
||||||
32bit platforms and 64ul on 64bit platforms (128/2=64)
|
32bit platforms and 64ul on 64bit platforms (128/2=64)
|
||||||
* added: macros: TTMATH_PLATFORM32 and TTMATH_PLATFORM64
|
* added: macros TTMATH_PLATFORM32 and TTMATH_PLATFORM64
|
||||||
* changed: a small optimisation in UInt::Mul2Big()
|
* changed: a small optimisation in UInt::Mul2Big()
|
||||||
* added: at the end of ttmath.h: #include "ttmathparser.h"
|
* added: at the end of ttmath.h: #include "ttmathparser.h"
|
||||||
this is for convenience for a programmer, he can only use #include
|
this is for convenience for a programmer, he can only use #include
|
||||||
with ttmath.h even if he uses the parser
|
with ttmath.h even if he uses the parser
|
||||||
* added: to samples: big.cpp, parser.cpp
|
* added: to samples: big.cpp, parser.cpp
|
||||||
* added/changes/fixed: in copy-constructors and operators= in Int,
|
* added/changes/fixed: in copy-constructors and operators= in Int,
|
||||||
Uint and Big (more info in the commit log)
|
Uint and Big (more info in the commit log)
|
||||||
* renamed Big::SetDotOne() into Big::Set05()
|
* renamed: Big::SetDotOne() into Big::Set05()
|
||||||
* changes: a few small optimisations in Big
|
* changes: a few small optimisations in Big
|
||||||
* deleted: the word 'virtual' from destructors: UInt, Int, Big
|
* deleted: the word 'virtual' from destructors: UInt, Int, Big
|
||||||
(types in this library are not projected to be base-classes for
|
(types in this library are not projected to be base-classes for
|
||||||
another ones derived from them)
|
another ones derived from them)
|
||||||
* and more small changes (look at the commit log)
|
* and more small changes (look at the commit log)
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.2 (2007.03.09):
|
Version 0.7.2 (2007.03.09):
|
||||||
* added: Big::Mod - the remainder from a division
|
* added: Big::Mod - the remainder from a division
|
||||||
* added: Big::Sgn - the 'sign' from the value (-1,0,1)
|
* added: Big::Sgn - the 'sign' from the value (-1,0,1)
|
||||||
* added: global functions Mod and Sgn too
|
* added: global functions Mod and Sgn too
|
||||||
* added: checking whether a user gives a correct value of a variable or function
|
* added: checking whether a user gives a correct value of a variable or function
|
||||||
(user-defined variables/functions in the mathematical parser)
|
(user-defined variables/functions in the mathematical parser)
|
||||||
* added: into the parser: logical operators: > < >= <= == != && ||
|
* added: into the parser: logical operators: > < >= <= == != && ||
|
||||||
* added: into the parser: logical functions: and() or() not() if()
|
* added: into the parser: logical functions: and() or() not() if()
|
||||||
* added: ErrorCode::err_unknown_operator when the parser couldn't read an operator
|
* added: ErrorCode::err_unknown_operator when the parser couldn't read an operator
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.1 (2007.02.27):
|
Version 0.7.1 (2007.02.27):
|
||||||
* fixed the error 'overflow during printing' which was caused
|
* fixed: the error 'overflow during printing' which was caused
|
||||||
by Big::FromInt(Int<int_size> value) (the sign has to be set at the end)
|
by Big::FromInt(Int<int_size> value) (the sign has to be set at the end)
|
||||||
* fixed many small errors
|
* fixed: many small errors
|
||||||
* added ATan (arctan), ACTan (arc ctan) functions
|
* added: ATan (arctan), ACTan (arc ctan) functions
|
||||||
|
|
||||||
|
|
||||||
Version 0.7.0 (2007.02.24):
|
Version 0.7.0 (2007.02.24):
|
||||||
* finished support for 64bit platforms
|
* finished: support for 64bit platforms
|
||||||
* added ASin (arcsin), ACos (arccos) functions
|
* added: ASin (arcsin), ACos (arccos) functions
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.4 (2007.01.29):
|
Version 0.6.4 (2007.01.29):
|
||||||
* fixed the problem with a sign in the mathematical parser /-(1) was 1/
|
* fixed: the problem with a sign in the mathematical parser /-(1) was 1/
|
||||||
* added UInt::AddInt and UInt::SubInt
|
* added: UInt::AddInt and UInt::SubInt
|
||||||
* changed UInt::AddOne and UInt::SubOne (much faster now)
|
* changed: UInt::AddOne and UInt::SubOne (much faster now)
|
||||||
* added UInt::SetBitInWord
|
* added: UInt::SetBitInWord
|
||||||
* changed UInt::SetBit (much faster now)
|
* changed: UInt::SetBit (much faster now)
|
||||||
* UInt::AddTwoUints renamed to UInt::AddTwoInts
|
UInt::AddTwoUints renamed to UInt::AddTwoInts
|
||||||
* UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord
|
UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord
|
||||||
* added UInt::SetBitInWord
|
UInt::Mul64 renamed to UInt::MulTwoWords
|
||||||
* UInt::Mul64 renamed to UInt::MulTwoWords
|
UInt::Div64 renamed to UInt::DivTwoWords
|
||||||
* UInt::Div64 renamed to UInt::DivTwoWords
|
* added: UInt::SetBitInWord
|
||||||
* and more small changes in UInt type
|
* and more small changes in UInt type
|
||||||
* start adding support for Amd64 (not finished yet) (added ttmathuint64.h)
|
* start adding support for Amd64 (not finished yet) (added ttmathuint64.h)
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.3 (2007.01.22):
|
Version 0.6.3 (2007.01.22):
|
||||||
* position of arguments (x and base) in logarithm functions are swapped
|
* changed: position of arguments (x and base) in logarithm functions are swapped
|
||||||
* it's possible to use any multiplication algorithms in the same time
|
* changed: it's possible to use any multiplication algorithms in the same time
|
||||||
(macros UINT_MUL_VERSION_'X' have gone)
|
(macros UINT_MUL_VERSION_'X' have gone)
|
||||||
* added ExceptionInfo, ReferenceError and RuntimeError classes
|
* added: ExceptionInfo, ReferenceError and RuntimeError classes
|
||||||
* the mess in macros has been cleaned up
|
* changed: the mess in macros has been cleaned up
|
||||||
* added TTMATH_RELEASE macro
|
* added: TTMATH_RELEASE macro
|
||||||
|
|
||||||
|
|
||||||
Version 0.6.2 (2007.01.10):
|
Version 0.6.2 (2007.01.10):
|
||||||
* New division algorithm (radix b) where b is 2^32
|
* added: New division algorithm (radix b) where b is 2^32
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2006-2007, Tomasz Sowa
|
Copyright (c) 2006-2008, 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
|
||||||
|
18
README
18
README
@@ -7,18 +7,20 @@ subtracting, multiplying, dividing etc. With the library also goes
|
|||||||
a mathematical parser which helps you solving input formulas read directly
|
a mathematical parser which helps you solving input formulas read directly
|
||||||
from a user.
|
from a user.
|
||||||
|
|
||||||
TTMath is developed under the (new) BSD licence which means that it is free
|
TTMath is developed under the BSD licence which means that it is free
|
||||||
for both personal and commercial use but the library has some technical
|
for both personal and commercial use.
|
||||||
limitations: you can use it only on i386 and Amd64, another platforms are
|
|
||||||
not supported (Intel 64bit platforms were not tested but should work as
|
The library has some technical limitations:
|
||||||
well), and you can use this library only with the C++ programming language.
|
* there are only two platforms that are supported: x86 and x86_64,
|
||||||
|
* you can use this library only with the C++ programming language.
|
||||||
|
|
||||||
The main goal of the library is to allow one to use big values in the same
|
The main goal of the library is to allow one to use big values in the same
|
||||||
way as the standard types like int, float, etc. It does not need to be
|
way as the standard types like int, float, etc. It does not need to be
|
||||||
compiled first because the whole library is written as the C++ templates.
|
compiled first because the whole library is written as the C++ templates.
|
||||||
This means only C++ developers can use this library and one thing they have
|
This means only C++ developers can use this library and one thing they have
|
||||||
to do is to use 'include' directive of the preprocessor. How big the
|
to do is to use 'include' directive of the preprocessor. How big the
|
||||||
values can be is set directly in the source code by the programmer.
|
values can be is set directly in the source code by the programmer.
|
||||||
|
|
||||||
Author: Tomasz Sowa <t.sowa AnTispam slimaczek.pl>
|
Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
Home page: http://sourceforge.net/projects/ttmath
|
Project pages: http://ttmath.slimaczek.pl
|
||||||
|
http://sourceforge.net/projects/ttmath
|
||||||
|
7
TODO
7
TODO
@@ -1,7 +0,0 @@
|
|||||||
TODO TTMath Library
|
|
||||||
===================
|
|
||||||
|
|
||||||
* Add bitwise operators (or functions) and, or, xor
|
|
||||||
* Add functions for generating random values
|
|
||||||
|
|
||||||
|
|
1257
doxygen.cfg
Normal file
1257
doxygen.cfg
Normal file
File diff suppressed because it is too large
Load Diff
473
ttmath/ttmath.h
473
ttmath/ttmath.h
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -275,6 +275,11 @@ namespace ttmath
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this namespace consists of auxiliary functions
|
||||||
|
(something like 'private' in a class)
|
||||||
|
*/
|
||||||
namespace auxiliaryfunctions
|
namespace auxiliaryfunctions
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1171,6 +1176,173 @@ namespace ttmath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* inverse hyperbolic functions
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic sine
|
||||||
|
|
||||||
|
asinh(x) = ln( x + sqrt(x^2 + 1) )
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ASinh(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType xx(x), one, result;
|
||||||
|
uint c = 0;
|
||||||
|
one.SetOne();
|
||||||
|
|
||||||
|
c += xx.Mul(x);
|
||||||
|
c += xx.Add(one);
|
||||||
|
one.exponent.SubOne(); // one=0.5
|
||||||
|
// xx is >= 1
|
||||||
|
c += xx.PowFrac(one); // xx=sqrt(xx)
|
||||||
|
c += xx.Add(x);
|
||||||
|
c += result.Ln(xx); // xx > 0
|
||||||
|
|
||||||
|
// here can only be a carry
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic cosine
|
||||||
|
|
||||||
|
acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity)
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ACosh(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType xx(x), one, result;
|
||||||
|
uint c = 0;
|
||||||
|
one.SetOne();
|
||||||
|
|
||||||
|
if( x < one )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += xx.Mul(x);
|
||||||
|
c += xx.Sub(one);
|
||||||
|
// xx is >= 0
|
||||||
|
// we can't call a PowFrac when the 'x' is zero
|
||||||
|
// if x is 0 the sqrt(0) is 0
|
||||||
|
if( !xx.IsZero() )
|
||||||
|
{
|
||||||
|
one.exponent.SubOne(); // one=0.5
|
||||||
|
c += xx.PowFrac(one); // xx=sqrt(xx)
|
||||||
|
}
|
||||||
|
c += xx.Add(x);
|
||||||
|
c += result.Ln(xx); // xx >= 1
|
||||||
|
|
||||||
|
// here can only be a carry
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic tangent
|
||||||
|
|
||||||
|
atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1)
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ATanh(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType nominator(x), denominator, one, result;
|
||||||
|
uint c = 0;
|
||||||
|
one.SetOne();
|
||||||
|
|
||||||
|
if( !x.SmallerWithoutSignThan(one) )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += nominator.Add(one);
|
||||||
|
denominator = one;
|
||||||
|
c += denominator.Sub(x);
|
||||||
|
c += nominator.Div(denominator);
|
||||||
|
c += result.Ln(nominator);
|
||||||
|
c += result.exponent.SubOne();
|
||||||
|
|
||||||
|
// here can only be a carry
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic tantent
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ATgh(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
return ATanh(x, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic cotangent
|
||||||
|
|
||||||
|
acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity)
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ACoth(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType nominator(x), denominator(x), one, result;
|
||||||
|
uint c = 0;
|
||||||
|
one.SetOne();
|
||||||
|
|
||||||
|
if( !x.GreaterWithoutSignThan(one) )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += nominator.Add(one);
|
||||||
|
c += denominator.Sub(one);
|
||||||
|
c += nominator.Div(denominator);
|
||||||
|
c += result.Ln(nominator);
|
||||||
|
c += result.exponent.SubOne();
|
||||||
|
|
||||||
|
// here can only be a carry
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
inverse hyperbolic cotantent
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType ACtgh(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
return ACoth(x, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1342,6 +1514,273 @@ namespace ttmath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace auxiliaryfunctions
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||||
|
{
|
||||||
|
if( index.IsSign() )
|
||||||
|
{
|
||||||
|
// index cannot be negative
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||||
|
{
|
||||||
|
if( index.IsZero() )
|
||||||
|
{
|
||||||
|
if( x.IsZero() )
|
||||||
|
{
|
||||||
|
// there isn't root(0;0) - we assume it's not defined
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// root(x;0) is 1 (if x!=0)
|
||||||
|
x.SetOne();
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = err_ok;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||||
|
{
|
||||||
|
ValueType one;
|
||||||
|
one.SetOne();
|
||||||
|
|
||||||
|
if( index == one )
|
||||||
|
{
|
||||||
|
//root(x;1) is x
|
||||||
|
// we do it because if we used the PowFrac function
|
||||||
|
// we would lose the precision
|
||||||
|
if( err )
|
||||||
|
*err = err_ok;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||||
|
{
|
||||||
|
ValueType indexfrac(index);
|
||||||
|
indexfrac.RemainFraction();
|
||||||
|
|
||||||
|
if( !indexfrac.IsZero() )
|
||||||
|
{
|
||||||
|
// index must be integer
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||||
|
{
|
||||||
|
if( x.IsZero() )
|
||||||
|
{
|
||||||
|
// root(0;index) is zero (if index!=0)
|
||||||
|
x.SetZero();
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = err_ok;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign)
|
||||||
|
{
|
||||||
|
*change_sign = false;
|
||||||
|
|
||||||
|
if( index.Mod2() )
|
||||||
|
{
|
||||||
|
// index is odd (1,3,5...)
|
||||||
|
if( x.IsSign() )
|
||||||
|
{
|
||||||
|
*change_sign = true;
|
||||||
|
x.Abs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// index is even
|
||||||
|
// x cannot be negative
|
||||||
|
if( x.IsSign() )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_improper_argument;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
indexth Root of x
|
||||||
|
index must be integer and not negative <0;1;2;3....)
|
||||||
|
|
||||||
|
if index==0 the result is one
|
||||||
|
if x==0 the result is zero and we assume root(0;0) is not defined
|
||||||
|
|
||||||
|
if index is even (2;4;6...) the result is x^(1/index) and x>0
|
||||||
|
if index is odd (1;2;3;...) the result is either
|
||||||
|
-(abs(x)^(1/index)) if x<0 or
|
||||||
|
x^(1/index)) if x>0
|
||||||
|
|
||||||
|
(for index==1 the result is equal x)
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
using namespace auxiliaryfunctions;
|
||||||
|
|
||||||
|
if( RootCheckIndexSign(x, index, err) ) return x;
|
||||||
|
if( RootCheckIndexZero(x, index, err) ) return x;
|
||||||
|
if( RootCheckIndexOne (x, index, err) ) return x;
|
||||||
|
if( RootCheckIndexFrac(x, index, err) ) return x;
|
||||||
|
if( RootCheckXZero(x, index, err) ) return x;
|
||||||
|
|
||||||
|
// index integer and index!=0
|
||||||
|
// x!=0
|
||||||
|
|
||||||
|
uint c = 0;
|
||||||
|
bool change_sign;
|
||||||
|
if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
|
||||||
|
|
||||||
|
ValueType newindex;
|
||||||
|
newindex.SetOne();
|
||||||
|
c += newindex.Div(index);
|
||||||
|
c += x.PowFrac(newindex); // here can only be a carry
|
||||||
|
|
||||||
|
if( change_sign )
|
||||||
|
{
|
||||||
|
// the value of x should be different from zero
|
||||||
|
// (x is actually tested by RootCheckXZero)
|
||||||
|
TTMATH_ASSERT( x.IsZero() == false )
|
||||||
|
|
||||||
|
x.SetSign();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace auxiliaryfunctions
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
uint FactorialInt( const ValueType & x, ErrorCode * err,
|
||||||
|
const volatile StopCalculating * stop,
|
||||||
|
ValueType & result)
|
||||||
|
{
|
||||||
|
uint maxvalue = TTMATH_UINT_MAX_VALUE;
|
||||||
|
|
||||||
|
if( x < TTMATH_UINT_MAX_VALUE )
|
||||||
|
x.ToUInt(maxvalue);
|
||||||
|
|
||||||
|
uint multipler = 1;
|
||||||
|
uint carry = 0;
|
||||||
|
|
||||||
|
while( !carry && multipler<maxvalue )
|
||||||
|
{
|
||||||
|
if( stop && stop->WasStopSignal() )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_interrupt;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
++multipler;
|
||||||
|
carry += result.MulUInt(multipler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = carry ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return carry ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
int FactorialMore( const ValueType & x, ErrorCode * err,
|
||||||
|
const volatile StopCalculating * stop,
|
||||||
|
ValueType & result)
|
||||||
|
{
|
||||||
|
ValueType multipler(TTMATH_UINT_MAX_VALUE);
|
||||||
|
ValueType one;
|
||||||
|
|
||||||
|
one.SetOne();
|
||||||
|
uint carry = 0;
|
||||||
|
|
||||||
|
while( !carry && multipler < x )
|
||||||
|
{
|
||||||
|
if( stop && stop->WasStopSignal() )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_interrupt;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
carry += multipler.Add(one);
|
||||||
|
carry += result.Mul(multipler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = carry ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return carry ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the factorial from given 'x'
|
the factorial from given 'x'
|
||||||
e.g.
|
e.g.
|
||||||
@@ -1350,6 +1789,8 @@ namespace ttmath
|
|||||||
template<class ValueType>
|
template<class ValueType>
|
||||||
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
||||||
{
|
{
|
||||||
|
using namespace auxiliaryfunctions;
|
||||||
|
|
||||||
static History<ValueType> history;
|
static History<ValueType> history;
|
||||||
ValueType result;
|
ValueType result;
|
||||||
|
|
||||||
@@ -1384,33 +1825,17 @@ namespace ttmath
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType multipler;
|
uint status = FactorialInt(x, err, stop, result);
|
||||||
ValueType one;
|
if( status == 0 )
|
||||||
uint carry = 0;
|
status = FactorialMore(x, err, stop, result);
|
||||||
|
|
||||||
one = result; // =1
|
|
||||||
multipler = result; // =1
|
|
||||||
|
|
||||||
while( !carry && multipler < x )
|
|
||||||
{
|
|
||||||
if( stop && stop->WasStopSignal() )
|
|
||||||
{
|
|
||||||
if( err )
|
|
||||||
*err = err_interrupt;
|
|
||||||
|
|
||||||
|
if( status == 2 )
|
||||||
|
// the calculation has been interrupted
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
carry += multipler.Add(one);
|
|
||||||
carry += result.Mul(multipler);
|
|
||||||
}
|
|
||||||
|
|
||||||
err_tmp = carry ? err_overflow : err_ok;
|
err_tmp = status==1 ? err_overflow : err_ok;
|
||||||
history.Add(x, result, err_tmp);
|
history.Add(x, result, err_tmp);
|
||||||
|
|
||||||
if( err )
|
|
||||||
*err = carry ? err_overflow : err_ok;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,7 +1857,7 @@ namespace ttmath
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
it returns the sign of the value
|
it returns the sign of the value
|
||||||
e.g. -2 = 1
|
e.g. -2 = -1
|
||||||
0 = 0
|
0 = 0
|
||||||
10 = 1
|
10 = 1
|
||||||
*/
|
*/
|
||||||
|
1061
ttmath/ttmathbig.h
1061
ttmath/ttmathbig.h
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -208,7 +208,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds two value with a sign and returns carry
|
this method adds two value with a sign and returns a carry
|
||||||
|
|
||||||
we're using methods from the base class because values are stored with U2
|
we're using methods from the base class because values are stored with U2
|
||||||
we must only make the carry correction
|
we must only make the carry correction
|
||||||
@@ -475,17 +475,14 @@ public:
|
|||||||
* convertion methods
|
* convertion methods
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method convert an UInt<another_size> type to this class
|
an auxiliary method for converting both from UInt and Int
|
||||||
|
|
||||||
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>
|
template<uint argument_size>
|
||||||
uint FromInt(const Int<argument_size> & p)
|
uint FromUIntOrInt(const UInt<argument_size> & p, bool UInt_type)
|
||||||
{
|
{
|
||||||
uint min_size = (value_size < argument_size)? value_size : argument_size;
|
uint min_size = (value_size < argument_size)? value_size : argument_size;
|
||||||
uint i;
|
uint i;
|
||||||
@@ -496,15 +493,25 @@ public:
|
|||||||
|
|
||||||
if( value_size > argument_size )
|
if( value_size > argument_size )
|
||||||
{
|
{
|
||||||
// 'this' is longer than 'p'
|
uint fill;
|
||||||
uint fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
|
|
||||||
|
|
||||||
|
if( UInt_type )
|
||||||
|
fill = 0;
|
||||||
|
else
|
||||||
|
fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)?
|
||||||
|
TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
|
// 'this' is longer than 'p'
|
||||||
for( ; i<value_size ; ++i)
|
for( ; i<value_size ; ++i)
|
||||||
UInt<value_size>::table[i] = fill;
|
UInt<value_size>::table[i] = fill;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
|
uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)?
|
||||||
|
TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
|
if( UInt_type && test!=0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
for( ; i<argument_size ; ++i)
|
for( ; i<argument_size ; ++i)
|
||||||
if( p.table[i] != test )
|
if( p.table[i] != test )
|
||||||
@@ -514,11 +521,27 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts an Int<another_size> type into 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)
|
||||||
|
{
|
||||||
|
return FromUIntOrInt(p, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the sint type into this class
|
this method converts the sint type into this class
|
||||||
*/
|
*/
|
||||||
void FromInt(sint value)
|
uint FromInt(sint value)
|
||||||
{
|
{
|
||||||
uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
|
uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
|
||||||
@@ -526,16 +549,46 @@ public:
|
|||||||
UInt<value_size>::table[i] = fill;
|
UInt<value_size>::table[i] = fill;
|
||||||
|
|
||||||
UInt<value_size>::table[0] = uint(value);
|
UInt<value_size>::table[0] = uint(value);
|
||||||
|
|
||||||
|
// there'll never be a carry here
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this operator converts an UInt<another_size> type to this class
|
this method converts UInt<another_size> into this class
|
||||||
|
|
||||||
it doesn't return a carry
|
|
||||||
*/
|
*/
|
||||||
template<uint argument_size>
|
template<uint argument_size>
|
||||||
Int<value_size> & operator=(const Int<argument_size> & p)
|
uint FromUInt(const UInt<argument_size> & p)
|
||||||
|
{
|
||||||
|
return FromUIntOrInt(p, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the uint type into this class
|
||||||
|
*/
|
||||||
|
uint FromUInt(uint value)
|
||||||
|
{
|
||||||
|
for(uint i=1 ; i<value_size ; ++i)
|
||||||
|
UInt<value_size>::table[i] = 0;
|
||||||
|
|
||||||
|
UInt<value_size>::table[0] = value;
|
||||||
|
|
||||||
|
// there can be a carry here when the size of this value is equal one word
|
||||||
|
// and the 'value' has the highest bit set
|
||||||
|
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// converting from Int
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the default assignment operator
|
||||||
|
*/
|
||||||
|
Int<value_size> & operator=(const Int<value_size> & p)
|
||||||
{
|
{
|
||||||
FromInt(p);
|
FromInt(p);
|
||||||
|
|
||||||
@@ -544,9 +597,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the default assignment operator
|
this operator converts an Int<another_size> type to this class
|
||||||
|
|
||||||
|
it doesn't return a carry
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(const Int<value_size> & p)
|
template<uint argument_size>
|
||||||
|
Int<value_size> & operator=(const Int<argument_size> & p)
|
||||||
{
|
{
|
||||||
FromInt(p);
|
FromInt(p);
|
||||||
|
|
||||||
@@ -575,11 +631,47 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the uint type to this class
|
a copy constructor
|
||||||
|
*/
|
||||||
|
Int(const Int<value_size> & u)
|
||||||
|
{
|
||||||
|
FromInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for copying from another types
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int(const Int<argument_size> & u)
|
||||||
|
{
|
||||||
|
// look that 'size' we still set as 'value_size' and not as u.value_size
|
||||||
|
FromInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// converting from UInt
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this operator converts an UInt<another_size> type to this class
|
||||||
|
|
||||||
|
it doesn't return a carry
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int<value_size> & operator=(const UInt<argument_size> & p)
|
||||||
|
{
|
||||||
|
FromUInt(p);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method converts the Uint type to this class
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(uint i)
|
Int<value_size> & operator=(uint i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(i);
|
FromUInt(i);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -590,10 +682,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int(uint i)
|
Int(uint i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(i);
|
FromUInt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for copying from another types
|
||||||
|
*/
|
||||||
|
template<uint argument_size>
|
||||||
|
Int(const UInt<argument_size> & u)
|
||||||
|
{
|
||||||
|
// look that 'size' we still set as 'value_size' and not as u.value_size
|
||||||
|
FromUInt(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -630,7 +735,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(unsigned int i)
|
Int<value_size> & operator=(unsigned int i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(uint(i));
|
FromUInt(uint(i));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -644,7 +749,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Int(unsigned int i)
|
Int(unsigned int i)
|
||||||
{
|
{
|
||||||
UInt<value_size>::FromUInt(uint(i));
|
FromUInt(uint(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -678,18 +783,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
the copy 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the destructor
|
the destructor
|
||||||
*/
|
*/
|
||||||
@@ -697,6 +790,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns the lowest value from table with a sign
|
this method returns the lowest value from table with a sign
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -102,7 +102,7 @@ public:
|
|||||||
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( can_be_digit && (c>='0' && c<='9') )
|
if( can_be_digit && ((c>='0' && c<='9') || c=='_') )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -66,7 +66,7 @@ namespace ttmath
|
|||||||
x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
|
x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
|
||||||
where:
|
where:
|
||||||
an operator can be:
|
an operator can be:
|
||||||
^ (pow) (the highest priority)
|
^ (pow) (almost the heighest priority, look below at 'short mul')
|
||||||
|
|
||||||
* (mul)
|
* (mul)
|
||||||
/ (div) (* and / have the same priority)
|
/ (div) (* and / have the same priority)
|
||||||
@@ -85,6 +85,12 @@ namespace ttmath
|
|||||||
|
|
||||||
|| (logical or) (the lowest priority)
|
|| (logical or) (the lowest priority)
|
||||||
|
|
||||||
|
short mul:
|
||||||
|
or if the second Value (Var below) is either a variable or function there cannot be
|
||||||
|
an operator between them, e.g.
|
||||||
|
[+|-]ValueVar is treated as [+|-]Value * Var and the multiplication
|
||||||
|
has the greatest priority: 2^3m equals 2^(3*m)
|
||||||
|
|
||||||
|
|
||||||
and Value can be:
|
and Value can be:
|
||||||
constant e.g. 100
|
constant e.g. 100
|
||||||
@@ -106,6 +112,7 @@ namespace ttmath
|
|||||||
for separating parameters
|
for separating parameters
|
||||||
"1 < 2" (the result will be: 1)
|
"1 < 2" (the result will be: 1)
|
||||||
"4 < 3" (the result will be: 0)
|
"4 < 3" (the result will be: 0)
|
||||||
|
"2+x" (of course if the variable 'x' is defined)
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
we can also use a semicolon for separating any 'x' input strings
|
we can also use a semicolon for separating any 'x' input strings
|
||||||
@@ -122,13 +129,15 @@ class Parser
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
there are 5 mathematical operators as follows:
|
there are 5 mathematical operators as follows (with their standard priorities):
|
||||||
add (+)
|
add (+)
|
||||||
sub (-)
|
sub (-)
|
||||||
mul (*)
|
mul (*)
|
||||||
div (/)
|
div (/)
|
||||||
pow (^)
|
pow (^)
|
||||||
with their standard priorities
|
and 'shortmul' used when there is no any operators between
|
||||||
|
a first parameter and a variable or function
|
||||||
|
(the 'shortmul' has the greatest priority e.g. '5^3m' equals '5^(3*m)' )
|
||||||
*/
|
*/
|
||||||
class MatOperator
|
class MatOperator
|
||||||
{
|
{
|
||||||
@@ -136,7 +145,7 @@ private:
|
|||||||
|
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land
|
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -181,6 +190,10 @@ private:
|
|||||||
priority = 14;
|
priority = 14;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case shortmul:
|
||||||
|
priority = 20;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Error( err_internal_error );
|
Error( err_internal_error );
|
||||||
break;
|
break;
|
||||||
@@ -426,7 +439,7 @@ void SkipWhiteCharacters()
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
|
||||||
{
|
{
|
||||||
@@ -444,7 +457,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
|
||||||
{
|
{
|
||||||
@@ -455,7 +468,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
|
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
|
||||||
{
|
{
|
||||||
@@ -618,6 +631,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err );
|
Error( err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Abs(int sindex, int amount_of_args, ValueType & result)
|
void Abs(int sindex, int amount_of_args, ValueType & result)
|
||||||
{
|
{
|
||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
@@ -1030,6 +1044,162 @@ void Coth(int sindex, int amount_of_args, ValueType & result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Root(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 2 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
ErrorCode err;
|
||||||
|
result = ttmath::Root(stack[sindex].value, stack[sindex+2].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ASinh(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
ErrorCode err;
|
||||||
|
result = ttmath::ASinh(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACosh(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
ErrorCode err;
|
||||||
|
result = ttmath::ACosh(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ATanh(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
ErrorCode err;
|
||||||
|
result = ttmath::ATanh(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACoth(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
ErrorCode err;
|
||||||
|
result = ttmath::ACoth(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitAnd(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 2 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
uint err;
|
||||||
|
result = stack[sindex].value;
|
||||||
|
err = result.BitAnd(stack[sindex+2].value);
|
||||||
|
|
||||||
|
switch(err)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Error( err_overflow );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Error( err_improper_argument );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitOr(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 2 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
uint err;
|
||||||
|
result = stack[sindex].value;
|
||||||
|
err = result.BitOr(stack[sindex+2].value);
|
||||||
|
|
||||||
|
switch(err)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Error( err_overflow );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Error( err_improper_argument );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitXor(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args != 2 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
uint err;
|
||||||
|
result = stack[sindex].value;
|
||||||
|
err = result.BitXor(stack[sindex+2].value);
|
||||||
|
|
||||||
|
switch(err)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Error( err_overflow );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Error( err_improper_argument );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Sum(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args == 0 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
result = stack[sindex].value;
|
||||||
|
|
||||||
|
for(int i=1 ; i<amount_of_args ; ++i )
|
||||||
|
if( result.Add( stack[ sindex + i*2 ].value ) )
|
||||||
|
Error( err_overflow );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avg(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
if( amount_of_args == 0 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
result = stack[sindex].value;
|
||||||
|
|
||||||
|
for(int i=1 ; i<amount_of_args ; ++i )
|
||||||
|
if( result.Add( stack[ sindex + i*2 ].value ) )
|
||||||
|
Error( err_overflow );
|
||||||
|
|
||||||
|
if( result.Div( amount_of_args ) )
|
||||||
|
Error( err_overflow );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns the value from a user-defined function
|
this method returns the value from a user-defined function
|
||||||
|
|
||||||
@@ -1107,7 +1277,7 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
insert a function to the functions' table
|
inserting a function to the functions' table
|
||||||
|
|
||||||
function_name - name of the function
|
function_name - name of the function
|
||||||
pf - pointer to the function (to the wrapper)
|
pf - pointer to the function (to the wrapper)
|
||||||
@@ -1119,7 +1289,7 @@ void InsertFunctionToTable(const std::string & function_name, pfunction pf)
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
insert a function to the variables' table
|
inserting a function to the variables' table
|
||||||
(this function returns value of variable)
|
(this function returns value of variable)
|
||||||
|
|
||||||
variable_name - name of the function
|
variable_name - name of the function
|
||||||
@@ -1178,11 +1348,26 @@ void CreateFunctionsTable()
|
|||||||
InsertFunctionToTable(std::string("tgh"), &Parser<ValueType>::Tanh);
|
InsertFunctionToTable(std::string("tgh"), &Parser<ValueType>::Tanh);
|
||||||
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
|
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
|
||||||
InsertFunctionToTable(std::string("ctgh"), &Parser<ValueType>::Coth);
|
InsertFunctionToTable(std::string("ctgh"), &Parser<ValueType>::Coth);
|
||||||
|
InsertFunctionToTable(std::string("root"), &Parser<ValueType>::Root);
|
||||||
|
InsertFunctionToTable(std::string("asinh"), &Parser<ValueType>::ASinh);
|
||||||
|
InsertFunctionToTable(std::string("acosh"), &Parser<ValueType>::ACosh);
|
||||||
|
InsertFunctionToTable(std::string("atanh"), &Parser<ValueType>::ATanh);
|
||||||
|
InsertFunctionToTable(std::string("atgh"), &Parser<ValueType>::ATanh);
|
||||||
|
InsertFunctionToTable(std::string("acoth"), &Parser<ValueType>::ACoth);
|
||||||
|
InsertFunctionToTable(std::string("actgh"), &Parser<ValueType>::ACoth);
|
||||||
|
InsertFunctionToTable(std::string("bitand"), &Parser<ValueType>::BitAnd);
|
||||||
|
InsertFunctionToTable(std::string("bitor"), &Parser<ValueType>::BitOr);
|
||||||
|
InsertFunctionToTable(std::string("bitxor"), &Parser<ValueType>::BitXor);
|
||||||
|
InsertFunctionToTable(std::string("band"), &Parser<ValueType>::BitAnd);
|
||||||
|
InsertFunctionToTable(std::string("bor"), &Parser<ValueType>::BitOr);
|
||||||
|
InsertFunctionToTable(std::string("bxor"), &Parser<ValueType>::BitXor);
|
||||||
|
InsertFunctionToTable(std::string("sum"), &Parser<ValueType>::Sum);
|
||||||
|
InsertFunctionToTable(std::string("avg"), &Parser<ValueType>::Avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method create the table of variables
|
this method creates the table of variables
|
||||||
*/
|
*/
|
||||||
void CreateVariablesTable()
|
void CreateVariablesTable()
|
||||||
{
|
{
|
||||||
@@ -1195,7 +1380,7 @@ void CreateVariablesTable()
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
convert from a big letter to a small one
|
converting from a big letter to a small one
|
||||||
*/
|
*/
|
||||||
int ToLowerCase(int c)
|
int ToLowerCase(int c)
|
||||||
{
|
{
|
||||||
@@ -1206,8 +1391,6 @@ return c;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method read the name of a variable or a function
|
this method read the name of a variable or a function
|
||||||
|
|
||||||
@@ -1224,29 +1407,31 @@ int character;
|
|||||||
|
|
||||||
|
|
||||||
result.erase();
|
result.erase();
|
||||||
character = ToLowerCase(*pstring);
|
character = *pstring;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
the first letter must be from range 'a' - 'z'
|
the first letter must be from range 'a' - 'z' or 'A' - 'Z'
|
||||||
*/
|
*/
|
||||||
if( character<'a' || character>'z' )
|
if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) )
|
||||||
Error( err_unknown_character );
|
Error( err_unknown_character );
|
||||||
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
result += character;
|
result += character;
|
||||||
character = ToLowerCase( * ++pstring );
|
character = * ++pstring;
|
||||||
}
|
}
|
||||||
while( (character>='a' && character<='z') ||
|
while( (character>='a' && character<='z') ||
|
||||||
(character>='0' && character<='9') );
|
(character>='A' && character<='Z') ||
|
||||||
|
(character>='0' && character<='9') ||
|
||||||
|
character=='_' );
|
||||||
|
|
||||||
|
|
||||||
SkipWhiteCharacters();
|
SkipWhiteCharacters();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if there's character '(' that means this name is a name of a function
|
if there's a character '(' that means this name is a name of a function
|
||||||
*/
|
*/
|
||||||
if( *pstring == '(' )
|
if( *pstring == '(' )
|
||||||
{
|
{
|
||||||
@@ -1327,7 +1512,6 @@ const char * new_stack_pointer;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the character ascii c into the value in range <0;base-1>
|
this method converts the character ascii c into the value in range <0;base-1>
|
||||||
|
|
||||||
@@ -1412,12 +1596,15 @@ int character;
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( character=='#' || character=='&' || CharToDigit(character, base)!=-1 )
|
if( character=='#' || character=='&' ||
|
||||||
|
character==TTMATH_COMMA_CHARACTER_1 ||
|
||||||
|
(character==TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0) ||
|
||||||
|
CharToDigit(character, base)!=-1 )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
warning:
|
warning:
|
||||||
if we're using for example the base equal 16
|
if we're using for example the base equal 16
|
||||||
we can find a first character like 'e' that is there is not e=2.71..
|
we can find a first character like 'e' that is not e=2.71..
|
||||||
but the value 14, for this case we must use something like var::e for variables
|
but the value 14, for this case we must use something like var::e for variables
|
||||||
(not implemented yet)
|
(not implemented yet)
|
||||||
*/
|
*/
|
||||||
@@ -1457,6 +1644,7 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type
|
|||||||
operators_table.insert( std::make_pair(name, type) );
|
operators_table.insert( std::make_pair(name, type) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method creates the table of operators
|
this method creates the table of operators
|
||||||
*/
|
*/
|
||||||
@@ -1478,13 +1666,22 @@ void CreateMathematicalOperatorsTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CanBeMathematicalOperator(unsigned char c)
|
/*!
|
||||||
{
|
returns true if 'str2' is the substring of str1
|
||||||
if( c=='|' || c=='&' || c=='!' || c=='=' || c=='<' || c=='>' ||
|
|
||||||
c=='*' || c=='/' || c=='+' || c=='-' || c=='^' )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
e.g.
|
||||||
|
true when str1="test" and str2="te"
|
||||||
|
*/
|
||||||
|
bool IsSubstring(const std::string & str1, const std::string & str2)
|
||||||
|
{
|
||||||
|
if( str2.length() > str1.length() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(std::string::size_type i=0 ; i<str2.length() ; ++i)
|
||||||
|
if( str1[i] != str2[i] )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1494,17 +1691,31 @@ return false;
|
|||||||
void ReadMathematicalOperator(Item & result)
|
void ReadMathematicalOperator(Item & result)
|
||||||
{
|
{
|
||||||
std::string oper;
|
std::string oper;
|
||||||
|
typename OperatorsTable::iterator iter_old, iter_new;
|
||||||
|
|
||||||
for( ; CanBeMathematicalOperator(*pstring) ; ++pstring )
|
iter_old = operators_table.end();
|
||||||
|
|
||||||
|
for( ; true ; ++pstring )
|
||||||
|
{
|
||||||
oper += *pstring;
|
oper += *pstring;
|
||||||
|
iter_new = operators_table.lower_bound(oper);
|
||||||
|
|
||||||
|
if( iter_new == operators_table.end() || !IsSubstring(iter_new->first, oper) )
|
||||||
|
{
|
||||||
|
oper.erase( --oper.end() ); // we've got mininum one element
|
||||||
|
|
||||||
typename OperatorsTable::iterator iter = operators_table.find(oper);
|
if( iter_old != operators_table.end() && iter_old->first == oper )
|
||||||
|
{
|
||||||
if( iter == operators_table.end() )
|
result.type = Item::mat_operator;
|
||||||
Error( err_unknown_operator );
|
result.moperator.SetType( iter_old->second );
|
||||||
|
break;
|
||||||
result.type = Item::mat_operator;
|
}
|
||||||
result.moperator.SetType( iter->second );
|
|
||||||
|
Error( err_unknown_operator );
|
||||||
|
}
|
||||||
|
|
||||||
|
iter_old = iter_new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1535,10 +1746,15 @@ int ReadOperator(Item & result)
|
|||||||
++pstring;
|
++pstring;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( CanBeMathematicalOperator(*pstring) )
|
if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') )
|
||||||
ReadMathematicalOperator(result);
|
{
|
||||||
|
// short mul (without any operators)
|
||||||
|
|
||||||
|
result.type = Item::mat_operator;
|
||||||
|
result.moperator.SetType( MatOperator::shortmul );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Error( err_unknown_character );
|
ReadMathematicalOperator(result);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1599,6 +1815,7 @@ int res;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MatOperator::mul:
|
case MatOperator::mul:
|
||||||
|
case MatOperator::shortmul:
|
||||||
if( value1.Mul(value2) ) Error( err_overflow );
|
if( value1.Mul(value2) ) Error( err_overflow );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1616,6 +1833,7 @@ int res;
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
on the stack left an unknown operator but we had to recognize its before
|
on the stack left an unknown operator but we had to recognize its before
|
||||||
@@ -1718,7 +1936,7 @@ return kod;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method calculate how many parameters there are on the stack
|
this method calculate how many parameters there are on the stack
|
||||||
and index of the first parameter
|
and the index of the first parameter
|
||||||
|
|
||||||
if there aren't any parameters on the stack this method returns
|
if there aren't any parameters on the stack this method returns
|
||||||
'size' equals zero and 'index' pointing after the first bracket
|
'size' equals zero and 'index' pointing after the first bracket
|
||||||
@@ -2113,7 +2331,6 @@ ErrorCode Parse(const char * str)
|
|||||||
|
|
||||||
stack.resize( default_stack_size );
|
stack.resize( default_stack_size );
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Parse();
|
Parse();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -58,10 +58,14 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
the version of the library
|
the version of the library
|
||||||
|
|
||||||
|
TTMATH_PRERELEASE_VER is either zero or one
|
||||||
|
if zero that means this is the release version of the library
|
||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 8
|
#define TTMATH_MINOR_VER 8
|
||||||
#define TTMATH_REVISION_VER 0
|
#define TTMATH_REVISION_VER 2
|
||||||
|
#define TTMATH_PRERELEASE_VER 0
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -178,7 +182,7 @@ namespace ttmath
|
|||||||
/*!
|
/*!
|
||||||
characters which represent the comma operator
|
characters which represent the comma operator
|
||||||
|
|
||||||
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing
|
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function)
|
||||||
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
|
TTMATH_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
|
that means you can input values for example 1.2345 and 1,2345 as well
|
||||||
|
|
||||||
@@ -193,6 +197,7 @@ namespace ttmath
|
|||||||
#define TTMATH_COMMA_CHARACTER_2 ','
|
#define TTMATH_COMMA_CHARACTER_2 ','
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this variable defines how many iterations are performed
|
this variable defines how many iterations are performed
|
||||||
during some kind of calculating when we're making any long formulas
|
during some kind of calculating when we're making any long formulas
|
||||||
@@ -243,7 +248,8 @@ namespace ttmath
|
|||||||
err_object_exists,
|
err_object_exists,
|
||||||
err_unknown_object,
|
err_unknown_object,
|
||||||
err_still_calculating,
|
err_still_calculating,
|
||||||
err_too_big_factorial
|
err_too_big_factorial,
|
||||||
|
err_in_short_form_used_function
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -52,6 +52,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief a namespace for the TTMath library
|
||||||
|
*/
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -69,8 +72,8 @@ class UInt
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
buffer for this integer value
|
buffer for the integer value
|
||||||
the first value (index 0) means the lowest word of this value
|
table[0] - the lowest word of the value
|
||||||
*/
|
*/
|
||||||
uint table[value_size];
|
uint table[value_size];
|
||||||
|
|
||||||
@@ -117,7 +120,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
it returns the size of the table
|
this method returns the size of the table
|
||||||
*/
|
*/
|
||||||
uint Size() const
|
uint Size() const
|
||||||
{
|
{
|
||||||
@@ -126,17 +129,19 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets value zero
|
this method sets zero
|
||||||
*/
|
*/
|
||||||
void SetZero()
|
void SetZero()
|
||||||
{
|
{
|
||||||
|
// in the future here can be 'memset'
|
||||||
|
|
||||||
for(uint i=0 ; i<value_size ; ++i)
|
for(uint i=0 ; i<value_size ; ++i)
|
||||||
table[i] = 0;
|
table[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets value one
|
this method sets one
|
||||||
*/
|
*/
|
||||||
void SetOne()
|
void SetOne()
|
||||||
{
|
{
|
||||||
@@ -218,6 +223,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* basic mathematic functions
|
* basic mathematic functions
|
||||||
@@ -225,14 +232,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adding ss2 to the this and adding carry if it's defined
|
adding ss2 to the this and adding carry if it's defined
|
||||||
(this = this + ss2 + c)
|
(this = this + ss2 + c)
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
c must be zero or one (might be a bigger value than 1)
|
||||||
function returns carry (1) (if it was)
|
function returns carry (1) (if it has been)
|
||||||
*/
|
*/
|
||||||
uint Add(const UInt<value_size> & ss2, uint c=0)
|
uint Add(const UInt<value_size> & ss2, uint c=0)
|
||||||
{
|
{
|
||||||
@@ -339,8 +344,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds one word (at a specific position)
|
adding one word (at a specific position)
|
||||||
and returns a carry (if it was)
|
and returning a carry (if it has been)
|
||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
@@ -355,7 +360,7 @@ public:
|
|||||||
table[1] = 30 + 2;
|
table[1] = 30 + 2;
|
||||||
table[2] = 5;
|
table[2] = 5;
|
||||||
|
|
||||||
of course if there was a carry from table[3] it would be returned
|
of course if there was a carry from table[2] it would be returned
|
||||||
*/
|
*/
|
||||||
uint AddInt(uint value, uint index = 0)
|
uint AddInt(uint value, uint index = 0)
|
||||||
{
|
{
|
||||||
@@ -462,7 +467,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds only two unsigned words to the existing value
|
adding only two unsigned words to the existing value
|
||||||
and these words begin on the 'index' position
|
and these words begin on the 'index' position
|
||||||
(it's used in the multiplication algorithm 2)
|
(it's used in the multiplication algorithm 2)
|
||||||
|
|
||||||
@@ -630,12 +635,12 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method's subtracting ss2 from the 'this' and subtracting
|
subtracting ss2 from the 'this' and subtracting
|
||||||
carry if it has been defined
|
carry if it has been defined
|
||||||
(this = this - ss2 - c)
|
(this = this - ss2 - c)
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
c must be zero or one (might be a bigger value than 1)
|
||||||
function returns carry (1) (if it was)
|
function returns carry (1) (if it has been)
|
||||||
*/
|
*/
|
||||||
uint Sub(const UInt<value_size> & ss2, uint c=0)
|
uint Sub(const UInt<value_size> & ss2, uint c=0)
|
||||||
{
|
{
|
||||||
@@ -819,7 +824,7 @@ public:
|
|||||||
|
|
||||||
"leal (%%ebx,%%edx,4), %%ebx \n"
|
"leal (%%ebx,%%edx,4), %%ebx \n"
|
||||||
|
|
||||||
"movl %%esi, %%edx \n"
|
"movl %%esi, %%edx \n"
|
||||||
"clc \n"
|
"clc \n"
|
||||||
"1: \n"
|
"1: \n"
|
||||||
|
|
||||||
@@ -878,18 +883,31 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM32
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving once all bits into the left side
|
this method moves all bits into the left hand side
|
||||||
return value <- this <- C
|
return value <- this <- c
|
||||||
|
|
||||||
the lowest bit will hold value of 'c' and
|
the lowest *bits* will be held the 'c' and
|
||||||
function returns the highest bit
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||||
*/
|
*/
|
||||||
uint Rcl(uint c=0)
|
uint Rcl2(uint bits, uint c)
|
||||||
{
|
{
|
||||||
|
if( bits == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
register sint b = value_size;
|
register sint b = value_size;
|
||||||
register uint * p1 = table;
|
register uint * p1 = table;
|
||||||
|
|
||||||
@@ -900,12 +918,16 @@ public:
|
|||||||
push eax
|
push eax
|
||||||
push ebx
|
push ebx
|
||||||
push ecx
|
push ecx
|
||||||
|
push edx
|
||||||
|
|
||||||
mov ecx,[b]
|
mov edx, [bits]
|
||||||
mov ebx,[p1]
|
|
||||||
|
a:
|
||||||
|
xor eax, eax
|
||||||
|
sub eax, [c]
|
||||||
|
|
||||||
mov eax,0
|
mov ecx, [b]
|
||||||
sub eax,[c]
|
mov ebx, [p1]
|
||||||
|
|
||||||
p:
|
p:
|
||||||
rcl dword ptr[ebx],1
|
rcl dword ptr[ebx],1
|
||||||
@@ -917,10 +939,15 @@ public:
|
|||||||
|
|
||||||
loop p
|
loop p
|
||||||
|
|
||||||
|
dec edx
|
||||||
|
|
||||||
|
jnz a
|
||||||
|
|
||||||
mov eax,0
|
mov eax,0
|
||||||
adc eax,eax
|
adc eax,eax
|
||||||
mov [c],eax
|
mov [c],eax
|
||||||
|
|
||||||
|
pop edx
|
||||||
pop ecx
|
pop ecx
|
||||||
pop ebx
|
pop ebx
|
||||||
pop eax
|
pop eax
|
||||||
@@ -931,12 +958,16 @@ public:
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%esi \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
"xorl %%eax,%%eax \n"
|
||||||
|
"subl %%edx,%%eax \n"
|
||||||
|
|
||||||
"push %%ebx \n"
|
"push %%ebx \n"
|
||||||
"push %%ecx \n"
|
"push %%ecx \n"
|
||||||
|
|
||||||
"movl $0,%%eax \n"
|
|
||||||
"subl %%edx,%%eax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
"1: \n"
|
||||||
"rcll $1,(%%ebx) \n"
|
"rcll $1,(%%ebx) \n"
|
||||||
|
|
||||||
@@ -947,14 +978,20 @@ public:
|
|||||||
|
|
||||||
"loop 1b \n"
|
"loop 1b \n"
|
||||||
|
|
||||||
"movl $0, %%edx \n"
|
|
||||||
"adcl %%edx,%%edx \n"
|
|
||||||
|
|
||||||
"pop %%ecx \n"
|
"pop %%ecx \n"
|
||||||
"pop %%ebx \n"
|
"pop %%ebx \n"
|
||||||
|
|
||||||
|
"decl %%esi \n"
|
||||||
|
|
||||||
|
"jnz 2b \n"
|
||||||
|
|
||||||
|
"movl $0, %%edx \n"
|
||||||
|
"adcl %%edx, %%edx \n"
|
||||||
|
|
||||||
|
"pop %%esi \n"
|
||||||
|
|
||||||
: "=d" (c)
|
: "=d" (c)
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||||
: "%eax", "cc", "memory" );
|
: "%eax", "cc", "memory" );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -965,14 +1002,24 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving once all bits into the right side
|
this method moves all bits into the right hand side
|
||||||
C -> *this -> return value
|
C -> this -> return value
|
||||||
|
|
||||||
the highest bit will be held value of 'c' and
|
the highest *bits* will be held the 'c' and
|
||||||
function returns the lowest bit
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||||
*/
|
*/
|
||||||
uint Rcr(uint c=0)
|
uint Rcr2(uint bits, uint c)
|
||||||
{
|
{
|
||||||
|
if( bits == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
register sint b = value_size;
|
register sint b = value_size;
|
||||||
register uint * p1 = table;
|
register uint * p1 = table;
|
||||||
|
|
||||||
@@ -983,15 +1030,19 @@ public:
|
|||||||
push eax
|
push eax
|
||||||
push ebx
|
push ebx
|
||||||
push ecx
|
push ecx
|
||||||
|
push edx
|
||||||
|
|
||||||
|
mov edx,[bits]
|
||||||
|
|
||||||
|
a:
|
||||||
|
|
||||||
|
xor eax,eax
|
||||||
|
sub eax,[c]
|
||||||
|
|
||||||
mov ebx,[p1]
|
mov ebx,[p1]
|
||||||
mov ecx,[b]
|
mov ecx,[b]
|
||||||
|
|
||||||
lea ebx,[ebx+4*ecx]
|
lea ebx,[ebx+4*ecx]
|
||||||
|
|
||||||
mov eax,0
|
|
||||||
sub eax,[c]
|
|
||||||
|
|
||||||
p:
|
p:
|
||||||
dec ebx
|
dec ebx
|
||||||
dec ebx
|
dec ebx
|
||||||
@@ -1001,11 +1052,16 @@ public:
|
|||||||
rcr dword ptr [ebx],1
|
rcr dword ptr [ebx],1
|
||||||
|
|
||||||
loop p
|
loop p
|
||||||
|
|
||||||
|
dec edx
|
||||||
|
|
||||||
|
jnz a
|
||||||
|
|
||||||
mov eax,0
|
mov eax,0
|
||||||
adc eax,eax
|
adc eax,eax
|
||||||
mov [c],eax
|
mov [c],eax
|
||||||
|
|
||||||
|
pop edx
|
||||||
pop ecx
|
pop ecx
|
||||||
pop ebx
|
pop ebx
|
||||||
pop eax
|
pop eax
|
||||||
@@ -1016,12 +1072,17 @@ public:
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%esi \n"
|
||||||
|
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
"push %%ebx \n"
|
"push %%ebx \n"
|
||||||
"push %%ecx \n"
|
"push %%ecx \n"
|
||||||
|
|
||||||
"leal (%%ebx,%%ecx,4),%%ebx \n"
|
"leal (%%ebx,%%ecx,4),%%ebx \n"
|
||||||
|
|
||||||
"movl $0, %%eax \n"
|
"xorl %%eax, %%eax \n"
|
||||||
"subl %%edx, %%eax \n"
|
"subl %%edx, %%eax \n"
|
||||||
|
|
||||||
"1: \n"
|
"1: \n"
|
||||||
@@ -1034,14 +1095,20 @@ public:
|
|||||||
|
|
||||||
"loop 1b \n"
|
"loop 1b \n"
|
||||||
|
|
||||||
"movl $0, %%edx \n"
|
|
||||||
"adcl %%edx,%%edx \n"
|
|
||||||
|
|
||||||
"pop %%ecx \n"
|
"pop %%ecx \n"
|
||||||
"pop %%ebx \n"
|
"pop %%ebx \n"
|
||||||
|
|
||||||
|
"decl %%esi \n"
|
||||||
|
|
||||||
|
"jnz 2b \n"
|
||||||
|
|
||||||
|
"movl $0, %%edx \n"
|
||||||
|
"adcl %%edx, %%edx \n"
|
||||||
|
|
||||||
|
"pop %%esi \n"
|
||||||
|
|
||||||
: "=d" (c)
|
: "=d" (c)
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||||
: "%eax", "cc", "memory" );
|
: "%eax", "cc", "memory" );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1052,8 +1119,49 @@ public:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for moving bits into the left hand side
|
||||||
|
|
||||||
|
this method moves only words
|
||||||
|
*/
|
||||||
|
void RclMoveAllWords( sint & all_words, uint & rest_bits, uint & last_c,
|
||||||
|
uint bits, uint c)
|
||||||
|
{
|
||||||
|
rest_bits = sint(bits % TTMATH_BITS_PER_UINT);
|
||||||
|
all_words = sint(bits / TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
|
if( all_words >= sint(value_size) )
|
||||||
|
{
|
||||||
|
if( all_words==value_size && rest_bits==0 )
|
||||||
|
last_c = table[0] & 1;
|
||||||
|
|
||||||
|
all_words = value_size; // not value_size - 1
|
||||||
|
rest_bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( all_words > 0 )
|
||||||
|
{
|
||||||
|
sint first;
|
||||||
|
sint second;
|
||||||
|
|
||||||
|
last_c = table[value_size - all_words] & 1; // all_words is greater than 0
|
||||||
|
|
||||||
|
// copying the first part of the value
|
||||||
|
for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
|
||||||
|
table[first] = table[second];
|
||||||
|
|
||||||
|
// sets the rest bits of value into 'c'
|
||||||
|
uint mask = c ? TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
for( ; first>=0 ; --first )
|
||||||
|
table[first] = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving all bits into the left side 'bits' times
|
moving all bits into the left side 'bits' times
|
||||||
return value <- this <- C
|
return value <- this <- C
|
||||||
|
|
||||||
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
|
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
|
||||||
@@ -1062,42 +1170,95 @@ public:
|
|||||||
the value c will be set into the lowest bits
|
the value c will be set into the lowest bits
|
||||||
and the method returns state of the last moved bit
|
and the method returns state of the last moved bit
|
||||||
*/
|
*/
|
||||||
uint Rcl(uint bits, uint c)
|
uint Rcl(uint bits, uint c=0)
|
||||||
{
|
{
|
||||||
sint first;
|
|
||||||
sint second;
|
|
||||||
uint last_c = 0;
|
uint last_c = 0;
|
||||||
|
sint all_words = 0;
|
||||||
if( bits > value_size*TTMATH_BITS_PER_UINT )
|
uint rest_bits = bits;
|
||||||
bits = value_size*TTMATH_BITS_PER_UINT;
|
|
||||||
|
|
||||||
sint all_words = sint(bits) / sint(TTMATH_BITS_PER_UINT);
|
if( bits >= TTMATH_BITS_PER_UINT )
|
||||||
|
RclMoveAllWords(all_words, rest_bits, last_c, bits, c);
|
||||||
|
|
||||||
if( all_words > 0 )
|
|
||||||
|
// rest_bits is from 0 to TTMATH_BITS_PER_UINT-1 now
|
||||||
|
if( rest_bits > 0 )
|
||||||
{
|
{
|
||||||
// copying the first part of the value
|
// if rest_bits is greater than a half of TTMATH_BITS_PER_UINT
|
||||||
for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second)
|
// we're moving bits into the right hand side
|
||||||
|
// (TTMATH_BITS_PER_UINT-rest_bits) times
|
||||||
|
// and then we're moving one word into left
|
||||||
|
if( rest_bits > TTMATH_BITS_PER_UINT/2 + 1 )
|
||||||
{
|
{
|
||||||
last_c = table[first] & 1;
|
uint temp = table[0];
|
||||||
table[first] = table[second];
|
Rcr2(TTMATH_BITS_PER_UINT-rest_bits,0);
|
||||||
|
last_c = table[value_size-1] & 1;
|
||||||
|
|
||||||
|
for(uint i=value_size-1 ; i>0 ; --i)
|
||||||
|
table[i] = table[i-1];
|
||||||
|
|
||||||
|
table[0] = temp << rest_bits;
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
uint mask = TTMATH_UINT_MAX_VALUE << rest_bits;
|
||||||
|
table[0] |= ~mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_c = Rcl2(rest_bits, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the rest bits of value into 'c'
|
|
||||||
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
|
|
||||||
for( ; first>=0 ; --first )
|
|
||||||
table[first] = mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sint rest_bits = sint(bits) % sint(TTMATH_BITS_PER_UINT);
|
|
||||||
for( ; rest_bits > 0 ; --rest_bits )
|
|
||||||
last_c = Rcl(c);
|
|
||||||
|
|
||||||
return last_c;
|
return last_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for moving bits into the right hand side
|
||||||
|
|
||||||
|
this method moves only words
|
||||||
|
*/
|
||||||
|
void RcrMoveAllWords( sint & all_words, uint & rest_bits, uint & last_c,
|
||||||
|
uint bits, uint c)
|
||||||
|
{
|
||||||
|
rest_bits = sint(bits % TTMATH_BITS_PER_UINT);
|
||||||
|
all_words = sint(bits / TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
|
if( all_words >= sint(value_size) )
|
||||||
|
{
|
||||||
|
if( all_words==value_size && rest_bits==0 )
|
||||||
|
last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
|
||||||
|
all_words = value_size; // not value_size - 1
|
||||||
|
rest_bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( all_words > 0 )
|
||||||
|
{
|
||||||
|
uint first;
|
||||||
|
uint second;
|
||||||
|
|
||||||
|
last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0
|
||||||
|
|
||||||
|
// copying the first part of the value
|
||||||
|
for(first=0, second=all_words ; second<value_size ; ++first, ++second)
|
||||||
|
table[first] = table[second];
|
||||||
|
|
||||||
|
// sets the rest bits of value into 'c'
|
||||||
|
uint mask = c ? TTMATH_UINT_MAX_VALUE : 0;
|
||||||
|
for( ; first<value_size ; ++first )
|
||||||
|
table[first] = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving all bits into the right side 'bits' times
|
moving all bits into the right side 'bits' times
|
||||||
c -> this -> return value
|
c -> this -> return value
|
||||||
|
|
||||||
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
|
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
|
||||||
@@ -1106,39 +1267,42 @@ public:
|
|||||||
the value c will be set into the highest bits
|
the value c will be set into the highest bits
|
||||||
and the method returns state of the last moved bit
|
and the method returns state of the last moved bit
|
||||||
*/
|
*/
|
||||||
uint Rcr(uint bits, uint c)
|
uint Rcr(uint bits, uint c=0)
|
||||||
{
|
{
|
||||||
sint first;
|
uint last_c = 0;
|
||||||
sint second;
|
sint all_words = 0;
|
||||||
sint last_c = 0;
|
uint rest_bits = bits;
|
||||||
|
|
||||||
if( bits > value_size*TTMATH_BITS_PER_UINT )
|
if( bits >= TTMATH_BITS_PER_UINT )
|
||||||
bits = value_size*TTMATH_BITS_PER_UINT;
|
RcrMoveAllWords(all_words, rest_bits, last_c, bits, c);
|
||||||
|
|
||||||
sint all_words = sint(bits) / sint(TTMATH_BITS_PER_UINT);
|
// rest_bits is from 0 to TTMATH_BITS_PER_UINT-1 now
|
||||||
|
if( rest_bits > 0 )
|
||||||
if( all_words > 0 )
|
|
||||||
{
|
{
|
||||||
// copying the first part of the value
|
if( rest_bits > TTMATH_BITS_PER_UINT/2 + 1 )
|
||||||
for(first=0, second=all_words ; second<sint(value_size) ; ++first, ++second)
|
|
||||||
{
|
{
|
||||||
last_c = table[first] & TTMATH_UINT_HIGHEST_BIT;
|
uint temp = table[value_size-1];
|
||||||
table[first] = table[second];
|
Rcl2(TTMATH_BITS_PER_UINT-rest_bits,0);
|
||||||
|
last_c = (table[0] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
|
||||||
|
for(uint i=0 ; i<value_size-1 ; ++i)
|
||||||
|
table[i] = table[i+1];
|
||||||
|
|
||||||
|
table[value_size-1] = temp >> rest_bits;
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
uint mask = TTMATH_UINT_MAX_VALUE >> rest_bits;
|
||||||
|
table[value_size-1] |= ~mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_c = Rcr2(rest_bits, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( last_c )
|
|
||||||
last_c = 1;
|
|
||||||
|
|
||||||
// sets the rest bits of value into 'c'
|
|
||||||
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
|
|
||||||
for( ; first<sint(value_size) ; ++first )
|
|
||||||
table[first] = mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sint rest_bits = sint(bits) % sint(TTMATH_BITS_PER_UINT);
|
|
||||||
for( ; rest_bits > 0 ; --rest_bits )
|
|
||||||
last_c = Rcr(c);
|
|
||||||
|
|
||||||
return last_c;
|
return last_c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1175,14 +1339,14 @@ public:
|
|||||||
table[i] = 0;
|
table[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// moving the rest bits (max TTMATH_BITS_PER_UINT -- only one word)
|
uint moving2 = FindLeadingBitInWord( table[value_size-1] );
|
||||||
while( !IsTheHighestBitSet() )
|
// moving2 is different from -1 because the value table[value_size-1]
|
||||||
{
|
// is not zero
|
||||||
Rcl();
|
|
||||||
++moving;
|
|
||||||
}
|
|
||||||
|
|
||||||
return moving;
|
moving2 = TTMATH_BITS_PER_UINT - moving2 - 1;
|
||||||
|
Rcl(moving2);
|
||||||
|
|
||||||
|
return moving + moving2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1314,7 +1478,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
it sets the bit bit_index
|
setting the 'bit_index' bit
|
||||||
|
|
||||||
bit_index bigger or equal zero
|
bit_index bigger or equal zero
|
||||||
*/
|
*/
|
||||||
@@ -1330,6 +1494,76 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method performs a bitwise operation AND
|
||||||
|
*/
|
||||||
|
void BitAnd(const UInt<value_size> & ss2)
|
||||||
|
{
|
||||||
|
for(uint x=0 ; x<value_size ; ++x)
|
||||||
|
table[x] &= ss2.table[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method performs a bitwise operation OR
|
||||||
|
*/
|
||||||
|
void BitOr(const UInt<value_size> & ss2)
|
||||||
|
{
|
||||||
|
for(uint x=0 ; x<value_size ; ++x)
|
||||||
|
table[x] |= ss2.table[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method performs a bitwise operation XOR
|
||||||
|
*/
|
||||||
|
void BitXor(const UInt<value_size> & ss2)
|
||||||
|
{
|
||||||
|
for(uint x=0 ; x<value_size ; ++x)
|
||||||
|
table[x] ^= ss2.table[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method performs a bitwise operation NOT
|
||||||
|
*/
|
||||||
|
void BitNot()
|
||||||
|
{
|
||||||
|
for(uint x=0 ; x<value_size ; ++x)
|
||||||
|
table[x] = ~table[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method performs a bitwise operation NOT but only
|
||||||
|
on the range of <0, leading_bit>
|
||||||
|
|
||||||
|
for example:
|
||||||
|
BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7
|
||||||
|
*/
|
||||||
|
void BitNot2()
|
||||||
|
{
|
||||||
|
uint table_id, index;
|
||||||
|
|
||||||
|
if( FindLeadingBit(table_id, index) )
|
||||||
|
{
|
||||||
|
for(uint x=0 ; x<table_id ; ++x)
|
||||||
|
table[x] = ~table[x];
|
||||||
|
|
||||||
|
uint mask = TTMATH_UINT_MAX_VALUE;
|
||||||
|
uint shift = TTMATH_BITS_PER_UINT - index - 1;
|
||||||
|
|
||||||
|
if(shift)
|
||||||
|
mask >>= shift;
|
||||||
|
|
||||||
|
table[table_id] ^= mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
table[0] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* Multiplication
|
* Multiplication
|
||||||
@@ -1340,7 +1574,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM32
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
|
||||||
@@ -1442,6 +1676,47 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result = this * ss2
|
||||||
|
|
||||||
|
we're using this method only when result_size is greater than value_size
|
||||||
|
if so there will not be a carry
|
||||||
|
*/
|
||||||
|
template<uint result_size>
|
||||||
|
uint MulInt(uint ss2, UInt<result_size> & result)
|
||||||
|
{
|
||||||
|
uint r2,r1;
|
||||||
|
uint x1size=value_size;
|
||||||
|
uint x1start=0;
|
||||||
|
|
||||||
|
if( value_size >= result_size )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result.SetZero();
|
||||||
|
|
||||||
|
if( value_size > 2 )
|
||||||
|
{
|
||||||
|
// if the value_size is smaller than or equal to 2
|
||||||
|
// there is no sense to set x1size and x1start to another values
|
||||||
|
|
||||||
|
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||||
|
|
||||||
|
if( x1size==0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint x1=x1start ; x1<x1size ; ++x1)
|
||||||
|
{
|
||||||
|
MulTwoWords(table[x1], ss2, &r2, &r1 );
|
||||||
|
result.AddTwoInts(r2,r1,x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the multiplication 'this' = 'this' * ss2
|
the multiplication 'this' = 'this' * ss2
|
||||||
@@ -1504,7 +1779,7 @@ public:
|
|||||||
if( Add(*this) )
|
if( Add(*this) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( ss1.Rcl() )
|
if( ss1.Rcl(1) )
|
||||||
if( Add(ss2) )
|
if( Add(ss2) )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1893,7 +2168,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
div_a:
|
div_a:
|
||||||
c = Rcl(c);
|
c = Rcl(1, c);
|
||||||
c = rest.Add(rest,c);
|
c = rest.Add(rest,c);
|
||||||
c = rest.Sub(divisor,c);
|
c = rest.Sub(divisor,c);
|
||||||
|
|
||||||
@@ -1908,12 +2183,12 @@ private:
|
|||||||
if(loop)
|
if(loop)
|
||||||
goto div_a;
|
goto div_a;
|
||||||
|
|
||||||
c = Rcl(c);
|
c = Rcl(1, c);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
div_c:
|
div_c:
|
||||||
c = Rcl(c);
|
c = Rcl(1, c);
|
||||||
c = rest.Add(rest,c);
|
c = rest.Add(rest,c);
|
||||||
c = rest.Add(divisor);
|
c = rest.Add(divisor);
|
||||||
|
|
||||||
@@ -1926,7 +2201,7 @@ private:
|
|||||||
if(loop)
|
if(loop)
|
||||||
goto div_c;
|
goto div_c;
|
||||||
|
|
||||||
c = Rcl(c);
|
c = Rcl(1, c);
|
||||||
c = rest.Add(divisor);
|
c = rest.Add(divisor);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2007,7 +2282,7 @@ private:
|
|||||||
|
|
||||||
if( CmpSmaller(divisor_copy, table_id) )
|
if( CmpSmaller(divisor_copy, table_id) )
|
||||||
{
|
{
|
||||||
divisor_copy.Rcr();
|
divisor_copy.Rcr(1);
|
||||||
--bits_diff;
|
--bits_diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2283,16 +2558,17 @@ private:
|
|||||||
{
|
{
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
|
|
||||||
|
// !!!!!!!!! change
|
||||||
for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
|
for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
|
||||||
{
|
{
|
||||||
// we can move the bits only to the 'n-1' index but at the moment
|
// we can move the bits only to the 'n-1' index but at the moment
|
||||||
// we don't have such method
|
// we don't have such method
|
||||||
// maybe it's time to write it now?
|
// maybe it's time to write it now?
|
||||||
v.Rcl(0);
|
v.Rcl(1, 0);
|
||||||
|
|
||||||
c <<= 1;
|
c <<= 1;
|
||||||
|
|
||||||
if( Rcl(0) )
|
if( Rcl(1, 0) )
|
||||||
c += 1;
|
c += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2388,7 +2664,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets n firt bits to value zero
|
this method sets n first bits to value zero
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
let n=2 then if there's a value 111 (bin) there'll be '100' (bin)
|
let n=2 then if there's a value 111 (bin) there'll be '100' (bin)
|
||||||
@@ -2424,7 +2700,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
it returns true if the highest bit of the value is set
|
this method returns true if the highest bit of the value is set
|
||||||
*/
|
*/
|
||||||
bool IsTheHighestBitSet() const
|
bool IsTheHighestBitSet() const
|
||||||
{
|
{
|
||||||
@@ -2433,7 +2709,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
it returns true if the lowest bit of the value is set
|
this method returns true if the lowest bit of the value is set
|
||||||
*/
|
*/
|
||||||
bool IsTheLowestBitSet() const
|
bool IsTheLowestBitSet() const
|
||||||
{
|
{
|
||||||
@@ -2442,7 +2718,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
it returns true if the value is equal zero
|
this method returns true if the value is equal zero
|
||||||
*/
|
*/
|
||||||
bool IsZero() const
|
bool IsZero() const
|
||||||
{
|
{
|
||||||
@@ -2475,7 +2751,7 @@ public:
|
|||||||
A -> 10
|
A -> 10
|
||||||
f -> 15
|
f -> 15
|
||||||
|
|
||||||
this method don't check whether c 'is' correct or not
|
this method don't check whether c is correct or not
|
||||||
*/
|
*/
|
||||||
static uint CharToDigit(uint c)
|
static uint CharToDigit(uint c)
|
||||||
{
|
{
|
||||||
@@ -2845,6 +3121,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* methods for comparing
|
* methods for comparing
|
||||||
@@ -2852,6 +3130,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'this' is smaller than 'l'
|
||||||
|
|
||||||
|
'index' is an index of the first word from will be the comparison performed
|
||||||
|
(note: we start the comparison from back - from the last word, when index is -1 /default/
|
||||||
|
it is automatically set into the last word)
|
||||||
|
I introduced it for some kind of optimization made in the second division algorithm (Div2)
|
||||||
|
*/
|
||||||
bool CmpSmaller(const UInt<value_size> & l, sint index = -1) const
|
bool CmpSmaller(const UInt<value_size> & l, sint index = -1) const
|
||||||
{
|
{
|
||||||
sint i;
|
sint i;
|
||||||
@@ -2874,6 +3160,15 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'this' is bigger than 'l'
|
||||||
|
|
||||||
|
'index' is an index of the first word from will be the comparison performed
|
||||||
|
(note: we start the comparison from back - from the last word, when index is -1 /default/
|
||||||
|
it is automatically set into the last word)
|
||||||
|
|
||||||
|
I introduced it for some kind of optimization made in the second division algorithm (Div2)
|
||||||
|
*/
|
||||||
bool CmpBigger(const UInt<value_size> & l, sint index = -1) const
|
bool CmpBigger(const UInt<value_size> & l, sint index = -1) const
|
||||||
{
|
{
|
||||||
sint i;
|
sint i;
|
||||||
@@ -2895,6 +3190,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'this' is equal 'l'
|
||||||
|
|
||||||
|
'index' is an index of the first word from will be the comparison performed
|
||||||
|
(note: we start the comparison from back - from the last word, when index is -1 /default/
|
||||||
|
it is automatically set into the last word)
|
||||||
|
*/
|
||||||
bool CmpEqual(const UInt<value_size> & l, sint index = -1) const
|
bool CmpEqual(const UInt<value_size> & l, sint index = -1) const
|
||||||
{
|
{
|
||||||
sint i;
|
sint i;
|
||||||
@@ -2912,6 +3214,15 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'this' is smaller than or equal 'l'
|
||||||
|
|
||||||
|
'index' is an index of the first word from will be the comparison performed
|
||||||
|
(note: we start the comparison from back - from the last word, when index is -1 /default/
|
||||||
|
it is automatically set into the last word)
|
||||||
|
*/
|
||||||
bool CmpSmallerEqual(const UInt<value_size> & l, sint index=-1) const
|
bool CmpSmallerEqual(const UInt<value_size> & l, sint index=-1) const
|
||||||
{
|
{
|
||||||
sint i;
|
sint i;
|
||||||
@@ -2932,6 +3243,15 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'this' is bigger than or equal 'l'
|
||||||
|
|
||||||
|
'index' is an index of the first word from will be the comparison performed
|
||||||
|
(note: we start the comparison from back - from the last word, when index is -1 /default/
|
||||||
|
it is automatically set into the last word)
|
||||||
|
*/
|
||||||
bool CmpBiggerEqual(const UInt<value_size> & l, sint index=-1) const
|
bool CmpBiggerEqual(const UInt<value_size> & l, sint index=-1) const
|
||||||
{
|
{
|
||||||
sint i;
|
sint i;
|
||||||
@@ -2953,7 +3273,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
/*
|
||||||
|
operators for comparising
|
||||||
|
*/
|
||||||
|
|
||||||
bool operator<(const UInt<value_size> & l) const
|
bool operator<(const UInt<value_size> & l) const
|
||||||
{
|
{
|
||||||
@@ -2961,7 +3283,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool operator>(const UInt<value_size> & l) const
|
bool operator>(const UInt<value_size> & l) const
|
||||||
{
|
{
|
||||||
return CmpBigger(l);
|
return CmpBigger(l);
|
||||||
@@ -2974,7 +3295,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool operator!=(const UInt<value_size> & l) const
|
bool operator!=(const UInt<value_size> & l) const
|
||||||
{
|
{
|
||||||
return !operator==(l);
|
return !operator==(l);
|
||||||
@@ -3090,6 +3410,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Prefix operator e.g ++variable
|
Prefix operator e.g ++variable
|
||||||
*/
|
*/
|
||||||
@@ -3183,6 +3504,11 @@ public:
|
|||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint Rcl2(uint bits, uint c);
|
||||||
|
uint Rcr2(uint bits, uint c);
|
||||||
|
|
||||||
|
public:
|
||||||
// these methods are for 64bit processors and are defined in 'ttmathuint64.h'
|
// these methods are for 64bit processors and are defined in 'ttmathuint64.h'
|
||||||
UInt<value_size> & operator=(unsigned int i);
|
UInt<value_size> & operator=(unsigned int i);
|
||||||
UInt(unsigned int i);
|
UInt(unsigned int i);
|
||||||
@@ -3194,8 +3520,6 @@ public:
|
|||||||
uint AddTwoInts(uint x2, uint x1, uint index);
|
uint AddTwoInts(uint x2, uint x1, uint index);
|
||||||
uint Sub(const UInt<value_size> & ss2, uint c=0);
|
uint Sub(const UInt<value_size> & ss2, uint c=0);
|
||||||
uint SubInt(uint value, uint index = 0);
|
uint SubInt(uint value, uint index = 0);
|
||||||
uint Rcl(uint c=0);
|
|
||||||
uint Rcr(uint c=0);
|
|
||||||
static sint FindLeadingBitInWord(uint x);
|
static sint FindLeadingBitInWord(uint x);
|
||||||
static uint SetBitInWord(uint value, uint bit);
|
static uint SetBitInWord(uint value, uint bit);
|
||||||
static void MulTwoWords(uint a, uint b, uint * result2, uint * result1);
|
static void MulTwoWords(uint a, uint b, uint * result2, uint * result1);
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2007, Tomasz Sowa
|
* Copyright (c) 2006-2008, 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
|
||||||
@@ -416,7 +416,7 @@ namespace ttmath
|
|||||||
"movq $0, %%rdx \n"
|
"movq $0, %%rdx \n"
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
"movq (%%rbx), %%rax \n"
|
||||||
"addq %%rsi, %%rax \n"
|
"addq %%rsi, %%rax \n"
|
||||||
"movq %%rax, (%%rbx) \n"
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
|
||||||
"inc %%rbx \n"
|
"inc %%rbx \n"
|
||||||
@@ -429,7 +429,7 @@ namespace ttmath
|
|||||||
"inc %%rbx \n"
|
"inc %%rbx \n"
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
"movq (%%rbx), %%rax \n"
|
||||||
"adcq %%rdi, %%rax \n"
|
"adcq %%rdi, %%rax \n"
|
||||||
"movq %%rax, (%%rbx) \n"
|
"movq %%rax, (%%rbx) \n"
|
||||||
"jnc 2f \n"
|
"jnc 2f \n"
|
||||||
|
|
||||||
@@ -638,17 +638,27 @@ namespace ttmath
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving once all bits into the left side
|
this method moves all bits into the left hand side
|
||||||
return value <- this <- C
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
the lowest bit will hold value of 'c' and
|
|
||||||
function returns the highest bit
|
|
||||||
*/
|
*/
|
||||||
template<uint value_size>
|
template<uint value_size>
|
||||||
uint UInt<value_size>::Rcl(uint c)
|
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
||||||
{
|
{
|
||||||
|
if( bits == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
register sint b = value_size;
|
register sint b = value_size;
|
||||||
register uint * p1 = table;
|
register uint * p1 = table;
|
||||||
|
|
||||||
@@ -659,12 +669,17 @@ namespace ttmath
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rsi \n"
|
||||||
|
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
"xorq %%rax,%%rax \n"
|
||||||
|
"subq %%rdx,%%rax \n"
|
||||||
|
|
||||||
"push %%rbx \n"
|
"push %%rbx \n"
|
||||||
"push %%rcx \n"
|
"push %%rcx \n"
|
||||||
|
|
||||||
"movq $0,%%rax \n"
|
|
||||||
"subq %%rdx,%%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
"1: \n"
|
||||||
"rclq $1,(%%rbx) \n"
|
"rclq $1,(%%rbx) \n"
|
||||||
|
|
||||||
@@ -679,14 +694,20 @@ namespace ttmath
|
|||||||
|
|
||||||
"loop 1b \n"
|
"loop 1b \n"
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx,%%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
"pop %%rcx \n"
|
||||||
"pop %%rbx \n"
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
"decq %%rsi \n"
|
||||||
|
|
||||||
|
"jnz 2b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
"adcq %%rdx, %%rdx \n"
|
||||||
|
|
||||||
|
"pop %%rsi \n"
|
||||||
|
|
||||||
: "=d" (c)
|
: "=d" (c)
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||||
: "%rax", "cc", "memory" );
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -697,17 +718,27 @@ namespace ttmath
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method moving once all bits into the right side
|
this method moves all bits into the right hand side
|
||||||
C -> *this -> return value
|
C -> this -> return value
|
||||||
|
|
||||||
|
the highest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
the highest bit will be held value of 'c' and
|
|
||||||
function returns the lowest bit
|
|
||||||
*/
|
*/
|
||||||
template<uint value_size>
|
template<uint value_size>
|
||||||
uint UInt<value_size>::Rcr(uint c)
|
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
||||||
{
|
{
|
||||||
|
if( bits == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
register sint b = value_size;
|
register sint b = value_size;
|
||||||
register uint * p1 = table;
|
register uint * p1 = table;
|
||||||
|
|
||||||
@@ -720,12 +751,18 @@ namespace ttmath
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rsi \n"
|
||||||
|
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
"push %%rbx \n"
|
||||||
"push %%rcx \n"
|
"push %%rcx \n"
|
||||||
|
|
||||||
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
"xorq %%rax, %%rax \n"
|
||||||
"subq %%rdx, %%rax \n"
|
"subq %%rdx, %%rax \n"
|
||||||
|
|
||||||
"1: \n"
|
"1: \n"
|
||||||
@@ -742,14 +779,20 @@ namespace ttmath
|
|||||||
|
|
||||||
"loop 1b \n"
|
"loop 1b \n"
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx,%%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
"pop %%rcx \n"
|
||||||
"pop %%rbx \n"
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
"decq %%rsi \n"
|
||||||
|
|
||||||
|
"jnz 2b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
"adcq %%rdx,%%rdx \n"
|
||||||
|
|
||||||
|
"pop %%rsi \n"
|
||||||
|
|
||||||
: "=d" (c)
|
: "=d" (c)
|
||||||
: "0" (c), "c" (b), "b" (p1)
|
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
||||||
: "%rax", "cc", "memory" );
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -940,4 +983,3 @@ namespace ttmath
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user