Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
51e938eaa7 | ||
|
e102086f80 | ||
|
51b2c974a1 | ||
|
5597373093 | ||
|
de58378488 | ||
|
de64608eba | ||
|
be8913866a | ||
|
b31d34ebdd | ||
|
be821b59dd | ||
|
de1e7ac957 | ||
|
fdc292e91a | ||
|
9b576ddbe2 | ||
|
a8c3a506ea | ||
|
3ba94dca90 | ||
|
cae50cd425 | ||
|
00e39d3608 | ||
|
37379d2f1f | ||
|
d7b67e4d47 | ||
|
c91bd24e98 | ||
|
cbc12db22f | ||
3e9bd5b093 |
251
CHANGELOG
251
CHANGELOG
@@ -1,135 +1,15 @@
|
||||
Version 0.9.3 (2012.12.28):
|
||||
* fixed: in Big::FromDouble(double value) (only 32 bit version)
|
||||
buffer overflow in referencing to UInt<2>
|
||||
this was used when 'value' was in so called "unnormalized" state
|
||||
(E=0 and F is nonzero)
|
||||
it produced incorrect mantissa (on about 8th decimal digit up)
|
||||
* added: Parser::InitCGamma()
|
||||
initializing coefficients used when calculating the gamma (or factorial) function
|
||||
this speed up the next calculations
|
||||
you don't have to call this method explicitly
|
||||
these coefficients will be calculated when needed
|
||||
* added: option 'group_digits' to Conv struct
|
||||
you can set how many digits should be grouped
|
||||
* changed: small optimizations in UInt::ToString() and Big::FromString()
|
||||
|
||||
|
||||
Version 0.9.2 (2010.09.23):
|
||||
* fixed: Big::Add() sometimes incorrectly rounded the last bit from its mantissa
|
||||
* fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN
|
||||
when the argument was negative (they only returned 2)
|
||||
* fixed: recurrence calling in Big::FromString(const std::string &, uint, const wchar_t **, bool *)
|
||||
it should have the signature: Big::FromString(const std::string &, uint, const char **, bool *)
|
||||
* fixed: Big::ToString method
|
||||
in some cases when in the output string the exponent should be equal zero
|
||||
the method changes the exponent to one so the last digit from the mantissa
|
||||
was lost
|
||||
* fixed: Big::ToDouble(double &) set always +INF (infinity)
|
||||
when the value was too large (even for negative values)
|
||||
(it should set -INF in such a case)
|
||||
* added: some missing operators
|
||||
UInt::operator~() /* bitwise neg */
|
||||
UInt::operator&() /* bitwise and */
|
||||
UInt::operator&=()
|
||||
UInt::operator|() /* bitwise or */
|
||||
UInt::operator|=()
|
||||
UInt::operator^() /* bitwise xor */
|
||||
UInt::operator^=()
|
||||
Big::operator&()
|
||||
Big::operator&=()
|
||||
Big::operator|()
|
||||
Big::operator|=()
|
||||
Big::operator^()
|
||||
Big::operator^=()
|
||||
for Big<> we do not define bitwise neg
|
||||
Big::operator++()
|
||||
Big::operator++(int)
|
||||
Big::operator--()
|
||||
Big::operator--(int)
|
||||
* added: macro TTMATH_DONT_USE_WCHAR
|
||||
if defined then the library does not use wide characters
|
||||
(wchar_t, std::wstring, ...) this is a workaround for some compilers
|
||||
* added: bool UInt::IsOnlyTheHighestBitSet()
|
||||
bool UInt::IsOnlyTheLowestBitSet()
|
||||
returning true if only the highest/lowest bit is set
|
||||
* added: uint Int::MulInt(sint ss2)
|
||||
* added: void UInt::Swap(UInt<value_size> & ss2)
|
||||
void Big::Swap(UInt<value_size> & ss2)
|
||||
method for swapping this for an argument
|
||||
* added: macro TTMATH_BIG_DEFAULT_CLEAR
|
||||
when defined the default constructor from Big<> clears its mantissa and exponent
|
||||
Big<1, 2> var;
|
||||
var.mantissa and var.exponent will be set to zero
|
||||
(but var has the NaN flag set too - it is not zero value, this is mainly for debug purposes)
|
||||
* added: only on 32bit platforms:
|
||||
uint UInt::FromUInt(uint64_t n)
|
||||
uint Int::FromInt(int64_t n)
|
||||
void Big::FromUInt(uint64_t n)
|
||||
void Big::FromInt(int64_t n)
|
||||
and appropriate constructors and operators
|
||||
* added: TTMATH_FORCEASM macro
|
||||
asm version of the library is available by default only for:
|
||||
x86 and amd64 platforms and for Microsoft Visual and GCC compilers,
|
||||
but you can force using asm version (the same asm as for Microsoft Visual)
|
||||
by defining TTMATH_FORCEASM macro
|
||||
you have to be sure that your compiler accept such an asm format
|
||||
* added: some missing methods for converting
|
||||
for UInt<>, Int<> and Big<> classes:
|
||||
uint ToUInt()
|
||||
sint ToInt()
|
||||
ToUInt(uint32_t &)
|
||||
ToInt(uint32_t &)
|
||||
ToInt(int32_t &)
|
||||
ToUInt(uint64_t &)
|
||||
ToInt(uint64_t &)
|
||||
ToInt(int64_t &)
|
||||
FromUInt(uint32_t &)
|
||||
FromInt(uint32_t &)
|
||||
FromInt(int32_t &)
|
||||
FromUInt(uint64_t &)
|
||||
FromInt(uint64_t &)
|
||||
FromInt(int64_t &)
|
||||
and appropriate constructors and operators
|
||||
* added: double Big::ToDouble() /there was only Big::ToDouble(double &) /
|
||||
uint Big::ToFloat(float &)
|
||||
float Big::ToFloat()
|
||||
* changed: now asm version is available only on x86 and amd64
|
||||
(and only for GCC and MS VC compilers)
|
||||
* removed: macro TTMATH_RELEASE (now the 'release' version is default)
|
||||
for debug version define TTMATH_DEBUG macro
|
||||
TTMATH_DEBUG is also automatically defined when DEBUG or _DEBUG is set
|
||||
* removed: macro TTMATH_REFERENCE_ASSERT from all methods in public interface
|
||||
|
||||
|
||||
Version 0.9.1 (2010.02.07):
|
||||
* fixed: the parser didn't use characters for changing the base (# and &)
|
||||
those characters were skipped
|
||||
(this bug was introduced in 0.9.0)
|
||||
* fixed: added in the parser: operator's associativity
|
||||
operator ^ (powering) is right-associative:
|
||||
sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24
|
||||
previously was: 2^3^4 = (2^3)^4 = 4096
|
||||
* fixed: in Big::ToString_CreateNewMantissaAndExponent() changed the formula:
|
||||
new_exp_ = [log base (2^exponent)] + 1
|
||||
now the part '+ 1' is only made when the logarithm is positive and with fraction
|
||||
if the value is negative we can only skip the fraction, previously
|
||||
we lost some last digits from the new mantissa
|
||||
Consider this binary value (32 bit mantissa):
|
||||
(bin)1.0000000000000000000000000000011
|
||||
previously ToString() gave 1, now we have: 1.000000001
|
||||
* changed: in Big::ToString() the base rounding is made only if the result value
|
||||
would not be an integer, e.g. if the value is 1.999999999999 then
|
||||
the base rounding will not be done - because as the result would be 2
|
||||
* added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
|
||||
floating point algorithms: Big::Add, Big::Sub, Big::Mul, Big::Div
|
||||
* added: static sint UInt<value_size>::FindLowestBitInWord(uint x)
|
||||
this method is looking for the lowest set bit in a word
|
||||
* added: UInt::FindLowestBit(uint & table_id, uint & index)
|
||||
this method is looking for the lowest set bit
|
||||
|
||||
|
||||
Version 0.9.0 (2009.11.25):
|
||||
* added: support for wide characters (wchar_t, std::wstring)
|
||||
Version 0.9.0 prerelease (2009.07.16):
|
||||
* added: support for wide characters (wchar_t)
|
||||
wide characters are used when macro TTMATH_USE_WCHAR is defined
|
||||
this macro is defined automatically when there is macro UNICODE or _UNICODE defined
|
||||
some types have been changed
|
||||
char -> tt_char
|
||||
std::string -> tt_string
|
||||
std::ostringstream -> tt_ostringstream
|
||||
std::ostream -> tt_ostream
|
||||
std::istream -> tt_istream
|
||||
normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on)
|
||||
(all typedef's are in ttmathtypes.h)
|
||||
* added: Big::IsInteger()
|
||||
returns true if the value is integer (without fraction)
|
||||
(NaN flag is not checked)
|
||||
@@ -137,117 +17,10 @@ Version 0.9.0 (2009.11.25):
|
||||
* added: gamma() function to the parser
|
||||
* added: CGamma<ValueType> class
|
||||
is used with Gamma() and Factorial() in multithreaded environment
|
||||
* added: multithread support for Big<> class
|
||||
you should compile with TTMATH_MULTITHREADS
|
||||
and use TTMATH_MULTITHREADS_HELPER macro somewhere in your *.cpp file
|
||||
* added: x86_64 asm code for Microsoft Visual compiler
|
||||
file: ttmathuint_x86_64_msvc.asm
|
||||
(this file should be compiled first because MS VC doesn't support inline assembler in x86_64 mode)
|
||||
* added: flag TTMATH_BIG_ZERO to Big<> class
|
||||
if this flag is set then there is a value zero
|
||||
Big::IsZero() is faster now
|
||||
* added: Big::ClearInfoBit(unsigned char)
|
||||
Big::SetInfoBit(unsigned char)
|
||||
Big::IsInfoBit(unsigned char)
|
||||
some methods for manipulating the info flags
|
||||
* added: macro: TTMATH_BITS(min_bits)
|
||||
which returns the number of machine words
|
||||
capable to hold min_bits bits
|
||||
* added: bool Parser::Calculated()
|
||||
this method returns true is something was calculated
|
||||
(at least one mathematical operator was used or a function or variable)
|
||||
* added: to the parser: operator percentage
|
||||
e.g. 1000-50%=1000-(1000*0,5)=500
|
||||
* added: struct: Conv
|
||||
consists of some parameters used
|
||||
in ToString() and FromString()
|
||||
* added: Big::ToString() can group digits
|
||||
e.g. 1234567 -> 1`234`567
|
||||
* added: Parser::SetGroup(int g)
|
||||
Parser::SetComma(int c, int c2 = 0)
|
||||
Parser::SetParamSep(int s)
|
||||
* added: std::string UInt::ToString(uint b = 10)
|
||||
std::wstring UInt::ToWString(uint b = 10)
|
||||
std::string Int::ToString(uint b = 10)
|
||||
std::wstring Int::ToWString(uint b = 10)
|
||||
uint Big::ToString(std::string & result, const Conv & conv)
|
||||
uint Big::ToString(std::wstring & result, const Conv & conv)
|
||||
std::string Big::ToString(const Conv & conv)
|
||||
std::string Big::ToString()
|
||||
std::wstring Big::ToWString(const Conv & conv)
|
||||
std::wstring Big::ToWString()
|
||||
* added: uint FromString(const char * source, const Conv & conv, const char **, bool *)
|
||||
uint FromString(const wchar_t * source, const Conv & conv, const wchar_t **, bool *)
|
||||
uint FromString(const std::string & string, const Conv & conv, const wchar_t **, bool *)
|
||||
uint FromString(const std::wstring & string, const Conv & conv, const wchar_t **, bool *)
|
||||
* added: UInt::Sqrt() - a new algorithm for calculating the square root
|
||||
* added: to the parser: function frac() - returns a value without the integer part
|
||||
(only fraction remains)
|
||||
* added: Int::DivInt(sint divisor, sint * remainder)
|
||||
* added: const char * UInt::LibTypeStr()
|
||||
const char * Big::LibTypeStr()
|
||||
LibTypeCode UInt::LibType()
|
||||
LibTypeCode Big::LibType()
|
||||
returning a string/enum represents the currect type of the library
|
||||
we have following types:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
* added: UInt::operator>>(int)
|
||||
UInt::operator>>=(int)
|
||||
UInt::operator<<(int)
|
||||
UInt::operator<<=(int)
|
||||
* changed: Factorial() is using the Gamma() function now
|
||||
* changed: Big::Div(ss2)
|
||||
Big::Mod(ss2)
|
||||
they return 2 when ss2 is zero
|
||||
previously returned 1
|
||||
* changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
|
||||
they were not too much accurate for some integers
|
||||
e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)
|
||||
* changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16
|
||||
the previous version was not accurate on some last digits (after the comma operator)
|
||||
consider this binary value (32 bit mantissa):
|
||||
base 2: 1.1111 1111 1111 1111 1111 1111 1110 101
|
||||
previous ToString() gave:
|
||||
base 4: 1.33333333333332
|
||||
base 8: 1.777777777
|
||||
base 16: 1.FFFFFF
|
||||
now we have:
|
||||
base 4: 1.3333333333333222
|
||||
base 8: 1.77777777724
|
||||
base 16: 1.FFFFFFEA
|
||||
* changed: in Big::ToString() some additional rounding (base_round) is now made only
|
||||
when the value is not an integer
|
||||
* changed: another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
|
||||
* removed: Parser<>::SetFactorialMax() method
|
||||
the factorial() is such a fast now that we don't need the method longer
|
||||
* removed: ErrorCode::err_too_big_factorial
|
||||
* removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
|
||||
the comma characters we have in Conv struct now
|
||||
|
||||
|
||||
Version 0.8.6 (2009.10.25):
|
||||
* fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
|
||||
equal 1 (should be set 2)
|
||||
this affected only no-asm parts - when macro TTMATH_NOASM was defined
|
||||
* fixed: UInt<value_size>::MulInt(uint ss2)
|
||||
there was a buffer overflow when value_size was equal 1
|
||||
* fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
|
||||
when macro TTMATH_NOASM was defined
|
||||
* fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
|
||||
* fixed: Int::FromString(const tt_string & s, uint b = 10)
|
||||
didn't use 'b' (always was '10')
|
||||
* fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
|
||||
* fixed: powering algorithm in:
|
||||
UInt::Pow(UInt<value_size> pow)
|
||||
Big::Pow(UInt<pow_size> pow)
|
||||
Big::PowUInt(Big<exp, man> pow)
|
||||
when 'pow' was sufficient large the algorithm returned carry
|
||||
but the result could have been calculated correctly
|
||||
|
||||
|
||||
Version 0.8.5 (2009.06.16):
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2006-2012, Tomasz Sowa
|
||||
Copyright (c) 2006-2009, Tomasz Sowa
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
35
README
35
README
@@ -1,23 +1,26 @@
|
||||
A bignum library for C++
|
||||
TTMath - a bignum library for C++
|
||||
|
||||
TTMath is a small library which allows one to perform arithmetic operations
|
||||
with big unsigned integer, big signed integer and big floating point numbers.
|
||||
It provides standard mathematical operations like adding, subtracting,
|
||||
multiplying, dividing. With the library also goes a mathematical parser to
|
||||
help you solving mathematical expressions.
|
||||
with big unsigned integer, big signed integer and big floating point
|
||||
numbers. It provides standard mathematical operations like adding,
|
||||
subtracting, multiplying, dividing etc. With the library also goes
|
||||
a mathematical parser which helps you solving input formulas read directly
|
||||
from a user.
|
||||
|
||||
TTMath is developed under the BSD licence which means that it is free for
|
||||
both personal and commercial use.
|
||||
TTMath is developed under the BSD licence which means that it is free
|
||||
for both personal and commercial use.
|
||||
|
||||
The library has some technical limitations:
|
||||
* 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
|
||||
way as the standard types like int or float. It does not need to be 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 to do is
|
||||
to use 'include' directive of the preprocessor. How big the values can be
|
||||
is set at compile time.
|
||||
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.
|
||||
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
|
||||
values can be is set directly in the source code by the programmer.
|
||||
|
||||
Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
WWW: http://www.ttmath.org
|
||||
|
||||
Contributors:
|
||||
Christian Kaiser <chk@online.de>
|
||||
Project pages: http://www.ttmath.org
|
||||
http://sourceforge.net/projects/ttmath
|
||||
|
@@ -31,7 +31,7 @@ PROJECT_NAME = TTMath
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.9.2
|
||||
PROJECT_NUMBER = 0.8.2
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
CC = g++
|
||||
CFLAGS = -Wall -pedantic -s -O2 -I.. -DTTMATH_DONT_USE_WCHAR
|
||||
CFLAGS = -Wall -pedantic -s -O2 -I..
|
||||
|
||||
|
||||
.SUFFIXES: .cpp .o
|
||||
@@ -8,7 +8,7 @@ CFLAGS = -Wall -pedantic -s -O2 -I.. -DTTMATH_DONT_USE_WCHAR
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
|
||||
all: uint int big big2 parser
|
||||
all: uint int big parser
|
||||
|
||||
|
||||
uint: uint.o
|
||||
@@ -20,9 +20,6 @@ int: int.o
|
||||
big: big.o
|
||||
$(CC) -o big $(CFLAGS) big.o
|
||||
|
||||
big2: big2.o
|
||||
$(CC) -o big2 $(CFLAGS) big2.o
|
||||
|
||||
parser: parser.o
|
||||
$(CC) -o parser $(CFLAGS) parser.o
|
||||
|
||||
@@ -30,7 +27,6 @@ parser: parser.o
|
||||
uint.o: uint.cpp
|
||||
int.o: int.cpp
|
||||
big.o: big.cpp
|
||||
big2.o: big2.cpp
|
||||
parser.o: parser.cpp
|
||||
|
||||
|
||||
@@ -40,7 +36,6 @@ clean:
|
||||
rm -f uint
|
||||
rm -f int
|
||||
rm -f big
|
||||
rm -f big2
|
||||
rm -f parser
|
||||
# on MS Windows can automatically be added suffixes .exe to the names of output programs
|
||||
rm -f *.exe
|
||||
|
@@ -5,8 +5,6 @@
|
||||
// this type has 2 words for its mantissa and 1 word for its exponent
|
||||
// (on a 32bit platform one word means a word of 32 bits,
|
||||
// and on a 64bit platform one word means a word of 64 bits)
|
||||
|
||||
// Big<exponent, mantissa>
|
||||
typedef ttmath::Big<1,2> MyBig;
|
||||
|
||||
|
||||
@@ -58,7 +56,6 @@ MyBig atemp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
MyBig a,b;
|
||||
@@ -88,13 +85,13 @@ a = 123456.543456
|
||||
b = 98767878.124322
|
||||
a + b = 98891334.667778
|
||||
a - b = -98644421.580866
|
||||
a * b = 12193540837712.27076
|
||||
a / b = 0.00124996654580957646
|
||||
a * b = 12193540837712.2708
|
||||
a / b = 0.0012499665458095765
|
||||
Calculating with a carry
|
||||
a = 1.6248012560666408782e+646457012
|
||||
b = 456.319999999999993
|
||||
a + b = 1.6248012560666408782e+646457012
|
||||
a - b = 1.6248012560666408782e+646457012
|
||||
a = 1.624801256070839555e+646457012
|
||||
b = 456.31999999999999
|
||||
a + b = 1.624801256070839555e+646457012
|
||||
a - b = 1.624801256070839555e+646457012
|
||||
a * b = (carry)
|
||||
a / b = 3.560661939136222174e+646457009
|
||||
a / b = 3.56066193914542334e+646457009
|
||||
*/
|
||||
|
113
samples/big2.cpp
113
samples/big2.cpp
@@ -1,113 +0,0 @@
|
||||
#include <ttmath/ttmath.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// this is a similar example to big.cpp
|
||||
// but now we're using TTMATH_BITS() macro
|
||||
// this macro returns how many words we need to store
|
||||
// the given number of bits
|
||||
|
||||
// TTMATH_BITS(64)
|
||||
// on a 32bit platform the macro returns 2 (2*32=64)
|
||||
// on a 64bit platform the macro returns 1
|
||||
|
||||
// TTMATH_BITS(128)
|
||||
// on a 32bit platform the macro returns 4 (4*32=128)
|
||||
// on a 64bit platform the macro returns 2 (2*64=128)
|
||||
|
||||
// Big<exponent, mantissa>
|
||||
typedef ttmath::Big<TTMATH_BITS(64), TTMATH_BITS(128)> MyBig;
|
||||
|
||||
// consequently on a 32bit platform we define: Big<2, 4>
|
||||
// and on a 64bit platform: Big<1, 2>
|
||||
// and the calculations will be the same on both platforms
|
||||
|
||||
|
||||
void SimpleCalculating(const MyBig & a, const MyBig & b)
|
||||
{
|
||||
std::cout << "Simple calculating" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
std::cout << "a + b = " << a+b << std::endl;
|
||||
std::cout << "a - b = " << a-b << std::endl;
|
||||
std::cout << "a * b = " << a*b << std::endl;
|
||||
std::cout << "a / b = " << a/b << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void CalculatingWithCarry(const MyBig & a, const MyBig & b)
|
||||
{
|
||||
MyBig atemp;
|
||||
|
||||
std::cout << "Calculating with a carry" << std::endl;
|
||||
std::cout << "a = " << a << std::endl;
|
||||
std::cout << "b = " << b << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Add(b) )
|
||||
std::cout << "a + b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a + b = (carry)" << std::endl;
|
||||
// it have no sense to print 'atemp' (it's undefined)
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Sub(b) )
|
||||
std::cout << "a - b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a - b = (carry)" << std::endl;
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Mul(b) )
|
||||
std::cout << "a * b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a * b = (carry)" << std::endl;
|
||||
|
||||
|
||||
atemp = a;
|
||||
if( !atemp.Div(b) )
|
||||
std::cout << "a / b = " << atemp << std::endl;
|
||||
else
|
||||
std::cout << "a / b = (carry or division by zero) " << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
MyBig a,b;
|
||||
|
||||
// conversion from 'const char *'
|
||||
a = "123456.543456";
|
||||
b = "98767878.124322";
|
||||
|
||||
SimpleCalculating(a,b);
|
||||
|
||||
// 'a' will have the max value which can be held in this type
|
||||
a.SetMax();
|
||||
|
||||
// conversion from double
|
||||
b = 456.32;
|
||||
|
||||
// Look at the value 'a' and the product from a+b and a-b
|
||||
// Don't worry this is the nature of floating point numbers
|
||||
CalculatingWithCarry(a,b);
|
||||
}
|
||||
|
||||
/*
|
||||
the result (the same on a 32 or 64bit platform):
|
||||
|
||||
Simple calculating
|
||||
a = 123456.543456
|
||||
b = 98767878.124322
|
||||
a + b = 98891334.667778
|
||||
a - b = -98644421.580866
|
||||
a * b = 12193540837712.270763536832
|
||||
a / b = 0.0012499665458095764605964485261668609133
|
||||
Calculating with a carry
|
||||
a = 2.34953455457111777368832820909595050034e+2776511644261678604
|
||||
b = 456.3199999999999931787897367030382156
|
||||
a + b = 2.34953455457111777368832820909595050034e+2776511644261678604
|
||||
a - b = 2.34953455457111777368832820909595050034e+2776511644261678604
|
||||
a * b = (carry)
|
||||
a / b = 5.1488748127873374141170361292780486452e+2776511644261678601
|
||||
*/
|
@@ -29,11 +29,6 @@ const char equation[] = " (34 + 24) * 123 - 34.32 ^ 6 * sin(2.56) - atan(10)";
|
||||
|
||||
/*
|
||||
the result (on 32 bit platform):
|
||||
-897705014.525731067
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
the result (on 64 bit platform):
|
||||
-897705014.5257310676097719585259773124
|
||||
-897705014.52573107
|
||||
*/
|
||||
|
412
ttmath/ttmath.h
412
ttmath/ttmath.h
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2012, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -48,13 +48,8 @@
|
||||
#ifdef _MSC_VER
|
||||
//warning C4127: conditional expression is constant
|
||||
#pragma warning( disable: 4127 )
|
||||
//warning C4702: unreachable code
|
||||
#pragma warning( disable: 4702 )
|
||||
//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
|
||||
#pragma warning( disable: 4800 )
|
||||
#endif
|
||||
|
||||
|
||||
#include "ttmathbig.h"
|
||||
#include "ttmathobjects.h"
|
||||
|
||||
@@ -69,6 +64,7 @@ namespace ttmath
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* functions for rounding
|
||||
@@ -240,7 +236,7 @@ namespace ttmath
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Ln(x);
|
||||
|
||||
if( err )
|
||||
@@ -273,19 +269,15 @@ namespace ttmath
|
||||
template<class ValueType>
|
||||
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
|
||||
{
|
||||
if( x.IsNan() )
|
||||
if( x.IsNan() || base.IsNan() )
|
||||
{
|
||||
if( err ) *err = err_improper_argument;
|
||||
return x;
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return ValueType(); // default NaN
|
||||
}
|
||||
|
||||
if( base.IsNan() )
|
||||
{
|
||||
if( err ) *err = err_improper_argument;
|
||||
return base;
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Log(x, base);
|
||||
|
||||
if( err )
|
||||
@@ -326,7 +318,7 @@ namespace ttmath
|
||||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint c = result.Exp(x);
|
||||
|
||||
if( err )
|
||||
@@ -524,10 +516,10 @@ namespace ttmath
|
||||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
if( err )
|
||||
@@ -592,7 +584,7 @@ namespace ttmath
|
||||
*err = err_overflow;
|
||||
|
||||
return ValueType(); // result is undefined (NaN is set by default)
|
||||
}
|
||||
}
|
||||
|
||||
return Sin(x, err);
|
||||
}
|
||||
@@ -858,7 +850,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
if( x.GreaterWithoutSignThan(one) )
|
||||
@@ -905,7 +897,7 @@ namespace ttmath
|
||||
ValueType temp;
|
||||
|
||||
temp.Set05Pi();
|
||||
temp.Sub(ASin(x, err));
|
||||
temp.Sub(ASin(x,err));
|
||||
|
||||
return temp;
|
||||
}
|
||||
@@ -1084,7 +1076,7 @@ namespace ttmath
|
||||
bool change_sign = false;
|
||||
|
||||
if( x.IsNan() )
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
|
||||
// if x is negative we're using the formula:
|
||||
// atan(-x) = -atan(x)
|
||||
@@ -1552,7 +1544,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
@@ -1588,7 +1580,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = 180;
|
||||
@@ -1633,9 +1625,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable
|
||||
|
||||
return delimiter;
|
||||
return delimiter; // NaN is set by default
|
||||
}
|
||||
|
||||
multipler = 60;
|
||||
@@ -1689,7 +1679,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
@@ -1725,7 +1715,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = 200;
|
||||
@@ -1757,7 +1747,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
@@ -1807,7 +1797,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return x;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
result = x;
|
||||
@@ -1848,12 +1838,23 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
return ValueType(); // NaN is set by default
|
||||
}
|
||||
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// Sqrt(0) = 0
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint c = x.Sqrt();
|
||||
ValueType pow;
|
||||
pow.Set05();
|
||||
|
||||
// PowFrac can return only a carry because x is greater than zero
|
||||
uint c = x.PowFrac(pow);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
@@ -1866,32 +1867,12 @@ namespace ttmath
|
||||
namespace auxiliaryfunctions
|
||||
{
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( index.IsSign() )
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
// index cannot be negative
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( index.IsZero() )
|
||||
{
|
||||
if( x.IsZero() )
|
||||
if( index.IsSign() )
|
||||
{
|
||||
// there isn't root(0;0) - we assume it's not defined
|
||||
// index cannot be negative
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
@@ -1900,155 +1881,132 @@ namespace ttmath
|
||||
return true;
|
||||
}
|
||||
|
||||
// root(x;0) is 1 (if x!=0)
|
||||
x.SetOne();
|
||||
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
ValueType one;
|
||||
one.SetOne();
|
||||
|
||||
if( index == one )
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
//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 RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( index == 2 )
|
||||
{
|
||||
x = Sqrt(x, err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
if( !index.IsInteger() )
|
||||
{
|
||||
// index must be integer
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckXZero(ValueType & x, ErrorCode * err)
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// root(0;index) is zero (if index!=0)
|
||||
// RootCheckIndexZero() must be called beforehand
|
||||
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() )
|
||||
if( index.IsZero() )
|
||||
{
|
||||
*change_sign = true;
|
||||
x.Abs();
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// there isn't root(0;0) - we assume it's not defined
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// root(x;0) is 1 (if x!=0)
|
||||
x.SetOne();
|
||||
|
||||
if( err )
|
||||
*err = err_ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
|
||||
{
|
||||
// index is even
|
||||
// x cannot be negative
|
||||
if( x.IsSign() )
|
||||
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)
|
||||
{
|
||||
if( !index.IsInteger() )
|
||||
{
|
||||
// index must be integer
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
bool RootCheckXZero(ValueType & x, ErrorCode * err)
|
||||
{
|
||||
if( x.IsZero() )
|
||||
{
|
||||
// root(0;index) is zero (if index!=0)
|
||||
// RootCheckIndexZero() must be called beforehand
|
||||
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;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class ValueType>
|
||||
uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index)
|
||||
{
|
||||
if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() )
|
||||
return 0;
|
||||
|
||||
// old_x is integer,
|
||||
// x is not integer,
|
||||
// index is relatively small (index.exponent<0 or index.exponent<=0)
|
||||
// (because we're using a special powering algorithm Big::PowUInt())
|
||||
|
||||
uint c = 0;
|
||||
|
||||
ValueType temp(x);
|
||||
c += temp.Round();
|
||||
|
||||
ValueType temp_round(temp);
|
||||
c += temp.PowUInt(index);
|
||||
|
||||
if( temp == old_x )
|
||||
x = temp_round;
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace auxiliaryfunctions
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
indexth Root of x
|
||||
index must be integer and not negative <0;1;2;3....)
|
||||
@@ -2073,41 +2031,36 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return x;
|
||||
return ValueType(); // NaN is set by default
|
||||
}
|
||||
|
||||
if( RootCheckIndexSign(x, index, err) ) return x;
|
||||
if( RootCheckIndexZero(x, index, err) ) return x;
|
||||
if( RootCheckIndexOne ( index, err) ) return x;
|
||||
if( RootCheckIndexTwo (x, index, err) ) return x;
|
||||
if( RootCheckIndexFrac(x, index, err) ) return x;
|
||||
if( RootCheckXZero (x, err) ) return x;
|
||||
|
||||
// index integer and index!=0
|
||||
// x!=0
|
||||
|
||||
ValueType old_x(x);
|
||||
uint c = 0;
|
||||
bool change_sign;
|
||||
|
||||
if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
|
||||
|
||||
ValueType temp;
|
||||
uint c = 0;
|
||||
|
||||
// we're using the formula: root(x ; n) = exp( ln(x) / n )
|
||||
c += temp.Ln(x);
|
||||
c += temp.Div(index);
|
||||
c += x.Exp(temp);
|
||||
ValueType newindex;
|
||||
newindex.SetOne();
|
||||
c += newindex.Div(index);
|
||||
c += x.PowFrac(newindex); // here can only be a carry
|
||||
|
||||
if( change_sign )
|
||||
{
|
||||
// x is different from zero
|
||||
// the value of x should be different from zero
|
||||
// (x is actually tested by RootCheckXZero)
|
||||
TTMATH_ASSERT( x.IsZero() == false )
|
||||
|
||||
x.SetSign();
|
||||
}
|
||||
|
||||
c += RootCorrectInteger(old_x, x, index);
|
||||
|
||||
if( err )
|
||||
*err = c ? err_overflow : err_ok;
|
||||
@@ -2164,9 +2117,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
a.SetNan();
|
||||
|
||||
return a;
|
||||
return ValueType(); // NaN is set by default
|
||||
}
|
||||
|
||||
uint c = a.Mod(b);
|
||||
@@ -2231,7 +2182,7 @@ namespace ttmath
|
||||
template<class ValueType>
|
||||
ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
|
||||
const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
{
|
||||
ValueType k_, temp, temp2, temp3, sum;
|
||||
|
||||
sum.SetZero();
|
||||
@@ -2281,7 +2232,7 @@ namespace ttmath
|
||||
*/
|
||||
template<class ValueType>
|
||||
bool SetBernoulliNumbersMore(CGamma<ValueType> & cgamma, uint start, const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
{
|
||||
ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_;
|
||||
|
||||
const uint n = 2;
|
||||
@@ -2315,10 +2266,10 @@ namespace ttmath
|
||||
{
|
||||
cgamma.bern.resize(m); // valid numbers are in [0, m-1]
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cgamma.bern[m].Div(denominator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2352,7 +2303,7 @@ namespace ttmath
|
||||
{
|
||||
cgamma.bern[0].SetOne();
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
if( cgamma.bern.size() == 1 )
|
||||
return true;
|
||||
@@ -2419,7 +2370,7 @@ namespace ttmath
|
||||
// there was the stop signal
|
||||
err = err_interrupt;
|
||||
return ValueType(); // NaN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp = cgamma.bern[m];
|
||||
@@ -2548,7 +2499,7 @@ namespace ttmath
|
||||
gamma(z+1) = z * gamma(z)
|
||||
then: gamma(z) = gamma(z+1) / z
|
||||
|
||||
e.g.
|
||||
e.g.
|
||||
gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 )
|
||||
*/
|
||||
template<class ValueType>
|
||||
@@ -2576,7 +2527,7 @@ namespace ttmath
|
||||
temp.Div(denominator);
|
||||
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
@@ -2584,7 +2535,7 @@ namespace ttmath
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
|
||||
{
|
||||
{
|
||||
if( n > TTMATH_GAMMA_BOUNDARY )
|
||||
return GammaPlusHigh(n, cgamma, err, stop);
|
||||
|
||||
@@ -2659,14 +2610,17 @@ namespace ttmath
|
||||
ValueType result;
|
||||
ErrorCode err_tmp;
|
||||
|
||||
|
||||
if( n.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return n;
|
||||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
TTMATH_USE_THREADSAFE_OBJ(cgamma.history);
|
||||
|
||||
if( cgamma.history.Get(n, result, err_tmp) )
|
||||
{
|
||||
if( err )
|
||||
@@ -2731,9 +2685,7 @@ namespace ttmath
|
||||
x! = gamma(x+1)
|
||||
*/
|
||||
template<class ValueType>
|
||||
ValueType Factorial2(ValueType x,
|
||||
CGamma<ValueType> * cgamma = 0,
|
||||
ErrorCode * err = 0,
|
||||
ValueType Factorial2(ValueType x, CGamma<ValueType> * cgamma = 0, ErrorCode * err = 0,
|
||||
const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
ValueType result, one;
|
||||
@@ -2743,9 +2695,7 @@ namespace ttmath
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
x.SetNan();
|
||||
|
||||
return x;
|
||||
return result; // NaN set by default
|
||||
}
|
||||
|
||||
one.SetOne();
|
||||
@@ -2769,7 +2719,7 @@ namespace ttmath
|
||||
it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial()
|
||||
e.g.
|
||||
typedef Big<1,2> MyBig;
|
||||
MyBig x=234, y=54345;
|
||||
MyBig x=234, y=345.53;
|
||||
CGamma<MyBig> cgamma;
|
||||
std::cout << Factorial(x, cgamma) << std::endl;
|
||||
std::cout << Factorial(y, cgamma) << std::endl;
|
||||
@@ -2796,7 +2746,7 @@ namespace ttmath
|
||||
template<class ValueType>
|
||||
ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
|
||||
{
|
||||
return auxiliaryfunctions::Factorial2(x, (CGamma<ValueType>*)0, err, 0);
|
||||
return auxiliaryfunctions::Factorial2(x, 0, err, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -2821,7 +2771,7 @@ namespace ttmath
|
||||
}
|
||||
|
||||
// the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1)
|
||||
// when x is larger then fewer coefficients we need
|
||||
// when x is larger then less coefficients we need
|
||||
Gamma(x, *this);
|
||||
}
|
||||
|
||||
@@ -2832,22 +2782,14 @@ namespace ttmath
|
||||
|
||||
/*!
|
||||
this is for convenience for the user
|
||||
he can only use '#include <ttmath/ttmath.h>'
|
||||
he can only use '#include <ttmath/ttmath.h>' even if he uses the parser
|
||||
*/
|
||||
#include "ttmathparser.h"
|
||||
|
||||
// Dec is not finished yet
|
||||
//#include "ttmathdec.h"
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//warning C4127: conditional expression is constant
|
||||
#pragma warning( default: 4127 )
|
||||
//warning C4702: unreachable code
|
||||
#pragma warning( default: 4702 )
|
||||
//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
|
||||
#pragma warning( default: 4800 )
|
||||
//warning C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
3187
ttmath/ttmathbig.h
3187
ttmath/ttmathbig.h
File diff suppressed because it is too large
Load Diff
110
ttmath/ttmathconfig.h
Normal file
110
ttmath/ttmathconfig.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the PNG licence.
|
||||
* Author: Christian Kaiser <chk@online.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2009 Christian Kaiser
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#ifndef headerfilettmathconfig
|
||||
#define headerfilettmathconfig
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(_MT)
|
||||
class clsCrit
|
||||
{
|
||||
private:
|
||||
mutable CRITICAL_SECTION _Crit;
|
||||
|
||||
clsCrit(const clsCrit&) // inhibit copy (easy mistake to do; use clsCritObj instead!!!)
|
||||
{
|
||||
}
|
||||
clsCrit& operator=(const clsCrit& rhs); // inhibit assignment
|
||||
public:
|
||||
clsCrit(void)
|
||||
{
|
||||
InitializeCriticalSection(&_Crit);
|
||||
}
|
||||
virtual ~clsCrit(void)
|
||||
{
|
||||
DeleteCriticalSection(&_Crit);
|
||||
}
|
||||
|
||||
void Enter(void) const
|
||||
{
|
||||
EnterCriticalSection(&_Crit);
|
||||
}
|
||||
void Leave(void) const
|
||||
{
|
||||
LeaveCriticalSection(&_Crit);
|
||||
}
|
||||
};
|
||||
|
||||
class clsCritObj
|
||||
{
|
||||
private:
|
||||
const clsCrit& _Crit;
|
||||
|
||||
clsCritObj& operator=(const clsCritObj& rhs); // not applicable
|
||||
public:
|
||||
clsCritObj(const clsCrit& Sync)
|
||||
: _Crit(Sync)
|
||||
{
|
||||
_Crit.Enter();
|
||||
}
|
||||
~clsCritObj(void)
|
||||
{
|
||||
_Crit.Leave();
|
||||
}
|
||||
};
|
||||
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ \
|
||||
private: \
|
||||
clsCrit CritSect; \
|
||||
public: \
|
||||
operator clsCrit&() \
|
||||
{ \
|
||||
return(CritSect); \
|
||||
}
|
||||
#define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c)
|
||||
#endif
|
||||
#else // defined(WIN32)
|
||||
// not Windows world: no threading synchronization for now
|
||||
#endif
|
||||
|
||||
#if !defined(TTMATH_IMPLEMENT_THREADSAFE_OBJ)
|
||||
// if we don't know about serialization, make it a no-op
|
||||
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ /* */
|
||||
#define TTMATH_USE_THREADSAFE_OBJ(c) /* */
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // headerfilettmathconfig
|
@@ -1,419 +0,0 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef headerfilettmathdec
|
||||
#define headerfilettmathdec
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
#include "ttmaththreads.h"
|
||||
#include "ttmathuint.h"
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
template<uint value_size, uint dec_digits>
|
||||
class Dec
|
||||
{
|
||||
public:
|
||||
|
||||
UInt<value_size> value;
|
||||
unsigned char info;
|
||||
|
||||
|
||||
/*!
|
||||
Sign
|
||||
the mask of a bit from 'info' which means that there is a sign
|
||||
(when the bit is set)
|
||||
*/
|
||||
#define TTMATH_DEC_SIGN 128
|
||||
|
||||
|
||||
/*!
|
||||
Not a number
|
||||
if this bit is set that there is not a valid number
|
||||
*/
|
||||
#define TTMATH_DEC_NAN 64
|
||||
|
||||
|
||||
|
||||
|
||||
Dec()
|
||||
{
|
||||
info = TTMATH_DEC_NAN;
|
||||
}
|
||||
|
||||
|
||||
Dec(const char * s)
|
||||
{
|
||||
info = TTMATH_DEC_NAN;
|
||||
FromString(s);
|
||||
}
|
||||
|
||||
|
||||
Dec<value_size, dec_digits> & operator=(const char * s)
|
||||
{
|
||||
FromString(s);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
return FromStringBase(s, after_source, value_read);
|
||||
}
|
||||
|
||||
|
||||
void ToString(std::string & result) const
|
||||
{
|
||||
ToStringBase(result);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method clears a specific bit in the 'info' variable
|
||||
|
||||
bit is one of:
|
||||
*/
|
||||
void ClearInfoBit(unsigned char bit)
|
||||
{
|
||||
info = info & (~bit);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets a specific bit in the 'info' variable
|
||||
|
||||
bit is one of:
|
||||
|
||||
*/
|
||||
void SetInfoBit(unsigned char bit)
|
||||
{
|
||||
info = info | bit;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if a specific bit in the 'info' variable is set
|
||||
|
||||
bit is one of:
|
||||
*/
|
||||
bool IsInfoBit(unsigned char bit) const
|
||||
{
|
||||
return (info & bit) != 0;
|
||||
}
|
||||
|
||||
|
||||
bool IsNan() const
|
||||
{
|
||||
return IsInfoBit(TTMATH_DEC_NAN);
|
||||
}
|
||||
|
||||
|
||||
bool IsSign() const
|
||||
{
|
||||
return IsInfoBit(TTMATH_DEC_SIGN);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the sign
|
||||
|
||||
e.g.
|
||||
-1 -> -1
|
||||
2 -> -2
|
||||
|
||||
we do not check whether there is a zero or not, if you're using this method
|
||||
you must be sure that the value is (or will be afterwards) different from zero
|
||||
*/
|
||||
void SetSign()
|
||||
{
|
||||
SetInfoBit(TTMATH_DEC_SIGN);
|
||||
}
|
||||
|
||||
|
||||
void SetNaN()
|
||||
{
|
||||
SetInfoBit(TTMATH_DEC_NAN);
|
||||
}
|
||||
|
||||
|
||||
void Abs()
|
||||
{
|
||||
ClearInfoBit(TTMATH_DEC_SIGN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint Add(const Dec<value_size, dec_digits> & arg)
|
||||
{
|
||||
uint c = 0;
|
||||
|
||||
if( IsSign() == arg.IsSign() )
|
||||
{
|
||||
c += value.Add(arg.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool is_sign;
|
||||
|
||||
if( value > arg.value )
|
||||
{
|
||||
is_sign = IsSign();
|
||||
value.Sub(arg.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_sign = arg.IsSign();
|
||||
UInt<value_size> temp(this->value);
|
||||
value = arg.value;
|
||||
value.Sub(temp);
|
||||
}
|
||||
|
||||
is_sign ? SetSign() : Abs();
|
||||
}
|
||||
|
||||
if( c )
|
||||
SetNaN();
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
uint Sub(const Dec<value_size, dec_digits> & arg)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef TTMATH_MULTITHREADS
|
||||
|
||||
/*!
|
||||
*/
|
||||
void SetMultipler(UInt<value_size> & result)
|
||||
{
|
||||
// this guardian is initialized before the program runs (static POD type)
|
||||
static int guardian = 0;
|
||||
static UInt<value_size> multipler;
|
||||
|
||||
if( guardian == 0 )
|
||||
{
|
||||
multipler = 10;
|
||||
multipler.Pow(dec_digits);
|
||||
guardian = 1;
|
||||
}
|
||||
|
||||
result = multipler;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
*/
|
||||
void SetMultipler(UInt<value_size> & result)
|
||||
{
|
||||
// this guardian is initialized before the program runs (static POD type)
|
||||
volatile static sig_atomic_t guardian = 0;
|
||||
static UInt<value_size> * pmultipler;
|
||||
|
||||
// double-checked locking
|
||||
if( guardian == 0 )
|
||||
{
|
||||
ThreadLock thread_lock;
|
||||
|
||||
// locking
|
||||
if( thread_lock.Lock() )
|
||||
{
|
||||
static UInt<value_size> multipler;
|
||||
|
||||
if( guardian == 0 )
|
||||
{
|
||||
pmultipler = &multipler;
|
||||
multipler = 10;
|
||||
multipler.Pow(dec_digits);
|
||||
guardian = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there was a problem with locking, we store the result directly in 'result' object
|
||||
result = 10;
|
||||
result.Pow(dec_digits);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// automatically unlocking
|
||||
}
|
||||
|
||||
result = *pmultipler;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting from a string
|
||||
*/
|
||||
template<class char_type>
|
||||
uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
UInt<value_size> multipler;
|
||||
const char_type * after;
|
||||
uint c = 0;
|
||||
info = 0;
|
||||
|
||||
Misc::SkipWhiteCharacters(s);
|
||||
|
||||
if( *s == '-' )
|
||||
{
|
||||
s += 1;
|
||||
SetSign();
|
||||
}
|
||||
else
|
||||
if( *s == '+' )
|
||||
{
|
||||
s += 1;
|
||||
}
|
||||
|
||||
c += value.FromString(s, 10, &after, value_read);
|
||||
|
||||
if( after_source )
|
||||
*after_source = after;
|
||||
|
||||
SetMultipler(multipler);
|
||||
c += value.Mul(multipler);
|
||||
|
||||
if( *after == '.' )
|
||||
c += FromStringBaseAfterComma(after+1, after_source);
|
||||
|
||||
if( c )
|
||||
SetInfoBit(TTMATH_DEC_NAN);
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
template<class char_type>
|
||||
uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
|
||||
{
|
||||
UInt<value_size> temp;
|
||||
UInt<value_size> multipler;
|
||||
sint z;
|
||||
uint c = 0;
|
||||
size_t i = dec_digits;
|
||||
|
||||
SetMultipler(multipler);
|
||||
|
||||
for( ; i>0 && (z=Misc::CharToDigit(*s, 10)) != -1 ; --i, ++s )
|
||||
{
|
||||
multipler.DivInt(10);
|
||||
temp.SetZero();
|
||||
|
||||
if( value_read )
|
||||
*value_read = true;
|
||||
|
||||
if( c == 0 )
|
||||
{
|
||||
temp.table[0] = z;
|
||||
c += temp.Mul(multipler);
|
||||
c += value.Add(temp);
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 0 && (z=Misc::CharToDigit(*s, 10)) != -1 && z >= 5 )
|
||||
c += value.AddOne();
|
||||
|
||||
if( after_source )
|
||||
{
|
||||
while( (z=Misc::CharToDigit(*s, 10)) != -1 )
|
||||
s += 1;
|
||||
|
||||
*after_source = s;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class string_type>
|
||||
void ToStringBase(string_type & result) const
|
||||
{
|
||||
if( IsNan() )
|
||||
{
|
||||
result = "NaN";
|
||||
return;
|
||||
}
|
||||
|
||||
value.ToStringBase(result, 10, IsSign());
|
||||
|
||||
if( dec_digits > 0 )
|
||||
{
|
||||
size_t size = result.size();
|
||||
|
||||
if( IsSign() && size > 0 )
|
||||
size -= 1;
|
||||
|
||||
if( dec_digits >= size )
|
||||
{
|
||||
size_t zeroes = dec_digits - size + 1;
|
||||
size_t start = IsSign() ? 1 : 0;
|
||||
result.insert(start, zeroes, '0');
|
||||
}
|
||||
|
||||
result.insert(result.end() - dec_digits, '.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef headerfilettmathmisc
|
||||
#define headerfilettmathmisc
|
||||
|
||||
|
||||
/*!
|
||||
\file ttmathmisc.h
|
||||
\brief some helpful functions
|
||||
*/
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
some helpful functions
|
||||
*/
|
||||
class Misc
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* AssignString(result, str)
|
||||
* result = str
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const char * str)
|
||||
{
|
||||
result = str;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::wstring & result, const char * str)
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for( ; *str ; ++str )
|
||||
result += *str;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::wstring & result, const std::string & str)
|
||||
{
|
||||
return AssignString(result, str.c_str());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const wchar_t * str)
|
||||
{
|
||||
result.clear();
|
||||
|
||||
for( ; *str ; ++str )
|
||||
result += static_cast<char>(*str);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
result = str
|
||||
*/
|
||||
static void AssignString(std::string & result, const std::wstring & str)
|
||||
{
|
||||
return AssignString(result, str.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* AddString(result, str)
|
||||
* result += str
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
result += str
|
||||
*/
|
||||
static void AddString(std::string & result, const char * str)
|
||||
{
|
||||
result += str;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
result += str
|
||||
*/
|
||||
static void AddString(std::wstring & result, const char * str)
|
||||
{
|
||||
for( ; *str ; ++str )
|
||||
result += *str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this method omits any white characters from the string
|
||||
char_type is char or wchar_t
|
||||
*/
|
||||
template<class char_type>
|
||||
static void SkipWhiteCharacters(const char_type * & c)
|
||||
{
|
||||
// 13 is at the end in a DOS text file (\r\n)
|
||||
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
|
||||
++c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method converts one character into its value
|
||||
|
||||
for example:
|
||||
1 -> 1
|
||||
8 -> 8
|
||||
A -> 10
|
||||
f -> 15
|
||||
|
||||
this method don't check whether c is correct or not
|
||||
*/
|
||||
static uint CharToDigit(uint c)
|
||||
{
|
||||
if(c>='0' && c<='9')
|
||||
return c-'0';
|
||||
|
||||
if(c>='a' && c<='z')
|
||||
return c-'a'+10;
|
||||
|
||||
return c-'A'+10;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method changes a character 'c' into its value
|
||||
(if there can't be a correct value it returns -1)
|
||||
|
||||
for example:
|
||||
c=2, base=10 -> function returns 2
|
||||
c=A, base=10 -> function returns -1
|
||||
c=A, base=16 -> function returns 10
|
||||
*/
|
||||
static sint CharToDigit(uint c, uint base)
|
||||
{
|
||||
if( c>='0' && c<='9' )
|
||||
c=c-'0';
|
||||
else
|
||||
if( c>='a' && c<='z' )
|
||||
c=c-'a'+10;
|
||||
else
|
||||
if( c>='A' && c<='Z' )
|
||||
c=c-'A'+10;
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
||||
if( c >= base )
|
||||
return -1;
|
||||
|
||||
|
||||
return sint(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method converts a digit into a char
|
||||
digit should be from <0,F>
|
||||
(we don't have to get a base)
|
||||
|
||||
for example:
|
||||
1 -> 1
|
||||
8 -> 8
|
||||
10 -> A
|
||||
15 -> F
|
||||
*/
|
||||
static uint DigitToChar(uint digit)
|
||||
{
|
||||
if( digit < 10 )
|
||||
return digit + '0';
|
||||
|
||||
return digit - 10 + 'A';
|
||||
}
|
||||
|
||||
|
||||
}; // struct Misc
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,13 +44,13 @@
|
||||
\brief Mathematic functions.
|
||||
*/
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
#include "ttmathmisc.h"
|
||||
|
||||
|
||||
namespace ttmath
|
||||
@@ -74,19 +74,19 @@ public:
|
||||
struct Item
|
||||
{
|
||||
// name of a variable of a function
|
||||
// internally we store variables and funcions as std::string (not std::wstring even when wide characters are used)
|
||||
std::string value;
|
||||
// (either std::string or std::wstring)
|
||||
tt_string value;
|
||||
|
||||
// number of parameters required by the function
|
||||
// (if there's a variable this 'param' is ignored)
|
||||
int param;
|
||||
|
||||
Item() {}
|
||||
Item(const std::string & v, int p) : value(v), param(p) {}
|
||||
Item(const tt_string & v, int p) : value(v), param(p) {}
|
||||
};
|
||||
|
||||
// 'Table' is the type of our table
|
||||
typedef std::map<std::string, Item> Table;
|
||||
typedef std::map<tt_string, Item> Table;
|
||||
typedef Table::iterator Iterator;
|
||||
typedef Table::const_iterator CIterator;
|
||||
|
||||
@@ -114,8 +114,7 @@ public:
|
||||
/*!
|
||||
this method returns true if the name can be as a name of an object
|
||||
*/
|
||||
template<class string_type>
|
||||
static bool IsNameCorrect(const string_type & name)
|
||||
static bool IsNameCorrect(const tt_string & name)
|
||||
{
|
||||
if( name.empty() )
|
||||
return false;
|
||||
@@ -123,7 +122,7 @@ public:
|
||||
if( !CorrectCharacter(name[0], false) )
|
||||
return false;
|
||||
|
||||
typename string_type::const_iterator i = name.begin();
|
||||
tt_string::const_iterator i=name.begin();
|
||||
|
||||
for(++i ; i!=name.end() ; ++i)
|
||||
if( !CorrectCharacter(*i, true) )
|
||||
@@ -136,7 +135,7 @@ public:
|
||||
/*!
|
||||
this method returns true if such an object is defined (name exists)
|
||||
*/
|
||||
bool IsDefined(const std::string & name)
|
||||
bool IsDefined(const tt_string & name)
|
||||
{
|
||||
Iterator i = table.find(name);
|
||||
|
||||
@@ -148,31 +147,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method returns true if such an object is defined (name exists)
|
||||
*/
|
||||
bool IsDefined(const std::wstring & name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return false;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return IsDefined(str_tmp1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
|
||||
ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -189,27 +167,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method adds one object (variable of function) into the table
|
||||
*/
|
||||
ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
Misc::AssignString(str_tmp2, value);
|
||||
|
||||
return Add(str_tmp1, str_tmp2, param);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method returns 'true' if the table is empty
|
||||
*/
|
||||
@@ -250,7 +207,7 @@ public:
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
|
||||
ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -267,32 +224,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the value and the number of parameters for a specific object
|
||||
*/
|
||||
ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
Misc::AssignString(str_tmp2, value);
|
||||
|
||||
return EditValue(str_tmp1, str_tmp2, param);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
|
||||
ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
|
||||
{
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
@@ -320,33 +255,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method changes the name of a specific object
|
||||
*/
|
||||
ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, old_name);
|
||||
Misc::AssignString(str_tmp2, new_name);
|
||||
|
||||
return EditName(str_tmp1, str_tmp2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const std::string & name)
|
||||
ErrorCode Delete(const tt_string & name)
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -362,31 +274,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method deletes an object
|
||||
*/
|
||||
ErrorCode Delete(const std::wstring & name)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return Delete(str_tmp1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||
ErrorCode GetValue(const tt_string & name, tt_string & value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -405,33 +296,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
*/
|
||||
ErrorCode GetValue(const std::wstring & name, std::wstring & value)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
ErrorCode err = GetValue(str_tmp1, str_tmp2);
|
||||
Misc::AssignString(value, str_tmp2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
||||
ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -450,32 +319,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValue(const std::wstring & name, const char ** value)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return GetValue(str_tmp1, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method gets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
||||
ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -496,35 +344,12 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
this method gets the value and the number of parameters
|
||||
of a specific object
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param);
|
||||
Misc::AssignString(value, str_tmp2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string)
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
|
||||
ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
|
||||
{
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
@@ -545,31 +370,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
|
||||
/*!
|
||||
this method sets the value and the number of parameters
|
||||
of a specific object
|
||||
(this version is used for not copying the whole string
|
||||
but in fact we make one copying during AssignString())
|
||||
*/
|
||||
ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param)
|
||||
{
|
||||
// we should check whether the name (in wide characters) are correct
|
||||
// before calling AssignString() function
|
||||
if( !IsNameCorrect(name) )
|
||||
return err_incorrect_name;
|
||||
|
||||
Misc::AssignString(str_tmp1, name);
|
||||
|
||||
return GetValueAndParam(str_tmp1, value, param);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method returns a pointer into the table
|
||||
*/
|
||||
@@ -582,7 +382,6 @@ public:
|
||||
private:
|
||||
|
||||
Table table;
|
||||
std::string str_tmp1, str_tmp2;
|
||||
|
||||
}; // end of class Objects
|
||||
|
||||
@@ -629,7 +428,7 @@ public:
|
||||
|
||||
/*!
|
||||
default constructor
|
||||
default max size of the History's container is 15 items
|
||||
default max size of the History's container is 10 items
|
||||
*/
|
||||
History()
|
||||
{
|
||||
@@ -792,8 +591,8 @@ struct CGamma
|
||||
you don't have to call this method, these coefficients will be automatically calculated
|
||||
when they are needed
|
||||
|
||||
you must note that calculating these coefficients is a little time-consuming operation,
|
||||
(especially when the mantissa is large) and first call to Gamma() or Factorial()
|
||||
you must note that calculating of the coefficients is a little time-consuming operation,
|
||||
(especially when the mantissa is large) and first called to Gamma() or Factorial()
|
||||
can take more time than next calls, and in the end this is the point when InitAll()
|
||||
comes in handy: you can call this method somewhere at the beginning of your program
|
||||
*/
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -52,7 +52,6 @@
|
||||
|
||||
#include "ttmath.h"
|
||||
#include "ttmathobjects.h"
|
||||
#include "ttmathmisc.h"
|
||||
|
||||
|
||||
|
||||
@@ -110,7 +109,8 @@ namespace ttmath
|
||||
for example a correct input string can be:
|
||||
"1"
|
||||
"2.1234"
|
||||
"2,1234" (they are the same, by default we can either use a comma or a dot)
|
||||
"2,1234" (they are the same, we can either use a comma or a dot in values)
|
||||
(look at the macro TTMATH_COMMA_CHARACTER_2)
|
||||
"1 + 2"
|
||||
"(1 + 2) * 3"
|
||||
"pi"
|
||||
@@ -131,8 +131,8 @@ namespace ttmath
|
||||
for example:
|
||||
"1+2;4+5"
|
||||
the result will be on the stack as follows:
|
||||
stack[0].value=3
|
||||
stack[1].value=9
|
||||
"3"
|
||||
"9"
|
||||
*/
|
||||
template<class ValueType>
|
||||
class Parser
|
||||
@@ -159,20 +159,14 @@ private:
|
||||
none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul
|
||||
};
|
||||
|
||||
enum Assoc
|
||||
{
|
||||
right, // right-associative
|
||||
non_right // associative or left-associative
|
||||
};
|
||||
|
||||
Type GetType() const { return type; }
|
||||
int GetPriority() const { return priority; }
|
||||
Assoc GetAssoc() const { return assoc; }
|
||||
Type GetType() const { return type; }
|
||||
int GetPriority() const { return priority; }
|
||||
|
||||
|
||||
void SetType(Type t)
|
||||
{
|
||||
type = t;
|
||||
assoc = non_right;
|
||||
type = t;
|
||||
|
||||
switch( type )
|
||||
{
|
||||
@@ -206,7 +200,6 @@ private:
|
||||
|
||||
case pow:
|
||||
priority = 14;
|
||||
assoc = right;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -215,15 +208,15 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
MatOperator(): type(none), priority(0), assoc(non_right)
|
||||
MatOperator(): type(none), priority(0)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Type type;
|
||||
int priority;
|
||||
Assoc assoc;
|
||||
Type type;
|
||||
int priority;
|
||||
|
||||
}; // end of MatOperator class
|
||||
|
||||
|
||||
@@ -262,7 +255,7 @@ public:
|
||||
bool function;
|
||||
|
||||
// if function is true
|
||||
std::string function_name;
|
||||
tt_string function_name;
|
||||
|
||||
/*
|
||||
the sign of value
|
||||
@@ -282,16 +275,9 @@ public:
|
||||
/*!
|
||||
stack on which we're keeping the Items
|
||||
|
||||
at the end of parsing we'll have the result here
|
||||
the result don't have to be one value, it can be
|
||||
more than one if we have used a semicolon in the global space
|
||||
e.g. such input string "1+2;3+4" will generate a result:
|
||||
stack[0].value=3
|
||||
stack[1].value=7
|
||||
|
||||
you should check if the stack is not empty, because if there was
|
||||
a syntax error in the input string then we do not have any results
|
||||
on the stack
|
||||
at the end of parsing we'll have the result on its
|
||||
the result don't have to be one value, it can be a list
|
||||
of values separated by the 'semicolon item'
|
||||
*/
|
||||
std::vector<Item> stack;
|
||||
|
||||
@@ -324,9 +310,11 @@ ErrorCode error;
|
||||
|
||||
/*!
|
||||
pointer to the currently reading char
|
||||
it's either char* or wchar_t*
|
||||
|
||||
when an error has occured it may be used to count the index of the wrong character
|
||||
*/
|
||||
const char * pstring;
|
||||
const tt_char * pstring;
|
||||
|
||||
|
||||
/*!
|
||||
@@ -363,7 +351,7 @@ const Objects * puser_variables;
|
||||
const Objects * puser_functions;
|
||||
|
||||
|
||||
typedef std::map<std::string, ValueType> FunctionLocalVariables;
|
||||
typedef std::map<tt_string, ValueType> FunctionLocalVariables;
|
||||
|
||||
/*!
|
||||
a pointer to the local variables of a function
|
||||
@@ -374,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
|
||||
/*!
|
||||
a temporary set using during parsing user defined variables
|
||||
*/
|
||||
std::set<std::string> visited_variables;
|
||||
std::set<tt_string> visited_variables;
|
||||
|
||||
|
||||
/*!
|
||||
a temporary set using during parsing user defined functions
|
||||
*/
|
||||
std::set<std::string> visited_functions;
|
||||
std::set<tt_string> visited_functions;
|
||||
|
||||
|
||||
|
||||
@@ -408,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
|
||||
table of mathematic functions
|
||||
|
||||
this map consists of:
|
||||
std::string - function's name
|
||||
tt_string - function's name
|
||||
pfunction - pointer to specific function
|
||||
*/
|
||||
typedef std::map<std::string, pfunction> FunctionsTable;
|
||||
typedef std::map<tt_string, pfunction> FunctionsTable;
|
||||
FunctionsTable functions_table;
|
||||
|
||||
|
||||
@@ -419,10 +407,10 @@ FunctionsTable functions_table;
|
||||
table of mathematic operators
|
||||
|
||||
this map consists of:
|
||||
std::string - operators's name
|
||||
tt_string - operators's name
|
||||
MatOperator::Type - type of the operator
|
||||
*/
|
||||
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
|
||||
typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
|
||||
OperatorsTable operators_table;
|
||||
|
||||
|
||||
@@ -430,10 +418,10 @@ OperatorsTable operators_table;
|
||||
table of mathematic variables
|
||||
|
||||
this map consists of:
|
||||
std::string - variable's name
|
||||
tt_string - variable's name
|
||||
pfunction_var - pointer to specific function which returns value of variable
|
||||
*/
|
||||
typedef std::map<std::string, pfunction_var> VariablesTable;
|
||||
typedef std::map<tt_string, pfunction_var> VariablesTable;
|
||||
VariablesTable variables_table;
|
||||
|
||||
|
||||
@@ -443,41 +431,6 @@ VariablesTable variables_table;
|
||||
CGamma<ValueType> cgamma;
|
||||
|
||||
|
||||
/*!
|
||||
temporary object for a whole string when Parse(std::wstring) is used
|
||||
*/
|
||||
std::string wide_to_ansi;
|
||||
|
||||
|
||||
/*!
|
||||
group character (used when parsing)
|
||||
default zero (not used)
|
||||
*/
|
||||
int group;
|
||||
|
||||
|
||||
/*!
|
||||
characters used as a comma
|
||||
default: '.' and ','
|
||||
comma2 can be zero (it means it is not used)
|
||||
*/
|
||||
int comma, comma2;
|
||||
|
||||
|
||||
/*!
|
||||
an additional character used as a separator between function parameters
|
||||
(semicolon is used always)
|
||||
*/
|
||||
int param_sep;
|
||||
|
||||
|
||||
/*!
|
||||
true if something was calculated (at least one mathematical operator was used or a function or a variable)
|
||||
*/
|
||||
bool calculated;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
we're using this method for reporting an error
|
||||
*/
|
||||
@@ -502,7 +455,7 @@ void SkipWhiteCharacters()
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
|
||||
{
|
||||
if( variable )
|
||||
{
|
||||
@@ -520,7 +473,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
|
||||
{
|
||||
if( variable )
|
||||
visited_variables.insert( name );
|
||||
@@ -532,7 +485,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
|
||||
/*!
|
||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||
*/
|
||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
|
||||
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
|
||||
{
|
||||
if( variable )
|
||||
visited_variables.erase( name );
|
||||
@@ -551,7 +504,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
|
||||
(there can be a recurrence here therefore we're using 'visited_variables'
|
||||
and 'visited_functions' sets to make a stop condition)
|
||||
*/
|
||||
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string,
|
||||
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tt_string & name, const tt_char * new_string,
|
||||
FunctionLocalVariables * local_variables = 0)
|
||||
{
|
||||
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
|
||||
@@ -595,18 +548,17 @@ public:
|
||||
/*!
|
||||
this method returns the user-defined value of a variable
|
||||
*/
|
||||
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
|
||||
bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
|
||||
{
|
||||
if( !puser_variables )
|
||||
return false;
|
||||
|
||||
const char * string_value;
|
||||
const tt_char * string_value;
|
||||
|
||||
if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
|
||||
return false;
|
||||
|
||||
result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
|
||||
calculated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -615,7 +567,7 @@ return true;
|
||||
/*!
|
||||
this method returns the value of a local variable of a function
|
||||
*/
|
||||
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
|
||||
bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
|
||||
{
|
||||
if( !pfunction_local_variables )
|
||||
return false;
|
||||
@@ -637,7 +589,7 @@ return true;
|
||||
we make an object of type ValueType then call a method which
|
||||
sets the correct value in it and finally we'll return the object
|
||||
*/
|
||||
ValueType GetValueOfVariable(const std::string & variable_name)
|
||||
ValueType GetValueOfVariable(const tt_string & variable_name)
|
||||
{
|
||||
ValueType result;
|
||||
|
||||
@@ -648,14 +600,13 @@ ValueType result;
|
||||
return result;
|
||||
|
||||
|
||||
typename std::map<std::string, pfunction_var>::iterator i =
|
||||
typename std::map<tt_string, pfunction_var>::iterator i =
|
||||
variables_table.find(variable_name);
|
||||
|
||||
if( i == variables_table.end() )
|
||||
Error( err_unknown_variable );
|
||||
|
||||
(result.*(i->second))();
|
||||
calculated = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1404,56 +1355,34 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
|
||||
}
|
||||
|
||||
|
||||
void Frac(int sindex, int amount_of_args, ValueType & result)
|
||||
{
|
||||
if( amount_of_args != 1 )
|
||||
Error( err_improper_amount_of_arguments );
|
||||
|
||||
result = stack[sindex].value;
|
||||
result.RemainFraction();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
we use such a method because 'wvsprintf' is not everywhere defined
|
||||
*/
|
||||
void Sprintf(char * buffer, int par)
|
||||
void Sprintf(tt_char * buffer, int par)
|
||||
{
|
||||
char buf[30]; // char, not wchar_t
|
||||
char buf[30]; // char, not tt_char
|
||||
int i;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable: 4996 )
|
||||
//warning C4996: 'sprintf': This function or variable may be unsafe.
|
||||
#endif
|
||||
|
||||
sprintf(buf, "%d", par);
|
||||
for(i=0 ; buf[i] != 0 ; ++i)
|
||||
buffer[i] = buf[i];
|
||||
|
||||
buffer[i] = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( default: 4996 )
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method returns the value from a user-defined function
|
||||
|
||||
(look at the description in 'CallFunction(...)')
|
||||
*/
|
||||
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
|
||||
bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||
{
|
||||
if( !puser_functions )
|
||||
return false;
|
||||
|
||||
const char * string_value;
|
||||
const tt_char * string_value;
|
||||
int param;
|
||||
|
||||
if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok )
|
||||
@@ -1467,7 +1396,7 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
|
||||
|
||||
if( amount_of_args > 0 )
|
||||
{
|
||||
char buffer[30];
|
||||
tt_char buffer[30];
|
||||
|
||||
// x = x1
|
||||
buffer[0] = 'x';
|
||||
@@ -1483,7 +1412,6 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
|
||||
}
|
||||
|
||||
stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
|
||||
calculated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1502,7 +1430,7 @@ return true;
|
||||
result will be stored in 'stack[sindex-1].value'
|
||||
(we don't have to set the correct type of this element, it'll be set later)
|
||||
*/
|
||||
void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
|
||||
void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
|
||||
{
|
||||
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
|
||||
return;
|
||||
@@ -1516,7 +1444,6 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
|
||||
calling the specify function
|
||||
*/
|
||||
(this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value);
|
||||
calculated = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1529,16 +1456,12 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
|
||||
function_name - name of the function
|
||||
pf - pointer to the function (to the wrapper)
|
||||
*/
|
||||
void InsertFunctionToTable(const char * function_name, pfunction pf)
|
||||
void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
|
||||
{
|
||||
std::string str;
|
||||
Misc::AssignString(str, function_name);
|
||||
|
||||
functions_table.insert( std::make_pair(str, pf) );
|
||||
functions_table.insert( std::make_pair(tt_string(function_name), pf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
inserting a function to the variables' table
|
||||
(this function returns value of variable)
|
||||
@@ -1546,12 +1469,9 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
|
||||
variable_name - name of the function
|
||||
pf - pointer to the function
|
||||
*/
|
||||
void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
||||
void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
|
||||
{
|
||||
std::string str;
|
||||
Misc::AssignString(str, variable_name);
|
||||
|
||||
variables_table.insert( std::make_pair(str, pf) );
|
||||
variables_table.insert( std::make_pair(tt_string(variable_name), pf));
|
||||
}
|
||||
|
||||
|
||||
@@ -1560,66 +1480,65 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
||||
*/
|
||||
void CreateFunctionsTable()
|
||||
{
|
||||
InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma);
|
||||
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
|
||||
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
|
||||
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
|
||||
InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
|
||||
InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable("int", &Parser<ValueType>::Int);
|
||||
InsertFunctionToTable("round", &Parser<ValueType>::Round);
|
||||
InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
|
||||
InsertFunctionToTable("log", &Parser<ValueType>::Log);
|
||||
InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
|
||||
InsertFunctionToTable("max", &Parser<ValueType>::Max);
|
||||
InsertFunctionToTable("min", &Parser<ValueType>::Min);
|
||||
InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
|
||||
InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
|
||||
InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
|
||||
InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
|
||||
InsertFunctionToTable("if", &Parser<ValueType>::If);
|
||||
InsertFunctionToTable("or", &Parser<ValueType>::Or);
|
||||
InsertFunctionToTable("and", &Parser<ValueType>::And);
|
||||
InsertFunctionToTable("not", &Parser<ValueType>::Not);
|
||||
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
|
||||
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
|
||||
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
|
||||
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
|
||||
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
|
||||
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
|
||||
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
|
||||
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
|
||||
InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
|
||||
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
|
||||
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
|
||||
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
|
||||
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable("root", &Parser<ValueType>::Root);
|
||||
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
|
||||
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
|
||||
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
|
||||
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
|
||||
InsertFunctionToTable("frac", &Parser<ValueType>::Frac);
|
||||
InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
|
||||
InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
|
||||
InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
|
||||
InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
|
||||
InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
|
||||
InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
|
||||
InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
|
||||
InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
|
||||
InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
|
||||
InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
|
||||
InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
|
||||
InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
|
||||
InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
|
||||
InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
|
||||
InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
|
||||
InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
|
||||
InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
|
||||
InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
|
||||
InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
|
||||
InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
|
||||
InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
|
||||
}
|
||||
|
||||
|
||||
@@ -1628,8 +1547,8 @@ void CreateFunctionsTable()
|
||||
*/
|
||||
void CreateVariablesTable()
|
||||
{
|
||||
InsertVariableToTable("pi", &ValueType::SetPi);
|
||||
InsertVariableToTable("e", &ValueType::SetE);
|
||||
InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
|
||||
InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1655,7 +1574,7 @@ return c;
|
||||
what should be returned is tested just by a '(' character that means if there's
|
||||
a '(' character after a name that function returns 'true'
|
||||
*/
|
||||
bool ReadName(std::string & result)
|
||||
bool ReadName(tt_string & result)
|
||||
{
|
||||
int character;
|
||||
|
||||
@@ -1672,7 +1591,7 @@ int character;
|
||||
|
||||
do
|
||||
{
|
||||
result += static_cast<char>( character );
|
||||
result += static_cast<tt_char>( character );
|
||||
character = * ++pstring;
|
||||
}
|
||||
while( (character>='a' && character<='z') ||
|
||||
@@ -1727,7 +1646,7 @@ return false;
|
||||
*/
|
||||
bool ReadVariableOrFunction(Item & result)
|
||||
{
|
||||
std::string name;
|
||||
tt_string name;
|
||||
bool is_it_name_of_function = ReadName(name);
|
||||
|
||||
if( is_it_name_of_function )
|
||||
@@ -1751,24 +1670,16 @@ return is_it_name_of_function;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
we're reading a numerical value directly from the string
|
||||
*/
|
||||
void ReadValue(Item & result, int reading_base)
|
||||
{
|
||||
const char * new_stack_pointer;
|
||||
const tt_char * new_stack_pointer;
|
||||
bool value_read;
|
||||
Conv conv;
|
||||
|
||||
conv.base = reading_base;
|
||||
conv.comma = comma;
|
||||
conv.comma2 = comma2;
|
||||
conv.group = group;
|
||||
|
||||
uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
|
||||
pstring = new_stack_pointer;
|
||||
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
||||
pstring = new_stack_pointer;
|
||||
|
||||
if( carry )
|
||||
Error( err_overflow );
|
||||
@@ -1778,18 +1689,43 @@ Conv conv;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method converts the character ascii c into the value in range <0;base-1>
|
||||
|
||||
if the character is incorrect for this base the funcion will return -1
|
||||
*/
|
||||
int CharToDigit(int c, int base)
|
||||
{
|
||||
if( c>='0' && c<='9' )
|
||||
c=c-'0';
|
||||
else
|
||||
if( c>='a' && c<='z' )
|
||||
c=c-'a'+10;
|
||||
else
|
||||
if( c>='A' && c<='Z' )
|
||||
c=c-'A'+10;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if( c >= base )
|
||||
return -1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too)
|
||||
*/
|
||||
bool ValueStarts(int character, int base)
|
||||
{
|
||||
if( character == comma )
|
||||
if( character == TTMATH_COMMA_CHARACTER_1 )
|
||||
return true;
|
||||
|
||||
if( comma2!=0 && character==comma2 )
|
||||
if( TTMATH_COMMA_CHARACTER_2 != 0 && character == TTMATH_COMMA_CHARACTER_2 )
|
||||
return true;
|
||||
|
||||
if( Misc::CharToDigit(character, base) != -1 )
|
||||
if( CharToDigit(character, base) != -1 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1912,9 +1848,9 @@ return 0;
|
||||
}
|
||||
|
||||
|
||||
void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
|
||||
void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
|
||||
{
|
||||
operators_table.insert( std::make_pair(std::string(name), type) );
|
||||
operators_table.insert( std::make_pair(tt_string(name), type) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1923,19 +1859,19 @@ void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
|
||||
*/
|
||||
void CreateMathematicalOperatorsTable()
|
||||
{
|
||||
InsertOperatorToTable("||", MatOperator::lor);
|
||||
InsertOperatorToTable("&&", MatOperator::land);
|
||||
InsertOperatorToTable("!=", MatOperator::neq);
|
||||
InsertOperatorToTable("==", MatOperator::eq);
|
||||
InsertOperatorToTable(">=", MatOperator::get);
|
||||
InsertOperatorToTable("<=", MatOperator::let);
|
||||
InsertOperatorToTable(">", MatOperator::gt);
|
||||
InsertOperatorToTable("<", MatOperator::lt);
|
||||
InsertOperatorToTable("-", MatOperator::sub);
|
||||
InsertOperatorToTable("+", MatOperator::add);
|
||||
InsertOperatorToTable("/", MatOperator::div);
|
||||
InsertOperatorToTable("*", MatOperator::mul);
|
||||
InsertOperatorToTable("^", MatOperator::pow);
|
||||
InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
|
||||
InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
|
||||
InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
|
||||
InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
|
||||
InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
|
||||
InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
|
||||
InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
|
||||
InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
|
||||
InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
|
||||
InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
|
||||
InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
|
||||
InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
|
||||
InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
|
||||
}
|
||||
|
||||
|
||||
@@ -1945,12 +1881,12 @@ void CreateMathematicalOperatorsTable()
|
||||
e.g.
|
||||
true when str1="test" and str2="te"
|
||||
*/
|
||||
bool IsSubstring(const std::string & str1, const std::string & str2)
|
||||
bool IsSubstring(const tt_string & str1, const tt_string & str2)
|
||||
{
|
||||
if( str2.length() > str1.length() )
|
||||
return false;
|
||||
|
||||
for(typename std::string::size_type i=0 ; i<str2.length() ; ++i)
|
||||
for(tt_string::size_type i=0 ; i<str2.length() ; ++i)
|
||||
if( str1[i] != str2[i] )
|
||||
return false;
|
||||
|
||||
@@ -1963,7 +1899,7 @@ return true;
|
||||
*/
|
||||
void ReadMathematicalOperator(Item & result)
|
||||
{
|
||||
std::string oper;
|
||||
tt_string oper;
|
||||
typename OperatorsTable::iterator iter_old, iter_new;
|
||||
|
||||
iter_old = operators_table.end();
|
||||
@@ -1992,31 +1928,6 @@ typename OperatorsTable::iterator iter_old, iter_new;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method makes a calculation for the percentage operator
|
||||
e.g.
|
||||
1000-50% = 1000-(1000*0,5) = 500
|
||||
*/
|
||||
void OperatorPercentage()
|
||||
{
|
||||
if( stack_index < 3 ||
|
||||
stack[stack_index-1].type != Item::numerical_value ||
|
||||
stack[stack_index-2].type != Item::mat_operator ||
|
||||
stack[stack_index-3].type != Item::numerical_value )
|
||||
Error(err_percent_from);
|
||||
|
||||
++pstring;
|
||||
SkipWhiteCharacters();
|
||||
|
||||
uint c = 0;
|
||||
c += stack[stack_index-1].value.Div(100);
|
||||
c += stack[stack_index-1].value.Mul(stack[stack_index-3].value);
|
||||
|
||||
if( c )
|
||||
Error(err_overflow);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method reads a mathematic operators
|
||||
or the final bracket or the semicolon operator
|
||||
@@ -2029,10 +1940,6 @@ int ReadOperator(Item & result)
|
||||
{
|
||||
SkipWhiteCharacters();
|
||||
|
||||
if( *pstring == '%' )
|
||||
OperatorPercentage();
|
||||
|
||||
|
||||
if( *pstring == 0 )
|
||||
return 1;
|
||||
else
|
||||
@@ -2042,7 +1949,7 @@ int ReadOperator(Item & result)
|
||||
++pstring;
|
||||
}
|
||||
else
|
||||
if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
|
||||
if( *pstring == ';' )
|
||||
{
|
||||
result.type = Item::semicolon;
|
||||
++pstring;
|
||||
@@ -2072,9 +1979,7 @@ return 0;
|
||||
void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator,
|
||||
const ValueType & value2)
|
||||
{
|
||||
uint res;
|
||||
|
||||
calculated = true;
|
||||
int res;
|
||||
|
||||
switch( mat_operator )
|
||||
{
|
||||
@@ -2137,6 +2042,7 @@ uint res;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/*
|
||||
on the stack left an unknown operator but we had to recognize its before
|
||||
@@ -2165,20 +2071,10 @@ void TryRollingUpStackWithOperatorPriority()
|
||||
{
|
||||
while( stack_index>=4 &&
|
||||
stack[stack_index-4].type == Item::numerical_value &&
|
||||
stack[stack_index-3].type == Item::mat_operator &&
|
||||
stack[stack_index-3].type == Item::mat_operator &&
|
||||
stack[stack_index-2].type == Item::numerical_value &&
|
||||
stack[stack_index-1].type == Item::mat_operator &&
|
||||
(
|
||||
(
|
||||
// the first operator has greater priority
|
||||
stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority()
|
||||
) ||
|
||||
(
|
||||
// or both operators have the same priority and the first operator is not right associative
|
||||
stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() &&
|
||||
stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right
|
||||
)
|
||||
)
|
||||
stack[stack_index-1].type == Item::mat_operator &&
|
||||
stack[stack_index-3].moperator.GetPriority() >= stack[stack_index-1].moperator.GetPriority()
|
||||
)
|
||||
{
|
||||
MakeStandardMathematicOperation(stack[stack_index-4].value,
|
||||
@@ -2527,16 +2423,12 @@ public:
|
||||
Parser(): default_stack_size(100)
|
||||
{
|
||||
pstop_calculating = 0;
|
||||
puser_variables = 0;
|
||||
puser_functions = 0;
|
||||
puser_variables = 0;
|
||||
puser_functions = 0;
|
||||
pfunction_local_variables = 0;
|
||||
base = 10;
|
||||
deg_rad_grad = 1;
|
||||
error = err_ok;
|
||||
group = 0;
|
||||
comma = '.';
|
||||
comma2 = ',';
|
||||
param_sep = 0;
|
||||
base = 10;
|
||||
deg_rad_grad = 1;
|
||||
error = err_ok;
|
||||
|
||||
CreateFunctionsTable();
|
||||
CreateVariablesTable();
|
||||
@@ -2555,11 +2447,7 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
|
||||
pfunction_local_variables = 0;
|
||||
base = p.base;
|
||||
deg_rad_grad = p.deg_rad_grad;
|
||||
error = p.error;
|
||||
group = p.group;
|
||||
comma = p.comma;
|
||||
comma2 = p.comma2;
|
||||
param_sep = p.param_sep;
|
||||
error = err_ok;
|
||||
|
||||
/*
|
||||
we don't have to call 'CreateFunctionsTable()' etc.
|
||||
@@ -2587,7 +2475,6 @@ Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
|
||||
|
||||
/*!
|
||||
the new base of mathematic system
|
||||
default is 10
|
||||
*/
|
||||
void SetBase(int b)
|
||||
{
|
||||
@@ -2642,49 +2529,15 @@ void SetFunctions(const Objects * pf)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting the group character
|
||||
default zero (not used)
|
||||
*/
|
||||
void SetGroup(int g)
|
||||
{
|
||||
group = g;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting the main comma operator and the additional comma operator
|
||||
the additional operator can be zero (which means it is not used)
|
||||
default are: '.' and ','
|
||||
*/
|
||||
void SetComma(int c, int c2 = 0)
|
||||
{
|
||||
comma = c;
|
||||
comma2 = c2;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
setting an additional character which is used as a parameters separator
|
||||
the main parameters separator is a semicolon (is used always)
|
||||
|
||||
this character is used also as a global separator
|
||||
*/
|
||||
void SetParamSep(int s)
|
||||
{
|
||||
param_sep = s;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the main method using for parsing string
|
||||
*/
|
||||
ErrorCode Parse(const char * str)
|
||||
ErrorCode Parse(const tt_char * str)
|
||||
{
|
||||
stack_index = 0;
|
||||
pstring = str;
|
||||
error = err_ok;
|
||||
calculated = false;
|
||||
|
||||
stack.resize( default_stack_size );
|
||||
|
||||
@@ -2695,7 +2548,6 @@ ErrorCode Parse(const char * str)
|
||||
catch(ErrorCode c)
|
||||
{
|
||||
error = c;
|
||||
calculated = false;
|
||||
}
|
||||
|
||||
NormalizeStack();
|
||||
@@ -2704,73 +2556,11 @@ return error;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the main method using for parsing string
|
||||
*/
|
||||
ErrorCode Parse(const std::string & str)
|
||||
{
|
||||
return Parse(str.c_str());
|
||||
}
|
||||
|
||||
|
||||
#ifndef TTMATH_DONT_USE_WCHAR
|
||||
|
||||
/*!
|
||||
the main method using for parsing string
|
||||
*/
|
||||
ErrorCode Parse(const wchar_t * str)
|
||||
{
|
||||
Misc::AssignString(wide_to_ansi, str);
|
||||
|
||||
return Parse(wide_to_ansi.c_str());
|
||||
|
||||
// !! wide_to_ansi clearing can be added here
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
the main method using for parsing string
|
||||
*/
|
||||
ErrorCode Parse(const std::wstring & str)
|
||||
{
|
||||
return Parse(str.c_str());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true is something was calculated
|
||||
(at least one mathematical operator was used or a function or variable)
|
||||
e.g. true if the string to Parse() looked like this:
|
||||
"1+1"
|
||||
"2*3"
|
||||
"sin(5)"
|
||||
|
||||
if the string was e.g. "678" the result is false
|
||||
*/
|
||||
bool Calculated()
|
||||
{
|
||||
return calculated;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
initializing coefficients used when calculating the gamma (or factorial) function
|
||||
this speed up the next calculations
|
||||
you don't have to call this method explicitly
|
||||
these coefficients will be calculated when needed
|
||||
*/
|
||||
void InitCGamma()
|
||||
{
|
||||
cgamma.InitAll();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* This file is a part of TTMath Bignum Library
|
||||
* and is distributed under the (new) BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||
* project may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmaththreads
|
||||
#define headerfilettmaththreads
|
||||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
#ifdef TTMATH_WIN32_THREADS
|
||||
#include <windows.h>
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_POSIX_THREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\file ttmaththreads.h
|
||||
\brief Some objects used in multithreads environment
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
this is a simple skeleton of a program in multithreads environment:
|
||||
|
||||
#define TTMATH_MULTITHREADS
|
||||
#include<ttmath/ttmath.h>
|
||||
|
||||
TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
int main()
|
||||
{
|
||||
[...]
|
||||
}
|
||||
|
||||
make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file)
|
||||
use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope)
|
||||
*/
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
|
||||
#ifdef TTMATH_WIN32_THREADS
|
||||
|
||||
/*
|
||||
we use win32 threads
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||
somewhere in *.cpp file
|
||||
|
||||
(at the moment in win32 this macro does nothing)
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
HANDLE mutex_handle;
|
||||
|
||||
|
||||
void CreateName(char * buffer) const
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4996)
|
||||
// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
|
||||
#endif
|
||||
|
||||
sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId());
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default : 4996)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
char buffer[50];
|
||||
|
||||
CreateName(buffer);
|
||||
mutex_handle = CreateMutexA(0, false, buffer);
|
||||
|
||||
if( mutex_handle == 0 )
|
||||
return false;
|
||||
|
||||
WaitForSingleObject(mutex_handle, INFINITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ThreadLock()
|
||||
{
|
||||
mutex_handle = 0;
|
||||
}
|
||||
|
||||
|
||||
~ThreadLock()
|
||||
{
|
||||
if( mutex_handle != 0 )
|
||||
{
|
||||
ReleaseMutex(mutex_handle);
|
||||
CloseHandle(mutex_handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifdef TTMATH_WIN32_THREADS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_POSIX_THREADS
|
||||
|
||||
/*
|
||||
we use posix threads
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro
|
||||
somewhere in *.cpp file
|
||||
(this macro defines a pthread_mutex_t object used by TTMath library)
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER \
|
||||
namespace ttmath \
|
||||
{ \
|
||||
pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro
|
||||
*/
|
||||
extern pthread_mutex_t ttmath_mutex;
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
if( pthread_mutex_lock(&ttmath_mutex) != 0 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
~ThreadLock()
|
||||
{
|
||||
pthread_mutex_unlock(&ttmath_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifdef TTMATH_POSIX_THREADS
|
||||
|
||||
|
||||
|
||||
|
||||
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
/*!
|
||||
we don't use win32 and pthreads
|
||||
*/
|
||||
|
||||
/*!
|
||||
*/
|
||||
#define TTMATH_MULTITHREADS_HELPER
|
||||
|
||||
|
||||
/*!
|
||||
objects of this class are used to synchronize
|
||||
actually we don't synchronize, the method Lock() returns always 'false'
|
||||
*/
|
||||
class ThreadLock
|
||||
{
|
||||
public:
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2012, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -56,96 +56,61 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
// for uint64_t and int64_t on a 32 bit platform
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
the version of the library
|
||||
|
||||
TTMATH_PRERELEASE_VER is either zero or one
|
||||
zero means that this is the release version of the library
|
||||
(one means something like beta)
|
||||
if zero that means this is the release version of the library
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 9
|
||||
#define TTMATH_REVISION_VER 3
|
||||
|
||||
#define TTMATH_PRERELEASE_VER 0
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
you can define a platform explicitly by defining either
|
||||
TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro
|
||||
*/
|
||||
#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*
|
||||
other platforms than x86 and amd64 are not recognized at the moment
|
||||
so you should set TTMATH_PLATFORMxx manually
|
||||
*/
|
||||
|
||||
// we're using a 32bit platform
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
// we're using a 64bit platform
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#define TTMATH_REVISION_VER 0
|
||||
#define TTMATH_PRERELEASE_VER 1
|
||||
|
||||
|
||||
/*!
|
||||
asm version of the library is available by default only for:
|
||||
x86 and amd64 platforms and for Microsoft Visual and GCC compilers
|
||||
TTMATH_DEBUG
|
||||
this macro enables further testing during writing your code
|
||||
you don't have to define it in a release mode
|
||||
|
||||
but you can force using asm version (the same asm as for Microsoft Visual)
|
||||
by defining TTMATH_FORCEASM macro
|
||||
you have to be sure that your compiler accept such an asm format
|
||||
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
|
||||
are set as well and these macros can throw an exception if a condition in it
|
||||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_RELEASE
|
||||
if you are confident that your code is perfect you can define TTMATH_RELEASE
|
||||
macro for example by using -D option in gcc
|
||||
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
||||
or by defining this macro in your code before using any header files of this library
|
||||
|
||||
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
|
||||
*/
|
||||
#ifndef TTMATH_FORCEASM
|
||||
|
||||
#if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64
|
||||
/*!
|
||||
x86 architecture:
|
||||
__i386__ defined by GNU C
|
||||
_X86_ defined by MinGW32
|
||||
_M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
|
||||
|
||||
amd64 architecture:
|
||||
__x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio
|
||||
_M_X64 defined by Visual Studio
|
||||
|
||||
asm version is available only for x86 or amd64 platforms
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined _MSC_VER && !defined __GNUC__
|
||||
/*!
|
||||
another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version
|
||||
(CLANG defines __GNUC__ too)
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
#ifndef TTMATH_RELEASE
|
||||
#define TTMATH_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*!
|
||||
we're using a 32bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
we're using a 64bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
@@ -155,116 +120,131 @@ namespace ttmath
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
/*!
|
||||
on 32 bit platform ulint and slint will be equal 64 bits
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
// long long on MS Windows (Visual and GCC mingw compilers) have 64 bits
|
||||
// stdint.h is not available on Visual Studio prior to VS 2010 version
|
||||
typedef unsigned long long int ulint;
|
||||
typedef signed long long int slint;
|
||||
#else
|
||||
// we do not use 'long' here because there is a difference in unix and windows
|
||||
// environments: in unix 'long' has 64 bits but in windows it has only 32 bits
|
||||
typedef uint64_t ulint;
|
||||
typedef int64_t slint;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
this type is twice bigger than uint
|
||||
(64bit on a 32bit platforms)
|
||||
|
||||
although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long)
|
||||
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
|
||||
|
||||
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 32u
|
||||
typedef unsigned long long int ulint;
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||
const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 32bit word (2^32 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
|
||||
|
||||
/*!
|
||||
the number of words (32bit words on 32bit platform)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||
|
||||
/*!
|
||||
this macro returns the number of machine words
|
||||
capable to hold min_bits bits
|
||||
e.g. TTMATH_BITS(128) returns 4
|
||||
*/
|
||||
#define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1)
|
||||
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 256u;
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
on 64bit platforms one word (uint, sint) will be equal 64bits
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
/* in VC 'long' type has 32 bits, __int64 is VC extension */
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned __int64 uint;
|
||||
typedef signed __int64 sint;
|
||||
typedef signed __int64 sint;
|
||||
#else
|
||||
typedef unsigned long uint;
|
||||
typedef signed long sint;
|
||||
typedef unsigned long long uint;
|
||||
typedef signed long long sint;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
on 64bit platforms we do not define ulint and slint
|
||||
*/
|
||||
on 64bit platform we do not define ulint
|
||||
sizeof(long long) is 8 (64bit) but we need 128bit
|
||||
|
||||
/*!
|
||||
how many bits there are in the uint type
|
||||
on 64 bit platform (when there is defined TTMATH_NOASM macro)
|
||||
methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit
|
||||
*/
|
||||
#define TTMATH_BITS_PER_UINT 64ul
|
||||
//typedef unsigned long long int ulint;
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 64bit word (2^63)
|
||||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
||||
const uint TTMATH_UINT_HIGHEST_BIT = 0x8000000000000000ul;
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 64bit word (2^64 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
||||
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffffffffffful;
|
||||
|
||||
/*!
|
||||
the number of words (64bit words on 64bit platforms)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
||||
|
||||
/*!
|
||||
this macro returns the number of machine words
|
||||
capable to hold min_bits bits
|
||||
e.g. TTMATH_BITS(128) returns 2
|
||||
*/
|
||||
#define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1)
|
||||
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 128ul;
|
||||
|
||||
#endif
|
||||
|
||||
const uint TTMATH_BITS_PER_UINT = (sizeof(uint)*8);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC)
|
||||
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS)
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define TTMATH_WIN32_THREADS
|
||||
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
||||
#define TTMATH_POSIX_THREADS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if defined(UNICODE) || defined(_UNICODE)
|
||||
#define TTMATH_USE_WCHAR
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TTMATH_USE_WCHAR
|
||||
|
||||
typedef wchar_t tt_char;
|
||||
typedef std::wstring tt_string;
|
||||
typedef std::wostringstream tt_ostringstream;
|
||||
typedef std::wostream tt_ostream;
|
||||
typedef std::wistream tt_istream;
|
||||
#define TTMATH_TEXT_HELPER(txt) L##txt
|
||||
|
||||
#else
|
||||
|
||||
typedef char tt_char;
|
||||
typedef std::string tt_string;
|
||||
typedef std::ostringstream tt_ostringstream;
|
||||
typedef std::ostream tt_ostream;
|
||||
typedef std::istream tt_istream;
|
||||
#define TTMATH_TEXT_HELPER(txt) txt
|
||||
|
||||
#endif
|
||||
|
||||
#define TTMATH_TEXT(txt) TTMATH_TEXT_HELPER(txt)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
characters which represent the comma operator
|
||||
|
||||
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
|
||||
that means you can input values for example 1.2345 and 1,2345 as well
|
||||
|
||||
if you don't want it just put 0 there e.g.
|
||||
#define TTMATH_COMMA_CHARACTER_2 0
|
||||
then only TTMATH_COMMA_CHARACTER_1 will be used
|
||||
|
||||
don't put there any special character which is used by the parser
|
||||
(for example a semicolon ';' shouldn't be there)
|
||||
*/
|
||||
#define TTMATH_COMMA_CHARACTER_1 '.'
|
||||
#define TTMATH_COMMA_CHARACTER_2 ','
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this variable defines how many iterations are performed
|
||||
@@ -287,15 +267,10 @@ namespace ttmath
|
||||
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
|
||||
the Karatsuba algorithm will use standard schoolbook multiplication
|
||||
*/
|
||||
#ifdef TTMATH_DEBUG_LOG
|
||||
// if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#ifdef __GNUC__
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
|
||||
#else
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||
#endif
|
||||
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
|
||||
#endif
|
||||
|
||||
|
||||
@@ -311,30 +286,9 @@ namespace ttmath
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
lib type codes:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
*/
|
||||
enum LibTypeCode
|
||||
{
|
||||
asm_vc_32 = 0,
|
||||
asm_gcc_32,
|
||||
asm_vc_64,
|
||||
asm_gcc_64,
|
||||
no_asm_32,
|
||||
no_asm_64
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
error codes
|
||||
*/
|
||||
@@ -365,140 +319,10 @@ namespace ttmath
|
||||
err_object_exists,
|
||||
err_unknown_object,
|
||||
err_still_calculating,
|
||||
err_in_short_form_used_function,
|
||||
err_percent_from
|
||||
err_in_short_form_used_function
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
this struct is used when converting to/from a string
|
||||
/temporarily only in Big::ToString() and Big::FromString()/
|
||||
*/
|
||||
struct Conv
|
||||
{
|
||||
/*!
|
||||
base (radix) on which the value will be shown (or read)
|
||||
default: 10
|
||||
*/
|
||||
uint base;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if true the value will be always shown in the scientific mode, e.g: 123e+30
|
||||
default: false
|
||||
*/
|
||||
bool scient;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
if scient is false then the value will be printed in the scientific mode
|
||||
only if the exponent is greater than scien_from
|
||||
default: 15
|
||||
*/
|
||||
sint scient_from;
|
||||
|
||||
|
||||
/*!
|
||||
if 'base_round' is true and 'base' is different from 2, 4, 8, or 16
|
||||
and the result value is not an integer then we make an additional rounding
|
||||
(after converting the last digit from the result is skipped)
|
||||
default: true
|
||||
|
||||
e.g.
|
||||
Conv c;
|
||||
c.base_round = false;
|
||||
Big<1, 1> a = "0.1"; // decimal input
|
||||
std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999
|
||||
*/
|
||||
bool base_round;
|
||||
|
||||
|
||||
/*!
|
||||
used only in Big::ToString()
|
||||
tells how many digits after comma are possible
|
||||
default: -1 which means all digits are printed
|
||||
|
||||
set it to zero if you want integer value only
|
||||
|
||||
for example when the value is:
|
||||
12.345678 and 'round' is 4
|
||||
then the result will be
|
||||
12.3457 (the last digit was rounded)
|
||||
*/
|
||||
sint round;
|
||||
|
||||
|
||||
/*!
|
||||
if true that not mattered digits in the mantissa will be cut off
|
||||
(zero characters at the end -- after the comma operator)
|
||||
e.g. 1234,78000 will be: 1234,78
|
||||
default: true
|
||||
*/
|
||||
bool trim_zeroes;
|
||||
|
||||
|
||||
/*!
|
||||
the main comma operator (used when reading and writing)
|
||||
default is a dot '.'
|
||||
*/
|
||||
uint comma;
|
||||
|
||||
|
||||
/*!
|
||||
additional comma operator (used only when reading)
|
||||
if you don't want it just set it to zero
|
||||
default is a comma ','
|
||||
|
||||
this allowes you to convert from a value:
|
||||
123.45 as well as from 123,45
|
||||
*/
|
||||
uint comma2;
|
||||
|
||||
|
||||
/*!
|
||||
it sets the character which is used for grouping
|
||||
if group=' ' then: 1234,56789 will be printed as: 1 234,567 89
|
||||
|
||||
if you don't want grouping just set it to zero (which is default)
|
||||
*/
|
||||
uint group;
|
||||
|
||||
|
||||
/*!
|
||||
how many digits should be grouped (it is used if 'group' is non zero)
|
||||
default: 3
|
||||
*/
|
||||
uint group_digits;
|
||||
|
||||
|
||||
/*!
|
||||
*/
|
||||
uint group_exp; // not implemented yet
|
||||
|
||||
|
||||
|
||||
|
||||
Conv()
|
||||
{
|
||||
// default values
|
||||
base = 10;
|
||||
scient = false;
|
||||
scient_from = 15;
|
||||
base_round = true;
|
||||
round = -1;
|
||||
trim_zeroes = true;
|
||||
comma = '.';
|
||||
comma2 = ',';
|
||||
group = 0;
|
||||
group_digits = 3;
|
||||
group_exp = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this simple class can be used in multithreading model
|
||||
(you can write your own class derived from this one)
|
||||
@@ -525,20 +349,20 @@ namespace ttmath
|
||||
*/
|
||||
class ExceptionInfo
|
||||
{
|
||||
const char * file;
|
||||
const tt_char * file;
|
||||
int line;
|
||||
|
||||
public:
|
||||
ExceptionInfo() : file(0), line(0) {}
|
||||
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
|
||||
ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
|
||||
|
||||
std::string Where() const
|
||||
tt_string Where() const
|
||||
{
|
||||
if( !file )
|
||||
return "unknown";
|
||||
return TTMATH_TEXT("unknown");
|
||||
|
||||
std::ostringstream result;
|
||||
result << file << ":" << line;
|
||||
tt_ostringstream result;
|
||||
result << file << TTMATH_TEXT(":") << line;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
@@ -551,28 +375,41 @@ namespace ttmath
|
||||
In the library is used macro TTMATH_REFERENCE_ASSERT which
|
||||
can throw an exception of this type
|
||||
|
||||
** from version 0.9.2 this macro is removed from all methods
|
||||
in public interface so you don't have to worry about it **
|
||||
|
||||
If you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string) with
|
||||
from using method Where() (it returns std::string (or std::wstring) with
|
||||
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
|
||||
was used)
|
||||
|
||||
What is the 'reference' error?
|
||||
Some kind of methods use a reference as their argument to another object,
|
||||
and the another object not always can be the same which is calling, e.g.
|
||||
Big<1,2> foo(10);
|
||||
foo.Mul(foo); // this is incorrect
|
||||
above method Mul is making something more with 'this' object and
|
||||
'this' cannot be passed as the argument because the result will be undefined
|
||||
|
||||
macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem
|
||||
|
||||
note! some methods can use 'this' object as the argument
|
||||
for example this code is correct:
|
||||
UInt<2> foo(10);
|
||||
foo.Add(foo);
|
||||
but there are only few methods which can do that
|
||||
*/
|
||||
class ReferenceError : public std::logic_error, public ExceptionInfo
|
||||
{
|
||||
public:
|
||||
|
||||
ReferenceError() : std::logic_error("reference error")
|
||||
ReferenceError() : std::logic_error ("reference error")
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceError(const char * f, int l) :
|
||||
std::logic_error("reference error"), ExceptionInfo(f,l)
|
||||
ReferenceError(const tt_char * f, int l) :
|
||||
std::logic_error ("reference error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Where() const
|
||||
tt_string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
@@ -587,7 +424,7 @@ namespace ttmath
|
||||
of this type
|
||||
|
||||
if you compile with gcc you can get a small benefit
|
||||
from using method Where() (it returns std::string) with
|
||||
from using method Where() (it returns std::string (or std::wstring) with
|
||||
the name and the line of a file where the macro TTMATH_ASSERT
|
||||
was used)
|
||||
*/
|
||||
@@ -595,16 +432,16 @@ namespace ttmath
|
||||
{
|
||||
public:
|
||||
|
||||
RuntimeError() : std::runtime_error("internal error")
|
||||
RuntimeError() : std::runtime_error ("internal error")
|
||||
{
|
||||
}
|
||||
|
||||
RuntimeError(const char * f, int l) :
|
||||
std::runtime_error("internal error"), ExceptionInfo(f,l)
|
||||
RuntimeError(const tt_char * f, int l) :
|
||||
std::runtime_error ("internal error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Where() const
|
||||
tt_string Where() const
|
||||
{
|
||||
return ExceptionInfo::Where();
|
||||
}
|
||||
@@ -613,30 +450,28 @@ namespace ttmath
|
||||
|
||||
|
||||
/*!
|
||||
TTMATH_DEBUG
|
||||
this macro enables further testing during writing your code
|
||||
you don't have to define it in a release mode
|
||||
|
||||
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
|
||||
are set as well and these macros can throw an exception if a condition in it
|
||||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined
|
||||
look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
|
||||
*/
|
||||
#if defined DEBUG || defined _DEBUG
|
||||
#define TTMATH_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TTMATH_DEBUG
|
||||
|
||||
#if defined(__FILE__) && defined(__LINE__)
|
||||
|
||||
#ifdef TTMATH_USE_WCHAR
|
||||
#define TTMATH_FILE_HELPER2(arg) L##arg
|
||||
#define TTMATH_FILE_HELPER(x) TTMATH_FILE_HELPER2(x)
|
||||
#define TTMATH_FILE TTMATH_FILE_HELPER(__FILE__)
|
||||
#else
|
||||
#define TTMATH_FILE __FILE__
|
||||
#endif
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||
if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
|
||||
|
||||
#define TTMATH_VERIFY(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
@@ -645,27 +480,38 @@ namespace ttmath
|
||||
|
||||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
|
||||
#define TTMATH_VERIFY(expression) \
|
||||
if( !(expression) ) throw RuntimeError();
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||
#define TTMATH_ASSERT(expression)
|
||||
#define TTMATH_VERIFY(expression) (void)(expression);
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(LOG_PRINTF)
|
||||
#define LOG_PRINTF printf
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_DEBUG_LOG
|
||||
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
|
||||
#define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout);
|
||||
#define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len);
|
||||
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len);
|
||||
#else
|
||||
#define TTMATH_LOG(msg)
|
||||
#define TTMATH_LOGC(msg, carry)
|
||||
#define TTMATH_VECTOR_LOG(msg, vector, len)
|
||||
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_USE_WCHAR
|
||||
#define TTMATH_LOG_HELPER(msg) \
|
||||
PrintLog(L##msg, std::wcout);
|
||||
#else
|
||||
#define TTMATH_LOG_HELPER(msg) \
|
||||
PrintLog(msg, std::cout);
|
||||
#endif
|
||||
|
||||
#define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
|
||||
|
||||
#else
|
||||
|
||||
#define TTMATH_LOG(msg)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
1569
ttmath/ttmathuint.h
1569
ttmath/ttmathuint.h
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#ifdef TTMATH_NOASM
|
||||
|
||||
#pragma message("TTMATH_NOASM")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_noasm.h
|
||||
\brief template class UInt<uint> with methods without any assembler code
|
||||
@@ -51,56 +53,6 @@
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
returning the string represents the currect type of the library
|
||||
we have following types:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
*/
|
||||
template<uint value_size>
|
||||
const char * UInt<value_size>::LibTypeStr()
|
||||
{
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
static const char info[] = "no_asm_32";
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
static const char info[] = "no_asm_64";
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
returning the currect type of the library
|
||||
*/
|
||||
template<uint value_size>
|
||||
LibTypeCode UInt<value_size>::LibType()
|
||||
{
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
LibTypeCode info = no_asm_32;
|
||||
#endif
|
||||
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
LibTypeCode info = no_asm_64;
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method adds two words together
|
||||
returns carry
|
||||
|
||||
this method is created only when TTMATH_NOASM macro is defined
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
@@ -145,7 +97,7 @@ namespace ttmath
|
||||
for(i=0 ; i<value_size ; ++i)
|
||||
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||
|
||||
TTMATH_LOGC("UInt::Add", c)
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -181,7 +133,7 @@ namespace ttmath
|
||||
for(i=index+1 ; i<value_size && c ; ++i)
|
||||
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||
|
||||
TTMATH_LOGC("UInt::AddInt", c)
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -234,7 +186,7 @@ namespace ttmath
|
||||
for(i=index+2 ; i<value_size && c ; ++i)
|
||||
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||
|
||||
TTMATH_LOGC("UInt::AddTwoInts", c)
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -274,7 +226,7 @@ namespace ttmath
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -282,12 +234,6 @@ namespace ttmath
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method subtractes one word from the other
|
||||
returns carry
|
||||
|
||||
this method is created only when TTMATH_NOASM macro is defined
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
@@ -329,7 +275,7 @@ namespace ttmath
|
||||
for(i=0 ; i<value_size ; ++i)
|
||||
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||
|
||||
TTMATH_LOGC("UInt::Sub", c)
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -367,7 +313,7 @@ namespace ttmath
|
||||
for(i=index+1 ; i<value_size && c ; ++i)
|
||||
c = SubTwoWords(table[i], 0, c, &table[i]);
|
||||
|
||||
TTMATH_LOGC("UInt::SubInt", c)
|
||||
TTMATH_LOG("UInt::SubInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -407,7 +353,7 @@ namespace ttmath
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -441,7 +387,7 @@ namespace ttmath
|
||||
c = new_c;
|
||||
}
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2_one", c)
|
||||
TTMATH_LOG("UInt::Rcl2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -480,9 +426,7 @@ namespace ttmath
|
||||
c = new_c;
|
||||
}
|
||||
|
||||
c = (c != 0)? 1 : 0;
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2_one", c)
|
||||
TTMATH_LOG("UInt::Rcr2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -520,7 +464,7 @@ namespace ttmath
|
||||
c = new_c;
|
||||
}
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2", (c & 1))
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
||||
return (c & 1);
|
||||
}
|
||||
@@ -559,19 +503,18 @@ namespace ttmath
|
||||
c = new_c;
|
||||
}
|
||||
|
||||
c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2", c)
|
||||
|
||||
return c;
|
||||
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
/*
|
||||
this method returns the number of the highest set bit in x
|
||||
if the 'x' is zero this method returns '-1'
|
||||
|
||||
*/
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||
@@ -592,34 +535,13 @@ namespace ttmath
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method returns the number of the highest set bit in x
|
||||
if the 'x' is zero this method returns '-1'
|
||||
*/
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLowestBitInWord(uint x)
|
||||
{
|
||||
if( x == 0 )
|
||||
return -1;
|
||||
|
||||
uint bit = 0;
|
||||
|
||||
while( (x & 1) == 0 )
|
||||
{
|
||||
x = x >> 1;
|
||||
++bit;
|
||||
}
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method sets a special bit in the 'value'
|
||||
and returns the last state of the bit (zero or one)
|
||||
|
||||
bit is from <0,TTMATH_BITS_PER_UINT-1>
|
||||
bit is from <0,63>
|
||||
|
||||
e.g.
|
||||
uint x = 100;
|
||||
@@ -633,7 +555,7 @@ namespace ttmath
|
||||
|
||||
uint mask = 1;
|
||||
|
||||
if( bit > 0 )
|
||||
if( bit > 1 )
|
||||
mask = mask << bit;
|
||||
|
||||
uint last = value & mask;
|
||||
@@ -821,11 +743,11 @@ namespace ttmath
|
||||
temp1.u_.high = a_.u_.low;
|
||||
temp1.u_.low = b_.u_.high;
|
||||
|
||||
res_.u_.high = (unsigned int)(temp1.u / c);
|
||||
temp2.u_.high = (unsigned int)(temp1.u % c);
|
||||
res_.u_.high = temp1.u / c;
|
||||
temp2.u_.high = temp1.u % c;
|
||||
temp2.u_.low = b_.u_.low;
|
||||
|
||||
res_.u_.low = (unsigned int)(temp2.u / c);
|
||||
res_.u_.low = temp2.u / c;
|
||||
*rest = temp2.u % c;
|
||||
|
||||
*r = res_.u;
|
||||
|
@@ -36,14 +36,13 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmathuint_x86
|
||||
#define headerfilettmathuint_x86
|
||||
|
||||
|
||||
#ifndef TTMATH_NOASM
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
#pragma message("TTMATH_ASM32")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_x86.h
|
||||
@@ -60,57 +59,12 @@
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
/*!
|
||||
returning the string represents the currect type of the library
|
||||
we have following types:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
*/
|
||||
template<uint value_size>
|
||||
const char * UInt<value_size>::LibTypeStr()
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
static const char info[] = "asm_vc_32";
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
static const char info[] = "asm_gcc_32";
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
returning the currect type of the library
|
||||
*/
|
||||
template<uint value_size>
|
||||
LibTypeCode UInt<value_size>::LibType()
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
LibTypeCode info = asm_vc_32;
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
LibTypeCode info = asm_gcc_32;
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
* basic mathematic functions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
adding ss2 to the this and adding carry if it's defined
|
||||
(this = this + ss2 + c)
|
||||
@@ -129,46 +83,31 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// this part might be compiled with for example visual c
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
xor eax,eax // eax=0
|
||||
xor edx,edx // edx=0
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
sub eax,[c] // CF=c
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4]
|
||||
adc [ebx+edx*4],eax
|
||||
mov eax,[esi+edx*4+0]
|
||||
adc [ebx+edx*4+0],eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -196,9 +135,9 @@ namespace ttmath
|
||||
: "cc", "memory" );
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Add", c)
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,14 +171,8 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
@@ -248,26 +181,21 @@ namespace ttmath
|
||||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
add [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -297,9 +225,9 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::AddInt", c)
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -340,59 +268,47 @@ namespace ttmath
|
||||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint c;
|
||||
uint c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov edx, [index]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov eax, [x1]
|
||||
sub ecx, edx // max uints to add (value_size - index)
|
||||
|
||||
add [ebx+edx*4], eax
|
||||
inc edx
|
||||
dec ecx
|
||||
lea ecx, [ecx-1]
|
||||
|
||||
mov eax, [x2]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
adc [ebx+edx*4], eax
|
||||
adc [ebx+edx*4+4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 0
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%ecx \n"
|
||||
"push %%edx \n"
|
||||
|
||||
"subl %%edx, %%ecx \n"
|
||||
|
||||
"addl %%esi, (%%ebx,%%edx,4) \n"
|
||||
@@ -418,9 +334,9 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::AddTwoInts", c)
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -458,21 +374,19 @@ namespace ttmath
|
||||
// this part might be compiled with for example visual c
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
||||
mov esi, [ss1]
|
||||
mov ebx, [ss2]
|
||||
mov edi, [result]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
adc eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
@@ -491,7 +405,7 @@ namespace ttmath
|
||||
adc eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
@@ -499,8 +413,6 @@ namespace ttmath
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -550,8 +462,6 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -575,40 +485,30 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
xor eax, eax
|
||||
mov edx, eax
|
||||
|
||||
sub eax, [c]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4]
|
||||
sbb [ebx+edx*4],eax
|
||||
mov eax, [esi+edx*4]
|
||||
sbb [ebx+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -638,9 +538,9 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Sub", c)
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -675,14 +575,8 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
@@ -691,26 +585,21 @@ namespace ttmath
|
||||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
sub [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -740,7 +629,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::SubInt", c)
|
||||
TTMATH_LOG("UInt::SubInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -786,7 +675,6 @@ namespace ttmath
|
||||
*/
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
@@ -800,7 +688,7 @@ namespace ttmath
|
||||
sbb eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
@@ -819,7 +707,7 @@ namespace ttmath
|
||||
sbb eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
@@ -827,8 +715,6 @@ namespace ttmath
|
||||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -878,8 +764,6 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -906,29 +790,25 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, edx
|
||||
sub ecx, [c]
|
||||
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcl dword ptr [ebx+edx*4], 1
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -956,7 +836,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2_one", c)
|
||||
TTMATH_LOG("UInt::Rcl2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -984,25 +864,22 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push ecx
|
||||
xor ecx, ecx
|
||||
sub ecx, [c]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcr dword ptr [ebx+ecx*4-4], 1
|
||||
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop ecx
|
||||
pop ebx
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1028,20 +905,13 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2_one", c)
|
||||
TTMATH_LOG("UInt::Rcr2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4731)
|
||||
//warning C4731: frame pointer register 'ebp' modified by inline assembly code
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
@@ -1059,62 +929,47 @@ namespace ttmath
|
||||
{
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shr edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
|
||||
mov eax, [c]
|
||||
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rol dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, ebp
|
||||
and eax, [mask]
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
pop ebp // restoring ebp
|
||||
|
||||
and eax, 1
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
mov dword ptr [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1162,9 +1017,9 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2", c)
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -1189,43 +1044,37 @@ namespace ttmath
|
||||
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shl edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
mov eax, [c]
|
||||
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
add edx, edi
|
||||
dec edx // edx is pointing at the end of the table (on last word)
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
dec edx // edx - is pointing at the last word
|
||||
|
||||
mov eax, [c]
|
||||
or eax, eax
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
ror dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, ebp
|
||||
and eax, [mask]
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
@@ -1234,18 +1083,10 @@ namespace ttmath
|
||||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
pop ebp // restoring ebp
|
||||
|
||||
rol eax, 1 // 31bit will be first
|
||||
rol eax, 1 // bit 31 will be bit 0
|
||||
and eax, 1
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
mov dword ptr [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1296,16 +1137,12 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2", c)
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default : 4731)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this method returns the number of the highest set bit in one 32-bit word
|
||||
@@ -1319,16 +1156,11 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx,-1
|
||||
bsr eax,[x]
|
||||
cmovz eax,edx
|
||||
mov [result], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
mov [result], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1353,50 +1185,6 @@ namespace ttmath
|
||||
|
||||
|
||||
|
||||
/*
|
||||
this method returns the number of the smallest set bit in one 32-bit word
|
||||
if the 'x' is zero this method returns '-1'
|
||||
*/
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLowestBitInWord(uint x)
|
||||
{
|
||||
sint result;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx,-1
|
||||
bsf eax,[x]
|
||||
cmovz eax,edx
|
||||
mov [result], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy;
|
||||
|
||||
__asm__ (
|
||||
|
||||
"movl $-1, %1 \n"
|
||||
"bsfl %2, %0 \n"
|
||||
"cmovz %1, %0 \n"
|
||||
|
||||
: "=r" (result), "=&r" (dummy)
|
||||
: "r" (x)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
@@ -1420,20 +1208,14 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push eax
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
|
||||
pop eax
|
||||
pop ebx
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1452,8 +1234,7 @@ namespace ttmath
|
||||
#endif
|
||||
|
||||
value = v;
|
||||
|
||||
return old_bit;
|
||||
return old_bit;
|
||||
}
|
||||
|
||||
|
||||
@@ -1484,17 +1265,11 @@ namespace ttmath
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1557,18 +1332,12 @@ namespace ttmath
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx, [a]
|
||||
mov eax, [b]
|
||||
div dword ptr [c]
|
||||
|
||||
mov [r_], eax
|
||||
mov [rest_], edx
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
||||
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,11 +39,10 @@
|
||||
#ifndef headerfilettmathuint_x86_64
|
||||
#define headerfilettmathuint_x86_64
|
||||
|
||||
|
||||
#ifndef TTMATH_NOASM
|
||||
#ifdef TTMATH_PLATFORM64
|
||||
|
||||
|
||||
#pragma message("TTMATH_ASM64")
|
||||
/*!
|
||||
\file ttmathuint_x86_64.h
|
||||
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
|
||||
@@ -51,77 +50,31 @@
|
||||
this file is included at the end of ttmathuint.h
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_M_X64)
|
||||
#include <intrin.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
|
||||
uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
|
||||
uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
|
||||
uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
|
||||
uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
|
||||
uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
|
||||
uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
|
||||
uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
|
||||
uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
|
||||
uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
returning the string represents the currect type of the library
|
||||
we have following types:
|
||||
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
|
||||
asm_gcc_32 - with asm code designed for GCC (32 bits)
|
||||
asm_vc_64 - with asm for VC (64 bit)
|
||||
asm_gcc_64 - with asm for GCC (64 bit)
|
||||
no_asm_32 - pure C++ version (32 bit) - without any asm code
|
||||
no_asm_64 - pure C++ version (64 bit) - without any asm code
|
||||
*/
|
||||
template<uint value_size>
|
||||
const char * UInt<value_size>::LibTypeStr()
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
static const char info[] = "asm_vc_64";
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
static const char info[] = "asm_gcc_64";
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
returning the currect type of the library
|
||||
*/
|
||||
template<uint value_size>
|
||||
LibTypeCode UInt<value_size>::LibType()
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
LibTypeCode info = asm_vc_64;
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
LibTypeCode info = asm_gcc_64;
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
* basic mathematic functions
|
||||
@@ -150,12 +103,15 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_adc_x64(p1,p2,b,c);
|
||||
#if defined(_M_X64)
|
||||
c = adc_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
uint dummy, dummy2;
|
||||
/*
|
||||
this part should be compiled with gcc
|
||||
*/
|
||||
@@ -175,12 +131,12 @@ namespace ttmath
|
||||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Add", c)
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -217,12 +173,15 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_addindexed_x64(p1,b,index,value);
|
||||
#if defined(_M_X64)
|
||||
c = addindexed_x64(p1,b,index,value);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -241,13 +200,13 @@ namespace ttmath
|
||||
"setc %%al \n"
|
||||
"movzx %%al, %%rdx \n"
|
||||
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "0" (index), "1" (value), "2" (b), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::AddInt", c)
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -288,6 +247,30 @@ namespace ttmath
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||
#if 0
|
||||
{
|
||||
uint i, c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
printf("add %Id + %Id\n",x1,x2);
|
||||
for(int i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
|
||||
c = AddTwoWords(table[index], x1, 0, &table[index]);
|
||||
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
|
||||
|
||||
for(i=index+2 ; i<value_size && c ; ++i)
|
||||
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||
for(i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
printf(" -> %d\n",c);
|
||||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
@@ -296,12 +279,22 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
|
||||
#if defined(_M_X64)
|
||||
//printf("add %Id + %Id\n",x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//if (table[0] == 1265784741359897913) DebugBreak();
|
||||
c = addindexed2_x64(p1,b,index,x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//printf(" -> %d\n",c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -330,94 +323,14 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::AddTwoInts", c)
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy1, dummy2, dummy3;
|
||||
uint rest = ss1_size - ss2_size;
|
||||
|
||||
// this part should be compiled with gcc
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"adc (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"adc %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
@@ -441,12 +354,15 @@ namespace ttmath
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_sbb_x64(p1,p2,b,c);
|
||||
#if defined(_M_X64)
|
||||
c = sbb_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
@@ -464,18 +380,18 @@ namespace ttmath
|
||||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Sub", c)
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method subtracts one word (at a specific position)
|
||||
and returns a carry (if it was)
|
||||
@@ -505,10 +421,13 @@ namespace ttmath
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_subindexed_x64(p1,b,index,value);
|
||||
#if defined(_M_X64)
|
||||
c = subindexed_x64(p1,b,index,value);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
@@ -535,92 +454,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::SubInt", c)
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
// the asm code is nearly the same as in AddVector
|
||||
// only two instructions 'adc' are changed to 'sbb'
|
||||
|
||||
uint dummy1, dummy2, dummy3;
|
||||
uint rest = ss1_size - ss2_size;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"sbb (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"sbb %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
|
||||
TTMATH_LOG("UInt64::SubInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -646,12 +480,14 @@ namespace ttmath
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_rcl_x64(p1,b,c);
|
||||
#if defined(_M_X64)
|
||||
c = rcl_x64(p1,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
@@ -675,7 +511,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2_one", c)
|
||||
TTMATH_LOG("UInt::Rcl2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -701,12 +537,14 @@ namespace ttmath
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_rcr_x64(p1,b,c);
|
||||
#if defined(_M_X64)
|
||||
c = rcr_x64(p1,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy;
|
||||
|
||||
@@ -728,7 +566,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2_one", c)
|
||||
TTMATH_LOG("UInt::Rcr2_one")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -757,12 +595,14 @@ namespace ttmath
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_rcl2_x64(p1,b,bits,c);
|
||||
#if defined(_M_X64)
|
||||
c = rcl2_x64(p1,b,bits,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
@@ -778,6 +618,7 @@ namespace ttmath
|
||||
|
||||
"xorq %%rdx, %%rdx \n"
|
||||
"movq %%rdx, %%rsi \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%r8, %%rsi \n"
|
||||
|
||||
@@ -797,12 +638,12 @@ namespace ttmath
|
||||
"and $1, %%rax \n"
|
||||
|
||||
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcl2", c)
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -830,9 +671,12 @@ namespace ttmath
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
c = ttmath_rcr2_x64(p1,b,bits,c);
|
||||
#if defined(_M_X64)
|
||||
c = rcr2_x64(p1,b,bits,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -853,6 +697,7 @@ namespace ttmath
|
||||
"movq %%rdx, %%rsi \n"
|
||||
"addq %%rdi, %%rdx \n"
|
||||
"decq %%rdx \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%R8, %%rsi \n"
|
||||
|
||||
@@ -860,7 +705,7 @@ namespace ttmath
|
||||
"rorq %%cl, (%%rbx,%%rdx,8) \n"
|
||||
|
||||
"movq (%%rbx,%%rdx,8), %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"xorq %%rax, (%%rbx,%%rdx,8) \n"
|
||||
"orq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||
"movq %%rax, %%rsi \n"
|
||||
@@ -878,7 +723,7 @@ namespace ttmath
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOGC("UInt::Rcr2", c)
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -893,21 +738,21 @@ namespace ttmath
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||
{
|
||||
sint result;
|
||||
|
||||
register sint result;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long nIndex(0);
|
||||
|
||||
unsigned long nIndex = 0;
|
||||
|
||||
if( _BitScanReverse64(&nIndex,x) == 0 )
|
||||
result = -1;
|
||||
else
|
||||
result = nIndex;
|
||||
|
||||
if (_BitScanReverse64(&nIndex,x) == 0)
|
||||
result = -1;
|
||||
else
|
||||
result = nIndex;
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy;
|
||||
|
||||
@@ -928,50 +773,6 @@ namespace ttmath
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
this method returns the number of the highest set bit in one 64-bit word
|
||||
if the 'x' is zero this method returns '-1'
|
||||
|
||||
***this method is created only on a 64bit platform***
|
||||
*/
|
||||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLowestBitInWord(uint x)
|
||||
{
|
||||
sint result;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
unsigned long nIndex = 0;
|
||||
|
||||
if( _BitScanForward64(&nIndex,x) == 0 )
|
||||
result = -1;
|
||||
else
|
||||
result = nIndex;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy;
|
||||
|
||||
__asm__ (
|
||||
|
||||
"movq $-1, %1 \n"
|
||||
"bsfq %2, %0 \n"
|
||||
"cmovz %1, %0 \n"
|
||||
|
||||
: "=r" (result), "=&r" (dummy)
|
||||
: "r" (x)
|
||||
: "cc" );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method sets a special bit in the 'value'
|
||||
and returns the last state of the bit (zero or one)
|
||||
@@ -995,10 +796,17 @@ namespace ttmath
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(TTMATH_PLATFORM64)
|
||||
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
|
||||
#else
|
||||
old_bit = _bittestandset((long*)&value,bit) != 0;
|
||||
#endif
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ (
|
||||
@@ -1050,12 +858,14 @@ namespace ttmath
|
||||
uint result1_;
|
||||
uint result2_;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
result1_ = _umul128(a,b,&result2_);
|
||||
#if defined(_MSC_VER)
|
||||
result1_ = _umul128(a,b,&result2_);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ (
|
||||
@@ -1083,6 +893,7 @@ namespace ttmath
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
/*!
|
||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||
@@ -1109,16 +920,16 @@ namespace ttmath
|
||||
|
||||
TTMATH_ASSERT( c != 0 )
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
ttmath_div_x64(&a,&b,c);
|
||||
r_ = a;
|
||||
rest_ = b;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
div_x64(&a,&b,c);
|
||||
r_ = a;
|
||||
rest_ = b;
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
__asm__ (
|
||||
@@ -1136,6 +947,133 @@ namespace ttmath
|
||||
*rest = rest_;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
uint temp;
|
||||
|
||||
if( carry == 0 )
|
||||
{
|
||||
temp = a + b;
|
||||
|
||||
if( temp < a )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
temp = a + b + carry;
|
||||
|
||||
if( temp > a ) // !(temp<=a)
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
*result = temp;
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
|
||||
{
|
||||
if( carry == 0 )
|
||||
{
|
||||
*result = a - b;
|
||||
|
||||
if( a < b )
|
||||
carry = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
carry = 1;
|
||||
*result = a - b - carry;
|
||||
|
||||
if( a > b ) // !(a <= b )
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = AddTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
uint i, c = 0;
|
||||
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
for(i=0 ; i<ss2_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
|
||||
|
||||
for( ; i<ss1_size ; ++i)
|
||||
c = SubTwoWords(ss1[i], 0, c, &result[i]);
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // #ifndef __GNUC__
|
||||
|
||||
} //namespace
|
||||
|
||||
|
||||
|
@@ -1,79 +1,30 @@
|
||||
;
|
||||
; This file is a part of TTMath Bignum Library
|
||||
; and is distributed under the (new) BSD licence.
|
||||
; Author: Christian Kaiser <chk@online.de>
|
||||
;
|
||||
PUBLIC adc_x64
|
||||
PUBLIC addindexed_x64
|
||||
PUBLIC addindexed2_x64
|
||||
|
||||
;
|
||||
; Copyright (c) 2009, Christian Kaiser
|
||||
; All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
;
|
||||
; * Redistributions of source code must retain the above copyright notice,
|
||||
; this list of conditions and the following disclaimer.
|
||||
;
|
||||
; * Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
;
|
||||
; * Neither the name Christian Kaiser nor the names of contributors to this
|
||||
; project may be used to endorse or promote products derived
|
||||
; from this software without specific prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
; THE POSSIBILITY OF SUCH DAMAGE.
|
||||
;
|
||||
PUBLIC sbb_x64
|
||||
PUBLIC subindexed_x64
|
||||
|
||||
;
|
||||
; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm
|
||||
; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm
|
||||
; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program
|
||||
;
|
||||
PUBLIC rcl_x64
|
||||
PUBLIC rcr_x64
|
||||
|
||||
PUBLIC ttmath_adc_x64
|
||||
PUBLIC ttmath_addindexed_x64
|
||||
PUBLIC ttmath_addindexed2_x64
|
||||
PUBLIC ttmath_addvector_x64
|
||||
PUBLIC rcl2_x64
|
||||
PUBLIC rcr2_x64
|
||||
|
||||
PUBLIC ttmath_sbb_x64
|
||||
PUBLIC ttmath_subindexed_x64
|
||||
PUBLIC ttmath_subvector_x64
|
||||
PUBLIC div_x64
|
||||
|
||||
PUBLIC ttmath_rcl_x64
|
||||
PUBLIC ttmath_rcr_x64
|
||||
|
||||
PUBLIC ttmath_rcl2_x64
|
||||
PUBLIC ttmath_rcr2_x64
|
||||
|
||||
PUBLIC ttmath_div_x64
|
||||
|
||||
;
|
||||
; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx
|
||||
;
|
||||
; "rax, rcx, rdx, r8-r11 are volatile."
|
||||
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
|
||||
;
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_adc_x64 PROC
|
||||
adc_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
; r8 = nSize
|
||||
@@ -96,7 +47,7 @@ ttmath_adc_x64 PROC
|
||||
|
||||
ret
|
||||
|
||||
ttmath_adc_x64 ENDP
|
||||
adc_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -104,7 +55,7 @@ ttmath_adc_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_addindexed_x64 PROC
|
||||
addindexed_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
@@ -137,7 +88,7 @@ done_with_cy:
|
||||
|
||||
ret
|
||||
|
||||
ttmath_addindexed_x64 ENDP
|
||||
addindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -145,7 +96,7 @@ ttmath_addindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_addindexed2_x64 PROC
|
||||
addindexed2_x64 PROC
|
||||
|
||||
; rcx = p1 (pointer)
|
||||
; rdx = b (value size)
|
||||
@@ -178,9 +129,7 @@ next:
|
||||
lea rax, [rax+1]
|
||||
ret
|
||||
|
||||
ttmath_addindexed2_x64 ENDP
|
||||
|
||||
|
||||
addindexed2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -188,61 +137,7 @@ ttmath_addindexed2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
|
||||
ttmath_addvector_x64 PROC
|
||||
; rcx = ss1
|
||||
; rdx = ss2
|
||||
; r8 = ss1_size
|
||||
; r9 = ss2_size
|
||||
; [esp+0x28] = result
|
||||
|
||||
mov r10, [esp+028h]
|
||||
sub r8, r9
|
||||
xor r11, r11 ; r11=0, cf=0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
adc rax, qword ptr [rdx + r11 * 8]
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r9
|
||||
jnz loop1
|
||||
|
||||
adc r9, r9 ; r9 has the cf state
|
||||
|
||||
or r8, r8
|
||||
jz done
|
||||
|
||||
neg r9 ; setting cf from r9
|
||||
mov r9, 0 ; don't use xor here (cf is used)
|
||||
loop2:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
adc rax, r9
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r8
|
||||
jnz loop2
|
||||
|
||||
adc r8, r8
|
||||
mov rax, r8
|
||||
|
||||
ret
|
||||
|
||||
done:
|
||||
mov rax, r9
|
||||
ret
|
||||
|
||||
ttmath_addvector_x64 ENDP
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_sbb_x64 PROC
|
||||
sbb_x64 PROC
|
||||
|
||||
; rcx = p1
|
||||
; rdx = p2
|
||||
@@ -266,7 +161,7 @@ ttmath_sbb_x64 PROC
|
||||
|
||||
ret
|
||||
|
||||
ttmath_sbb_x64 ENDP
|
||||
sbb_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -274,7 +169,7 @@ ttmath_sbb_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_subindexed_x64 PROC
|
||||
subindexed_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nPos
|
||||
@@ -291,17 +186,17 @@ loop1:
|
||||
mov r9, 1
|
||||
dec rdx
|
||||
jnz loop1
|
||||
|
||||
mov rax, 1
|
||||
ret
|
||||
jc return_1 ; most of the times, there will be NO carry (I hope)
|
||||
|
||||
done:
|
||||
xor rax, rax
|
||||
ret
|
||||
|
||||
ttmath_subindexed_x64 ENDP
|
||||
|
||||
return_1:
|
||||
mov rax, 1
|
||||
ret
|
||||
|
||||
subindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -309,64 +204,7 @@ ttmath_subindexed_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb'
|
||||
|
||||
ttmath_subvector_x64 PROC
|
||||
; rcx = ss1
|
||||
; rdx = ss2
|
||||
; r8 = ss1_size
|
||||
; r9 = ss2_size
|
||||
; [esp+0x28] = result
|
||||
|
||||
mov r10, [esp+028h]
|
||||
sub r8, r9
|
||||
xor r11, r11 ; r11=0, cf=0
|
||||
|
||||
ALIGN 16
|
||||
loop1:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
sbb rax, qword ptr [rdx + r11 * 8]
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r9
|
||||
jnz loop1
|
||||
|
||||
adc r9, r9 ; r9 has the cf state
|
||||
|
||||
or r8, r8
|
||||
jz done
|
||||
|
||||
neg r9 ; setting cf from r9
|
||||
mov r9, 0 ; don't use xor here (cf is used)
|
||||
loop2:
|
||||
mov rax, qword ptr [rcx + r11 * 8]
|
||||
sbb rax, r9
|
||||
mov qword ptr [r10 + r11 * 8], rax
|
||||
inc r11
|
||||
dec r8
|
||||
jnz loop2
|
||||
|
||||
adc r8, r8
|
||||
mov rax, r8
|
||||
|
||||
ret
|
||||
|
||||
done:
|
||||
mov rax, r9
|
||||
ret
|
||||
|
||||
ttmath_subvector_x64 ENDP
|
||||
|
||||
|
||||
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcl_x64 PROC
|
||||
rcl_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = b
|
||||
; r8 = nLowestBit
|
||||
@@ -387,7 +225,7 @@ loop1:
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcl_x64 ENDP
|
||||
rcl_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -395,7 +233,7 @@ ttmath_rcl_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcr_x64 PROC
|
||||
rcr_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = nLowestBit
|
||||
@@ -414,7 +252,7 @@ loop1:
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcr_x64 ENDP
|
||||
rcr_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -422,7 +260,7 @@ ttmath_rcr_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_div_x64 PROC
|
||||
div_x64 PROC
|
||||
|
||||
; rcx = &Hi
|
||||
; rdx = &Lo
|
||||
@@ -439,7 +277,7 @@ ttmath_div_x64 PROC
|
||||
|
||||
ret
|
||||
|
||||
ttmath_div_x64 ENDP
|
||||
div_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -447,7 +285,7 @@ ttmath_div_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcl2_x64 PROC
|
||||
rcl2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
@@ -490,7 +328,7 @@ loop1:
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
ttmath_rcl2_x64 ENDP
|
||||
rcl2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
@@ -498,7 +336,7 @@ ttmath_rcl2_x64 ENDP
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
ttmath_rcr2_x64 PROC
|
||||
rcr2_x64 PROC
|
||||
; rcx = p1
|
||||
; rdx = nSize
|
||||
; r8 = bits
|
||||
@@ -543,6 +381,6 @@ loop1:
|
||||
|
||||
ret
|
||||
|
||||
ttmath_rcr2_x64 ENDP
|
||||
rcr2_x64 ENDP
|
||||
|
||||
END
|
Reference in New Issue
Block a user