35 Commits
0.8.4 ... 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
53547cfab5 * added: global Gamma() function
* added:   gamma() function to the parser
* added:   Big::IsInteger() method
           returns true if the value is integer
* added:   CGamma<ValueType> class
           is used with Gamma() and Factorial() in multithreaded environment
* changed: Factorial() is using the Gamma() function now
* removed: Parser<>::SetFactorialMax() method
           the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@178 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-16 03:22:29 +00:00
d3a64b79ca 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)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@177 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-07-02 01:04:25 +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
c70a947c07 updated changelog to previous commit
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@164 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-16 18:33:20 +00:00
8972fdfdb3 fixed: Sqrt(), Root() and Factorial() didn't correctly treat the NaN flag
fixed: some methods should set 'err_improper_argument' when the argument is a NaN object
       (was: err_overflow)
changed: version of the library: 0.8.5 now



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@163 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-16 18:31:39 +00:00
019a902fed changed: small optimization in Big::ExpSurrounding0() and Big::LnSurrounding1()
the remainder from a division '%' was changed with a bitwise And operation '&'
         ((i % 5) == 0) was changed to: ((i & 3) == 0) - it means ((i % 4) == 0)
         now the test if performed after 4 iterations (early were after 5 iterations)
         we can do that when the divisor is a power of 2
changed: optimization in Factorial()
         we're testing WasStopSignal() only after a few iterations
         it's faster now about 4 times on GCC 4.3.3 (when stop object is provided to the factorial)


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@161 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-14 19:55:15 +00:00
74553109a5 fixed: (performance) in Big::LnSurrounding1() and Big::ExpSurrounding0()
we can copy 'old_value = *this' only when 'testing' is true


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@160 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-14 18:45:36 +00:00
9e42a5a9fd fixed: Big::FromDouble() on a 32 bit platform:
SetNaN() should be SetNan() /*compilation error*/


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@158 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 15:03:22 +00:00
1b6858616d fixed: in Big::FromDouble(): SetNaN() should be SetNan();
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@157 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 10:04:50 +00:00
d789ac5396 added: using NaN flag in method Big::ToDouble() and Big::FromDouble()
changed: some cosmetic changes to get rid of warnings generated by 
         MS Visual 2008 when warning level is 4
changed: names of labels in asm code: p to ttmath_loop, end to ttmath_end
         p2 to ttmath_loop2
         Robert Muir reported that there was a confict with boost::end


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@156 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-06-11 02:31:41 +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
bb2583649e added: to Big<> class: support for NaN flag (Not a Number)
bool Big::IsNan() - returns true if the NaN flag is set
       void Big::SetNan() - sets the NaN flag
       The NaN flag is set by default after creating an object:
         Big<1, 2> a;    // NaN is set (it means the object has not a valid number)
         std::cout << a; // cout gives "NaN"
         a = 123;        // now NaN is not set
         std::cout << a; // cout gives "123"
       The NaN is set if there was a carry during calculations
         a.Mul(very_big_value); // a will have a NaN set
	   The NaN is set if an argument is NaN too
	     b.SetNan();
	     a.Add(b);  // a will have NaN because b has NaN too
       If you try to do something on a NaN object, the result is a NaN too
         a.SetNan();
         a.Add(2);  // a is still a NaN 
       The NaN is set if you use incorrect arguments
         a.Ln(-10); // a will have the NaN flag
       The only way to clear the NaN flag is to assign a correct value or other correct object
         supposing 'a' has NaN flag, to remove the flag you can either:
         a = 10;
         a.FromInt(30);
         a.SetOne(); 
         a.FromBig(other_object_without_nan);
         etc.
changed: renamed macro CONSTANTSGENERATOR to TTMATH_CONSTANTSGENERATOR



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@152 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-26 23:13:22 +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
5e5a106605 changed: a little changes in all asm code
it should be a little faster


git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@149 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-17 00:04:42 +00:00
eaa19dd46a added: uint UInt::Mul3(const UInt<value_size> & ss2)
void UInt::Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
         a new multiplication algorithm: Karatsuba multiplication,
         on a vector UInt<100> with all items different from zero this algorithm is faster
         about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from
         zero this algorithm is faster more than 5 times than Mul2Big()
         (measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE)
added:   uint MulFastest(const UInt<value_size> & ss2)
         void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
         those methods are trying to select the fastest multiplication algorithm
changed: uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
         void MulBig(const UInt<value_size> & ss2, UInt<value_size*2> & result, uint algorithm = 100)
         those methods by default use MulFastest() and MulFastestBig()
changed: changed a little Mul2Big() to cooperate with Mul3Big()
changed: names of methods in macros TTMATH_LOG()
added:   uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
         uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
         three forms: asm x86, asm x86_64, no-asm
         those methods are used by the Karatsuba multiplication algorithm



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@148 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-15 22:27:04 +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
939d0f7519 fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x)
fixed:   global function Mod(x) didn't set an ErrorCode object
fixed:   global function Round() didn't test a carry
         now it sets ErrorCode object
changed: function Sin(x) to Sin(x, ErrorCode * err=0)
         when x was very big the function returns zero
         now it sets ErrorCode object to err_overflow
         and the result is undefined
         the same is to Cos() function
changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
         should be a little accurate especially on a very big 'x'



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@143 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-11 01:50:00 +00:00
05b67e7103 changed: corrected spaces in changelog
git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@142 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-05-09 01:34:45 +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
15 changed files with 16853 additions and 14147 deletions

View File

@@ -1,3 +1,86 @@
Version 0.9.0 prerelease (2009.07.16):
* added: support for wide characters (wchar_t)
wide characters are used when macro TTMATH_USE_WCHAR is defined
this macro is defined automatically when there is macro UNICODE or _UNICODE defined
some types have been changed
char -> tt_char
std::string -> tt_string
std::ostringstream -> tt_ostringstream
std::ostream -> tt_ostream
std::istream -> tt_istream
normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on)
(all typedef's are in ttmathtypes.h)
* added: Big::IsInteger()
returns true if the value is integer (without fraction)
(NaN flag is not checked)
* added: global Gamma() function
* added: gamma() function to the parser
* added: CGamma<ValueType> class
is used with Gamma() and Factorial() in multithreaded environment
* changed: Factorial() is using the Gamma() function now
* removed: Parser<>::SetFactorialMax() method
the factorial() is such a fast now that we don't need the method longer
* removed: ErrorCode::err_too_big_factorial
Version 0.8.5 (2009.06.16):
* fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x)
* fixed: global function Mod(x) didn't set an ErrorCode object
* fixed: global function Round() didn't test a carry
now it sets ErrorCode object
* changed: function Sin(x) to Sin(x, ErrorCode * err=0)
when x was very big the function returns zero
now it sets ErrorCode object to err_overflow
and the result has a NaN flag set
the same is to Cos() function
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
should be a little accurate especially on a very big 'x'
* changed: uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
void MulBig(const UInt<value_size> & ss2, UInt<value_size*2> & result, uint algorithm = 100)
those methods by default use MulFastest() and MulFastestBig()
* changed: changed a little Mul2Big() to cooperate with Mul3Big()
* added: uint UInt::Mul3(const UInt<value_size> & ss2)
void UInt::Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
a new multiplication algorithm: Karatsuba multiplication,
on a vector UInt<100> with all items different from zero this algorithm is faster
about 3 times than Mul2Big(), and on a vector UInt<1000> with all items different from
zero this algorithm is faster more than 5 times than Mul2Big()
(measured on 32bit platform with GCC 4.3.3 with -O3 and -DTTMATH_RELEASE)
* added: uint MulFastest(const UInt<value_size> & ss2)
void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
those methods are trying to select the fastest multiplication algorithm
* added: uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
three forms: asm x86, asm x86_64, no-asm
those methods are used by the Karatsuba multiplication algorithm
* added: to Big<> class: support for NaN flag (Not a Number)
bool Big::IsNan() - returns true if the NaN flag is set
void Big::SetNan() - sets the NaN flag
The NaN flag is set by default after creating an object:
Big<1, 2> a; // NaN is set (it means the object has not a valid number)
std::cout << a; // cout gives "NaN"
a = 123; // now NaN is not set
std::cout << a; // cout gives "123"
The NaN is set if there was a carry during calculations
a.Mul(very_big_value); // a will have a NaN set
The NaN is set if an argument is NaN too
b.SetNan();
a.Add(b); // a will have NaN because b has NaN too
If you try to do something on a NaN object, the result is a NaN too
a.SetNan();
a.Add(2); // a is still a NaN
The NaN is set if you use incorrect arguments
a.Ln(-10); // a will have the NaN flag
The only way to clear the NaN flag is to assign a correct value or other correct object,
supposing 'a' has NaN flag, to remove the flag you can either:
a = 10;
a.FromInt(30);
a.SetOne();
a.FromBig(other_object_without_nan);
etc.
Version 0.8.4 (2009.05.08):
* fixed: UInt::DivInt() didn't check whether the divisor is zero
there was a hardware interruption when the divisor was zero

View File

@@ -1,6 +1,6 @@
o = main.o
CC = g++
CFLAGS = -s -O2 -DCONSTANTSGENERATOR
CFLAGS = -s -O2 -DTTMATH_CONSTANTSGENERATOR
name = gen

View File

@@ -91,7 +91,7 @@ void CalcE()
ttmath::Big<1,400> e;
ttmath::uint steps;
// macro CONSTANTSGENERATOR has to be defined
// macro TTMATH_CONSTANTSGENERATOR has to be defined
e.ExpSurrounding0(1, &steps);
std::cout << "---------------- e ----------------" << std::endl;
e.mantissa.PrintTable(std::cout);
@@ -105,7 +105,7 @@ void CalcLn(int x)
ttmath::Big<1,400> ln;
ttmath::uint steps;
// macro CONSTANTSGENERATOR has to be defined
// macro TTMATH_CONSTANTSGENERATOR has to be defined
ln.LnSurrounding1(x, &steps);
std::cout << "---------------- ln(" << x << ") ----------------" << std::endl;
ln.mantissa.PrintTable(std::cout);

