21 Commits
0.9.0 ... chk

Author SHA1 Message Date
Christian Kaiser
51e938eaa7 - update to current root trunc's version
- update to root trunc's UNICODE support

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@182 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-29 10:46:48 +00:00
Christian Kaiser
e102086f80 - fixed a bug in 64 bit ASM for MSVC
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@181 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-28 16:34:04 +00:00
Christian Kaiser
51b2c974a1 - changed "AboutEqualWithoutSign()" to "AboutEqual()" because we need to take the sign into account!
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@173 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-26 15:24:27 +00:00
Christian Kaiser
5597373093 - "streamlined" ttmathconfig.h a bit:
a) Unicode support if TTMATH_USE_WCHAR is set (compiler must know wchar_t etc, of course)
  b) threading synchonisation uses WIN32 instead of __MSVC__ define, as this is OS dependent, not compiler dependent

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@172 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-26 11:14:51 +00:00
Christian Kaiser
de58378488 - added AboutEqualWithoutSign() to big<> to allow 'suppression' of some unexpected results (that are perfectly logical though, given the possibly unrepresentable nature of binary representation of decimals) like
big<>("10.456466") * 2 == big<>("20.912932")

resulting in FALSE result.

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@171 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-25 14:11:17 +00:00
Christian Kaiser
de64608eba Merged against the current original ttmath trunk
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@170 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-25 11:07:55 +00:00
Christian Kaiser
be8913866a - 32 bit ASM code and ASSERTS did not work as the ASM code put its result in EAX, but the ASSERT afterwards did destroy the EAX's contents, of course.
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@155 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-28 14:42:19 +00:00
Christian Kaiser
b31d34ebdd - fixed a bug in ttmath.g (missing closing brace in Cos())
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@154 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-28 11:52:31 +00:00
Christian Kaiser
be821b59dd - optimizations
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@153 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-28 11:31:29 +00:00
Christian Kaiser
de1e7ac957 more optimizations for MSVC assembler (parallelism, prefetch optimization, loop alignment, ...)
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@151 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-20 08:48:51 +00:00
Christian Kaiser
fdc292e91a current chk version - too many changes on both sides for now ;-(
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@150 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-19 10:50:41 +00:00
Christian Kaiser
9b576ddbe2 - corrected 64 bit assembler code (ebx was not preserved)
- minor optimization

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@147 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-15 14:42:43 +00:00
Christian Kaiser
a8c3a506ea MSVC ASM improvements (no register saves necessary, as this is done automatically by the C compiler)
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@146 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-14 12:59:12 +00:00
Christian Kaiser
3ba94dca90 git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@145 e52654a7-88a9-db11-a3e9-0013d4bc506e 2009-05-11 12:30:05 +00:00
Christian Kaiser
cae50cd425 - merged Tomasz' version 0.8.5
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@144 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-11 12:25:25 +00:00
Christian Kaiser
00e39d3608 added thread-safety to static history buffers (factorial and logarithm) for MSVC
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@135 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-07 11:37:10 +00:00
Christian Kaiser
37379d2f1f - fulfills test file log diff (32 and 64 bit)
- macro for issuing the debug output to something else than std::out if specified


git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@134 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-07 09:33:57 +00:00
Christian Kaiser
d7b67e4d47 - minor changes for ASSERT macros
- some more "unification" of 32 and 64 bits in typedefs
- use of 'char' instead of 'unsigned char', as I may hope that 'char' usually is set to 'unsigned' in most development environments

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@133 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-06 15:47:15 +00:00
Christian Kaiser
c91bd24e98 - support for MS specific code (__int64 etc) and warnings
- support for AMD64 assembler (not thoroughly tested)
- support for UNICODE I/O (strings and streams)

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@132 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-06 15:11:29 +00:00
Christian Kaiser
cbc12db22f dummy commit (user/password checking)
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@131 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-06 13:24:00 +00:00
3e9bd5b093 creating a chk branch for ChristianK
git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@130 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-06 13:16:56 +00:00
16 changed files with 16636 additions and 19099 deletions

121
CHANGELOG
View File

@@ -1,5 +1,15 @@
Version 0.9.0 (2009.11.25): Version 0.9.0 prerelease (2009.07.16):
* added: support for wide characters (wchar_t, std::wstring) * added: support for wide characters (wchar_t)
wide characters are used when macro TTMATH_USE_WCHAR is defined
this macro is defined automatically when there is macro UNICODE or _UNICODE defined
some types have been changed
char -> tt_char
std::string -> tt_string
std::ostringstream -> tt_ostringstream
std::ostream -> tt_ostream
std::istream -> tt_istream
normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on)
(all typedef's are in ttmathtypes.h)
* added: Big::IsInteger() * added: Big::IsInteger()
returns true if the value is integer (without fraction) returns true if the value is integer (without fraction)
(NaN flag is not checked) (NaN flag is not checked)
@@ -7,117 +17,10 @@ Version 0.9.0 (2009.11.25):
* added: gamma() function to the parser * added: gamma() function to the parser
* added: CGamma<ValueType> class * added: CGamma<ValueType> class
is used with Gamma() and Factorial() in multithreaded environment 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: 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 * removed: Parser<>::SetFactorialMax() method
the factorial() is such a fast now that we don't need the method longer the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial * removed: ErrorCode::err_too_big_factorial
* removed: macros: TTMATH_COMMA_CHARACTER_1 and TTMATH_COMMA_CHARACTER_2
the comma characters we have in Conv struct now
Version 0.8.6 (2009.10.25):
* fixed: UInt::SetBitInWord(uint & value, uint bit) set 1 if the bit was
equal 1 (should be set 2)
this affected only no-asm parts - when macro TTMATH_NOASM was defined
* fixed: UInt<value_size>::MulInt(uint ss2)
there was a buffer overflow when value_size was equal 1
* fixed: UInt::AddVector() and UInt::SubVector() didn't want to compile
when macro TTMATH_NOASM was defined
* fixed: Big::operator>> didn't correctly recognize values in scientific mode (with 'e' character)
* fixed: Int::FromString(const tt_string & s, uint b = 10)
didn't use 'b' (always was '10')
* fixed: buffer overflow in Big::ToInt(Int<int_size> & result)
* fixed: powering algorithm in:
UInt::Pow(UInt<value_size> pow)
Big::Pow(UInt<pow_size> pow)
Big::PowUInt(Big<exp, man> pow)
when 'pow' was sufficient large the algorithm returned carry
but the result could have been calculated correctly
Version 0.8.5 (2009.06.16): Version 0.8.5 (2009.06.16):

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 TTMath is a small library which allows one to perform arithmetic operations
with big unsigned integer, big signed integer and big floating point numbers. with big unsigned integer, big signed integer and big floating point
It provides standard mathematical operations like adding, subtracting, numbers. It provides standard mathematical operations like adding,
multiplying, dividing. With the library also goes a mathematical parser to subtracting, multiplying, dividing etc. With the library also goes
help you solving mathematical expressions. 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 TTMath is developed under the BSD licence which means that it is free
both personal and commercial use. 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 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 way as the standard types like int, float, etc. It does not need to be
first because the whole library is written as the C++ templates. This means compiled first because the whole library is written as the C++ templates.
only C++ developers can use this library and one thing they have to do is This means only C++ developers can use this library and one thing they have
to use 'include' directive of the preprocessor. How big the values can be to do is to use 'include' directive of the preprocessor. How big the
is set at compile time. values can be is set directly in the source code by the programmer.
Author: Tomasz Sowa <t.sowa@ttmath.org> Author: Tomasz Sowa <t.sowa@ttmath.org>
WWW: http://www.ttmath.org Project pages: http://www.ttmath.org
http://sourceforge.net/projects/ttmath
Contributors:
Christian Kaiser <chk@online.de>

View File

@@ -48,13 +48,8 @@
#ifdef _MSC_VER #ifdef _MSC_VER
//warning C4127: conditional expression is constant //warning C4127: conditional expression is constant
#pragma warning( disable: 4127 ) #pragma warning( disable: 4127 )
//warning C4702: unreachable code
#pragma warning( disable: 4702 )
//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( disable: 4800 )
#endif #endif
#include "ttmathbig.h" #include "ttmathbig.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"
@@ -69,6 +64,7 @@ namespace ttmath
*/ */
/* /*
* *
* functions for rounding * functions for rounding
@@ -1845,7 +1841,20 @@ namespace ttmath
return ValueType(); // NaN is set by default return ValueType(); // NaN is set by default
} }
uint c = x.Sqrt(); if( x.IsZero() )
{
// Sqrt(0) = 0
if( err )
*err = err_ok;
return x;
}
ValueType pow;
pow.Set05();
// PowFrac can return only a carry because x is greater than zero
uint c = x.PowFrac(pow);
if( err ) if( err )
*err = c ? err_overflow : err_ok; *err = c ? err_overflow : err_ok;
@@ -1926,20 +1935,6 @@ namespace ttmath
} }
template<class ValueType>
bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err)
{
if( index == 2 )
{
x = Sqrt(x, err);
return true;
}
return false;
}
template<class ValueType> template<class ValueType>
bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
{ {
@@ -2009,38 +2004,9 @@ namespace ttmath
return false; return false;
} }
template<class ValueType>
uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index)
{
if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() )
return 0;
// old_x is integer,
// x is not integer,
// index is relatively small (index.exponent<0 or index.exponent<=0)
// (because we're using a special powering algorithm Big::PowUInt())
uint c = 0;
ValueType temp(x);
c += temp.Round();
ValueType temp_round(temp);
c += temp.PowUInt(index);
if( temp == old_x )
x = temp_round;
return (c==0)? 0 : 1;
} }
} // namespace auxiliaryfunctions
/*! /*!
indexth Root of x indexth Root of x
index must be integer and not negative <0;1;2;3....) index must be integer and not negative <0;1;2;3....)
@@ -2071,33 +2037,30 @@ namespace ttmath
if( RootCheckIndexSign(x, index, err) ) return x; if( RootCheckIndexSign(x, index, err) ) return x;
if( RootCheckIndexZero(x, index, err) ) return x; if( RootCheckIndexZero(x, index, err) ) return x;
if( RootCheckIndexOne ( index, err) ) return x; if( RootCheckIndexOne ( index, err) ) return x;
if( RootCheckIndexTwo (x, index, err) ) return x;
if( RootCheckIndexFrac(x, index, err) ) return x; if( RootCheckIndexFrac(x, index, err) ) return x;
if( RootCheckXZero (x, err) ) return x; if( RootCheckXZero (x, err) ) return x;
// index integer and index!=0 // index integer and index!=0
// x!=0 // x!=0
ValueType old_x(x); uint c = 0;
bool change_sign; bool change_sign;
if( RootCheckIndex(x, index, err, &change_sign ) ) return x; if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
ValueType temp; ValueType newindex;
uint c = 0; newindex.SetOne();
c += newindex.Div(index);
// we're using the formula: root(x ; n) = exp( ln(x) / n ) c += x.PowFrac(newindex); // here can only be a carry
c += temp.Ln(x);
c += temp.Div(index);
c += x.Exp(temp);
if( change_sign ) if( change_sign )
{ {
// x is different from zero // the value of x should be different from zero
// (x is actually tested by RootCheckXZero)
TTMATH_ASSERT( x.IsZero() == false )
x.SetSign(); x.SetSign();
} }
c += RootCorrectInteger(old_x, x, index);
if( err ) if( err )
*err = c ? err_overflow : err_ok; *err = c ? err_overflow : err_ok;
@@ -2647,6 +2610,7 @@ namespace ttmath
ValueType result; ValueType result;
ErrorCode err_tmp; ErrorCode err_tmp;
if( n.IsNan() ) if( n.IsNan() )
{ {
if( err ) if( err )
@@ -2655,6 +2619,8 @@ namespace ttmath
return result; // NaN is set by default return result; // NaN is set by default
} }
TTMATH_USE_THREADSAFE_OBJ(cgamma.history);
if( cgamma.history.Get(n, result, err_tmp) ) if( cgamma.history.Get(n, result, err_tmp) )
{ {
if( err ) if( err )
@@ -2719,9 +2685,7 @@ namespace ttmath
x! = gamma(x+1) x! = gamma(x+1)
*/ */
template<class ValueType> template<class ValueType>
ValueType Factorial2(ValueType x, ValueType Factorial2(ValueType x, CGamma<ValueType> * cgamma = 0, ErrorCode * err = 0,
CGamma<ValueType> * cgamma = 0,
ErrorCode * err = 0,
const volatile StopCalculating * stop = 0) const volatile StopCalculating * stop = 0)
{ {
ValueType result, one; ValueType result, one;
@@ -2755,7 +2719,7 @@ namespace ttmath
it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial()
e.g. e.g.
typedef Big<1,2> MyBig; typedef Big<1,2> MyBig;
MyBig x=234, y=54345; MyBig x=234, y=345.53;
CGamma<MyBig> cgamma; CGamma<MyBig> cgamma;
std::cout << Factorial(x, cgamma) << std::endl; std::cout << Factorial(x, cgamma) << std::endl;
std::cout << Factorial(y, cgamma) << std::endl; std::cout << Factorial(y, cgamma) << std::endl;
@@ -2782,7 +2746,7 @@ namespace ttmath
template<class ValueType> template<class ValueType>
ValueType Factorial(const ValueType & x, ErrorCode * err = 0) ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
{ {
return auxiliaryfunctions::Factorial2(x, (CGamma<ValueType>*)0, err, 0); return auxiliaryfunctions::Factorial2(x, 0, err, 0);
} }
@@ -2824,12 +2788,8 @@ namespace ttmath
#ifdef _MSC_VER #ifdef _MSC_VER
//warning C4127: conditional expression is constant
#pragma warning( default: 4127 ) #pragma warning( default: 4127 )
//warning C4702: unreachable code //warning C4127: conditional expression is constant
#pragma warning( default: 4702 )
//warning C4800: forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( default: 4800 )
#endif #endif
#endif #endif

File diff suppressed because it is too large Load Diff

110
ttmath/ttmathconfig.h Normal file
View File

@@ -0,0 +1,110 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the PNG licence.
* Author: Christian Kaiser <chk@online.de>
*/
/*
Copyright (c) 2009 Christian Kaiser
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef headerfilettmathconfig
#define headerfilettmathconfig
#pragma once
#include <sstream>
namespace ttmath
{
#if defined(WIN32)
#include <windows.h>
#if defined(_MT)
class clsCrit
{
private:
mutable CRITICAL_SECTION _Crit;
clsCrit(const clsCrit&) // inhibit copy (easy mistake to do; use clsCritObj instead!!!)
{
}
clsCrit& operator=(const clsCrit& rhs); // inhibit assignment
public:
clsCrit(void)
{
InitializeCriticalSection(&_Crit);
}
virtual ~clsCrit(void)
{
DeleteCriticalSection(&_Crit);
}
void Enter(void) const
{
EnterCriticalSection(&_Crit);
}
void Leave(void) const
{
LeaveCriticalSection(&_Crit);
}
};
class clsCritObj
{
private:
const clsCrit& _Crit;
clsCritObj& operator=(const clsCritObj& rhs); // not applicable
public:
clsCritObj(const clsCrit& Sync)
: _Crit(Sync)
{
_Crit.Enter();
}
~clsCritObj(void)
{
_Crit.Leave();
}
};
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ \
private: \
clsCrit CritSect; \
public: \
operator clsCrit&() \
{ \
return(CritSect); \
}
#define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c)
#endif
#else // defined(WIN32)
// not Windows world: no threading synchronization for now
#endif
#if !defined(TTMATH_IMPLEMENT_THREADSAFE_OBJ)
// if we don't know about serialization, make it a no-op
#define TTMATH_IMPLEMENT_THREADSAFE_OBJ /* */
#define TTMATH_USE_THREADSAFE_OBJ(c) /* */
#endif
} // namespace
#endif // headerfilettmathconfig

View File

@@ -47,6 +47,10 @@
#include "ttmathuint.h" #include "ttmathuint.h"
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace ttmath namespace ttmath
{ {
@@ -468,64 +472,6 @@ public:
} }
/*!
division this = this / ss2 (ss2 is int)
returned values:
0 - ok
1 - division by zero
for example: (result means 'this')
20 / 3 --> result: 6 remainder: 2
-20 / 3 --> result: -6 remainder: -2
20 / -3 --> result: -6 remainder: 2
-20 / -3 --> result: 6 remainder: -2
in other words: this(old) = ss2 * this(new)(result) + remainder
*/
uint DivInt(sint ss2, sint * remainder = 0)
{
bool ss1_is_sign, ss2_is_sign;
ss1_is_sign = IsSign();
/*
we don't have to test the carry from Abs as well as in Mul
*/
Abs();
if( ss2 < 0 )
{
ss2 = -ss2;
ss2_is_sign = true;
}
else
{
ss2_is_sign = false;
}
uint rem;
uint c = UInt<value_size>::DivInt((uint)ss2, &rem);
if( ss1_is_sign != ss2_is_sign )
SetSign();
if( remainder )
{
if( ss1_is_sign )
*remainder = -sint(rem);
else
*remainder = sint(rem);
}
return c;
}
uint DivInt(sint ss2, sint & remainder)
{
return DivInt(ss2, &remainder);
}
private: private:
@@ -572,7 +518,7 @@ public:
return Pow2(pow); return Pow2(pow);
if( UInt<value_size>::IsZero() ) if( UInt<value_size>::IsZero() )
// if 'pow' is negative then // if 'p' is negative then
// 'this' must be different from zero // 'this' must be different from zero
return 2; return 2;
@@ -592,7 +538,6 @@ public:
} }
/*! /*!
* *
* convertion methods * convertion methods
@@ -700,8 +645,14 @@ public:
// there can be a carry here when the size of this value is equal one word // there can be a carry here when the size of this value is equal one word
// and the 'value' has the highest bit set // and the 'value' has the highest bit set
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
return 1; return 1;
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
return 0; return 0;
} }
@@ -880,16 +831,7 @@ public:
/*! /*!
a constructor for converting string to this class (with the base=10) a constructor for converting string to this class (with the base=10)
*/ */
Int(const char * s) Int(const tt_char * s)
{
FromString(s);
}
/*!
a constructor for converting string to this class (with the base=10)
*/
Int(const wchar_t * s)
{ {
FromString(s); FromString(s);
} }
@@ -898,16 +840,7 @@ public:
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
Int(const std::string & s) Int(const tt_string & s)
{
FromString( s.c_str() );
}
/*!
a constructor for converting a string to this class (with the base=10)
*/
Int(const std::wstring & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
} }
@@ -943,13 +876,10 @@ public:
} }
private:
/*! /*!
an auxiliary method for converting to a string this method converts the value to a string with a base equal 'b'
*/ */
template<class string_type> void ToString(tt_string & result, uint b = 10) const
void ToStringBase(string_type & result, uint b = 10) const
{ {
if( IsSign() ) if( IsSign() )
{ {
@@ -965,71 +895,42 @@ private:
} }
} }
public:
/*!
this method converts the value to a string with a base equal 'b'
*/
void ToString(std::string & result, uint b = 10) const
{
return ToStringBase(result, b);
}
/*! /*!
this method converts the value to a string with a base equal 'b' this method converts a string into its value
string is given either as 'const char *' or 'const wchar_t *'
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
string is ended with a non-digit value, for example:
"-12" will be translated to -12
as well as:
"- 12foo" will be translated to -12 too
existing first white characters will be ommited
(between '-' and a first digit can be white characters too)
after_source (if exists) is pointing at the end of the parsed string
value_read (if exists) tells whether something has actually been read (at least one digit)
*/ */
void ToString(std::wstring & result, uint b = 10) const uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{
return ToStringBase(result, b);
}
/*!
this method converts the value to a string with a base equal 'b'
*/
std::string ToString(uint b = 10) const
{
std::string result;
ToStringBase(result, b);
return result;
}
/*!
this method converts the value to a string with a base equal 'b'
*/
std::wstring ToWString(uint b = 10) const
{
std::wstring result;
ToStringBase(result, b);
return result;
}
private:
/*!
an auxiliary method for converting from a string
*/
template<class char_type>
uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0)
{ {
bool is_sign = false; bool is_sign = false;
Misc::SkipWhiteCharacters(s); UInt<value_size>::SkipWhiteCharacters(s);
if( *s == '-' ) if( *s == '-' )
{ {
is_sign = true; is_sign = true;
Misc::SkipWhiteCharacters(++s); UInt<value_size>::SkipWhiteCharacters(++s);
} }
else else
if( *s == '+' ) if( *s == '+' )
{ {
Misc::SkipWhiteCharacters(++s); UInt<value_size>::SkipWhiteCharacters(++s);
} }
if( UInt<value_size>::FromString(s,b,after_source,value_read) ) if( UInt<value_size>::FromString(s,b,after_source,value_read) )
@@ -1068,54 +969,11 @@ private:
} }
public:
/*!
this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
string is ended with a non-digit value, for example:
"-12" will be translated to -12
as well as:
"- 12foo" will be translated to -12 too
existing first white characters will be ommited
(between '-' and a first digit can be white characters too)
after_source (if exists) is pointing at the end of the parsed string
value_read (if exists) tells whether something has actually been read (at least one digit)
*/
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
{
return FromStringBase(s, b, after_source, value_read);
}
/*!
this method converts a string into its value
*/
uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
{
return FromStringBase(s, b, after_source, value_read);
}
/*! /*!
this method converts a string into its value this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given it returns carry=1 if the value will be too big or an incorrect base 'b' is given
*/ */
uint FromString(const std::string & s, uint b = 10) uint FromString(const tt_string & s, uint b = 10)
{
return FromString( s.c_str(), b );
}
/*!
this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given
*/
uint FromString(const std::wstring & s, uint b = 10)
{ {
return FromString( s.c_str(), b ); return FromString( s.c_str(), b );
} }
@@ -1124,7 +982,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const char * s) Int<value_size> & operator=(const tt_char * s)
{ {
FromString(s); FromString(s);
@@ -1135,18 +993,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const wchar_t * s) Int<value_size> & operator=(const tt_string & s)
{
FromString(s);
return *this;
}
/*!
this operator converts a string into its value (with base = 10)
*/
Int<value_size> & operator=(const std::string & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
@@ -1154,15 +1001,6 @@ public:
} }
/*!
this operator converts a string into its value (with base = 10)
*/
Int<value_size> & operator=(const std::wstring & s)
{
FromString( s.c_str() );
return *this;
}
/*! /*!
@@ -1442,15 +1280,14 @@ public:
* *
*/ */
private:
/*! /*!
an auxiliary method for outputing to standard streams output for standard streams
tt_ostream is either std::ostream or std::wostream
*/ */
template<class ostream_type, class string_type> friend tt_ostream & operator<<(tt_ostream & s, const Int<value_size> & l)
static ostream_type & OutputToStream(ostream_type & s, const Int<value_size> & l)
{ {
string_type ss; tt_string ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@@ -1459,41 +1296,17 @@ private:
} }
public:
/*! /*!
output to standard streams input from standard streams
tt_istream is either std::istream or std::wistream
*/ */
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l) friend tt_istream & operator>>(tt_istream & s, Int<value_size> & l)
{ {
return OutputToStream<std::ostream, std::string>(s, l); tt_string ss;
}
// tt_char for operator>>
/*! tt_char z;
output to standard streams
*/
friend std::wostream & operator<<(std::wostream & s, const Int<value_size> & l)
{
return OutputToStream<std::wostream, std::wstring>(s, l);
}
private:
/*!
an auxiliary method for converting from a string
*/
template<class istream_type, class string_type, class char_type>
static istream_type & InputFromStream(istream_type & s, Int<value_size> & l)
{
string_type ss;
// char or wchar_t for operator>>
char_type z;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
s >> z; s >> z;
@@ -1505,10 +1318,10 @@ private:
} }
// we're reading only digits (base=10) // we're reading only digits (base=10)
while( s.good() && Misc::CharToDigit(z, 10)>=0 ) while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
{ {
ss += z; ss += z;
z = static_cast<char_type>(s.get()); z = static_cast<tt_char>(s.get());
} }
// we're leaving the last readed character // we're leaving the last readed character
@@ -1520,28 +1333,13 @@ private:
return s; return s;
} }
public:
/*!
input from standard streams
*/
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
{
return InputFromStream<std::istream, std::string, char>(s, l);
}
/*!
input from standard streams
*/
friend std::wistream & operator>>(std::wistream & s, Int<value_size> & l)
{
return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
}
}; };
} // namespace } // namespace
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
#endif #endif

