5 Commits
0.9.2 ... 0.8.6

Author SHA1 Message Date
5584adb23d changed version: 0.8.6 now
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/0.8.x@222 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-25 15:55:15 +00:00
a4bb0b6f64 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



git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/0.8.x@215 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-16 21:38:25 +00:00
e046aba6d2 fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/0.8.x@211 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-15 01:40:13 +00:00
5ef27bdbd0 Some fixes from trunk:
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')


git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/0.8.x@204 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-10-07 17:33:03 +00:00
b80f73f16b creating 0.8.x branch of the ttmath library (copied from trunk)
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/0.8.x@166 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-16 20:28:52 +00:00
21 changed files with 1675 additions and 7824 deletions

216
CHANGELOG
View File

@@ -1,219 +1,3 @@
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)
* added: Big::IsInteger()
returns true if the value is integer (without fraction)
(NaN flag is not checked)
* added: global Gamma() function
* 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)

View File

@@ -1,4 +1,4 @@
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

35
README
View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -1,11 +1,11 @@
/*
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* 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,12 @@
\brief Mathematic functions.
*/
#include "ttmathtypes.h"
#include <string>
#include <vector>
#include <list>
#include <map>
#include "ttmathtypes.h"
#include "ttmathmisc.h"
namespace ttmath
@@ -74,7 +73,6 @@ 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;
// number of parameters required by the function
@@ -114,8 +112,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 std::string & name)
{
if( name.empty() )
return false;
@@ -123,7 +120,7 @@ public:
if( !CorrectCharacter(name[0], false) )
return false;
typename string_type::const_iterator i = name.begin();
std::string::const_iterator i=name.begin();
for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) )
@@ -148,27 +145,6 @@ 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
*/
@@ -189,27 +165,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
*/
@@ -267,28 +222,6 @@ 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
*/
@@ -320,29 +253,6 @@ 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
*/
@@ -362,27 +272,6 @@ 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
*/
@@ -405,28 +294,6 @@ 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)
@@ -450,27 +317,6 @@ 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
@@ -496,29 +342,6 @@ 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
@@ -545,31 +368,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 +380,6 @@ public:
private:
Table table;
std::string str_tmp1, str_tmp2;
}; // end of class Objects
@@ -629,11 +426,11 @@ 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()
{
buffer_max_size = 15;
buffer_max_size = 10;
}
@@ -690,118 +487,10 @@ public:
return false;
}
/*!
this methods deletes an item
we assume that there is only one item with the 'key'
(this methods removes the first one)
*/
bool Remove(const ValueType & key)
{
typename buffer_type::iterator i = buffer.begin();
for( ; i != buffer.end() ; ++i )
{
if( i->key == key )
{
buffer.erase(i);
return true;
}
}
return false;
}
}; // end of class History
/*!
this is an auxiliary class used when calculating Gamma() or Factorial()
in multithreaded environment you can provide an object of this class to
the Gamma() or Factorial() function, e.g;
typedef Big<1, 3> MyBig;
MyBig x = 123456;
CGamma<MyBig> cgamma;
std::cout << Gamma(x, cgamma);
each thread should have its own CGamma<> object
in a single-thread environment a CGamma<> object is a static variable
in a second version of Gamma() and you don't have to explicitly use it, e.g.
typedef Big<1, 3> MyBig;
MyBig x = 123456;
std::cout << Gamma(x);
*/
template<class ValueType>
struct CGamma
{
/*!
this table holds factorials
1
1
2
6
24
120
720
.......
*/
std::vector<ValueType> fact;
/*!
this table holds Bernoulli numbers
1
-0.5
0.166666666666666666666666667
0
-0.0333333333333333333333333333
0
0.0238095238095238095238095238
0
-0.0333333333333333333333333333
0
0.075757575757575757575757576
.....
*/
std::vector<ValueType> bern;
/*!
here we store some calculated values
(this is for speeding up, if the next argument of Gamma() or Factorial()
is in the 'history' then the result we are not calculating but simply
return from the 'history' object)
*/
History<ValueType> history;
/*!
this method prepares some coefficients: factorials and Bernoulli numbers
stored in 'fact' and 'bern' objects
how many values should be depends on the size of the mantissa - if
the mantissa is larger then we must calculate more values
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
we have to calculate about 30 values (the size of fact and bern will be 30),
and for a 2048 bits mantissa we have to calculate 306 coefficients
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()
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
*/
void InitAll();
// definition is in ttmath.h
};
} // namespace