File diff suppressed because it is too large Load Diff

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

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -47,6 +47,10 @@
#include "ttmathuint.h"
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace ttmath
{
@@ -641,8 +645,14 @@ public:
// there can be a carry here when the size of this value is equal one word
// and the 'value' has the highest bit set
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
return 1;
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
return 0;
}
@@ -821,7 +831,7 @@ public:
/*!
a constructor for converting string to this class (with the base=10)
*/
Int(const char * s)
Int(const tt_char * s)
{
FromString(s);
}
@@ -830,7 +840,7 @@ public:
/*!
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() );
}
@@ -869,7 +879,7 @@ public:
/*!
this method converts the value to a string with a base equal 'b'
*/
void ToString(std::string & result, uint b = 10) const
void ToString(tt_string & result, uint b = 10) const
{
if( IsSign() )
{
@@ -890,12 +900,14 @@ public:
/*!
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
"- 12foo" will be translated to -12 too
existing first white characters will be ommited
(between '-' and a first digit can be white characters too)
@@ -904,7 +916,7 @@ public:
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)
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{
bool is_sign = false;
@@ -961,16 +973,16 @@ 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
*/
uint FromString(const std::string & s, uint b = 10)
uint FromString(const tt_string & s, uint b = 10)
{
return FromString( s.c_str() );
return FromString( s.c_str(), b );
}
/*!
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);
@@ -981,7 +993,7 @@ public:
/*!
this operator converts a string into its value (with base = 10)
*/
Int<value_size> & operator=(const std::string & s)
Int<value_size> & operator=(const tt_string & s)
{
FromString( s.c_str() );
@@ -1268,9 +1280,14 @@ public:
*
*/
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l)
/*!
output for standard streams
tt_ostream is either std::ostream or std::wostream
*/
friend tt_ostream & operator<<(tt_ostream & s, const Int<value_size> & l)
{
std::string ss;
tt_string ss;
l.ToString(ss);
s << ss;
@@ -1279,13 +1296,17 @@ public:
}
/*!
input from standard streams
friend std::istream & operator>>(std::istream & s, Int<value_size> & l)
tt_istream is either std::istream or std::wistream
*/
friend tt_istream & operator>>(tt_istream & s, Int<value_size> & l)
{
std::string ss;
tt_string ss;
// char for operator>>
unsigned char z;
// tt_char for operator>>
tt_char z;
// operator>> omits white characters if they're set for ommiting
s >> z;
@@ -1300,7 +1321,7 @@ public:
while( s.good() && UInt<value_size>::CharToDigit(z, 10)>=0 )
{
ss += z;
z = s.get();
z = static_cast<tt_char>(s.get());
}
// we're leaving the last readed character
@@ -1316,5 +1337,9 @@ public:
} // namespace
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
#endif

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -47,6 +47,7 @@
#include "ttmathtypes.h"
#include <string>
#include <vector>
#include <list>
#include <map>
@@ -73,18 +74,19 @@ public:
struct Item
{
// name of a variable of a function
std::string value;
// (either std::string or std::wstring)
tt_string value;
// number of parameters required by the function
// (if there's a variable this 'param' is ignored)
int param;
Item() {}
Item(const std::string & v, int p) : value(v), param(p) {}
Item(const tt_string & v, int p) : value(v), param(p) {}
};
// 'Table' is the type of our table
typedef std::map<std::string, Item> Table;
typedef std::map<tt_string, Item> Table;
typedef Table::iterator Iterator;
typedef Table::const_iterator CIterator;
@@ -112,7 +114,7 @@ public:
/*!
this method returns true if the name can be as a name of an object
*/
static bool IsNameCorrect(const std::string & name)
static bool IsNameCorrect(const tt_string & name)
{
if( name.empty() )
return false;
@@ -120,7 +122,7 @@ public:
if( !CorrectCharacter(name[0], false) )
return false;
std::string::const_iterator i=name.begin();
tt_string::const_iterator i=name.begin();
for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) )
@@ -133,7 +135,7 @@ public:
/*!
this method returns true if such an object is defined (name exists)
*/
bool IsDefined(const std::string & name)
bool IsDefined(const tt_string & name)
{
Iterator i = table.find(name);
@@ -148,7 +150,7 @@ public:
/*!
this method adds one object (variable of function) into the table
*/
ErrorCode Add(const std::string & name, const std::string & value, int param = 0)
ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0)
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -205,7 +207,7 @@ public:
/*!
this method changes the value and the number of parameters for a specific object
*/
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0)
ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0)
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -225,7 +227,7 @@ public:
/*!
this method changes the name of a specific object
*/
ErrorCode EditName(const std::string & old_name, const std::string & new_name)
ErrorCode EditName(const tt_string & old_name, const tt_string & new_name)
{
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
return err_incorrect_name;
@@ -256,7 +258,7 @@ public:
/*!
this method deletes an object
*/
ErrorCode Delete(const std::string & name)
ErrorCode Delete(const tt_string & name)
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -275,7 +277,7 @@ public:
/*!
this method gets the value of a specific object
*/
ErrorCode GetValue(const std::string & name, std::string & value) const
ErrorCode GetValue(const tt_string & name, tt_string & value) const
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -298,7 +300,7 @@ public:
this method gets the value of a specific object
(this version is used for not copying the whole string)
*/
ErrorCode GetValue(const std::string & name, const char ** value) const
ErrorCode GetValue(const tt_string & name, const tt_char ** value) const
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -321,7 +323,7 @@ public:
this method gets the value and the number of parameters
of a specific object
*/
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -347,7 +349,7 @@ public:
of a specific object
(this version is used for not copying the whole string)
*/
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const
ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const
{
if( !IsNameCorrect(name) )
return err_incorrect_name;
@@ -430,7 +432,7 @@ public:
*/
History()
{
buffer_max_size = 10;
buffer_max_size = 15;
}
@@ -487,10 +489,118 @@ public:
return false;
}
/*!
this methods deletes an item
we assume that there is only one item with the 'key'
(this methods removes the first one)
*/
bool Remove(const ValueType & key)
{
typename buffer_type::iterator i = buffer.begin();
for( ; i != buffer.end() ; ++i )
{
if( i->key == key )
{
buffer.erase(i);
return true;
}
}
return false;
}
}; // end of class History
/*!
this is an auxiliary class used when calculating Gamma() or Factorial()
in multithreaded environment you can provide an object of this class to
the Gamma() or Factorial() function, e.g;
typedef Big<1, 3> MyBig;
MyBig x = 123456;
CGamma<MyBig> cgamma;
std::cout << Gamma(x, cgamma);
each thread should have its own CGamma<> object
in a single-thread environment a CGamma<> object is a static variable
in a second version of Gamma() and you don't have to explicitly use it, e.g.
typedef Big<1, 3> MyBig;
MyBig x = 123456;
std::cout << Gamma(x);
*/
template<class ValueType>
struct CGamma
{
/*!
this table holds factorials
1
1
2
6
24
120
720
.......
*/
std::vector<ValueType> fact;
/*!
this table holds Bernoulli numbers
1
-0.5
0.166666666666666666666666667
0
-0.0333333333333333333333333333
0
0.0238095238095238095238095238
0
-0.0333333333333333333333333333
0
0.075757575757575757575757576
.....
*/
std::vector<ValueType> bern;
/*!
here we store some calculated values
(this is for speeding up, if the next argument of Gamma() or Factorial()
is in the 'history' then the result we are not calculating but simply
return from the 'history' object)
*/
History<ValueType> history;
/*!
this method prepares some coefficients: factorials and Bernoulli numbers
stored in 'fact' and 'bern' objects
how many values should be depends on the size of the mantissa - if
the mantissa is larger then we must calculate more values
for a mantissa which consists of 256 bits (8 words on a 32bit platform)
we have to calculate about 30 values (the size of fact and bern will be 30),
and for a 2048 bits mantissa we have to calculate 306 coefficients
you don't have to call this method, these coefficients will be automatically calculated
when they are needed
you must note that calculating of the coefficients is a little time-consuming operation,
(especially when the mantissa is large) and first called to Gamma() or Factorial()
can take more time than next calls, and in the end this is the point when InitAll()
comes in handy: you can call this method somewhere at the beginning of your program
*/
void InitAll();
// definition is in ttmath.h
};
} // namespace

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Mathematical Library
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -45,7 +45,7 @@
\brief A mathematical parser
*/
#include <fstream>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
@@ -137,7 +137,6 @@ namespace ttmath
template<class ValueType>
class Parser
{
private:
/*!
@@ -256,7 +255,7 @@ public:
bool function;
// if function is true
std::string function_name;
tt_string function_name;
/*
the sign of value
@@ -311,10 +310,11 @@ ErrorCode error;
/*!
pointer to the currently reading char
it's either char* or wchar_t*
when an error has occured it may be used to count the index of the wrong character
*/
const char * pstring;
const tt_char * pstring;
/*!
@@ -351,7 +351,7 @@ const Objects * puser_variables;
const Objects * puser_functions;
typedef std::map<std::string, ValueType> FunctionLocalVariables;
typedef std::map<tt_string, ValueType> FunctionLocalVariables;
/*!
a pointer to the local variables of a function
@@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
/*!
a temporary set using during parsing user defined variables
*/
std::set<std::string> visited_variables;
std::set<tt_string> visited_variables;
/*!
a temporary set using during parsing user defined functions
*/
std::set<std::string> visited_functions;
std::set<tt_string> visited_functions;
@@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
table of mathematic functions
this map consists of:
std::string - function's name
tt_string - function's name
pfunction - pointer to specific function
*/
typedef std::map<std::string, pfunction> FunctionsTable;
typedef std::map<tt_string, pfunction> FunctionsTable;
FunctionsTable functions_table;
@@ -407,10 +407,10 @@ FunctionsTable functions_table;
table of mathematic operators
this map consists of:
std::string - operators's name
tt_string - operators's name
MatOperator::Type - type of the operator
*/
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable;
typedef std::map<tt_string, typename MatOperator::Type> OperatorsTable;
OperatorsTable operators_table;
@@ -418,18 +418,17 @@ OperatorsTable operators_table;
table of mathematic variables
this map consists of:
std::string - variable's name
tt_string - variable's name
pfunction_var - pointer to specific function which returns value of variable
*/
typedef std::map<std::string, pfunction_var> VariablesTable;
typedef std::map<tt_string, pfunction_var> VariablesTable;
VariablesTable variables_table;
/*!
you can't calculate the factorial if the argument is greater than 'factorial_max'
default value is zero which means there are not any limitations
some coefficients used when calculating the gamma (or factorial) function
*/
ValueType factorial_max;
CGamma<ValueType> cgamma;
/*!
@@ -456,7 +455,7 @@ void SkipWhiteCharacters()
/*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name)
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name)
{
if( variable )
{
@@ -474,7 +473,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
/*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name)
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name)
{
if( variable )
visited_variables.insert( name );
@@ -486,7 +485,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
/*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name)
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name)
{
if( variable )
visited_variables.erase( name );
@@ -505,7 +504,8 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
(there can be a recurrence here therefore we're using 'visited_variables'
and 'visited_functions' sets to make a stop condition)
*/
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0)
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tt_string & name, const tt_char * new_string,
FunctionLocalVariables * local_variables = 0)
{
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
RecurrenceParsingVariablesOrFunction_AddName(variable, name);
@@ -548,12 +548,12 @@ public:
/*!
this method returns the user-defined value of a variable
*/
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result)
bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result)
{
if( !puser_variables )
return false;
const char * string_value;
const tt_char * string_value;
if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
return false;
@@ -567,7 +567,7 @@ return true;
/*!
this method returns the value of a local variable of a function
*/
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result)
bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result)
{
if( !pfunction_local_variables )
return false;
@@ -589,7 +589,7 @@ return true;
we make an object of type ValueType then call a method which
sets the correct value in it and finally we'll return the object
*/
ValueType GetValueOfVariable(const std::string & variable_name)
ValueType GetValueOfVariable(const tt_string & variable_name)
{
ValueType result;
@@ -600,7 +600,7 @@ ValueType result;
return result;
typename std::map<std::string, pfunction_var>::iterator i =
typename std::map<tt_string, pfunction_var>::iterator i =
variables_table.find(variable_name);
if( i == variables_table.end() )
@@ -674,6 +674,20 @@ return result;
}
void Gamma(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
ErrorCode err;
result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok)
Error( err );
}
/*!
factorial
result = 1 * 2 * 3 * 4 * .... * x
@@ -685,10 +699,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
ErrorCode err;
if( !factorial_max.IsZero() && stack[sindex].value > factorial_max )
Error( err_too_big_factorial );
result = ttmath::Factorial(stack[sindex].value, &err, pstop_calculating);
result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating);
if(err != err_ok)
Error( err );
@@ -708,7 +719,11 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) );
ErrorCode err;
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
}
void Cos(int sindex, int amount_of_args, ValueType & result)
@@ -716,7 +731,11 @@ void Cos(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) );
ErrorCode err;
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
}
void Tan(int sindex, int amount_of_args, ValueType & result)
@@ -757,7 +776,10 @@ void Round(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Round(stack[sindex].value);
result = stack[sindex].value;
if( result.Round() )
Error( err_overflow );
}
@@ -973,7 +995,7 @@ void Not(int sindex, int amount_of_args, ValueType & result)
void DegToRad(int sindex, int amount_of_args, ValueType & result)
{
ErrorCode err;
ErrorCode err = err_ok;
if( amount_of_args == 1 )
{
@@ -1052,7 +1074,7 @@ void RadToGrad(int sindex, int amount_of_args, ValueType & result)
void DegToGrad(int sindex, int amount_of_args, ValueType & result)
{
ErrorCode err;
ErrorCode err = err_ok;
if( amount_of_args == 1 )
{
@@ -1333,17 +1355,34 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
}
/*!
we use such a method because 'wvsprintf' is not everywhere defined
*/
void Sprintf(tt_char * buffer, int par)
{
char buf[30]; // char, not tt_char
int i;
sprintf(buf, "%d", par);
for(i=0 ; buf[i] != 0 ; ++i)
buffer[i] = buf[i];
buffer[i] = 0;
}
/*!
this method returns the value from a user-defined function
(look at the description in 'CallFunction(...)')
*/
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex)
bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex)
{
if( !puser_functions )
return false;
const char * string_value;
const tt_char * string_value;
int param;
if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
@@ -1357,15 +1396,17 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
if( amount_of_args > 0 )
{
char buffer[20];
tt_char buffer[30];
// x = x1
sprintf(buffer,"x");
buffer[0] = 'x';
buffer[1] = 0;
local_variables.insert( std::make_pair(buffer, stack[sindex].value) );
for(int i=0 ; i<amount_of_args ; ++i)
{
sprintf(buffer,"x%d",i+1);
buffer[0] = 'x';
Sprintf(buffer+1, i+1);
local_variables.insert( std::make_pair(buffer, stack[sindex + i*2].value) );
}
}
@@ -1389,7 +1430,7 @@ return true;
result will be stored in 'stack[sindex-1].value'
(we don't have to set the correct type of this element, it'll be set later)
*/
void CallFunction(const std::string & function_name, int amount_of_args, int sindex)
void CallFunction(const tt_string & function_name, int amount_of_args, int sindex)
{
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
return;
@@ -1415,9 +1456,9 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
function_name - name of the function
pf - pointer to the function (to the wrapper)
*/
void InsertFunctionToTable(const char * function_name, pfunction pf)
void InsertFunctionToTable(const tt_char * function_name, pfunction pf)
{
functions_table.insert( std::make_pair(std::string(function_name), pf));
functions_table.insert( std::make_pair(tt_string(function_name), pf));
}
@@ -1428,9 +1469,9 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
variable_name - name of the function
pf - pointer to the function
*/
void InsertVariableToTable(const char * variable_name, pfunction_var pf)
void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf)
{
variables_table.insert( std::make_pair(std::string(variable_name), pf));
variables_table.insert( std::make_pair(tt_string(variable_name), pf));
}
@@ -1439,67 +1480,65 @@ void InsertVariableToTable(const char * variable_name, pfunction_var pf)
*/
void CreateFunctionsTable()
{
/*
names of functions should consist of small letters
*/
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
InsertFunctionToTable("int", &Parser<ValueType>::Int);
InsertFunctionToTable("round", &Parser<ValueType>::Round);
InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
InsertFunctionToTable("log", &Parser<ValueType>::Log);
InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
InsertFunctionToTable("max", &Parser<ValueType>::Max);
InsertFunctionToTable("min", &Parser<ValueType>::Min);
InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
InsertFunctionToTable("if", &Parser<ValueType>::If);
InsertFunctionToTable("or", &Parser<ValueType>::Or);
InsertFunctionToTable("and", &Parser<ValueType>::And);
InsertFunctionToTable("not", &Parser<ValueType>::Not);
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
InsertFunctionToTable("root", &Parser<ValueType>::Root);
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
InsertFunctionToTable("band", &Parser<ValueType>::BitAnd);
InsertFunctionToTable("bor", &Parser<ValueType>::BitOr);
InsertFunctionToTable("bxor", &Parser<ValueType>::BitXor);
InsertFunctionToTable("sum", &Parser<ValueType>::Sum);
InsertFunctionToTable("avg", &Parser<ValueType>::Avg);
InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser<ValueType>::Gamma);
InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser<ValueType>::Factorial);
InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser<ValueType>::Abs);
InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser<ValueType>::Sin);
InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser<ValueType>::Cos);
InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser<ValueType>::Tan);
InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser<ValueType>::Tan);
InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser<ValueType>::Cot);
InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser<ValueType>::Cot);
InsertFunctionToTable(TTMATH_TEXT("int"), &Parser<ValueType>::Int);
InsertFunctionToTable(TTMATH_TEXT("round"), &Parser<ValueType>::Round);
InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser<ValueType>::Ln);
InsertFunctionToTable(TTMATH_TEXT("log"), &Parser<ValueType>::Log);
InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser<ValueType>::Exp);
InsertFunctionToTable(TTMATH_TEXT("max"), &Parser<ValueType>::Max);
InsertFunctionToTable(TTMATH_TEXT("min"), &Parser<ValueType>::Min);
InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser<ValueType>::ASin);
InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser<ValueType>::ACos);
InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser<ValueType>::ATan);
InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser<ValueType>::ATan);
InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser<ValueType>::ACot);
InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser<ValueType>::ACot);
InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser<ValueType>::Sgn);
InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser<ValueType>::Mod);
InsertFunctionToTable(TTMATH_TEXT("if"), &Parser<ValueType>::If);
InsertFunctionToTable(TTMATH_TEXT("or"), &Parser<ValueType>::Or);
InsertFunctionToTable(TTMATH_TEXT("and"), &Parser<ValueType>::And);
InsertFunctionToTable(TTMATH_TEXT("not"), &Parser<ValueType>::Not);
InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser<ValueType>::DegToRad);
InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser<ValueType>::RadToDeg);
InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser<ValueType>::DegToDeg);
InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser<ValueType>::GradToRad);
InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser<ValueType>::RadToGrad);
InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser<ValueType>::DegToGrad);
InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser<ValueType>::GradToDeg);
InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser<ValueType>::Ceil);
InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser<ValueType>::Floor);
InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser<ValueType>::Sqrt);
InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser<ValueType>::Sinh);
InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser<ValueType>::Cosh);
InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser<ValueType>::Tanh);
InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser<ValueType>::Coth);
InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser<ValueType>::Coth);
InsertFunctionToTable(TTMATH_TEXT("root"), &Parser<ValueType>::Root);
InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser<ValueType>::ASinh);
InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser<ValueType>::ACosh);
InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser<ValueType>::ATanh);
InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser<ValueType>::ACoth);
InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser<ValueType>::ACoth);
InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable(TTMATH_TEXT("band"), &Parser<ValueType>::BitAnd);
InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser<ValueType>::BitOr);
InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser<ValueType>::BitXor);
InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser<ValueType>::Sum);
InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser<ValueType>::Avg);
}
@@ -1508,11 +1547,8 @@ void CreateFunctionsTable()
*/
void CreateVariablesTable()
{
/*
names of variables should consist of small letters
*/
InsertVariableToTable("pi", &ValueType::SetPi);
InsertVariableToTable("e", &ValueType::SetE);
InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi);
InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE);
}
@@ -1538,7 +1574,7 @@ return c;
what should be returned is tested just by a '(' character that means if there's
a '(' character after a name that function returns 'true'
*/
bool ReadName(std::string & result)
bool ReadName(tt_string & result)
{
int character;
@@ -1555,7 +1591,7 @@ int character;
do
{
result += character;
result += static_cast<tt_char>( character );
character = * ++pstring;
}
while( (character>='a' && character<='z') ||
@@ -1610,7 +1646,7 @@ return false;
*/
bool ReadVariableOrFunction(Item & result)
{
std::string name;
tt_string name;
bool is_it_name_of_function = ReadName(name);
if( is_it_name_of_function )
@@ -1639,7 +1675,7 @@ return is_it_name_of_function;
*/
void ReadValue(Item & result, int reading_base)
{
const char * new_stack_pointer;
const tt_char * new_stack_pointer;
bool value_read;
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
@@ -1812,9 +1848,9 @@ return 0;
}
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type)
void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type)
{
operators_table.insert( std::make_pair(name, type) );
operators_table.insert( std::make_pair(tt_string(name), type) );
}
@@ -1823,19 +1859,19 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type
*/
void CreateMathematicalOperatorsTable()
{
InsertOperatorToTable(std::string("||"), MatOperator::lor);
InsertOperatorToTable(std::string("&&"), MatOperator::land);
InsertOperatorToTable(std::string("!="), MatOperator::neq);
InsertOperatorToTable(std::string("=="), MatOperator::eq);
InsertOperatorToTable(std::string(">="), MatOperator::get);
InsertOperatorToTable(std::string("<="), MatOperator::let);
InsertOperatorToTable(std::string(">"), MatOperator::gt);
InsertOperatorToTable(std::string("<"), MatOperator::lt);
InsertOperatorToTable(std::string("-"), MatOperator::sub);
InsertOperatorToTable(std::string("+"), MatOperator::add);
InsertOperatorToTable(std::string("/"), MatOperator::div);
InsertOperatorToTable(std::string("*"), MatOperator::mul);
InsertOperatorToTable(std::string("^"), MatOperator::pow);
InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor);
InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land);
InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq);
InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq);
InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get);
InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let);
InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt);
InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt);
InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub);
InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add);
InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div);
InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul);
InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow);
}
@@ -1845,12 +1881,12 @@ void CreateMathematicalOperatorsTable()
e.g.
true when str1="test" and str2="te"
*/
bool IsSubstring(const std::string & str1, const std::string & str2)
bool IsSubstring(const tt_string & str1, const tt_string & str2)
{
if( str2.length() > str1.length() )
return false;
for(std::string::size_type i=0 ; i<str2.length() ; ++i)
for(tt_string::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] )
return false;
@@ -1863,7 +1899,7 @@ return true;
*/
void ReadMathematicalOperator(Item & result)
{
std::string oper;
tt_string oper;
typename OperatorsTable::iterator iter_old, iter_new;
iter_old = operators_table.end();
@@ -2393,7 +2429,6 @@ Parser(): default_stack_size(100)
base = 10;
deg_rad_grad = 1;
error = err_ok;
factorial_max.SetZero();
CreateFunctionsTable();
CreateVariablesTable();
@@ -2413,7 +2448,6 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
base = p.base;
deg_rad_grad = p.deg_rad_grad;
error = err_ok;
factorial_max = p.factorial_max;
/*
we don't have to call 'CreateFunctionsTable()' etc.
@@ -2495,22 +2529,11 @@ void SetFunctions(const Objects * pf)
}
/*!
you will not be allowed to calculate the factorial
if its argument is greater than 'm'
there'll be: ErrorCode::err_too_big_factorial
default 'factorial_max' is zero which means you can calculate what you want to
*/
void SetFactorialMax(const ValueType & m)
{
factorial_max = m;
}
/*!
the main method using for parsing string
*/
ErrorCode Parse(const char * str)
ErrorCode Parse(const tt_char * str)
{
stack_index = 0;
pstring = str;
@@ -2533,11 +2556,11 @@ return error;
}
};
} // namespace

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -54,7 +54,7 @@
#include <stdexcept>
#include <sstream>
#include <vector>
/*!
the version of the library
@@ -63,9 +63,9 @@
if zero that means this is the release version of the library
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 4
#define TTMATH_PRERELEASE_VER 0
#define TTMATH_MINOR_VER 9
#define TTMATH_REVISION_VER 0
#define TTMATH_PRERELEASE_VER 1
/*!
@@ -120,6 +120,7 @@ namespace ttmath
typedef unsigned int uint;
typedef signed int sint;
/*!
this type is twice bigger than uint
(64bit on a 32bit platforms)
@@ -128,43 +129,39 @@ namespace ttmath
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
but only on a 32bit platform
*/
#ifdef TTMATH_NOASM
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)
*/
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
/*!
the max value of the unsigned 32bit word (2^32 - 1)
(all bits equal one)
*/
#define TTMATH_UINT_MAX_VALUE 4294967295u
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
/*!
the number of words (32bit words on 32bit platform)
which are kept in built-in variables for a Big<> type
(these variables are defined in ttmathbig.h)
*/
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 256u;
#else
/*!
on 64bit platforms one word (uint, sint) will be equal 64bits
*/
typedef unsigned long uint;
typedef signed long sint;
#if defined(_MSC_VER)
typedef unsigned __int64 uint;
typedef signed __int64 sint;
#else
typedef unsigned long long uint;
typedef signed long long sint;
#endif
/*!
on 64bit platform we do not define ulint
sizeof(long long) is 8 (64bit) but we need 128bit
@@ -174,33 +171,61 @@ namespace ttmath
*/
//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)
*/
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
const uint TTMATH_UINT_HIGHEST_BIT = 0x8000000000000000ul;
/*!
the max value of the unsigned 64bit word (2^64 - 1)
(all bits equal one)
*/
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffffffffffful;
/*!
the number of words (64bit words on 64bit platforms)
which are kept in built-in variables for a Big<> type
(these variables are defined in ttmathbig.h)
*/
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
const uint TTMATH_BUILTIN_VARIABLES_SIZE = 128ul;
#endif
const uint TTMATH_BITS_PER_UINT = (sizeof(uint)*8);
}
#if defined(UNICODE) || defined(_UNICODE)
#define TTMATH_USE_WCHAR
#endif
#ifdef TTMATH_USE_WCHAR
typedef wchar_t tt_char;
typedef std::wstring tt_string;
typedef std::wostringstream tt_ostringstream;
typedef std::wostream tt_ostream;
typedef std::wistream tt_istream;
#define TTMATH_TEXT_HELPER(txt) L##txt
#else
typedef char tt_char;
typedef std::string tt_string;
typedef std::ostringstream tt_ostringstream;
typedef std::ostream tt_ostream;
typedef std::istream tt_istream;
#define TTMATH_TEXT_HELPER(txt) txt
#endif
#define TTMATH_TEXT(txt) TTMATH_TEXT_HELPER(txt)
/*!
characters which represent the comma operator
@@ -237,6 +262,29 @@ namespace ttmath
/*!
this is a limit when calculating Karatsuba multiplication
if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE
the Karatsuba algorithm will use standard schoolbook multiplication
*/
#ifdef __GNUC__
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3
#else
#define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5
#endif
/*!
this is a special value used when calculating the Gamma(x) function
if x is greater than this value then the Gamma(x) will be calculated using
some kind of series
don't use smaller values than about 100
*/
#define TTMATH_GAMMA_BOUNDARY 2000
namespace ttmath
{
@@ -271,7 +319,6 @@ namespace ttmath
err_object_exists,
err_unknown_object,
err_still_calculating,
err_too_big_factorial,
err_in_short_form_used_function
};
@@ -302,20 +349,20 @@ namespace ttmath
*/
class ExceptionInfo
{
const char * file;
const tt_char * file;
int line;
public:
ExceptionInfo() : file(0), line(0) {}
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
ExceptionInfo(const tt_char * f, int l) : file(f), line(l) {}
std::string Where() const
tt_string Where() const
{
if( !file )
return "unknown";
return TTMATH_TEXT("unknown");
std::ostringstream result;
result << file << ":" << line;
tt_ostringstream result;
result << file << TTMATH_TEXT(":") << line;
return result.str();
}
@@ -329,7 +376,7 @@ namespace ttmath
can throw an exception of this type
If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with
from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used)
@@ -349,7 +396,7 @@ namespace ttmath
foo.Add(foo);
but there are only few methods which can do that
*/
class ReferenceError : public std::logic_error, ExceptionInfo
class ReferenceError : public std::logic_error, public ExceptionInfo
{
public:
@@ -357,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::string Where() const
tt_string Where() const
{
return ExceptionInfo::Where();
}
@@ -377,11 +424,11 @@ namespace ttmath
of this type
if you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with
from using method Where() (it returns std::string (or std::wstring) with
the name and the line of a file where the macro TTMATH_ASSERT
was used)
*/
class RuntimeError : public std::runtime_error, ExceptionInfo
class RuntimeError : public std::runtime_error, public ExceptionInfo
{
public:
@@ -389,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::string Where() const
tt_string Where() const
{
return ExceptionInfo::Where();
}
@@ -409,11 +456,22 @@ namespace ttmath
#if defined(__FILE__) && defined(__LINE__)
#ifdef TTMATH_USE_WCHAR
#define TTMATH_FILE_HELPER2(arg) L##arg
#define TTMATH_FILE_HELPER(x) TTMATH_FILE_HELPER2(x)
#define TTMATH_FILE TTMATH_FILE_HELPER(__FILE__)
#else
#define TTMATH_FILE __FILE__
#endif
#define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
if( &(expression) == this ) throw ttmath::ReferenceError(TTMATH_FILE, __LINE__);
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
#define TTMATH_VERIFY(expression) \
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
#else
@@ -422,19 +480,32 @@ namespace ttmath
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw RuntimeError();
#define TTMATH_VERIFY(expression) \
if( !(expression) ) throw RuntimeError();
#endif
#else
#define TTMATH_REFERENCE_ASSERT(expression)
#define TTMATH_ASSERT(expression)
#define TTMATH_VERIFY(expression) (void)(expression);
#endif
#if !defined(LOG_PRINTF)
#define LOG_PRINTF printf
#endif
#ifdef TTMATH_DEBUG_LOG
#define TTMATH_LOG(msg) \
#ifdef TTMATH_USE_WCHAR
#define TTMATH_LOG_HELPER(msg) \
PrintLog(L##msg, std::wcout);
#else
#define TTMATH_LOG_HELPER(msg) \
PrintLog(msg, std::cout);
#endif
#define TTMATH_LOG(msg) TTMATH_LOG_HELPER(msg)
#else
@@ -443,7 +514,9 @@ namespace ttmath
#endif
} // namespace
#endif

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -40,6 +40,7 @@
#ifndef headerfilettmathuint
#define headerfilettmathuint
/*!
\file ttmathuint.h
\brief template class UInt<uint>
@@ -48,9 +49,12 @@
#include <iostream>
#include <iomanip>
#include "ttmathtypes.h"
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
/*!
\brief a namespace for the TTMath library
@@ -84,7 +88,10 @@ public:
it prints the table in a nice form of several columns
*/
void PrintTable(std::ostream & output) const
#ifndef TTMATH_USE_WCHAR
// gcc has a problem with std::setfill when wchar_t is used
void PrintTable(tt_ostream & output) const
{
// how many columns there'll be
const int columns = 8;
@@ -92,7 +99,7 @@ public:
int c = 1;
for(int i=value_size-1 ; i>=0 ; --i)
{
output << "0x" << std::setfill('0');
output << TTMATH_TEXT("0x") << std::setfill('0');
#ifdef TTMATH_PLATFORM32
output << std::setw(8);
@@ -104,7 +111,7 @@ public:
if( i>0 )
{
output << ", ";
output << TTMATH_TEXT(", ");
if( ++c > columns )
{
@@ -116,14 +123,14 @@ public:
output << std::dec << std::endl;
}
#endif
void PrintLog(const char * msg, std::ostream & output) const
void PrintLog(const tt_char * msg, tt_ostream & output) const
{
output << msg << std::endl;
for(uint i=0 ; i<value_size ; ++i)
output << " table[" << i << "]: " << table[i] << std::endl;
output << TTMATH_TEXT(" table[") << i << TTMATH_TEXT("]: ") << table[i] << std::endl;
}
@@ -840,8 +847,10 @@ public:
/*!
the multiplication 'this' = 'this' * ss2
algorithm: 100 - means automatically choose the fastest algorithm
*/
uint Mul(const UInt<value_size> & ss2, uint algorithm = 2)
uint Mul(const UInt<value_size> & ss2, uint algorithm = 100)
{
switch( algorithm )
{
@@ -849,8 +858,14 @@ public:
return Mul1(ss2);
case 2:
default:
return Mul2(ss2);
case 3:
return Mul3(ss2);
case 100:
default:
return MulFastest(ss2);
}
}
@@ -860,10 +875,12 @@ public:
since the 'result' is twice bigger than 'this' and 'ss2'
this method never returns a carry
algorithm: 100 - means automatically choose the fastest algorithm
*/
void MulBig(const UInt<value_size> & ss2,
UInt<value_size*2> & result,
uint algorithm = 2)
uint algorithm = 100)
{
switch( algorithm )
{
@@ -871,8 +888,14 @@ public:
return Mul1Big(ss2, result);
case 2:
default:
return Mul2Big(ss2, result);
case 3:
return Mul3Big(ss2, result);
case 100:
default:
return MulFastestBig(ss2, result);
}
}
@@ -964,7 +987,7 @@ public:
uint Mul2(const UInt<value_size> & ss2)
{
UInt<value_size*2> result;
uint i;
uint i, c = 0;
Mul2Big(ss2, result);
@@ -975,11 +998,14 @@ public:
// testing carry
for( ; i<value_size*2 ; ++i)
if( result.table[i] != 0 )
return 1;
{
c = 1;
break;
}
TTMATH_LOG("UInt::Mul2")
return 0;
return c;
}
@@ -991,44 +1017,385 @@ public:
*/
void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
{
uint r2,r1;
uint x1size=value_size, x2size=value_size;
Mul2Big2<value_size>(table, ss2.table, result);
TTMATH_LOG("UInt::Mul2Big")
}
private:
/*!
an auxiliary method for calculating the multiplication
arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding
unnecessary copying objects), the result should be taken as a pointer too,
but at the moment there is no method AddTwoInts() which can operate on pointers
*/
template<uint ss_size>
void Mul2Big2(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result)
{
uint x1size = ss_size, x2size = ss_size;
uint x1start = 0, x2start = 0;
if( ss_size > 2 )
{
// if the ss_size is smaller than or equal to 2
// there is no sense to set x1size (and others) to another values
for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size);
for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size);
for(x1start=0 ; x1start<x1size && ss1[x1start]==0 ; ++x1start);
for(x2start=0 ; x2start<x2size && ss2[x2start]==0 ; ++x2start);
}
Mul2Big3<ss_size>(ss1, ss2, result, x1start, x1size, x2start, x2size);
}
/*!
an auxiliary method for calculating the multiplication
*/
template<uint ss_size>
void Mul2Big3(const uint * ss1, const uint * ss2, UInt<ss_size*2> & result, uint x1start, uint x1size, uint x2start, uint x2size)
{
uint r2, r1;
result.SetZero();
if( value_size > 2 )
if( x1size==0 || x2size==0 )
return;
for(uint x1=x1start ; x1<x1size ; ++x1)
{
// if the value_size is smaller than or equal to 2
// there is no sense to set x1size (and others) to another values
for(uint x2=x2start ; x2<x2size ; ++x2)
{
MulTwoWords(ss1[x1], ss2[x2], &r2, &r1);
result.AddTwoInts(r2, r1, x2+x1);
// here will never be a carry
}
}
}
public:
/*!
multiplication: this = this * ss2
This is Karatsuba Multiplication algorithm, we're using it when value_size is greater than
or equal to TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE macro (defined in ttmathuint.h).
If value_size is smaller then we're using Mul2Big() instead.
Karatsuba multiplication:
Assume we have:
this = x = x1*B^m + x0
ss2 = y = y1*B^m + y0
where x0 and y0 are less than B^m
the product from multiplication we can show as:
x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
where
z2 = x1*y1
z1 = x1*y0 + x0*y1
z0 = x0*y0
this is standard schoolbook algorithm with O(n^2), Karatsuba observed that z1 can be given in other form:
z1 = (x1 + x0)*(y1 + y0) - z2 - z0 / z1 = (x1*y1 + x1*y0 + x0*y1 + x0*y0) - x1*y1 - x0*y0 = x1*y0 + x0*y1 /
and to calculate the multiplication we need only three multiplications (with some additions and subtractions)
Our objects 'this' and 'ss2' we divide into two parts and by using recurrence we calculate the multiplication.
Karatsuba multiplication has O( n^(ln(3)/ln(2)) )
*/
uint Mul3(const UInt<value_size> & ss2)
{
UInt<value_size*2> result;
uint i, c = 0;
Mul3Big(ss2, result);
// copying result
for(i=0 ; i<value_size ; ++i)
table[i] = result.table[i];
// testing carry
for( ; i<value_size*2 ; ++i)
if( result.table[i] != 0 )
{
c = 1;
break;
}
TTMATH_LOG("UInt::Mul3")
return c;
}
/*!
multiplication: result = this * ss2
result is twice bigger than this and ss2,
this method never returns carry,
(Karatsuba multiplication)
*/
void Mul3Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
{
Mul3Big2<value_size>(table, ss2.table, result.table);
TTMATH_LOG("UInt::Mul3Big")
}
private:
/*!
an auxiliary method for calculating the Karatsuba multiplication
result_size is equal ss_size*2
*/
template<uint ss_size>
void Mul3Big2(const uint * ss1, const uint * ss2, uint * result)
{
const uint * x1, * x0, * y1, * y0;
if( ss_size>1 && ss_size<TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
{
UInt<ss_size*2> res;
Mul2Big2<ss_size>(ss1, ss2, res);
for(uint i=0 ; i<ss_size*2 ; ++i)
result[i] = res.table[i];
return;
}
else
if( ss_size == 1 )
{
return MulTwoWords(*ss1, *ss2, &result[1], &result[0]);
}
if( (ss_size & 1) == 1 )
{
// ss_size is odd
x0 = ss1;
y0 = ss2;
x1 = ss1 + ss_size / 2 + 1;
y1 = ss2 + ss_size / 2 + 1;
// the second vectors (x1 and y1) are smaller about one from the first ones (x0 and y0)
Mul3Big3<ss_size/2 + 1, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
}
else
{
// ss_size is even
x0 = ss1;
y0 = ss2;
x1 = ss1 + ss_size / 2;
y1 = ss2 + ss_size / 2;
// all four vectors (x0 x1 y0 y1) are equal in size
Mul3Big3<ss_size/2, ss_size/2, ss_size*2>(x1, x0, y1, y0, result);
}
}
#ifdef _MSC_VER
#pragma warning (disable : 4717)
//warning C4717: recursive on all control paths, function will cause runtime stack overflow
//we have the stop point in Mul3Big2() method
#endif
/*!
an auxiliary method for calculating the Karatsuba multiplication
x = x1*B^m + x0
y = y1*B^m + y0
first_size - is the size of vectors: x0 and y0
second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size)
x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0
where
z0 = x0*y0
z2 = x1*y1
z1 = (x1 + x0)*(y1 + y0) - z2 - z0
*/
template<uint first_size, uint second_size, uint result_size>
void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result)
{
uint i, c, xc, yc;
UInt<first_size> temp, temp2;
UInt<first_size*3> z1;
// z0 and z2 we store directly in the result (we don't use any temporary variables)
Mul3Big2<first_size>(x0, y0, result); // z0
Mul3Big2<second_size>(x1, y1, result+first_size*2); // z2
// now we calculate z1
// temp = (x0 + x1)
// temp2 = (y0 + y1)
// we're using temp and temp2 with UInt<first_size>, although there can be a carry but
// we simple remember it in xc and yc (xc and yc can be either 0 or 1),
// and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm):
//
// xc | temp
// yc | temp2
// --------------------
// (temp * temp2)
// xc*temp2 |
// yc*temp |
// xc*yc |
// ---------- z1 --------
//
// and the result is never larger in size than 3*first_size
xc = AddVector(x0, x1, first_size, second_size, temp.table);
yc = AddVector(y0, y1, first_size, second_size, temp2.table);
Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
// clearing the rest of z1
for(i=first_size*2 ; i<first_size*3 ; ++i)
z1.table[i] = 0;
if( xc )
{
c = AddVector(z1.table+first_size, temp2.table, first_size*3-first_size, first_size, z1.table+first_size);
TTMATH_ASSERT( c==0 )
}
if( yc )
{
c = AddVector(z1.table+first_size, temp.table, first_size*3-first_size, first_size, z1.table+first_size);
TTMATH_ASSERT( c==0 )
}
if( xc && yc )
{
for( i=first_size*2 ; i<first_size*3 ; ++i )
if( ++z1.table[i] != 0 )
break; // break if there was no carry
}
// z1 = z1 - z2
c = SubVector(z1.table, result+first_size*2, first_size*3, second_size*2, z1.table);
TTMATH_ASSERT(c==0)
// z1 = z1 - z0
c = SubVector(z1.table, result, first_size*3, first_size*2, z1.table);
TTMATH_ASSERT(c==0)
// here we've calculated the z1
// now we're adding it to the result
if( first_size > second_size )
{
uint z1_size = result_size - first_size;
TTMATH_ASSERT( z1_size <= first_size*3 )
for(i=z1_size ; i<first_size*3 ; ++i)
TTMATH_ASSERT( z1.table[i] == 0 )
;
c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
TTMATH_ASSERT(c==0)
}
else
{
c = AddVector(result+first_size, z1.table, result_size-first_size, first_size*3, result+first_size);
TTMATH_ASSERT(c==0)
}
}
#ifdef _MSC_VER
#pragma warning (default : 4717)
#endif
public:
/*!
multiplication this = this * ss2
*/
uint MulFastest(const UInt<value_size> & ss2)
{
UInt<value_size*2> result;
uint i, c = 0;
MulFastestBig(ss2, result);
// copying result
for(i=0 ; i<value_size ; ++i)
table[i] = result.table[i];
// testing carry
for( ; i<value_size*2 ; ++i)
if( result.table[i] != 0 )
{
c = 1;
break;
}
TTMATH_LOG("UInt::MulFastest")
return c;
}
/*!
multiplication result = this * ss2
this method is trying to select the fastest algorithm
(in the future this method can be improved)
*/
void MulFastestBig(const UInt<value_size> & ss2, UInt<value_size*2> & result)
{
if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE )
return Mul2Big(ss2, result);
uint x1size = value_size, x2size = value_size;
uint x1start = 0, x2start = 0;
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
if( x1size==0 || x2size==0 )
{
TTMATH_LOG("UInt::Mul2Big")
// either 'this' or 'ss2' is equal zero - the result is zero too
result.SetZero();
return;
}
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
}
for(uint x1=x1start ; x1<x1size ; ++x1)
{
for(uint x2=x2start ; x2<x2size ; ++x2)
{
MulTwoWords(table[x1], ss2.table[x2], &r2, &r1);
result.AddTwoInts(r2,r1,x2+x1);
// here will never be a carry
}
}
uint distancex1 = x1size - x1start;
uint distancex2 = x2size - x2start;
TTMATH_LOG("UInt::Mul2Big")
}
if( distancex1 < 3 || distancex2 < 3 )
// either 'this' or 'ss2' have only 2 (or 1) item different from zero (side by side)
// (this condition in the future can be improved)
return Mul2Big3<value_size>(table, ss2.table, result, x1start, x1size, x2start, x2size);
// Karatsuba multiplication
Mul3Big(ss2, result);
TTMATH_LOG("UInt::MulFastestBig")
}
/*!
@@ -1453,7 +1820,7 @@ private:
if( Div2_DivisorGreaterOrEqual( divisor, remainder,
table_id, index,
divisor_table_id, divisor_index) )
divisor_index) )
{
TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
return 0;
@@ -1473,7 +1840,7 @@ private:
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
UInt<value_size> * remainder,
uint table_id, uint index,
uint divisor_table_id, uint divisor_index )
uint divisor_index )
{
if( divisor_index > index )
{
@@ -1604,7 +1971,7 @@ private:
for(uint i = j+1 ; i<value_size ; ++i)
q.table[i] = 0;
while( true )
for (;;)
{
u1 = table[j+n-1];
u0 = table[j+n-2];
@@ -1921,7 +2288,7 @@ public:
*/
bool IsTheLowestBitSet() const
{
return (*table & 1) != 0;
return (table[0] & 1) != 0;
}
@@ -2005,7 +2372,7 @@ public:
/*!
this method converts a digit into a char
this method converts a digit into a tt_char
digit should be from <0,F>
(we don't have to get a base)
@@ -2015,12 +2382,12 @@ public:
10 -> A
15 -> F
*/
static uint DigitToChar(uint digit)
static tt_char DigitToChar(uint digit)
{
if( digit < 10 )
return digit + '0';
return (tt_char)(digit + '0');
return digit - 10 + 'A';
return((tt_char)(digit - 10 + 'A'));
}
@@ -2141,7 +2508,7 @@ public:
this constant 10 has the int type (signed int), if we don't give such
operators and constructors the compiler will not compile the program,
because it has to make a conversion and doesn't know into which type
(the UInt class has operator=(const char*), operator=(uint) etc.)
(the UInt class has operator=(const tt_char*), operator=(uint) etc.)
*/
UInt<value_size> & operator=(sint i)
{
@@ -2256,18 +2623,18 @@ public:
/*!
a constructor for converting a string to this class (with the base=10)
*/
UInt(const char * s)
UInt(const tt_char * s)
{
FromString(s);
TTMATH_LOG("UInt::UInt(const char *)")
TTMATH_LOG("UInt::UInt(const tt_char *)")
}
/*!
a constructor for converting a string to this class (with the base=10)
*/
UInt(const std::string & s)
UInt(const tt_string & s)
{
FromString( s.c_str() );
}
@@ -2282,6 +2649,7 @@ public:
{
}
/*!
a copy constructor
*/
@@ -2332,10 +2700,10 @@ public:
/*!
this method converts the value to a string with a base equal 'b'
*/
void ToString(std::string & result, uint b = 10) const
void ToString(tt_string & result, uint b = 10) const
{
UInt<value_size> temp( *this );
char character;
tt_char character;
uint rem;
result.clear();
@@ -2346,7 +2714,7 @@ public:
do
{
temp.DivInt(b, &rem);
character = DigitToChar( rem );
character = static_cast<tt_char>( DigitToChar(rem) );
result.insert(result.begin(), character);
}
while( !temp.IsZero() );
@@ -2360,7 +2728,7 @@ public:
/*
this method's ommiting any white characters from the string
*/
static void SkipWhiteCharacters(const char * & c)
static void SkipWhiteCharacters(const tt_char * & c)
{
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
++c;
@@ -2384,7 +2752,7 @@ public:
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)
uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0)
{
UInt<value_size> base( b );
UInt<value_size> temp;
@@ -2434,7 +2802,7 @@ public:
(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 );
}
@@ -2444,11 +2812,11 @@ public:
/*!
this operator converts a string into its value (with base = 10)
*/
UInt<value_size> & operator=(const char * s)
UInt<value_size> & operator=(const tt_char * s)
{
FromString(s);
TTMATH_LOG("UInt::operator=(const char *)")
TTMATH_LOG("UInt::operator=(const tt_char *)")
return *this;
}
@@ -2457,7 +2825,7 @@ public:
/*!
this operator converts a string into its value (with base = 10)
*/
UInt<value_size> & operator=(const std::string & s)
UInt<value_size> & operator=(const tt_string & s)
{
FromString( s.c_str() );
@@ -2825,9 +3193,15 @@ public:
*
*/
friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l)
/*!
output for standard streams
tt_ostream is either std::ostream or std::wostream
*/
friend tt_ostream & operator<<(tt_ostream & s, const UInt<value_size> & l)
{
std::string ss;
tt_string ss;
l.ToString(ss);
s << ss;
@@ -2837,12 +3211,17 @@ public:
friend std::istream & operator>>(std::istream & s, UInt<value_size> & l)
{
std::string ss;
/*!
input from standard streams
// char for operator>>
unsigned char z;
tt_istream is either std::istream or std::wistream
*/
friend tt_istream & operator>>(tt_istream & s, UInt<value_size> & l)
{
tt_string ss;
// tt_char for operator>>
tt_char z;
// operator>> omits white characters if they're set for ommiting
s >> z;
@@ -2851,10 +3230,10 @@ public:
while( s.good() && CharToDigit(z, 10)>=0 )
{
ss += z;
z = s.get();
z = static_cast<tt_char>(s.get());
}
// we're leaving the last readed character
// we're leaving the last read character
// (it's not belonging to the value)
s.unget();
@@ -2874,7 +3253,6 @@ public:
ttmathuint_noasm.h
*/
#ifdef TTMATH_NOASM
static uint AddTwoWords(uint a, uint b, uint carry, uint * result);
static uint SubTwoWords(uint a, uint b, uint carry, uint * result);
@@ -2899,8 +3277,6 @@ public:
static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_);
#endif // TTMATH_PLATFORM64
#endif // TTMATH_NOASM
private:
uint Rcl2_one(uint c);
@@ -2909,12 +3285,13 @@ private:
uint Rcr2(uint bits, uint c);
public:
uint Add(const UInt<value_size> & ss2, uint c=0);
uint AddInt(uint value, uint index = 0);
uint AddTwoInts(uint x2, uint x1, uint index);
static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
uint Sub(const UInt<value_size> & ss2, uint c=0);
uint SubInt(uint value, uint index = 0);
static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
static sint FindLeadingBitInWord(uint x);
static uint SetBitInWord(uint & value, uint bit);
static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low);
@@ -2922,8 +3299,29 @@ public:
};
/*!
this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array"
when compiling Mul3Big2() method
*/
template<>
class UInt<0>
{
public:
uint table[1];
void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) };
void SetZero() { TTMATH_ASSERT(false) };
uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; };
};
} //namespace
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
#include "ttmathuint_x86.h"
#include "ttmathuint_x86_64.h"

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -41,6 +41,8 @@
#ifdef TTMATH_NOASM
#pragma message("TTMATH_NOASM")
/*!
\file ttmathuint_noasm.h
\brief template class UInt<uint> with methods without any assembler code
@@ -95,7 +97,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i)
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOG("UInt_noasm::Add")
TTMATH_LOG("UInt::Add")
return c;
}
@@ -131,7 +133,7 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt_noasm::AddInt")
TTMATH_LOG("UInt::AddInt")
return c;
}
@@ -184,13 +186,54 @@ namespace ttmath
for(i=index+2 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt64::AddTwoInts")
TTMATH_LOG("UInt::AddTwoInts")
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)
{
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;
}
template<uint value_size>
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
{
@@ -232,7 +275,7 @@ namespace ttmath
for(i=0 ; i<value_size ; ++i)
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
TTMATH_LOG("UInt_noasm::Sub")
TTMATH_LOG("UInt::Sub")
return c;
}
@@ -270,12 +313,51 @@ namespace ttmath
for(i=index+1 ; i<value_size && c ; ++i)
c = SubTwoWords(table[i], 0, c, &table[i]);
TTMATH_LOG("UInt_noasm::SubInt")
TTMATH_LOG("UInt::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)
{
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;
}
/*!
@@ -305,7 +387,7 @@ namespace ttmath
c = new_c;
}
TTMATH_LOG("UInt64::Rcl2_one")
TTMATH_LOG("UInt::Rcl2_one")
return c;
}
@@ -344,7 +426,7 @@ namespace ttmath
c = new_c;
}
TTMATH_LOG("UInt64::Rcr2_one")
TTMATH_LOG("UInt::Rcr2_one")
return c;
}
@@ -421,7 +503,7 @@ namespace ttmath
c = new_c;
}
TTMATH_LOG("UInt64::Rcr2")
TTMATH_LOG("UInt::Rcr2")
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
@@ -39,11 +39,10 @@
#ifndef headerfilettmathuint_x86_64
#define headerfilettmathuint_x86_64
#ifndef TTMATH_NOASM
#ifdef TTMATH_PLATFORM64
#pragma message("TTMATH_ASM64")
/*!
\file ttmathuint_x86_64.h
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
@@ -51,10 +50,31 @@
this file is included at the end of ttmathuint.h
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace ttmath
{
#if defined(_M_X64)
#include <intrin.h>
extern "C"
{
uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
};
#endif
/*!
*
* basic mathematic functions
@@ -78,23 +98,27 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
#ifndef __GNUC__
#if defined(_M_X64)
c = adc_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
/*
this part should be compiled with gcc
*/
__asm__ __volatile__(
"xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n"
@@ -112,7 +136,7 @@ namespace ttmath
#endif
TTMATH_LOG("UInt64::Add")
TTMATH_LOG("UInt::Add")
return c;
}
@@ -145,15 +169,19 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__
#if defined(_M_X64)
c = addindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
@@ -173,12 +201,12 @@ namespace ttmath
"movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2)
: "a" (value), "c" (b), "0" (index), "b" (p1)
: "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" );
#endif
TTMATH_LOG("UInt64::AddInt")
TTMATH_LOG("UInt::AddInt")
return c;
}
@@ -219,19 +247,55 @@ namespace ttmath
*/
template<uint value_size>
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
#if 0
{
uint i, c;
TTMATH_ASSERT( index < value_size )
printf("add %Id + %Id\n",x1,x2);
for(int i=index ; i<value_size ; ++i)
printf("%d: %Id\n",i,table[i]);
c = AddTwoWords(table[index], x1, 0, &table[index]);
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
for(i=index+2 ; i<value_size && c ; ++i)
c = AddTwoWords(table[i], 0, c, &table[i]);
for(i=index ; i<value_size ; ++i)
printf("%d: %Id\n",i,table[i]);
printf(" -> %d\n",c);
TTMATH_LOG("UInt::AddTwoInts")
return c;
}
#else
{
uint b = value_size;
uint * p1 = table;
uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size - 1 )
#ifndef __GNUC__
#if defined(_M_X64)
//printf("add %Id + %Id\n",x1,x2);
//for(int i=index ; i<value_size ; ++i)
// printf("%d: %Id\n",i,table[i]);
//if (table[0] == 1265784741359897913) DebugBreak();
c = addindexed2_x64(p1,b,index,x1,x2);
//for(int i=index ; i<value_size ; ++i)
// printf("%d: %Id\n",i,table[i]);
//printf(" -> %d\n",c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
"subq %%rdx, %%rcx \n"
@@ -254,15 +318,16 @@ namespace ttmath
"movzx %%al, %%rax \n"
: "=a" (c), "=c" (dummy), "=d" (dummy2)
: "1" (b), "2" (index), "b" (p1), "S" (x1), "0" (x2)
: "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1)
: "cc", "memory" );
#endif
TTMATH_LOG("UInt64::AddTwoInts")
TTMATH_LOG("UInt::AddTwoInts")
return c;
}
#endif
@@ -284,20 +349,25 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it
#ifndef __GNUC__
#if defined(_M_X64)
c = sbb_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
"xorq %%rdx, %%rdx \n"
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n"
"movq (%%rsi,%%rdx,8), %%rax \n"
@@ -316,7 +386,7 @@ namespace ttmath
#endif
TTMATH_LOG("UInt64::Sub")
TTMATH_LOG("UInt::Sub")
return c;
}
@@ -347,15 +417,20 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__
#if defined(_M_X64)
c = subindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
"subq %%rdx, %%rcx \n"
@@ -374,7 +449,7 @@ namespace ttmath
"movzx %%al, %%rdx \n"
: "=d" (c), "=a" (dummy), "=c" (dummy2)
: "1" (value), "2" (b), "0" (index), "b" (p1)
: "0" (index), "1" (value), "2" (b), "b" (p1)
: "cc", "memory" );
#endif
@@ -404,17 +479,22 @@ namespace ttmath
{
sint b = value_size;
uint * p1 = table;
uint dummy, dummy2;
#ifndef __GNUC__
#if defined(_M_X64)
c = rcl_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__(
"xorq %%rdx, %%rdx \n" // rdx=0
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n"
"rclq $1, (%%rbx, %%rdx, 8) \n"
@@ -426,12 +506,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy), "=d" (dummy2)
: "1" (c), "0" (b), "b" (p1)
: "0" (b), "1" (c), "b" (p1)
: "cc", "memory" );
#endif
TTMATH_LOG("UInt64::Rcl2_one")
TTMATH_LOG("UInt::Rcl2_one")
return c;
}
@@ -456,16 +536,21 @@ namespace ttmath
{
sint b = value_size;
uint * p1 = table;
uint dummy;
#ifndef __GNUC__
#if defined(_M_X64)
c = rcr_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy;
__asm__ __volatile__(
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
"1: \n"
"rcrq $1, -8(%%rbx, %%rcx, 8) \n"
@@ -476,12 +561,12 @@ namespace ttmath
"adcq %%rcx, %%rcx \n"
: "=c" (c), "=a" (dummy)
: "1" (c), "0" (b), "b" (p1)
: "0" (b), "1" (c), "b" (p1)
: "cc", "memory" );
#endif
TTMATH_LOG("UInt64::Rcr2_one")
TTMATH_LOG("UInt::Rcr2_one")
return c;
}
@@ -509,13 +594,18 @@ namespace ttmath
uint b = value_size;
uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__
#if defined(_M_X64)
c = rcl2_x64(p1,b,bits,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__(
"movq %%rcx, %%rsi \n"
@@ -553,7 +643,7 @@ namespace ttmath
#endif
TTMATH_LOG("UInt64::Rcl2")
TTMATH_LOG("UInt::Rcl2")
return c;
}
@@ -580,14 +670,19 @@ namespace ttmath
sint b = value_size;
uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__
#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 __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__(
"movq %%rcx, %%rsi \n"
@@ -628,7 +723,7 @@ namespace ttmath
#endif
TTMATH_LOG("UInt64::Rcr2")
TTMATH_LOG("UInt::Rcr2")
return c;
}
@@ -646,19 +741,29 @@ namespace ttmath
register sint result;
#ifndef __GNUC__
#if defined(_MSC_VER)
unsigned long nIndex(0);
if (_BitScanReverse64(&nIndex,x) == 0)
result = -1;
else
result = nIndex;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
__asm__ __volatile__(
uint dummy;
"bsrq %1, %0 \n"
"jnz 1f \n"
"movq $-1, %0 \n"
"1: \n"
__asm__ (
: "=R" (result)
: "R" (x)
"movq $-1, %1 \n"
"bsrq %2, %0 \n"
"cmovz %1, %0 \n"
: "=r" (result), "=&r" (dummy)
: "r" (x)
: "cc" );
#endif
@@ -691,14 +796,22 @@ namespace ttmath
#ifndef __GNUC__
#if defined(_MSC_VER)
#if defined(TTMATH_PLATFORM64)
old_bit = _bittestandset64((__int64*)&value,bit) != 0;
#else
old_bit = _bittestandset((long*)&value,bit) != 0;
#endif
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
__asm__ __volatile__(
__asm__ (
"btsq %%rbx, %%rax \n"
"setc %%bl \n"
"movzx %%bl, %%rbx \n"
@@ -742,16 +855,20 @@ namespace ttmath
this has no effect in visual studio but it's usefull when
using gcc and options like -O
*/
register uint result1_;
register uint result2_;
uint result1_;
uint result2_;
#ifndef __GNUC__
#if defined(_MSC_VER)
result1_ = _umul128(a,b,&result2_);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
__asm__ __volatile__(
__asm__ (
"mulq %%rdx \n"
@@ -776,6 +893,7 @@ namespace ttmath
*
*/
#ifndef __GNUC__
/*!
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
@@ -793,8 +911,8 @@ namespace ttmath
template<uint value_size>
void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
{
register uint r_;
register uint rest_;
uint r_;
uint rest_;
/*
these variables have similar meaning like those in
the multiplication algorithm MulTwoWords
@@ -803,12 +921,18 @@ namespace ttmath
TTMATH_ASSERT( c != 0 )
#ifndef __GNUC__
#if defined(_MSC_VER)
div_x64(&a,&b,c);
r_ = a;
rest_ = b;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif
#ifdef __GNUC__
__asm__ __volatile__(
__asm__ (
"divq %%rcx \n"
@@ -823,6 +947,132 @@ namespace ttmath
*rest = rest_;
}
template<uint value_size>
uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
{
uint temp;
if( carry == 0 )
{
temp = a + b;
if( temp < a )
carry = 1;
}
else
{
carry = 1;
temp = a + b + carry;
if( temp > a ) // !(temp<=a)
carry = 0;
}
*result = temp;
return carry;
}
template<uint value_size>
uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
{
if( carry == 0 )
{
*result = a - b;
if( a < b )
carry = 1;
}
else
{
carry = 1;
*result = a - b - carry;
if( a > b ) // !(a <= b )
carry = 0;
}
return carry;
}
/*!
this static method addes one vector to the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5+1
4 3 4+3
2 7 2+7
6 6
9 9
of course the carry is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = AddTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_LOG("UInt::AddVector")
return c;
}
/*!
this static method subtractes one vector from the other
'ss1' is larger in size or equal to 'ss2'
ss1 points to the first (larger) vector
ss2 points to the second vector
ss1_size - size of the ss1 (and size of the result too)
ss2_size - size of the ss2
result - is the result vector (which has size the same as ss1: ss1_size)
Example: ss1_size is 5, ss2_size is 3
ss1: ss2: result (output):
5 1 5-1
4 3 4-3
2 7 2-7
6 6-1 (the borrow from previous item)
9 9
return (carry): 0
of course the carry (borrow) is propagated and will be returned from the last item
(this method is used by the Karatsuba multiplication algorithm)
*/
template<uint value_size>
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
{
uint i, c = 0;
TTMATH_ASSERT( ss1_size >= ss2_size )
for(i=0 ; i<ss2_size ; ++i)
c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
for( ; i<ss1_size ; ++i)
c = SubTwoWords(ss1[i], 0, c, &result[i]);
TTMATH_LOG("UInt::SubVector")
return c;
}
#endif // #ifndef __GNUC__
} //namespace

View File

@@ -0,0 +1,386 @@
PUBLIC adc_x64
PUBLIC addindexed_x64
PUBLIC addindexed2_x64
PUBLIC sbb_x64
PUBLIC subindexed_x64
PUBLIC rcl_x64
PUBLIC rcr_x64
PUBLIC rcl2_x64
PUBLIC rcr2_x64
PUBLIC div_x64
;
; "rax, rcx, rdx, r8-r11 are volatile."
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
;
.CODE
ALIGN 8
;----------------------------------------
adc_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nSize
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
adc qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
adc_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
addindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
xor rax, rax ; rax = result
sub rdx, r8 ; rdx = remaining count of uints
add qword ptr [rcx + r8 * 8], r9
jc next1
ret
next1:
mov r9, 1
ALIGN 16
loop1:
dec rdx
jz done_with_cy
lea r8, [r8+1]
add qword ptr [rcx + r8 * 8], r9
jc loop1
ret
done_with_cy:
lea rax, [rax+1] ; rax = 1
ret
addindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
addindexed2_x64 PROC
; rcx = p1 (pointer)
; rdx = b (value size)
; r8 = nPos
; r9 = nValue1
; [esp+0x28] = nValue2
xor rax, rax ; return value
mov r11, rcx ; table
sub rdx, r8 ; rdx = remaining count of uints
mov r10, [esp+028h] ; r10 = nValue2
add qword ptr [r11 + r8 * 8], r9
lea r8, [r8+1]
lea rdx, [rdx-1]
adc qword ptr [r11 + r8 * 8], r10
jc next
ret
ALIGN 16
loop1:
lea r8, [r8+1]
add qword ptr [r11 + r8 * 8], 1
jc next
ret
next:
dec rdx ; does not modify CY too...
jnz loop1
lea rax, [rax+1]
ret
addindexed2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
sbb_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nCount
; r9 = nCarry
xor rax, rax
xor r11, r11
sub rax, r9 ; sets CARRY if r9 != 0
ALIGN 16
loop1:
mov rax,qword ptr [rdx + r11 * 8]
sbb qword ptr [rcx + r11 * 8], rax
lea r11, [r11+1]
dec r8
jnz loop1
setc al
movzx rax, al
ret
sbb_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
subindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
sub rdx, r8 ; rdx = remaining count of uints
ALIGN 16
loop1:
sub qword ptr [rcx + r8 * 8], r9
jnc done
lea r8, [r8+1]
mov r9, 1
dec rdx
jnz loop1
jc return_1 ; most of the times, there will be NO carry (I hope)
done:
xor rax, rax
ret
return_1:
mov rax, 1
ret
subindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcl_x64 PROC
; rcx = p1
; rdx = b
; r8 = nLowestBit
mov r11, rcx ; table
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcl qword ptr [r11 + r10 * 8], 1
lea r10, [r10+1]
dec rdx
jnz loop1
setc al
movzx rax, al
ret
rcl_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcr_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nLowestBit
xor r10, r10
neg r8 ; CY set if r8 <> 0
ALIGN 16
loop1:
rcr qword ptr -8[rcx + rdx * 8], 1
dec rdx
jnz loop1
setc al
movzx rax, al
ret
rcr_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
div_x64 PROC
; rcx = &Hi
; rdx = &Lo
; r8 = nDiv
mov r11, rcx
mov r10, rdx
mov rdx, qword ptr [r11]
mov rax, qword ptr [r10]
div r8
mov qword ptr [r10], rdx ; remainder
mov qword ptr [r11], rax ; value
ret
div_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcl2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shr r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rax ; r9 = index (0..nSize-1)
ALIGN 16
loop1:
rol qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9+1]
dec rdx
jnz loop1
and rax, 1
pop rbx
ret
rcl2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcr2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
push rbx
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shl r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rdx ; r9 = index (0..nSize-1)
lea r9, [r9-1]
ALIGN 16
loop1:
ror qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
lea r9, [r9-1]
dec rdx
jnz loop1
rol rax, 1
and rax, 1
pop rbx
ret
rcr2_x64 ENDP
END