View File

@@ -1,243 +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 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;
}
/*!
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());
}
/*
*
* AddString(result, str)
* result += str
*
*/
/*!
result += str
*/
static void AddString(std::string & result, const char * str)
{
result += str;
}
/*!
result += str
*/
static void AddString(std::wstring & result, const char * str)
{
for( ; *str ; ++str )
result += *str;
}
/*
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

@@ -44,13 +44,13 @@
\brief Mathematic functions. \brief Mathematic functions.
*/ */
#include "ttmathtypes.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include "ttmathtypes.h"
#include "ttmathmisc.h"
namespace ttmath namespace ttmath
@@ -74,19 +74,19 @@ public:
struct Item struct Item
{ {
// name of a variable of a function // 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) // (either std::string or std::wstring)
std::string value; tt_string value;
// number of parameters required by the function // number of parameters required by the function
// (if there's a variable this 'param' is ignored) // (if there's a variable this 'param' is ignored)
int param; int param;
Item() {} Item() {}
Item(const std::string & v, int p) : value(v), param(p) {} Item(const tt_string & v, int p) : value(v), param(p) {}
}; };
// 'Table' is the type of our table // 'Table' is the type of our table
typedef std::map<std::string, Item> Table; typedef std::map<tt_string, Item> Table;
typedef Table::iterator Iterator; typedef Table::iterator Iterator;
typedef Table::const_iterator CIterator; typedef Table::const_iterator CIterator;
@@ -99,7 +99,7 @@ public:
if 'can_be_digit' is true that means when the 'c' is a digit this if 'can_be_digit' is true that means when the 'c' is a digit this
method returns true otherwise it returns false method returns true otherwise it returns false
*/ */
static bool CorrectCharacter(wchar_t c, bool can_be_digit) static bool CorrectCharacter(int c, bool can_be_digit)
{ {
if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) if( (c>='a' && c<='z') || (c>='A' && c<='Z') )
return true; return true;
@@ -114,8 +114,7 @@ public:
/*! /*!
this method returns true if the name can be as a name of an object this method returns true if the name can be as a name of an object
*/ */
template<class string_type> static bool IsNameCorrect(const tt_string & name)
static bool IsNameCorrect(const string_type & name)
{ {
if( name.empty() ) if( name.empty() )
return false; return false;
@@ -123,7 +122,7 @@ public:
if( !CorrectCharacter(name[0], false) ) if( !CorrectCharacter(name[0], false) )
return false; return false;
typename string_type::const_iterator i = name.begin(); tt_string::const_iterator i=name.begin();
for(++i ; i!=name.end() ; ++i) for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) ) if( !CorrectCharacter(*i, true) )
@@ -136,7 +135,7 @@ public:
/*! /*!
this method returns true if such an object is defined (name exists) this method returns true if such an object is defined (name exists)
*/ */
bool IsDefined(const std::string & name) bool IsDefined(const tt_string & name)
{ {
Iterator i = table.find(name); Iterator i = table.find(name);
@@ -148,26 +147,10 @@ public:
} }
/*!
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);
}
/*! /*!
this method adds one object (variable of function) into the table this method adds one object (variable of function) into the table
*/ */
ErrorCode Add(const std::string & name, const std::string & value, int param = 0) ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -184,23 +167,6 @@ public:
} }
/*!
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);
}
/*! /*!
this method returns 'true' if the table is empty this method returns 'true' if the table is empty
*/ */
@@ -241,7 +207,7 @@ public:
/*! /*!
this method changes the value and the number of parameters for a specific object this method changes the value and the number of parameters for a specific object
*/ */
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -258,27 +224,10 @@ public:
} }
/*!
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);
}
/*! /*!
this method changes the name of a specific object this method changes the name of a specific object
*/ */
ErrorCode EditName(const std::string & old_name, const std::string & new_name) ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
{ {
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
return err_incorrect_name; return err_incorrect_name;
@@ -306,27 +255,10 @@ public:
} }
/*!
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);
}
/*! /*!
this method deletes an object this method deletes an object
*/ */
ErrorCode Delete(const std::string & name) ErrorCode Delete(const tt_string & name)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -342,26 +274,10 @@ public:
} }
/*!
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);
}
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
*/ */
ErrorCode GetValue(const std::string & name, std::string & value) const ErrorCode GetValue(const tt_string & name, tt_string & value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -380,29 +296,11 @@ public:
} }
/*!
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;
}
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValue(const std::string & name, const char ** value) const ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -421,28 +319,11 @@ public:
} }
/*!
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);
}
/*! /*!
this method gets the value and the number of parameters this method gets the value and the number of parameters
of a specific object of a specific object
*/ */
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -463,31 +344,12 @@ public:
} }
/*!
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;
}
/*! /*!
this method sets the value and the number of parameters this method sets the value and the number of parameters
of a specific object of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@@ -508,25 +370,6 @@ public:
} }
/*!
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);
}
/*! /*!
this method returns a pointer into the table this method returns a pointer into the table
*/ */
@@ -539,7 +382,6 @@ public:
private: private:
Table table; Table table;
std::string str_tmp1, str_tmp2;
}; // end of class Objects }; // end of class Objects
@@ -586,7 +428,7 @@ public:
/*! /*!
default constructor 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() History()
{ {
@@ -749,8 +591,8 @@ struct CGamma
you don't have to call this method, these coefficients will be automatically calculated you don't have to call this method, these coefficients will be automatically calculated
when they are needed when they are needed
you must note that calculating these coefficients is a little time-consuming operation, you must note that calculating of the coefficients is a little time-consuming operation,
(especially when the mantissa is large) and first call to Gamma() or Factorial() (especially when the mantissa is large) and first called to Gamma() or Factorial()
can take more time than next calls, and in the end this is the point when InitAll() 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 comes in handy: you can call this method somewhere at the beginning of your program
*/ */