View File

@@ -1,11 +1,11 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* 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
@@ -45,14 +45,13 @@
\brief A mathematical parser
*/
#include <cstdio>
#include <fstream>
#include <vector>
#include <map>
#include <set>
#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,12 +131,13 @@ 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
{
private:
/*!
@@ -159,20 +160,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; }
void SetType(Type t)
{
type = t;
assoc = non_right;
switch( type )
{
@@ -206,7 +201,6 @@ private:
case pow:
priority = 14;
assoc = right;
break;
default:
@@ -215,7 +209,7 @@ private:
}
}
MatOperator(): type(none), priority(0), assoc(non_right)
MatOperator(): type(none), priority(0)
{
}
@@ -223,7 +217,7 @@ private:
Type type;
int priority;
Assoc assoc;
}; // end of MatOperator class
@@ -282,16 +276,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,6 +311,7 @@ ErrorCode error;
/*!
pointer to the currently reading char
when an error has occured it may be used to count the index of the wrong character
*/
const char * pstring;
@@ -438,44 +426,10 @@ VariablesTable variables_table;
/*!
some coefficients used when calculating the gamma (or factorial) function
you can't calculate the factorial if the argument is greater than 'factorial_max'
default value is zero which means there are not any limitations
*/
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;
ValueType factorial_max;
/*!
@@ -551,8 +505,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,
FunctionLocalVariables * local_variables = 0)
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0)
{
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
RecurrenceParsingVariablesOrFunction_AddName(variable, name);
@@ -606,7 +559,6 @@ bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType &
return false;
result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
calculated = true;
return true;
}
@@ -655,7 +607,6 @@ ValueType result;
Error( err_unknown_variable );
(result.*(i->second))();
calculated = true;
return result;
}
@@ -723,20 +674,6 @@ return result;
}
void Gamma(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
ErrorCode err;
result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok)
Error( err );
}
/*!
factorial
result = 1 * 2 * 3 * 4 * .... * x
@@ -748,7 +685,10 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
ErrorCode err;
result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
if( !factorial_max.IsZero() && stack[sindex].value > factorial_max )
Error( err_too_big_factorial );
result = ttmath::Factorial(stack[sindex].value, &err, pstop_calculating);
if(err != err_ok)
Error( err );
@@ -1404,45 +1344,6 @@ 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)
{
char buf[30]; // char, not wchar_t
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
@@ -1467,23 +1368,20 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
if( amount_of_args > 0 )
{
char buffer[30];
char buffer[20];
// x = x1
buffer[0] = 'x';
buffer[1] = 0;
sprintf(buffer,"x");
local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
for(int i=0 ; i<amount_of_args ; ++i)
{
buffer[0] = 'x';
Sprintf(buffer+1, i+1);
sprintf(buffer,"x%d",i+1);
local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
}
}
stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
calculated = true;
return true;
}
@@ -1516,7 +1414,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;
}
@@ -1531,14 +1428,10 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
*/
void InsertFunctionToTable(const 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(std::string(function_name), pf));
}
/*!
inserting a function to the variables' table
(this function returns value of variable)
@@ -1548,10 +1441,7 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
*/
void InsertVariableToTable(const 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(std::string(variable_name), pf));
}
@@ -1560,7 +1450,9 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
*/
void CreateFunctionsTable()
{
InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma);
/*
names of functions should consist of small letters
*/
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
@@ -1619,7 +1511,6 @@ void CreateFunctionsTable()
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
InsertFunctionToTable("frac", &Parser<ValueType>::Frac);
}
@@ -1628,6 +1519,9 @@ void CreateFunctionsTable()
*/
void CreateVariablesTable()
{
/*
names of variables should consist of small letters
*/
InsertVariableToTable("pi", &ValueType::SetPi);
InsertVariableToTable("e", &ValueType::SetE);
}
@@ -1751,8 +1645,6 @@ return is_it_name_of_function;
}
/*!
we're reading a numerical value directly from the string
*/
@@ -1760,14 +1652,8 @@ void ReadValue(Item & result, int reading_base)
{
const 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);
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
pstring = new_stack_pointer;
if( carry )
@@ -1778,18 +1664,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 +1823,9 @@ return 0;
}
void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type)
{
operators_table.insert( std::make_pair(std::string(name), type) );
operators_table.insert( std::make_pair(name, type) );
}
@@ -1923,19 +1834,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(std::string("||"), MatOperator::lor);
InsertOperatorToTable(std::string("&&"), MatOperator::land);
InsertOperatorToTable(std::string("!="), MatOperator::neq);
InsertOperatorToTable(std::string("=="), MatOperator::eq);
InsertOperatorToTable(std::string(">="), MatOperator::get);
InsertOperatorToTable(std::string("<="), MatOperator::let);
InsertOperatorToTable(std::string(">"), MatOperator::gt);
InsertOperatorToTable(std::string("<"), MatOperator::lt);
InsertOperatorToTable(std::string("-"), MatOperator::sub);
InsertOperatorToTable(std::string("+"), MatOperator::add);
InsertOperatorToTable(std::string("/"), MatOperator::div);
InsertOperatorToTable(std::string("*"), MatOperator::mul);
InsertOperatorToTable(std::string("^"), MatOperator::pow);
}
@@ -1950,7 +1861,7 @@ bool IsSubstring(const std::string & str1, const std::string & str2)
if( str2.length() > str1.length() )
return false;
for(typename std::string::size_type i=0 ; i<str2.length() ; ++i)
for(std::string::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] )
return false;
@@ -1992,31 +1903,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 +1915,6 @@ int ReadOperator(Item & result)
{
SkipWhiteCharacters();
if( *pstring == '%' )
OperatorPercentage();
if( *pstring == 0 )
return 1;
else
@@ -2042,7 +1924,7 @@ int ReadOperator(Item & result)
++pstring;
}
else
if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) )
if( *pstring == ';' )
{
result.type = Item::semicolon;
++pstring;
@@ -2072,9 +1954,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 +2017,7 @@ uint res;
break;
default:
/*
on the stack left an unknown operator but we had to recognize its before
@@ -2168,17 +2049,7 @@ void TryRollingUpStackWithOperatorPriority()
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-3].moperator.GetPriority() >= stack[stack_index-1].moperator.GetPriority()
)
{
MakeStandardMathematicOperation(stack[stack_index-4].value,
@@ -2533,10 +2404,7 @@ Parser(): default_stack_size(100)
base = 10;
deg_rad_grad = 1;
error = err_ok;
group = 0;
comma = '.';
comma2 = ',';
param_sep = 0;
factorial_max.SetZero();
CreateFunctionsTable();
CreateVariablesTable();
@@ -2555,11 +2423,8 @@ 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;
factorial_max = p.factorial_max;
/*
we don't have to call 'CreateFunctionsTable()' etc.
@@ -2587,7 +2452,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)
{
@@ -2643,36 +2507,14 @@ void SetFunctions(const Objects * pf)
/*!
setting the group character
default zero (not used)
you will not be allowed to calculate the factorial
if its argument is greater than 'm'
there'll be: ErrorCode::err_too_big_factorial
default 'factorial_max' is zero which means you can calculate what you want to
*/
void SetGroup(int g)
void SetFactorialMax(const ValueType & m)
{
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;
factorial_max = m;
}
@@ -2684,7 +2526,6 @@ ErrorCode Parse(const char * str)
stack_index = 0;
pstring = str;
error = err_ok;
calculated = false;
stack.resize( default_stack_size );
@@ -2695,7 +2536,6 @@ ErrorCode Parse(const char * str)
catch(ErrorCode c)
{
error = c;
calculated = false;
}
NormalizeStack();
@@ -2704,61 +2544,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;
}
};
} // namespace