View File

@@ -52,7 +52,6 @@
#include "ttmath.h" #include "ttmath.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"
#include "ttmathmisc.h"
@@ -110,7 +109,8 @@ namespace ttmath
for example a correct input string can be: for example a correct input string can be:
"1" "1"
"2.1234" "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"
"(1 + 2) * 3" "(1 + 2) * 3"
"pi" "pi"
@@ -255,7 +255,7 @@ public:
bool function; bool function;
// if function is true // if function is true
std::string function_name; tt_string function_name;
/* /*
the sign of value the sign of value
@@ -314,7 +314,7 @@ ErrorCode error;
when an error has occured it may be used to count the index of the wrong character when an error has occured it may be used to count the index of the wrong character
*/ */
const char * pstring; const tt_char * pstring;
/*! /*!
@@ -351,7 +351,7 @@ const Objects * puser_variables;
const Objects * puser_functions; const Objects * puser_functions;
typedef std::map<std::string, ValueType> FunctionLocalVariables; typedef std::map<tt_string, ValueType> FunctionLocalVariables;
/*! /*!
a pointer to the local variables of a function a pointer to the local variables of a function
@@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
/*! /*!
a temporary set using during parsing user defined variables a temporary set using during parsing user defined variables
*/ */
std::set<std::string> visited_variables; std::set<tt_string> visited_variables;
/*! /*!
a temporary set using during parsing user defined functions a temporary set using during parsing user defined functions
*/ */
std::set<std::string> visited_functions; std::set<tt_string> visited_functions;
@@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
table of mathematic functions table of mathematic functions
this map consists of: this map consists of:
std::string - function's name tt_string - function's name
pfunction - pointer to specific function pfunction - pointer to specific function
*/ */
typedef std::map<std::string, pfunction> FunctionsTable; typedef std::map<tt_string, pfunction> FunctionsTable;
FunctionsTable functions_table; FunctionsTable functions_table;
@@ -407,10 +407,10 @@ FunctionsTable functions_table;
table of mathematic operators table of mathematic operators
this map consists of: this map consists of:
std::string - operators's name tt_string - operators's name
MatOperator::Type - type of the operator MatOperator::Type - type of the operator
*/ */
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable; typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
OperatorsTable operators_table; OperatorsTable operators_table;
@@ -418,10 +418,10 @@ OperatorsTable operators_table;
table of mathematic variables table of mathematic variables
this map consists of: this map consists of:
std::string - variable's name tt_string - variable's name
pfunction_var - pointer to specific function which returns value of variable pfunction_var - pointer to specific function which returns value of variable
*/ */
typedef std::map<std::string, pfunction_var> VariablesTable; typedef std::map<tt_string, pfunction_var> VariablesTable;
VariablesTable variables_table; VariablesTable variables_table;
@@ -431,39 +431,6 @@ VariablesTable variables_table;
CGamma<ValueType> cgamma; CGamma<ValueType> cgamma;
/*!
temporary object for a whole string when Parse(std::wstring) is used
*/
std::string wide_to_ansi;
/*!
group character (used when parsing)
default zero (not used)
*/
int group;
/*!
characters used as a comma
default: '.' and ','
comma2 can be zero (it means it is not used)
*/
int comma, comma2;
/*!
an additional character used as a separator between function parameters
(semicolon is used always)
*/
int param_sep;
/*!
true if something was calculated (at least one mathematical operator was used or a function or a variable)
*/
bool calculated;
/*! /*!
we're using this method for reporting an error we're using this method for reporting an error
*/ */
@@ -488,7 +455,7 @@ void SkipWhiteCharacters()
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
{ {
@@ -506,7 +473,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
visited_variables.insert( name ); visited_variables.insert( name );
@@ -518,7 +485,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
{ {
if( variable ) if( variable )
visited_variables.erase( name ); visited_variables.erase( name );
@@ -537,7 +504,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
(there can be a recurrence here therefore we're using 'visited_variables' (there can be a recurrence here therefore we're using 'visited_variables'
and 'visited_functions' sets to make a stop condition) and 'visited_functions' sets to make a stop condition)
*/ */
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tt_string & name, const tt_char * new_string,
FunctionLocalVariables * local_variables = 0) FunctionLocalVariables * local_variables = 0)
{ {
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
@@ -581,18 +548,17 @@ public:
/*! /*!
this method returns the user-defined value of a variable this method returns the user-defined value of a variable
*/ */
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
{ {
if( !puser_variables ) if( !puser_variables )
return false; return false;
const char * string_value; const tt_char * string_value;
if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
return false; return false;
result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value); result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value);
calculated = true;
return true; return true;
} }
@@ -601,7 +567,7 @@ return true;
/*! /*!
this method returns the value of a local variable of a function this method returns the value of a local variable of a function
*/ */
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
{ {
if( !pfunction_local_variables ) if( !pfunction_local_variables )
return false; return false;
@@ -623,7 +589,7 @@ return true;
we make an object of type ValueType then call a method which we make an object of type ValueType then call a method which
sets the correct value in it and finally we'll return the object sets the correct value in it and finally we'll return the object
*/ */
ValueType GetValueOfVariable(const std::string & variable_name) ValueType GetValueOfVariable(const tt_string & variable_name)
{ {
ValueType result; ValueType result;
@@ -634,14 +600,13 @@ ValueType result;
return result; return result;
typename std::map<std::string, pfunction_var>::iterator i = typename std::map<tt_string, pfunction_var>::iterator i =
variables_table.find(variable_name); variables_table.find(variable_name);
if( i == variables_table.end() ) if( i == variables_table.end() )
Error( err_unknown_variable ); Error( err_unknown_variable );
(result.*(i->second))(); (result.*(i->second))();
calculated = true;
return result; return result;
} }
@@ -1390,56 +1355,34 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
} }
void Frac(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = stack[sindex].value;
result.RemainFraction();
}
/*! /*!
we use such a method because 'wvsprintf' is not everywhere defined we use such a method because 'wvsprintf' is not everywhere defined
*/ */
void Sprintf(char * buffer, int par) void Sprintf(tt_char * buffer, int par)
{ {
char buf[30]; // char, not wchar_t etc. char buf[30]; // char, not tt_char
int i; int i;
#ifdef _MSC_VER
#pragma warning( disable: 4996 )
//warning C4996: 'sprintf': This function or variable may be unsafe.
#endif
sprintf(buf, "%d", par); sprintf(buf, "%d", par);
for(i=0 ; buf[i] != 0 ; ++i) for(i=0 ; buf[i] != 0 ; ++i)
buffer[i] = buf[i]; buffer[i] = buf[i];
buffer[i] = 0; buffer[i] = 0;
#ifdef _MSC_VER
#pragma warning( default: 4996 )
#endif
} }
/*! /*!
this method returns the value from a user-defined function this method returns the value from a user-defined function
(look at the description in 'CallFunction(...)') (look at the description in 'CallFunction(...)')
*/ */
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex) bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
{ {
if( !puser_functions ) if( !puser_functions )
return false; return false;
const char * string_value; const tt_char * string_value;
int param; int param;
if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok ) if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
@@ -1453,7 +1396,7 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
if( amount_of_args > 0 ) if( amount_of_args > 0 )
{ {
char buffer[30]; tt_char buffer[30];
// x = x1 // x = x1
buffer[0] = 'x'; buffer[0] = 'x';
@@ -1469,7 +1412,6 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
} }
stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables); stack[sindex-1].value = RecurrenceParsingVariablesOrFunction(false, function_name, string_value, &local_variables);
calculated = true;
return true; return true;
} }
@@ -1488,7 +1430,7 @@ return true;
result will be stored in 'stack[sindex-1].value' result will be stored in 'stack[sindex-1].value'
(we don't have to set the correct type of this element, it'll be set later) (we don't have to set the correct type of this element, it'll be set later)
*/ */
void CallFunction(const std::string & function_name, int amount_of_args, int sindex) void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
{ {
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
return; return;
@@ -1502,7 +1444,6 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
calling the specify function calling the specify function
*/ */
(this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value); (this->*(i->second))(sindex, amount_of_args, stack[sindex-1].value);
calculated = true;
} }
@@ -1515,16 +1456,12 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
function_name - name of the function function_name - name of the function
pf - pointer to the function (to the wrapper) pf - pointer to the function (to the wrapper)
*/ */
void InsertFunctionToTable(const char * function_name, pfunction pf) void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
{ {
std::string str; functions_table.insert( std::make_pair(tt_string(function_name), pf));
Misc::AssignString(str, function_name);
functions_table.insert( std::make_pair(str, pf) );
} }
/*! /*!
inserting a function to the variables' table inserting a function to the variables' table
(this function returns value of variable) (this function returns value of variable)
@@ -1532,12 +1469,9 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
variable_name - name of the function variable_name - name of the function
pf - pointer to the function pf - pointer to the function
*/ */
void InsertVariableToTable(const char * variable_name, pfunction_var pf) void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
{ {
std::string str; variables_table.insert( std::make_pair(tt_string(variable_name), pf));
Misc::AssignString(str, variable_name);
variables_table.insert( std::make_pair(str, pf) );
} }
@@ -1546,66 +1480,65 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
*/ */
void CreateFunctionsTable() void CreateFunctionsTable()
{ {
InsertFunctionToTable("gamma", &Parser<ValueType>::Gamma); InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial); InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
InsertFunctionToTable("abs", &Parser<ValueType>::Abs); InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
InsertFunctionToTable("sin", &Parser<ValueType>::Sin); InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
InsertFunctionToTable("cos", &Parser<ValueType>::Cos); InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
InsertFunctionToTable("tan", &Parser<ValueType>::Tan); InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
InsertFunctionToTable("tg", &Parser<ValueType>::Tan); InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
InsertFunctionToTable("cot", &Parser<ValueType>::Cot); InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot); InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
InsertFunctionToTable("int", &Parser<ValueType>::Int); InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
InsertFunctionToTable("round", &Parser<ValueType>::Round); InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
InsertFunctionToTable("ln", &Parser<ValueType>::Ln); InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
InsertFunctionToTable("log", &Parser<ValueType>::Log); InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
InsertFunctionToTable("exp", &Parser<ValueType>::Exp); InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
InsertFunctionToTable("max", &Parser<ValueType>::Max); InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
InsertFunctionToTable("min", &Parser<ValueType>::Min); InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
InsertFunctionToTable("asin", &Parser<ValueType>::ASin); InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
InsertFunctionToTable("acos", &Parser<ValueType>::ACos); InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
InsertFunctionToTable("atan", &Parser<ValueType>::ATan); InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
InsertFunctionToTable("atg", &Parser<ValueType>::ATan); InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
InsertFunctionToTable("acot", &Parser<ValueType>::ACot); InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
InsertFunctionToTable("actg", &Parser<ValueType>::ACot); InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn); InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
InsertFunctionToTable("mod", &Parser<ValueType>::Mod); InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
InsertFunctionToTable("if", &Parser<ValueType>::If); InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
InsertFunctionToTable("or", &Parser<ValueType>::Or); InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
InsertFunctionToTable("and", &Parser<ValueType>::And); InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
InsertFunctionToTable("not", &Parser<ValueType>::Not); InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad); InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg); InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg); InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad); InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad); InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad); InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg); InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil); InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
InsertFunctionToTable("floor", &Parser<ValueType>::Floor); InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt); InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh); InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh); InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh); InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh); InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable("coth", &Parser<ValueType>::Coth); InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth); InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
InsertFunctionToTable("root", &Parser<ValueType>::Root); InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh); InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh); InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh); InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh); InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth); InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth); InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd); InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr); InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor); InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd); InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr); InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor); InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable("sum", &Parser<ValueType>::Sum); InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
InsertFunctionToTable("avg", &Parser<ValueType>::Avg); InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
InsertFunctionToTable("frac", &Parser<ValueType>::Frac);
} }
@@ -1614,8 +1547,8 @@ void CreateFunctionsTable()
*/ */
void CreateVariablesTable() void CreateVariablesTable()
{ {
InsertVariableToTable("pi", &ValueType::SetPi); InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
InsertVariableToTable("e", &ValueType::SetE); InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
} }
@@ -1641,7 +1574,7 @@ return c;
what should be returned is tested just by a '(' character that means if there's what should be returned is tested just by a '(' character that means if there's
a '(' character after a name that function returns 'true' a '(' character after a name that function returns 'true'
*/ */
bool ReadName(std::string & result) bool ReadName(tt_string & result)
{ {
int character; int character;
@@ -1658,7 +1591,7 @@ int character;
do do
{ {
result += static_cast<char>( character ); result += static_cast<tt_char>( character );
character = * ++pstring; character = * ++pstring;
} }
while( (character>='a' && character<='z') || while( (character>='a' && character<='z') ||
@@ -1713,7 +1646,7 @@ return false;
*/ */
bool ReadVariableOrFunction(Item & result) bool ReadVariableOrFunction(Item & result)
{ {
std::string name; tt_string name;
bool is_it_name_of_function = ReadName(name); bool is_it_name_of_function = ReadName(name);
if( is_it_name_of_function ) if( is_it_name_of_function )
@@ -1742,16 +1675,10 @@ return is_it_name_of_function;
*/ */
void ReadValue(Item & result, int reading_base) void ReadValue(Item & result, int reading_base)
{ {
const char * new_stack_pointer; const tt_char * new_stack_pointer;
bool value_read; bool value_read;
Conv conv;
conv.base = base; int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
conv.comma = comma;
conv.comma2 = comma2;
conv.group = group;
uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read);
pstring = new_stack_pointer; pstring = new_stack_pointer;
if( carry ) if( carry )
@@ -1762,18 +1689,43 @@ Conv conv;
} }
/*!
this method converts the character ascii c into the value in range <0;base-1>
if the character is incorrect for this base the funcion will return -1
*/
int CharToDigit(int c, int base)
{
if( c>='0' && c<='9' )
c=c-'0';
else
if( c>='a' && c<='z' )
c=c-'a'+10;
else
if( c>='A' && c<='Z' )
c=c-'A'+10;
else
return -1;
if( c >= base )
return -1;
return c;
}
/*! /*!
this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too) 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) bool ValueStarts(int character, int base)
{ {
if( character == comma ) if( character == TTMATH_COMMA_CHARACTER_1 )
return true; return true;
if( comma2!=0 && character==comma2 ) if( TTMATH_COMMA_CHARACTER_2 != 0 && character == TTMATH_COMMA_CHARACTER_2 )
return true; return true;
if( Misc::CharToDigit(character, base) != -1 ) if( CharToDigit(character, base) != -1 )
return true; return true;
return false; return false;
@@ -1896,9 +1848,9 @@ return 0;
} }
void InsertOperatorToTable(const char * name, typename MatOperator::Type type) void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
{ {
operators_table.insert( std::make_pair(std::string(name), type) ); operators_table.insert( std::make_pair(tt_string(name), type) );
} }
@@ -1907,19 +1859,19 @@ void InsertOperatorToTable(const char * name, typename MatOperator::Type type)
*/ */
void CreateMathematicalOperatorsTable() void CreateMathematicalOperatorsTable()
{ {
InsertOperatorToTable("||", MatOperator::lor); InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
InsertOperatorToTable("&&", MatOperator::land); InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
InsertOperatorToTable("!=", MatOperator::neq); InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
InsertOperatorToTable("==", MatOperator::eq); InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
InsertOperatorToTable(">=", MatOperator::get); InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
InsertOperatorToTable("<=", MatOperator::let); InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
InsertOperatorToTable(">", MatOperator::gt); InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
InsertOperatorToTable("<", MatOperator::lt); InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
InsertOperatorToTable("-", MatOperator::sub); InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
InsertOperatorToTable("+", MatOperator::add); InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
InsertOperatorToTable("/", MatOperator::div); InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
InsertOperatorToTable("*", MatOperator::mul); InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
InsertOperatorToTable("^", MatOperator::pow); InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
} }
@@ -1929,12 +1881,12 @@ void CreateMathematicalOperatorsTable()
e.g. e.g.
true when str1="test" and str2="te" true when str1="test" and str2="te"
*/ */
bool IsSubstring(const std::string & str1, const std::string & str2) bool IsSubstring(const tt_string & str1, const tt_string & str2)
{ {
if( str2.length() > str1.length() ) if( str2.length() > str1.length() )
return false; return false;
for(typename std::string::size_type i=0 ; i<str2.length() ; ++i) for(tt_string::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] ) if( str1[i] != str2[i] )
return false; return false;
@@ -1947,7 +1899,7 @@ return true;
*/ */
void ReadMathematicalOperator(Item & result) void ReadMathematicalOperator(Item & result)
{ {
std::string oper; tt_string oper;
typename OperatorsTable::iterator iter_old, iter_new; typename OperatorsTable::iterator iter_old, iter_new;
iter_old = operators_table.end(); iter_old = operators_table.end();
@@ -1976,31 +1928,6 @@ typename OperatorsTable::iterator iter_old, iter_new;
} }
/*!
this method makes a calculation for the percentage operator
e.g.
1000-50% = 1000-(1000*0,5) = 500
*/
void OperatorPercentage()
{
if( stack_index < 3 ||
stack[stack_index-1].type != Item::numerical_value ||
stack[stack_index-2].type != Item::mat_operator ||
stack[stack_index-3].type != Item::numerical_value )
Error(err_percent_from);
++pstring;
SkipWhiteCharacters();
uint c = 0;
c += stack[stack_index-1].value.Div(100);
c += stack[stack_index-1].value.Mul(stack[stack_index-3].value);
if( c )
Error(err_overflow);
}
/*! /*!
this method reads a mathematic operators this method reads a mathematic operators
or the final bracket or the semicolon operator or the final bracket or the semicolon operator
@@ -2013,10 +1940,6 @@ int ReadOperator(Item & result)
{ {
SkipWhiteCharacters(); SkipWhiteCharacters();
if( *pstring == '%' )
OperatorPercentage();
if( *pstring == 0 ) if( *pstring == 0 )
return 1; return 1;
else else
@@ -2026,7 +1949,7 @@ int ReadOperator(Item & result)
++pstring; ++pstring;
} }
else else
if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) ) if( *pstring == ';' )
{ {
result.type = Item::semicolon; result.type = Item::semicolon;
++pstring; ++pstring;
@@ -2056,9 +1979,7 @@ return 0;
void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator, void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator,
const ValueType & value2) const ValueType & value2)
{ {
uint res; int res;
calculated = true;
switch( mat_operator ) switch( mat_operator )
{ {
@@ -2121,6 +2042,7 @@ uint res;
break; break;
default: default:
/* /*
on the stack left an unknown operator but we had to recognize its before on the stack left an unknown operator but we had to recognize its before
@@ -2507,10 +2429,6 @@ Parser(): default_stack_size(100)
base = 10; base = 10;
deg_rad_grad = 1; deg_rad_grad = 1;
error = err_ok; error = err_ok;
group = 0;
comma = '.';
comma2 = ',';
param_sep = 0;
CreateFunctionsTable(); CreateFunctionsTable();
CreateVariablesTable(); CreateVariablesTable();
@@ -2529,11 +2447,7 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
pfunction_local_variables = 0; pfunction_local_variables = 0;
base = p.base; base = p.base;
deg_rad_grad = p.deg_rad_grad; deg_rad_grad = p.deg_rad_grad;
error = p.error; error = err_ok;
group = p.group;
comma = p.comma;
comma2 = p.comma2;
param_sep = p.param_sep;
/* /*
we don't have to call 'CreateFunctionsTable()' etc. we don't have to call 'CreateFunctionsTable()' etc.
@@ -2561,7 +2475,6 @@ Parser(const Parser<ValueType> & p): default_stack_size(p.default_stack_size)
/*! /*!
the new base of mathematic system the new base of mathematic system
default is 10
*/ */
void SetBase(int b) void SetBase(int b)
{ {
@@ -2616,49 +2529,15 @@ void SetFunctions(const Objects * pf)
} }
/*!
setting the group character
default zero (not used)
*/
void SetGroup(int g)
{
group = g;
}
/*!
setting the main comma operator and the additional comma operator
the additional operator can be zero (which means it is not used)
default are: '.' and ','
*/
void SetComma(int c, int c2 = 0)
{
comma = c;
comma2 = c2;
}
/*!
setting an additional character which is used as a parameters separator
the main parameters separator is a semicolon (is used always)
this character is used also as a global separator
*/
void SetParamSep(int s)
{
param_sep = s;
}
/*! /*!
the main method using for parsing string the main method using for parsing string
*/ */
ErrorCode Parse(const char * str) ErrorCode Parse(const tt_char * str)
{ {
stack_index = 0; stack_index = 0;
pstring = str; pstring = str;
error = err_ok; error = err_ok;
calculated = false;
stack.resize( default_stack_size ); stack.resize( default_stack_size );
@@ -2669,7 +2548,6 @@ ErrorCode Parse(const char * str)
catch(ErrorCode c) catch(ErrorCode c)
{ {
error = c; error = c;
calculated = false;
} }
NormalizeStack(); NormalizeStack();
@@ -2678,54 +2556,11 @@ return error;
} }
/*!
the main method using for parsing string
*/
ErrorCode Parse(const std::string & str)
{
return Parse(str.c_str());
}
/*!
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());
}
/*!
the main method using for parsing string
*/
ErrorCode Parse(const std::wstring & str)
{
return Parse(str.c_str());
}
/*!
this method returns true is something was calculated
(at least one mathematical operator was used or a function or variable)
e.g. 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 } // 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

@@ -65,7 +65,7 @@
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 9 #define TTMATH_MINOR_VER 9
#define TTMATH_REVISION_VER 0 #define TTMATH_REVISION_VER 0
#define TTMATH_PRERELEASE_VER 0 #define TTMATH_PRERELEASE_VER 1
/*! /*!
@@ -112,15 +112,6 @@ namespace ttmath
/*!
another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
*/
#if !defined _MSC_VER && !defined __GNUC__
#define TTMATH_NOASM
#endif
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
/*! /*!
@@ -129,6 +120,7 @@ namespace ttmath
typedef unsigned int uint; typedef unsigned int uint;
typedef signed int sint; typedef signed int sint;
/*! /*!
this type is twice bigger than uint this type is twice bigger than uint
(64bit on a 32bit platforms) (64bit on a 32bit platforms)
@@ -137,56 +129,39 @@ namespace ttmath
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it 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 this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
but only on a 32bit platform
*/ */
#ifdef TTMATH_NOASM
typedef unsigned long long int ulint; typedef unsigned long long int ulint;
#endif
/*!
how many bits there are in the uint type
*/
#define TTMATH_BITS_PER_UINT 32u
/*! /*!
the mask for the highest bit in the unsigned 32bit word (2^31) the mask for the highest bit in the unsigned 32bit word (2^31)
*/ */
#define TTMATH_UINT_HIGHEST_BIT 2147483648u const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
/*! /*!
the max value of the unsigned 32bit word (2^32 - 1) the max value of the unsigned 32bit word (2^32 - 1)
(all bits equal one) (all bits equal one)
*/ */
#define TTMATH_UINT_MAX_VALUE 4294967295u const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
/*! /*!
the number of words (32bit words on 32bit platform) the number of words (32bit words on 32bit platform)
which are kept in built-in variables for a Big<> type which are kept in built-in variables for a Big<> type
(these variables are defined in ttmathbig.h) (these variables are defined in ttmathbig.h)
*/ */
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u const uint 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 #else
/*! /*!
on 64bit platforms one word (uint, sint) will be equal 64bits on 64bit platforms one word (uint, sint) will be equal 64bits
*/ */
#ifdef _MSC_VER #if defined(_MSC_VER)
/* in VC 'long' type has 32 bits, __int64 is VC extension */
typedef unsigned __int64 uint; typedef unsigned __int64 uint;
typedef signed __int64 sint; typedef signed __int64 sint;
#else #else
typedef unsigned long uint; typedef unsigned long long uint;
typedef signed long sint; typedef signed long long sint;
#endif #endif
/*! /*!
on 64bit platform we do not define ulint on 64bit platform we do not define ulint
sizeof(long long) is 8 (64bit) but we need 128bit sizeof(long long) is 8 (64bit) but we need 128bit
@@ -196,51 +171,78 @@ namespace ttmath
*/ */
//typedef unsigned long long int ulint; //typedef unsigned long long int ulint;
/*!
how many bits there are in the uint type
*/
#define TTMATH_BITS_PER_UINT 64ul
/*! /*!
the mask for the highest bit in the unsigned 64bit word (2^63) the mask for the highest bit in the unsigned 64bit word (2^63)
*/ */
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul const uint TTMATH_UINT_HIGHEST_BIT = 0x8000000000000000ul;
/*! /*!
the max value of the unsigned 64bit word (2^64 - 1) the max value of the unsigned 64bit word (2^64 - 1)
(all bits equal one) (all bits equal one)
*/ */
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul const uint TTMATH_UINT_MAX_VALUE = 0xfffffffffffffffful;
/*! /*!
the number of words (64bit words on 64bit platforms) the number of words (64bit words on 64bit platforms)
which are kept in built-in variables for a Big<> type which are kept in built-in variables for a Big<> type
(these variables are defined in ttmathbig.h) (these variables are defined in ttmathbig.h)
*/ */
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul const uint 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 #endif
const uint TTMATH_BITS_PER_UINT = (sizeof(uint)*8);
} }
#if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) #if defined(UNICODE) || defined(_UNICODE)
#if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) #define TTMATH_USE_WCHAR
#if defined(_WIN32)
#define TTMATH_WIN32_THREADS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#define TTMATH_POSIX_THREADS
#endif #endif
#ifdef TTMATH_USE_WCHAR
typedef wchar_t tt_char;
typedef std::wstring tt_string;
typedef std::wostringstream tt_ostringstream;
typedef std::wostream tt_ostream;
typedef std::wistream tt_istream;
#define TTMATH_TEXT_HELPER(txt) L##txt
#else
typedef char tt_char;
typedef std::string tt_string;
typedef std::ostringstream tt_ostringstream;
typedef std::ostream tt_ostream;
typedef std::istream tt_istream;
#define TTMATH_TEXT_HELPER(txt) txt
#endif #endif
#endif
#define TTMATH_TEXT(txt) TTMATH_TEXT_HELPER(txt)
/*!
characters which represent the comma operator
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function)
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
that means you can input values for example 1.2345 and 1,2345 as well
if you don't want it just put 0 there e.g.
#define TTMATH_COMMA_CHARACTER_2 0
then only TTMATH_COMMA_CHARACTER_1 will be used
don't put there any special character which is used by the parser
(for example a semicolon ';' shouldn't be there)
*/
#define TTMATH_COMMA_CHARACTER_1 '.'
#define TTMATH_COMMA_CHARACTER_2 ','
@@ -265,16 +267,11 @@ namespace ttmath
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
the Karatsuba algorithm will use standard schoolbook multiplication 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__ #ifdef __GNUC__
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
#else #else
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
#endif #endif
#endif
/*! /*!
@@ -289,30 +286,9 @@ namespace ttmath
namespace ttmath namespace ttmath
{ {
/*!
lib type codes:
asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
asm_gcc_32 - with asm code designed for GCC (32 bits)
asm_vc_64 - with asm for VC (64 bit)
asm_gcc_64 - with asm for GCC (64 bit)
no_asm_32 - pure C++ version (32 bit) - without any asm code
no_asm_64 - pure C++ version (64 bit) - without any asm code
*/
enum LibTypeCode
{
asm_vc_32 = 0,
asm_gcc_32,
asm_vc_64,
asm_gcc_64,
no_asm_32,
no_asm_64
};
/*! /*!
error codes error codes
*/ */
@@ -343,132 +319,10 @@ namespace ttmath
err_object_exists, err_object_exists,
err_unknown_object, err_unknown_object,
err_still_calculating, err_still_calculating,
err_in_short_form_used_function, err_in_short_form_used_function
err_percent_from
}; };
/*!
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 print 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 this simple class can be used in multithreading model
(you can write your own class derived from this one) (you can write your own class derived from this one)
@@ -495,20 +349,20 @@ namespace ttmath
*/ */
class ExceptionInfo class ExceptionInfo
{ {
const char * file; const tt_char * file;
int line; int line;
public: public:
ExceptionInfo() : file(0), line(0) {} ExceptionInfo() : file(0), line(0) {}
ExceptionInfo(const char * f, int l) : file(f), line(l) {} ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
std::string Where() const tt_string Where() const
{ {
if( !file ) if( !file )
return "unknown"; return TTMATH_TEXT("unknown");
std::ostringstream result; tt_ostringstream result;
result << file << ":" << line; result << file << TTMATH_TEXT(":") << line;
return result.str(); return result.str();
} }
@@ -522,7 +376,7 @@ namespace ttmath
can throw an exception of this type can throw an exception of this type
If you compile with gcc you can get a small benefit If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string) with from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used) was used)
@@ -550,12 +404,12 @@ namespace ttmath
{ {
} }
ReferenceError(const char * f, int l) : ReferenceError(const tt_char * f, int l) :
std::logic_error ("reference error"), ExceptionInfo(f,l) std::logic_error ("reference error"), ExceptionInfo(f,l)
{ {
} }
std::string Where() const tt_string Where() const
{ {
return ExceptionInfo::Where(); return ExceptionInfo::Where();
} }
@@ -570,7 +424,7 @@ namespace ttmath
of this type of this type
if you compile with gcc you can get a small benefit if you compile with gcc you can get a small benefit
from using method Where() (it returns std::string) with from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_ASSERT the name and the line of a file where the macro TTMATH_ASSERT
was used) was used)
*/ */
@@ -582,12 +436,12 @@ namespace ttmath
{ {
} }
RuntimeError(const char * f, int l) : RuntimeError(const tt_char * f, int l) :
std::runtime_error ("internal error"), ExceptionInfo(f,l) std::runtime_error ("internal error"), ExceptionInfo(f,l)
{ {
} }
std::string Where() const tt_string Where() const
{ {
return ExceptionInfo::Where(); return ExceptionInfo::Where();
} }
@@ -602,11 +456,22 @@ namespace ttmath
#if defined(__FILE__) && defined(__LINE__) #if defined(__FILE__) && defined(__LINE__)
#ifdef TTMATH_USE_WCHAR
#define TTMATH_FILE_HELPER2(arg) L##arg
#define TTMATH_FILE_HELPER(x) TTMATH_FILE_HELPER2(x)
#define TTMATH_FILE TTMATH_FILE_HELPER(__FILE__)
#else
#define TTMATH_FILE __FILE__
#endif
#define TTMATH_REFERENCE_ASSERT(expression) \ #define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
#define TTMATH_ASSERT(expression) \ #define TTMATH_ASSERT(expression) \
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
#define TTMATH_VERIFY(expression) \
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
#else #else
@@ -615,27 +480,38 @@ namespace ttmath
#define TTMATH_ASSERT(expression) \ #define TTMATH_ASSERT(expression) \
if( !(expression) ) throw RuntimeError(); if( !(expression) ) throw RuntimeError();
#define TTMATH_VERIFY(expression) \
if( !(expression) ) throw RuntimeError();
#endif #endif
#else #else
#define TTMATH_REFERENCE_ASSERT(expression) #define TTMATH_REFERENCE_ASSERT(expression)
#define TTMATH_ASSERT(expression) #define TTMATH_ASSERT(expression)
#define TTMATH_VERIFY(expression) (void)(expression);
#endif #endif
#if !defined(LOG_PRINTF)
#define LOG_PRINTF printf
#endif
#ifdef TTMATH_DEBUG_LOG #ifdef TTMATH_DEBUG_LOG
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
#define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); #ifdef TTMATH_USE_WCHAR
#define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); #define TTMATH_LOG_HELPER(msg) \
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); PrintLog(L##msg, std::wcout);
#else #else
#define TTMATH_LOG(msg) #define TTMATH_LOG_HELPER(msg) \
#define TTMATH_LOGC(msg, carry) PrintLog(msg, std::cout);
#define TTMATH_VECTOR_LOG(msg, vector, len)
#define TTMATH_VECTOR_LOGC(msg, carry, vector, len)
#endif #endif
#define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
#else
#define TTMATH_LOG(msg)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,8 @@
#ifdef TTMATH_NOASM #ifdef TTMATH_NOASM
#pragma message("TTMATH_NOASM")
/*! /*!
\file ttmathuint_noasm.h \file ttmathuint_noasm.h
\brief template class UInt<uint> with methods without any assembler code \brief template class UInt<uint> with methods without any assembler code
@@ -51,56 +53,6 @@
namespace ttmath 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> template<uint value_size>
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result) uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
{ {
@@ -145,7 +97,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i) for(i=0 ; i<value_size ; ++i)
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]); c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOGC("UInt::Add", c) TTMATH_LOG("UInt::Add")
return c; return c;
} }
@@ -181,7 +133,7 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i) for(i=index+1 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]); c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOGC("UInt::AddInt", c) TTMATH_LOG("UInt::AddInt")
return c; return c;
} }
@@ -234,7 +186,7 @@ namespace ttmath
for(i=index+2 ; i<value_size && c ; ++i) for(i=index+2 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]); c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOGC("UInt::AddTwoInts", c) TTMATH_LOG("UInt::AddTwoInts")
return c; return c;
} }
@@ -274,7 +226,7 @@ namespace ttmath
for( ; i<ss1_size ; ++i) for( ; i<ss1_size ; ++i)
c = AddTwoWords(ss1[i], 0, c, &result[i]); c = AddTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) TTMATH_LOG("UInt::AddVector")
return c; return c;
} }
@@ -282,12 +234,6 @@ namespace ttmath
/*!
this method subtractes one word from the other
returns carry
this method is created only when TTMATH_NOASM macro is defined
*/
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result) uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
{ {
@@ -329,7 +275,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i) for(i=0 ; i<value_size ; ++i)
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]); c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOGC("UInt::Sub", c) TTMATH_LOG("UInt::Sub")
return c; return c;
} }
@@ -367,7 +313,7 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i) for(i=index+1 ; i<value_size && c ; ++i)
c = SubTwoWords(table[i], 0, c, &table[i]); c = SubTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOGC("UInt::SubInt", c) TTMATH_LOG("UInt::SubInt")
return c; return c;
} }
@@ -407,7 +353,7 @@ namespace ttmath
for( ; i<ss1_size ; ++i) for( ; i<ss1_size ; ++i)
c = SubTwoWords(ss1[i], 0, c, &result[i]); c = SubTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) TTMATH_LOG("UInt::SubVector")
return c; return c;
} }
@@ -441,7 +387,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOGC("UInt::Rcl2_one", c) TTMATH_LOG("UInt::Rcl2_one")
return c; return c;
} }
@@ -480,7 +426,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOGC("UInt::Rcr2_one", c) TTMATH_LOG("UInt::Rcr2_one")
return c; return c;
} }
@@ -518,7 +464,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOGC("UInt::Rcl2", c) TTMATH_LOG("UInt::Rcl2")
return (c & 1); return (c & 1);
} }
@@ -557,7 +503,7 @@ namespace ttmath
c = new_c; c = new_c;
} }
TTMATH_LOGC("UInt::Rcr2", c) TTMATH_LOG("UInt::Rcr2")
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
} }
@@ -565,9 +511,10 @@ namespace ttmath
/*! /*
this method returns the number of the highest set bit in x this method returns the number of the highest set bit in x
if the 'x' is zero this method returns '-1' if the 'x' is zero this method returns '-1'
*/ */
template<uint value_size> template<uint value_size>
sint UInt<value_size>::FindLeadingBitInWord(uint x) sint UInt<value_size>::FindLeadingBitInWord(uint x)
@@ -594,7 +541,7 @@ namespace ttmath
this method sets a special bit in the 'value' this method sets a special bit in the 'value'
and returns the last state of the bit (zero or one) 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. e.g.
uint x = 100; uint x = 100;
@@ -608,7 +555,7 @@ namespace ttmath
uint mask = 1; uint mask = 1;
if( bit > 0 ) if( bit > 1 )
mask = mask << bit; mask = mask << bit;
uint last = value & mask; uint last = value & mask;
@@ -796,11 +743,11 @@ namespace ttmath
temp1.u_.high = a_.u_.low; temp1.u_.high = a_.u_.low;
temp1.u_.low = b_.u_.high; temp1.u_.low = b_.u_.high;
res_.u_.high = (unsigned int)(temp1.u / c); res_.u_.high = temp1.u / c;
temp2.u_.high = (unsigned int)(temp1.u % c); temp2.u_.high = temp1.u % c;
temp2.u_.low = b_.u_.low; temp2.u_.low = b_.u_.low;
res_.u_.low = (unsigned int)(temp2.u / c); res_.u_.low = temp2.u / c;
*rest = temp2.u % c; *rest = temp2.u % c;
*r = res_.u; *r = res_.u;

View File

@@ -36,14 +36,13 @@
*/ */
#ifndef headerfilettmathuint_x86 #ifndef headerfilettmathuint_x86
#define headerfilettmathuint_x86 #define headerfilettmathuint_x86
#ifndef TTMATH_NOASM #ifndef TTMATH_NOASM
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
#pragma message("TTMATH_ASM32")
/*! /*!
\file ttmathuint_x86.h \file ttmathuint_x86.h
@@ -60,57 +59,12 @@
namespace ttmath 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 * basic mathematic functions
* *
*/ */
/*! /*!
adding ss2 to the this and adding carry if it's defined adding ss2 to the this and adding carry if it's defined
(this = this + ss2 + c) (this = this + ss2 + c)
@@ -129,46 +83,31 @@ namespace ttmath
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
// this part might be compiled with for example visual c // this part might be compiled with for example visual c
__asm __asm
{ {
push eax xor eax,eax // eax=0
push ebx xor edx,edx // edx=0
push ecx
push edx
push esi
mov ecx,[b] mov ecx,[b]
mov ebx,[p1] mov ebx,[p1]
mov esi,[p2] mov esi,[p2]
xor edx,edx // edx=0 sub eax,[c] // CF=c
mov eax,[c]
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
ALIGN 16
ttmath_loop: ttmath_loop:
mov eax,[esi+edx*4] mov eax,[esi+edx*4+0]
adc [ebx+edx*4],eax adc [ebx+edx*4+0],eax
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
adc ecx, ecx setc al
mov [c], ecx movzx eax, al
mov [c], eax
pop esi
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -196,7 +135,7 @@ namespace ttmath
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOGC("UInt::Add", c) TTMATH_LOG("UInt::Add")
return c; return c;
} }
@@ -232,14 +171,8 @@ namespace ttmath
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
mov ecx, [b] mov ecx, [b]
sub ecx, [index] sub ecx, [index]
@@ -248,26 +181,21 @@ namespace ttmath
mov eax, [value] mov eax, [value]
ALIGN 16
ttmath_loop: ttmath_loop:
add [ebx+edx*4], eax add [ebx+edx*4], eax
jnc ttmath_end jnc ttmath_end
mov eax, 1 mov eax, 1
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
ttmath_end: ttmath_end:
setc al setc al
movzx edx, al movzx eax, al
mov [c], edx mov [c], eax
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -297,7 +225,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::AddInt", c) TTMATH_LOG("UInt::AddInt")
return c; return c;
} }
@@ -347,52 +275,40 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
mov ecx, [b] mov ecx, [b]
sub ecx, [index]
mov ebx, [p1]
mov edx, [index] mov edx, [index]
mov ebx, [p1]
mov eax, [x1] mov eax, [x1]
sub ecx, edx // max uints to add (value_size - index)
add [ebx+edx*4], eax add [ebx+edx*4], eax
inc edx lea ecx, [ecx-1]
dec ecx
mov eax, [x2] mov eax, [x2]
ALIGN 16
ttmath_loop: ttmath_loop:
adc [ebx+edx*4], eax adc [ebx+edx*4+4], eax
jnc ttmath_end jnc ttmath_end
mov eax, 0 mov eax, 0
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
ttmath_end: ttmath_end:
setc al setc al
movzx edx, al movzx eax, al
mov [c], edx mov [c], eax
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"push %%ecx \n"
"push %%edx \n"
"subl %%edx, %%ecx \n" "subl %%edx, %%ecx \n"
"addl %%esi, (%%ebx,%%edx,4) \n" "addl %%esi, (%%ebx,%%edx,4) \n"
@@ -418,7 +334,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::AddTwoInts", c) TTMATH_LOG("UInt::AddTwoInts")
return c; return c;
} }
@@ -458,21 +374,19 @@ namespace ttmath
// this part might be compiled with for example visual c // this part might be compiled with for example visual c
__asm __asm
{ {
pushad
mov ecx, [ss2_size] mov ecx, [ss2_size]
xor edx, edx // edx = 0, cf = 0 xor edx, edx // edx = 0, cf = 0
mov esi, [ss1] mov esi, [ss1]
mov ebx, [ss2] mov ebx, [ss2]
mov edi, [result] mov edi, [result]
ALIGN 16
ttmath_loop: ttmath_loop:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
adc eax, [ebx+edx*4] adc eax, [ebx+edx*4]
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
@@ -491,7 +405,7 @@ namespace ttmath
adc eax, ebx adc eax, ebx
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop2 jnz ttmath_loop2
@@ -499,8 +413,6 @@ namespace ttmath
ttmath_end: ttmath_end:
mov [c], ecx mov [c], ecx
popad
} }
#endif #endif
@@ -550,8 +462,6 @@ namespace ttmath
#endif #endif
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
return c; return c;
} }
@@ -575,40 +485,30 @@ namespace ttmath
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
push esi
mov ecx,[b] mov ecx,[b]
mov ebx,[p1] mov ebx,[p1]
mov esi,[p2] mov esi,[p2]
xor edx,edx // edx=0 xor eax, eax
mov eax,[c] mov edx, eax
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
sub eax, [c]
ALIGN 16
ttmath_loop: ttmath_loop:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
sbb [ebx+edx*4], eax sbb [ebx+edx*4], eax
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
adc ecx, ecx setc al
mov [c], ecx movzx eax, al
mov [c], eax
pop esi
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -638,7 +538,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Sub", c) TTMATH_LOG("UInt::Sub")
return c; return c;
} }
@@ -675,14 +575,8 @@ namespace ttmath
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
mov ecx, [b] mov ecx, [b]
sub ecx, [index] sub ecx, [index]
@@ -691,26 +585,21 @@ namespace ttmath
mov eax, [value] mov eax, [value]
ALIGN 16
ttmath_loop: ttmath_loop:
sub [ebx+edx*4], eax sub [ebx+edx*4], eax
jnc ttmath_end jnc ttmath_end
mov eax, 1 mov eax, 1
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
ttmath_end: ttmath_end:
setc al setc al
movzx edx, al movzx eax, al
mov [c], edx mov [c], eax
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -740,7 +629,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::SubInt", c) TTMATH_LOG("UInt::SubInt")
return c; return c;
} }
@@ -786,7 +675,6 @@ namespace ttmath
*/ */
__asm __asm
{ {
pushad
mov ecx, [ss2_size] mov ecx, [ss2_size]
xor edx, edx // edx = 0, cf = 0 xor edx, edx // edx = 0, cf = 0
@@ -800,7 +688,7 @@ namespace ttmath
sbb eax, [ebx+edx*4] sbb eax, [ebx+edx*4]
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx lea edx, [edx+1]
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
@@ -819,7 +707,7 @@ namespace ttmath
sbb eax, ebx sbb eax, ebx
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx lea edx, [edx+1]
dec ecx dec ecx
jnz ttmath_loop2 jnz ttmath_loop2
@@ -827,8 +715,6 @@ namespace ttmath
ttmath_end: ttmath_end:
mov [c], ecx mov [c], ecx
popad
} }
#endif #endif
@@ -878,8 +764,6 @@ namespace ttmath
#endif #endif
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
return c; return c;
} }
@@ -906,29 +790,25 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push ebx
push ecx
push edx
mov ebx, [p1] mov ebx, [p1]
xor edx, edx xor edx, edx
mov ecx, [c] mov ecx, edx
neg ecx sub ecx, [c]
mov ecx, [b] mov ecx, [b]
ALIGN 16
ttmath_loop: ttmath_loop:
rcl dword ptr [ebx+edx*4], 1 rcl dword ptr [ebx+edx*4], 1
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
adc ecx, ecx setc al
mov [c], ecx movzx eax, al
mov [c], eax
pop edx
pop ecx
pop ebx
} }
#endif #endif
@@ -956,7 +836,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcl2_one", c) TTMATH_LOG("UInt::Rcl2_one")
return c; return c;
} }
@@ -984,25 +864,22 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push ebx xor ecx, ecx
push ecx sub ecx, [c]
mov ebx, [p1] mov ebx, [p1]
mov ecx, [c]
neg ecx
mov ecx, [b] mov ecx, [b]
ALIGN 16
ttmath_loop: ttmath_loop:
rcr dword ptr [ebx+ecx*4-4], 1 rcr dword ptr [ebx+ecx*4-4], 1
dec ecx dec ecx
jnz ttmath_loop jnz ttmath_loop
adc ecx, ecx setc al
mov [c], ecx movzx eax, al
mov [c], eax
pop ecx
pop ebx
} }
#endif #endif
@@ -1028,20 +905,13 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcr2_one", c) TTMATH_LOG("UInt::Rcr2_one")
return c; return c;
} }
#ifdef _MSC_VER
#pragma warning (disable : 4731)
//warning C4731: frame pointer register 'ebp' modified by inline assembly code
#endif
/*! /*!
this method moves all bits into the left hand side this method moves all bits into the left hand side
return value <- this <- c return value <- this <- c
@@ -1059,62 +929,47 @@ namespace ttmath
{ {
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT ) TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
uint b = value_size; register sint b = value_size;
uint * p1 = table; register uint * p1 = table;
register uint mask;
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
mov edi, [b] mov edi, [b]
mov ecx, 32 mov ecx, 32
sub ecx, [bits] sub ecx, [bits]
mov edx, -1 mov edx, -1
shr edx, cl shr edx, cl
mov [mask], edx
mov ecx, [bits] mov ecx, [bits]
mov ebx, [p1] mov ebx, [p1]
mov eax, [c]
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
xor edx, edx // edx = 0 xor edx, edx // edx = 0
mov esi, edx mov esi, edx // old value = 0
or eax, eax
cmovnz esi, ebp // if(c) esi=mask else esi=0
mov eax, [c]
or eax, eax
cmovnz esi, [mask] // if c then old value = mask
ALIGN 16
ttmath_loop: ttmath_loop:
rol dword ptr [ebx+edx*4], cl rol dword ptr [ebx+edx*4], cl
mov eax, [ebx+edx*4] mov eax, [ebx+edx*4]
and eax, ebp and eax, [mask]
xor [ebx+edx*4], eax // clearing bits xor [ebx+edx*4], eax // clearing bits
or [ebx+edx*4], esi // saving old value or [ebx+edx*4], esi // saving old value
mov esi, eax mov esi, eax
inc edx lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
dec edi dec edi
jnz ttmath_loop jnz ttmath_loop
pop ebp // restoring ebp
and eax, 1 and eax, 1
mov [c], eax mov dword ptr [c], eax
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -1162,7 +1017,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcl2", c) TTMATH_LOG("UInt::Rcl2")
return c; return c;
} }
@@ -1189,43 +1044,37 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint mask;
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
mov edi, [b] mov edi, [b]
mov ecx, 32 mov ecx, 32
sub ecx, [bits] sub ecx, [bits]
mov edx, -1 mov edx, -1
shl edx, cl shl edx, cl
mov [mask], edx
mov ecx, [bits] mov ecx, [bits]
mov ebx, [p1] mov ebx, [p1]
mov eax, [c]
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
xor edx, edx // edx = 0 xor edx, edx // edx = 0
mov esi, edx mov esi, edx // old value = 0
add edx, edi add edx, edi
dec edx // edx is pointing at the end of the table (on last word) dec edx // edx - is pointing at the last word
or eax, eax
cmovnz esi, ebp // if(c) esi=mask else esi=0
mov eax, [c]
or eax, eax
cmovnz esi, [mask] // if c then old value = mask
ALIGN 16
ttmath_loop: ttmath_loop:
ror dword ptr [ebx+edx*4], cl ror dword ptr [ebx+edx*4], cl
mov eax, [ebx+edx*4] mov eax, [ebx+edx*4]
and eax, ebp and eax, [mask]
xor [ebx+edx*4], eax // clearing bits xor [ebx+edx*4], eax // clearing bits
or [ebx+edx*4], esi // saving old value or [ebx+edx*4], esi // saving old value
mov esi, eax mov esi, eax
@@ -1234,18 +1083,10 @@ namespace ttmath
dec edi dec edi
jnz ttmath_loop jnz ttmath_loop
pop ebp // restoring ebp rol eax, 1 // bit 31 will be bit 0
rol eax, 1 // 31bit will be first
and eax, 1 and eax, 1
mov [c], eax
pop edi mov dword ptr [c], eax
pop esi
pop edx
pop ecx
pop ebx
pop eax
} }
#endif #endif
@@ -1296,16 +1137,12 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcr2", c) TTMATH_LOG("UInt::Rcr2")
return c; return c;
} }
#ifdef _MSC_VER
#pragma warning (default : 4731)
#endif
/* /*
this method returns the number of the highest set bit in one 32-bit word this method returns the number of the highest set bit in one 32-bit word
@@ -1319,16 +1156,11 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push edx
mov edx,-1 mov edx,-1
bsr eax,[x] bsr eax,[x]
cmovz eax,edx cmovz eax,edx
mov [result], eax
pop edx mov [result], eax
pop eax
} }
#endif #endif
@@ -1376,9 +1208,6 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push ebx
push eax
mov eax, [v] mov eax, [v]
mov ebx, [bit] mov ebx, [bit]
bts eax, ebx bts eax, ebx
@@ -1387,9 +1216,6 @@ namespace ttmath
setc bl setc bl
movzx ebx, bl movzx ebx, bl
mov [old_bit], ebx mov [old_bit], ebx
pop eax
pop ebx
} }
#endif #endif
@@ -1408,7 +1234,6 @@ namespace ttmath
#endif #endif
value = v; value = v;
return old_bit; return old_bit;
} }
@@ -1440,17 +1265,11 @@ namespace ttmath
__asm __asm
{ {
push eax
push edx
mov eax, [a] mov eax, [a]
mul dword ptr [b] mul dword ptr [b]
mov [result2_], edx mov [result2_], edx
mov [result1_], eax mov [result1_], eax
pop edx
pop eax
} }
#endif #endif
@@ -1513,18 +1332,12 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
__asm __asm
{ {
push eax
push edx
mov edx, [a] mov edx, [a]
mov eax, [b] mov eax, [b]
div dword ptr [c] div dword ptr [c]
mov [r_], eax mov [r_], eax
mov [rest_], edx mov [rest_], edx
pop edx
pop eax
} }
#endif #endif

View File

@@ -39,11 +39,10 @@
#ifndef headerfilettmathuint_x86_64 #ifndef headerfilettmathuint_x86_64
#define headerfilettmathuint_x86_64 #define headerfilettmathuint_x86_64
#ifndef TTMATH_NOASM #ifndef TTMATH_NOASM
#ifdef TTMATH_PLATFORM64 #ifdef TTMATH_PLATFORM64
#pragma message("TTMATH_ASM64")
/*! /*!
\file ttmathuint_x86_64.h \file ttmathuint_x86_64.h
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors \brief template class UInt<uint> with assembler code for 64bit x86_64 processors
@@ -51,77 +50,31 @@
this file is included at the end of ttmathuint.h this file is included at the end of ttmathuint.h
*/ */
#ifdef _MSC_VER #define WIN32_LEAN_AND_MEAN
#include <intrin.h> #include <windows.h>
#endif
namespace ttmath namespace ttmath
{ {
#ifdef _MSC_VER #if defined(_M_X64)
#include <intrin.h>
extern "C" extern "C"
{ {
uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); uint __fastcall 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 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 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 sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
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 #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()
{
#ifdef _MSC_VER
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()
{
#ifdef _MSC_VER
LibTypeCode info = asm_vc_64;
#endif
#ifdef __GNUC__
LibTypeCode info = asm_gcc_64;
#endif
return info;
}
/*! /*!
* *
* basic mathematic functions * basic mathematic functions
@@ -149,17 +102,16 @@ namespace ttmath
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
c = adc_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_adc_x64(p1,p2,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
/* /*
this part should be compiled with gcc this part should be compiled with gcc
*/ */
@@ -184,7 +136,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Add", c) TTMATH_LOG("UInt::Add")
return c; return c;
} }
@@ -220,16 +172,14 @@ namespace ttmath
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
c = addindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_addindexed_x64(p1,b,index,value);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
@@ -256,7 +206,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::AddInt", c) TTMATH_LOG("UInt::AddInt")
return c; return c;
} }
@@ -297,6 +247,30 @@ namespace ttmath
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index) uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
#if 0
{
uint i, c;
TTMATH_ASSERT( index < value_size )
printf("add %Id + %Id\n",x1,x2);
for(int i=index ; i<value_size ; ++i)
printf("%d: %Id\n",i,table[i]);
c = AddTwoWords(table[index], x1, 0, &table[index]);
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
for(i=index+2 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]);
for(i=index ; i<value_size ; ++i)
printf("%d: %Id\n",i,table[i]);
printf(" -> %d\n",c);
TTMATH_LOG("UInt::AddTwoInts")
return c;
}
#else
{ {
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
@@ -304,16 +278,21 @@ namespace ttmath
TTMATH_ASSERT( index < value_size - 1 ) TTMATH_ASSERT( index < value_size - 1 )
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
//printf("add %Id + %Id\n",x1,x2);
//for(int i=index ; i<value_size ; ++i)
// printf("%d: %Id\n",i,table[i]);
//if (table[0] == 1265784741359897913) DebugBreak();
c = addindexed2_x64(p1,b,index,x1,x2);
//for(int i=index ; i<value_size ; ++i)
// printf("%d: %Id\n",i,table[i]);
//printf(" -> %d\n",c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
@@ -344,98 +323,13 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::AddTwoInts", c) TTMATH_LOG("UInt::AddTwoInts")
return c; return c;
} }
/*!
this static method addes one vector to the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5+1
4 3 4+3
2 7 2+7
6 6
9 9
of course the carry is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint c;
#if !defined(__GNUC__) && !defined(_MSC_VER)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
#endif #endif
#ifdef _MSC_VER
c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
#ifdef __GNUC__
uint dummy1, dummy2, dummy3;
uint rest = ss1_size - ss2_size;
// this part should be compiled with gcc
__asm__ __volatile__(
"mov %%rdx, %%r8 \n"
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
"1: \n"
"mov (%%rsi,%%rdx,8), %%rax \n"
"adc (%%rbx,%%rdx,8), %%rax \n"
"mov %%rax, (%%rdi,%%rdx,8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 1b \n"
"adc %%rcx, %%rcx \n" // rcx has the cf state
"or %%r8, %%r8 \n"
"jz 3f \n"
"xor %%rbx, %%rbx \n" // ebx = 0
"neg %%rcx \n" // setting cf from rcx
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
"2: \n"
"mov (%%rsi, %%rdx, 8), %%rax \n"
"adc %%rbx, %%rax \n"
"mov %%rax, (%%rdi, %%rdx, 8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 2b \n"
"adc %%rcx, %%rcx \n"
"3: \n"
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
: "%r8", "cc", "memory" );
#endif
TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
return c;
}
@@ -456,20 +350,17 @@ namespace ttmath
uint * p1 = table; uint * p1 = table;
const uint * p2 = ss2.table; const uint * p2 = ss2.table;
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
c = sbb_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_sbb_x64(p1,p2,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
@@ -492,15 +383,15 @@ namespace ttmath
: "0" (b), "1" (c), "b" (p1), "S" (p2) : "0" (b), "1" (c), "b" (p1), "S" (p2)
: "cc", "memory" ); : "cc", "memory" );
#endif #endif
TTMATH_LOGC("UInt::Sub", c) TTMATH_LOG("UInt::Sub")
return c; return c;
} }
/*! /*!
this method subtracts one word (at a specific position) this method subtracts one word (at a specific position)
and returns a carry (if it was) and returns a carry (if it was)
@@ -529,16 +420,14 @@ namespace ttmath
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
c = subindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_subindexed_x64(p1,b,index,value);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
@@ -565,97 +454,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::SubInt", c) TTMATH_LOG("UInt64::SubInt")
return c;
}
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5-1
4 3 4-3
2 7 2-7
6 6-1 (the borrow from previous item)
9 9
return (carry): 0
of course the carry (borrow) is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
TTMATH_ASSERT( ss1_size >= ss2_size )
uint c;
#if !defined(__GNUC__) && !defined(_MSC_VER)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
#endif
#ifdef _MSC_VER
c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
#endif
#ifdef __GNUC__
// the asm code is nearly the same as in AddVector
// only two instructions 'adc' are changed to 'sbb'
uint dummy1, dummy2, dummy3;
uint rest = ss1_size - ss2_size;
__asm__ __volatile__(
"mov %%rdx, %%r8 \n"
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
"1: \n"
"mov (%%rsi,%%rdx,8), %%rax \n"
"sbb (%%rbx,%%rdx,8), %%rax \n"
"mov %%rax, (%%rdi,%%rdx,8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 1b \n"
"adc %%rcx, %%rcx \n" // rcx has the cf state
"or %%r8, %%r8 \n"
"jz 3f \n"
"xor %%rbx, %%rbx \n" // ebx = 0
"neg %%rcx \n" // setting cf from rcx
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
"2: \n"
"mov (%%rsi, %%rdx, 8), %%rax \n"
"sbb %%rbx, %%rax \n"
"mov %%rax, (%%rdi, %%rdx, 8) \n"
"inc %%rdx \n"
"dec %%rcx \n"
"jnz 2b \n"
"adc %%rcx, %%rcx \n"
"3: \n"
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
: "%r8", "cc", "memory" );
#endif
TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
return c; return c;
} }
@@ -681,17 +480,14 @@ namespace ttmath
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
#ifndef __GNUC__
#if !defined(__GNUC__) && !defined(_MSC_VER) #if defined(_M_X64)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" c = rcl_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_rcl_x64(p1,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2; uint dummy, dummy2;
@@ -715,7 +511,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcl2_one", c) TTMATH_LOG("UInt::Rcl2_one")
return c; return c;
} }
@@ -741,17 +537,14 @@ namespace ttmath
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
#ifndef __GNUC__
#if !defined(__GNUC__) && !defined(_MSC_VER) #if defined(_M_X64)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" c = rcr_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_rcr_x64(p1,b,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy; uint dummy;
@@ -773,7 +566,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcr2_one", c) TTMATH_LOG("UInt::Rcr2_one")
return c; return c;
} }
@@ -802,17 +595,14 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
#ifndef __GNUC__
#if !defined(__GNUC__) && !defined(_MSC_VER) #if defined(_M_X64)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" c = rcl2_x64(p1,b,bits,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_rcl2_x64(p1,b,bits,c);
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2, dummy3; uint dummy, dummy2, dummy3;
@@ -828,6 +618,7 @@ namespace ttmath
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
"movq %%rdx, %%rsi \n" "movq %%rdx, %%rsi \n"
"orq %%rax, %%rax \n" "orq %%rax, %%rax \n"
"cmovnz %%r8, %%rsi \n" "cmovnz %%r8, %%rsi \n"
@@ -852,7 +643,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcl2", c) TTMATH_LOG("UInt::Rcl2")
return c; return c;
} }
@@ -880,13 +671,12 @@ namespace ttmath
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_M_X64)
c = rcr2_x64(p1,b,bits,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif #endif
#ifdef _MSC_VER
c = ttmath_rcr2_x64(p1,b,bits,c);
#endif #endif
@@ -907,6 +697,7 @@ namespace ttmath
"movq %%rdx, %%rsi \n" "movq %%rdx, %%rsi \n"
"addq %%rdi, %%rdx \n" "addq %%rdi, %%rdx \n"
"decq %%rdx \n" "decq %%rdx \n"
"orq %%rax, %%rax \n" "orq %%rax, %%rax \n"
"cmovnz %%R8, %%rsi \n" "cmovnz %%R8, %%rsi \n"
@@ -932,7 +723,7 @@ namespace ttmath
#endif #endif
TTMATH_LOGC("UInt::Rcr2", c) TTMATH_LOG("UInt::Rcr2")
return c; return c;
} }
@@ -947,25 +738,20 @@ namespace ttmath
template<uint value_size> template<uint value_size>
sint UInt<value_size>::FindLeadingBitInWord(uint x) sint UInt<value_size>::FindLeadingBitInWord(uint x)
{ {
sint result; register sint result;
#ifndef __GNUC__
#if !defined(__GNUC__) && !defined(_MSC_VER) #if defined(_MSC_VER)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" unsigned long nIndex(0);
#endif
#ifdef _MSC_VER
unsigned long nIndex = 0;
if (_BitScanReverse64(&nIndex,x) == 0) if (_BitScanReverse64(&nIndex,x) == 0)
result = -1; result = -1;
else else
result = nIndex; result = nIndex;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy; uint dummy;
@@ -1008,15 +794,18 @@ namespace ttmath
uint old_bit; uint old_bit;
uint v = value; uint v = value;
#if !defined(__GNUC__) && !defined(_MSC_VER)
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro"
#endif
#ifndef __GNUC__
#ifdef _MSC_VER #if defined(_MSC_VER)
#if defined(TTMATH_PLATFORM64)
old_bit = _bittestandset64((__int64*)&value,bit) != 0; old_bit = _bittestandset64((__int64*)&value,bit) != 0;
#else
old_bit = _bittestandset((long*)&value,bit) != 0;
#endif
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@@ -1069,15 +858,13 @@ namespace ttmath
uint result1_; uint result1_;
uint result2_; uint result2_;
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_MSC_VER)
#endif
#ifdef _MSC_VER
result1_ = _umul128(a,b,&result2_); result1_ = _umul128(a,b,&result2_);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@@ -1106,6 +893,7 @@ namespace ttmath
* *
*/ */
#ifndef __GNUC__
/*! /*!
this method calculates 64bits word a:b / 32bits c (a higher, b lower word) this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
@@ -1132,19 +920,15 @@ namespace ttmath
TTMATH_ASSERT( c != 0 ) TTMATH_ASSERT( c != 0 )
#if !defined(__GNUC__) && !defined(_MSC_VER) #ifndef __GNUC__
#error "another compiler than GCC or Microsoft VC is currently not supported in 64bit mode, you can compile with TTMATH_NOASM macro" #if defined(_MSC_VER)
#endif div_x64(&a,&b,c);
#ifdef _MSC_VER
ttmath_div_x64(&a,&b,c);
r_ = a; r_ = a;
rest_ = b; rest_ = b;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@@ -1163,6 +947,133 @@ namespace ttmath
*rest = rest_; *rest = rest_;
} }
template<uint value_size>
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
{
uint temp;
if( carry == 0 )
{
temp = a + b;
if( temp < a )
carry = 1;
}
else
{
carry = 1;
temp = a + b + carry;
if( temp > a ) // !(temp<=a)
carry = 0;
}
*result = temp;
return carry;
}
template<uint value_size>
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
{
if( carry == 0 )
{
*result = a - b;
if( a < b )
carry = 1;
}
else
{
carry = 1;
*result = a - b - carry;
if( a > b ) // !(a <= b )
carry = 0;
}
return carry;
}
/*!
this static method addes one vector to the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5+1
4 3 4+3
2 7 2+7
6 6
9 9
of course the carry is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = AddTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_LOG("UInt::AddVector")
return c;
}
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5-1
4 3 4-3
2 7 2-7
6 6-1 (the borrow from previous item)
9 9
return (carry): 0
of course the carry (borrow) is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = SubTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_LOG("UInt::SubVector")
return c;
}
#endif // #ifndef __GNUC__
} //namespace } //namespace

View File

@@ -1,79 +1,30 @@
; PUBLIC adc_x64
; This file is a part of TTMath Bignum Library PUBLIC addindexed_x64
; and is distributed under the (new) BSD licence. PUBLIC addindexed2_x64
; Author: Christian Kaiser <chk@online.de>
;
; PUBLIC sbb_x64
; Copyright (c) 2009, Christian Kaiser PUBLIC subindexed_x64
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;
; * Redistributions of source code must retain the above copyright notice,
; this list of conditions and the following disclaimer.
;
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; * Neither the name Christian Kaiser nor the names of contributors to this
; project may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
; THE POSSIBILITY OF SUCH DAMAGE.
;
; PUBLIC rcl_x64
; compile with debug info: ml64.exe /Zd /Zi ttmathuint_x86_64_msvc.asm PUBLIC rcr_x64
; compile without debug info: ml64.exe ttmathuint_x86_64_msvc.asm
; this create ttmathuint_x86_64_msvc.obj file which can be linked with your program
;
PUBLIC ttmath_adc_x64 PUBLIC rcl2_x64
PUBLIC ttmath_addindexed_x64 PUBLIC rcr2_x64
PUBLIC ttmath_addindexed2_x64
PUBLIC ttmath_addvector_x64
PUBLIC ttmath_sbb_x64 PUBLIC div_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." ; "rax, rcx, rdx, r8-r11 are volatile."
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." ; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
; ;
.CODE .CODE
ALIGN 8 ALIGN 8
;---------------------------------------- ;----------------------------------------
ttmath_adc_x64 PROC adc_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = p2 ; rdx = p2
; r8 = nSize ; r8 = nSize
@@ -96,7 +47,7 @@ ttmath_adc_x64 PROC
ret ret
ttmath_adc_x64 ENDP adc_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -104,7 +55,7 @@ ttmath_adc_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_addindexed_x64 PROC addindexed_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = nSize ; rdx = nSize
@@ -137,7 +88,7 @@ done_with_cy:
ret ret
ttmath_addindexed_x64 ENDP addindexed_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -145,7 +96,7 @@ ttmath_addindexed_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_addindexed2_x64 PROC addindexed2_x64 PROC
; rcx = p1 (pointer) ; rcx = p1 (pointer)
; rdx = b (value size) ; rdx = b (value size)
@@ -178,9 +129,7 @@ next:
lea rax, [rax+1] lea rax, [rax+1]
ret ret
ttmath_addindexed2_x64 ENDP addindexed2_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -188,61 +137,7 @@ ttmath_addindexed2_x64 ENDP
;---------------------------------------- ;----------------------------------------
sbb_x64 PROC
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 ; rcx = p1
; rdx = p2 ; rdx = p2
@@ -266,7 +161,7 @@ ttmath_sbb_x64 PROC
ret ret
ttmath_sbb_x64 ENDP sbb_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -274,7 +169,7 @@ ttmath_sbb_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_subindexed_x64 PROC subindexed_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = nSize ; rdx = nSize
; r8 = nPos ; r8 = nPos
@@ -291,17 +186,17 @@ loop1:
mov r9, 1 mov r9, 1
dec rdx dec rdx
jnz loop1 jnz loop1
jc return_1 ; most of the times, there will be NO carry (I hope)
mov rax, 1
ret
done: done:
xor rax, rax xor rax, rax
ret ret
ttmath_subindexed_x64 ENDP return_1:
mov rax, 1
ret
subindexed_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -309,64 +204,7 @@ ttmath_subindexed_x64 ENDP
;---------------------------------------- ;----------------------------------------
; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' rcl_x64 PROC
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 ; rcx = p1
; rdx = b ; rdx = b
; r8 = nLowestBit ; r8 = nLowestBit
@@ -387,7 +225,7 @@ loop1:
ret ret
ttmath_rcl_x64 ENDP rcl_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -395,7 +233,7 @@ ttmath_rcl_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_rcr_x64 PROC rcr_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = nSize ; rdx = nSize
; r8 = nLowestBit ; r8 = nLowestBit
@@ -414,7 +252,7 @@ loop1:
ret ret
ttmath_rcr_x64 ENDP rcr_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -422,7 +260,7 @@ ttmath_rcr_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_div_x64 PROC div_x64 PROC
; rcx = &Hi ; rcx = &Hi
; rdx = &Lo ; rdx = &Lo
@@ -439,7 +277,7 @@ ttmath_div_x64 PROC
ret ret
ttmath_div_x64 ENDP div_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -447,7 +285,7 @@ ttmath_div_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_rcl2_x64 PROC rcl2_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = nSize ; rdx = nSize
; r8 = bits ; r8 = bits
@@ -490,7 +328,7 @@ loop1:
pop rbx pop rbx
ret ret
ttmath_rcl2_x64 ENDP rcl2_x64 ENDP
;---------------------------------------- ;----------------------------------------
@@ -498,7 +336,7 @@ ttmath_rcl2_x64 ENDP
;---------------------------------------- ;----------------------------------------
ttmath_rcr2_x64 PROC rcr2_x64 PROC
; rcx = p1 ; rcx = p1
; rdx = nSize ; rdx = nSize
; r8 = bits ; r8 = bits
@@ -543,6 +381,6 @@ loop1:
ret ret
ttmath_rcr2_x64 ENDP rcr2_x64 ENDP
END END