View File

@@ -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

View File

@@ -1,11 +1,11 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* 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
@@ -54,97 +54,63 @@
#include <stdexcept>
#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 2
#define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 6
#define TTMATH_PRERELEASE_VER 0
/*!
you can define a platform explicitly by defining either
TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro
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_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
*/
#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
#ifndef TTMATH_RELEASE
#define TTMATH_DEBUG
#endif
#endif
/*!
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
*/
#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 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 by default use no asm version
*/
#define TTMATH_NOASM
#endif
#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,18 +121,17 @@ namespace ttmath
typedef signed int sint;
/*!
on 32 bit platform ulint and slint will be equal 64 bits
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
but only on a 32bit platform
*/
#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
#ifdef TTMATH_NOASM
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
/*!
@@ -192,30 +157,22 @@ namespace ttmath
*/
#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)
#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 */
typedef unsigned __int64 uint;
typedef signed __int64 sint;
#else
typedef unsigned long uint;
typedef signed 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
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
*/
//typedef unsigned long long int ulint;
/*!
how many bits there are in the uint type
@@ -240,28 +197,27 @@ namespace ttmath
*/
#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)
#endif
}
#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
/*!
characters which represent the comma operator
#endif
#endif
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 ','
@@ -286,54 +242,16 @@ 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
#else
#ifdef __GNUC__
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
#else
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
#endif
#endif
/*!
this is a special value used when calculating the Gamma(x) function
if x is greater than this value then the Gamma(x) will be calculated using
some kind of series
don't use smaller values than about 100
*/
#define TTMATH_GAMMA_BOUNDARY 2000
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
*/
@@ -364,132 +282,11 @@ namespace ttmath
err_object_exists,
err_unknown_object,
err_still_calculating,
err_in_short_form_used_function,
err_percent_from
err_too_big_factorial,
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;
/*!
*/
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_exp = 0;
}
};
/*!
this simple class can be used in multithreading model
(you can write your own class derived from this one)
@@ -542,13 +339,26 @@ 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 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
{
@@ -578,7 +388,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 with
the name and the line of a file where the macro TTMATH_ASSERT
was used)
*/
@@ -604,21 +414,8 @@ 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__)
@@ -646,22 +443,18 @@ namespace ttmath
#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);
#define TTMATH_LOG(msg) \
PrintLog(msg, std::cout);
#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
} // namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* 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
@@ -51,56 +51,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 +95,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 +131,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 +184,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 +224,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 +232,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 +273,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 +311,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 +351,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 +385,7 @@ namespace ttmath
c = new_c;
}
TTMATH_LOGC("UInt::Rcl2_one", c)
TTMATH_LOG("UInt::Rcl2_one")
return c;
}
@@ -480,9 +424,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 +462,7 @@ namespace ttmath
c = new_c;
}
TTMATH_LOGC("UInt::Rcl2", (c & 1))
TTMATH_LOG("UInt::Rcl2")
return (c & 1);
}
@@ -559,19 +501,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 +533,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;
@@ -821,11 +741,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;

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
@@ -60,50 +60,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()
{
#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
@@ -196,7 +152,7 @@ namespace ttmath
: "cc", "memory" );
#endif
TTMATH_LOGC("UInt::Add", c)
TTMATH_LOG("UInt::Add")
return c;
}
@@ -297,7 +253,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::AddInt", c)
TTMATH_LOG("UInt::AddInt")
return c;
}
@@ -418,7 +374,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::AddTwoInts", c)
TTMATH_LOG("UInt::AddTwoInts")
return c;
}
@@ -550,7 +506,7 @@ namespace ttmath
#endif
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
TTMATH_LOG("UInt::AddVector")
return c;
}
@@ -638,7 +594,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Sub", c)
TTMATH_LOG("UInt::Sub")
return c;
}
@@ -740,7 +696,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::SubInt", c)
TTMATH_LOG("UInt::SubInt")
return c;
}
@@ -878,7 +834,7 @@ namespace ttmath
#endif
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
TTMATH_LOG("UInt::SubVector")
return c;
}
@@ -956,7 +912,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcl2_one", c)
TTMATH_LOG("UInt::Rcl2_one")
return c;
}
@@ -1028,7 +984,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcr2_one", c)
TTMATH_LOG("UInt::Rcr2_one")
return c;
}
@@ -1162,7 +1118,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcl2", c)
TTMATH_LOG("UInt::Rcl2")
return c;
}
@@ -1296,7 +1252,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcr2", c)
TTMATH_LOG("UInt::Rcr2")
return c;
}
@@ -1353,50 +1309,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;
}
/*!

View File

@@ -1,11 +1,11 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* 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
@@ -51,77 +51,10 @@
this file is included at the end of ttmathuint.h
*/
#ifndef __GNUC__
#include <intrin.h>
#endif
namespace ttmath
{
#ifndef __GNUC__
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);
};
#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,7 +83,7 @@ namespace ttmath
// this algorithm doesn't require it
#ifndef __GNUC__
c = ttmath_adc_x64(p1,p2,b,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
@@ -180,7 +113,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Add", c)
TTMATH_LOG("UInt::Add")
return c;
}
@@ -217,10 +150,9 @@ namespace ttmath
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__
c = ttmath_addindexed_x64(p1,b,index,value);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2;
@@ -247,7 +179,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::AddInt", c)
TTMATH_LOG("UInt::AddInt")
return c;
}
@@ -296,10 +228,9 @@ namespace ttmath
TTMATH_ASSERT( index < value_size - 1 )
#ifndef __GNUC__
c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2;
@@ -330,7 +261,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::AddTwoInts", c)
TTMATH_LOG("UInt::AddTwoInts")
return c;
}
@@ -362,16 +293,15 @@ namespace ttmath
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint rest = ss1_size - ss2_size;
uint c;
#ifndef __GNUC__
c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy1, dummy2, dummy3;
uint rest = ss1_size - ss2_size;
// this part should be compiled with gcc
@@ -413,13 +343,15 @@ namespace ttmath
#endif
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
TTMATH_LOG("UInt::AddVector")
return c;
}
/*!
this method's subtracting ss2 from the 'this' and subtracting
carry if it has been defined
@@ -437,14 +369,14 @@ namespace ttmath
uint * p1 = table;
const uint * p2 = ss2.table;
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
#ifndef __GNUC__
c = ttmath_sbb_x64(p1,p2,b,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2;
@@ -469,13 +401,12 @@ namespace ttmath
#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)
@@ -501,17 +432,15 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__
c = ttmath_subindexed_x64(p1,b,index,value);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
"subq %%rdx, %%rcx \n"
@@ -535,12 +464,14 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::SubInt", c)
TTMATH_LOG("UInt::SubInt")
return c;
}
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
@@ -567,20 +498,20 @@ namespace ttmath
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint rest = ss1_size - ss2_size;
uint c;
#ifndef __GNUC__
c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
// the asm code is nearly the same as in AddVector
// only two instructions 'adc' are changed to 'sbb'
/*
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"
@@ -620,12 +551,13 @@ namespace ttmath
#endif
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
TTMATH_LOG("UInt::SubVector")
return c;
}
/*!
this method moves all bits into the left hand side
return value <- this <- c
@@ -648,10 +580,9 @@ namespace ttmath
#ifndef __GNUC__
c = ttmath_rcl_x64(p1,b,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2;
@@ -675,7 +606,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcl2_one", c)
TTMATH_LOG("UInt::Rcl2_one")
return c;
}
@@ -703,10 +634,9 @@ namespace ttmath
#ifndef __GNUC__
c = ttmath_rcr_x64(p1,b,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy;
@@ -728,7 +658,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcr2_one", c)
TTMATH_LOG("UInt::Rcr2_one")
return c;
}
@@ -759,10 +689,9 @@ namespace ttmath
#ifndef __GNUC__
c = ttmath_rcl2_x64(p1,b,bits,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2, dummy3;
@@ -802,7 +731,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcl2", c)
TTMATH_LOG("UInt::Rcl2")
return c;
}
@@ -829,16 +758,14 @@ namespace ttmath
sint b = value_size;
uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__
c = ttmath_rcr2_x64(p1,b,bits,c);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__(
"movq %%rcx, %%rsi \n"
@@ -878,7 +805,7 @@ namespace ttmath
#endif
TTMATH_LOGC("UInt::Rcr2", c)
TTMATH_LOG("UInt::Rcr2")
return c;
}
@@ -897,17 +824,9 @@ namespace ttmath
#ifndef __GNUC__
unsigned long nIndex = 0;
if( _BitScanReverse64(&nIndex,x) == 0 )
result = -1;
else
result = nIndex;
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
uint dummy;
@@ -928,50 +847,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 +870,9 @@ namespace ttmath
#ifndef __GNUC__
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
__asm__ (
@@ -1050,12 +924,10 @@ namespace ttmath
uint result1_;
uint result2_;
#ifndef __GNUC__
result1_ = _umul128(a,b,&result2_);
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
__asm__ (
@@ -1109,16 +981,10 @@ namespace ttmath
TTMATH_ASSERT( c != 0 )
#ifndef __GNUC__
ttmath_div_x64(&a,&b,c);
r_ = a;
rest_ = b;
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#ifdef __GNUC__
__asm__ (
@@ -1136,6 +1002,7 @@ namespace ttmath
*rest = rest_;
}
} //namespace

View File

@@ -1,548 +0,0 @@
;
; This file is a part of TTMath Bignum Library
; and is distributed under the (new) BSD licence.
; Author: Christian Kaiser <chk@online.de>
;
;
; 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.
;
;
; 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 ttmath_adc_x64
PUBLIC ttmath_addindexed_x64
PUBLIC ttmath_addindexed2_x64
PUBLIC ttmath_addvector_x64
PUBLIC ttmath_sbb_x64
PUBLIC ttmath_subindexed_x64
PUBLIC ttmath_subvector_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
; rcx = p1
; rdx = p2
; r8 = nSize
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
adc qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
ttmath_adc_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_addindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
xor rax, rax ; rax = result
sub rdx, r8 ; rdx = remaining count of uints
add qword ptr [rcx + r8 * 8], r9
jc next1
ret
next1:
mov r9, 1
ALIGN 16
loop1:
dec rdx
jz done_with_cy
lea r8, [r8+1]
add qword ptr [rcx + r8 * 8], r9
jc loop1
ret
done_with_cy:
lea rax, [rax+1] ; rax = 1
ret
ttmath_addindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_addindexed2_x64 PROC
; rcx = p1 (pointer)
; rdx = b (value size)
; r8 = nPos
; r9 = nValue1
; [esp+0x28] = nValue2
xor rax, rax ; return value
mov r11, rcx ; table
sub rdx, r8 ; rdx = remaining count of uints
mov r10, [esp+028h] ; r10 = nValue2
add qword ptr [r11 + r8 * 8], r9
lea r8, [r8+1]
lea rdx, [rdx-1]
adc qword ptr [r11 + r8 * 8], r10
jc next
ret
ALIGN 16
loop1:
lea r8, [r8+1]
add qword ptr [r11 + r8 * 8], 1
jc next
ret
next:
dec rdx ; does not modify CY too...
jnz loop1
lea rax, [rax+1]
ret
ttmath_addindexed2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
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
; rcx = p1
; rdx = p2
; r8 = nCount
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
sbb qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
ttmath_sbb_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_subindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
sub rdx, r8 ; rdx = remaining count of uints
ALIGN 16
loop1:
sub qword ptr [rcx + r8 * 8], r9
jnc done
lea r8, [r8+1]
mov r9, 1
dec rdx
jnz loop1
mov rax, 1
ret
done:
xor rax, rax
ret
ttmath_subindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
; 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
; rcx = p1
; rdx = b
; r8 = nLowestBit
mov r11, rcx ; table
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcl qword ptr [r11 + r10 * 8], 1
lea r10, [r10+1]
dec rdx
jnz loop1
setc al
movzx rax, al
ret
ttmath_rcl_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcr_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nLowestBit
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcr qword ptr -8[rcx + rdx * 8], 1
dec rdx
jnz loop1
setc al
movzx rax, al
ret
ttmath_rcr_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_div_x64 PROC
; rcx = &Hi
; rdx = &Lo
; r8 = nDiv
mov r11, rcx
mov r10, rdx
mov rdx, qword ptr [r11]
mov rax, qword ptr [r10]
div r8
mov qword ptr [r10], rdx ; remainder
mov qword ptr [r11], rax ; value
ret
ttmath_div_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcl2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shr r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rax ; r9 = index (0..nSize-1)
ALIGN 16
loop1:
rol qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9+1]
dec rdx
jnz loop1
and rax, 1
pop rbx
ret
ttmath_rcl2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
ttmath_rcr2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shl r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rdx ; r9 = index (0..nSize-1)
lea r9, [r9-1]
ALIGN 16
loop1:
ror qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9-1]
dec rdx
jnz loop1
rol rax, 1
and rax, 1
pop rbx
ret
ttmath_rcr2_x64 ENDP
END