Compare commits
21 Commits
Author | SHA1 | Date |
---|---|---|
Christian Kaiser | 51e938eaa7 | |
Christian Kaiser | e102086f80 | |
Christian Kaiser | 51b2c974a1 | |
Christian Kaiser | 5597373093 | |
Christian Kaiser | de58378488 | |
Christian Kaiser | de64608eba | |
Christian Kaiser | be8913866a | |
Christian Kaiser | b31d34ebdd | |
Christian Kaiser | be821b59dd | |
Christian Kaiser | de1e7ac957 | |
Christian Kaiser | fdc292e91a | |
Christian Kaiser | 9b576ddbe2 | |
Christian Kaiser | a8c3a506ea | |
Christian Kaiser | 3ba94dca90 | |
Christian Kaiser | cae50cd425 | |
Christian Kaiser | 00e39d3608 | |
Christian Kaiser | 37379d2f1f | |
Christian Kaiser | d7b67e4d47 | |
Christian Kaiser | c91bd24e98 | |
Christian Kaiser | cbc12db22f | |
Tomasz Sowa | 3e9bd5b093 |
|
@ -64,6 +64,7 @@ namespace ttmath
|
|||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* functions for rounding
|
||||
|
@ -235,7 +236,7 @@ namespace ttmath
|
|||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Ln(x);
|
||||
|
||||
if( err )
|
||||
|
@ -276,7 +277,7 @@ namespace ttmath
|
|||
return ValueType(); // default NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint state = result.Log(x, base);
|
||||
|
||||
if( err )
|
||||
|
@ -317,7 +318,7 @@ namespace ttmath
|
|||
return x; // NaN
|
||||
}
|
||||
|
||||
ValueType result;
|
||||
ValueType result;
|
||||
uint c = result.Exp(x);
|
||||
|
||||
if( err )
|
||||
|
@ -515,7 +516,7 @@ namespace ttmath
|
|||
|
||||
if( x.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return result; // NaN is set by default
|
||||
|
@ -583,7 +584,7 @@ namespace ttmath
|
|||
*err = err_overflow;
|
||||
|
||||
return ValueType(); // result is undefined (NaN is set by default)
|
||||
}
|
||||
}
|
||||
|
||||
return Sin(x, err);
|
||||
}
|
||||
|
@ -896,7 +897,7 @@ namespace ttmath
|
|||
ValueType temp;
|
||||
|
||||
temp.Set05Pi();
|
||||
temp.Sub(ASin(x, err));
|
||||
temp.Sub(ASin(x,err));
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
@ -1624,7 +1625,7 @@ namespace ttmath
|
|||
if( err )
|
||||
*err = err_improper_argument;
|
||||
|
||||
return delimiter ; // NaN is set by default
|
||||
return delimiter; // NaN is set by default
|
||||
}
|
||||
|
||||
multipler = 60;
|
||||
|
@ -2181,7 +2182,7 @@ namespace ttmath
|
|||
template<class ValueType>
|
||||
ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
|
||||
const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
{
|
||||
ValueType k_, temp, temp2, temp3, sum;
|
||||
|
||||
sum.SetZero();
|
||||
|
@ -2231,7 +2232,7 @@ namespace ttmath
|
|||
*/
|
||||
template<class ValueType>
|
||||
bool SetBernoulliNumbersMore(CGamma<ValueType> & cgamma, uint start, const volatile StopCalculating * stop = 0)
|
||||
{
|
||||
{
|
||||
ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_;
|
||||
|
||||
const uint n = 2;
|
||||
|
@ -2265,10 +2266,10 @@ namespace ttmath
|
|||
{
|
||||
cgamma.bern.resize(m); // valid numbers are in [0, m-1]
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cgamma.bern[m].Div(denominator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2302,7 +2303,7 @@ namespace ttmath
|
|||
{
|
||||
cgamma.bern[0].SetOne();
|
||||
++start;
|
||||
}
|
||||
}
|
||||
|
||||
if( cgamma.bern.size() == 1 )
|
||||
return true;
|
||||
|
@ -2369,7 +2370,7 @@ namespace ttmath
|
|||
// there was the stop signal
|
||||
err = err_interrupt;
|
||||
return ValueType(); // NaN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp = cgamma.bern[m];
|
||||
|
@ -2498,7 +2499,7 @@ namespace ttmath
|
|||
gamma(z+1) = z * gamma(z)
|
||||
then: gamma(z) = gamma(z+1) / z
|
||||
|
||||
e.g.
|
||||
e.g.
|
||||
gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 )
|
||||
*/
|
||||
template<class ValueType>
|
||||
|
@ -2526,7 +2527,7 @@ namespace ttmath
|
|||
temp.Div(denominator);
|
||||
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -2534,7 +2535,7 @@ namespace ttmath
|
|||
*/
|
||||
template<class ValueType>
|
||||
ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
|
||||
{
|
||||
{
|
||||
if( n > TTMATH_GAMMA_BOUNDARY )
|
||||
return GammaPlusHigh(n, cgamma, err, stop);
|
||||
|
||||
|
@ -2609,6 +2610,7 @@ namespace ttmath
|
|||
ValueType result;
|
||||
ErrorCode err_tmp;
|
||||
|
||||
|
||||
if( n.IsNan() )
|
||||
{
|
||||
if( err )
|
||||
|
@ -2617,6 +2619,8 @@ namespace ttmath
|
|||
return result; // NaN is set by default
|
||||
}
|
||||
|
||||
TTMATH_USE_THREADSAFE_OBJ(cgamma.history);
|
||||
|
||||
if( cgamma.history.Get(n, result, err_tmp) )
|
||||
{
|
||||
if( err )
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#ifndef headerfilettmathbig
|
||||
#define headerfilettmathbig
|
||||
|
||||
#include "ttmathconfig.h"
|
||||
|
||||
/*!
|
||||
\file ttmathbig.h
|
||||
\brief A Class for representing floating point numbers
|
||||
|
@ -47,6 +49,10 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
|
@ -79,9 +85,9 @@ class Big
|
|||
|
||||
public:
|
||||
|
||||
Int<exp> exponent;
|
||||
UInt<man> mantissa;
|
||||
unsigned char info;
|
||||
Int<exp> exponent;
|
||||
UInt<man> mantissa;
|
||||
tt_char info;
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -420,7 +426,7 @@ public:
|
|||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
|
||||
// and on 64bit platform value 128 (256/2=128))
|
||||
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(unsigned int));
|
||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
||||
info = 0;
|
||||
}
|
||||
|
@ -754,10 +760,10 @@ public:
|
|||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
@ -805,10 +811,10 @@ public:
|
|||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
@ -853,10 +859,10 @@ public:
|
|||
if( IsSign() || ss2.IsSign() )
|
||||
return 2;
|
||||
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
Int<exp> exp_offset( exponent );
|
||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||
|
||||
uint c = 0;
|
||||
uint c = 0;
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
@ -907,7 +913,7 @@ public:
|
|||
{
|
||||
// 'i' will be from 0 to TTMATH_BITS_PER_UINT
|
||||
i = man_result.CompensationToLeft();
|
||||
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
mantissa.table[i] = man_result.table[i+1];
|
||||
|
@ -1028,7 +1034,7 @@ public:
|
|||
|
||||
UInt<man*2> man1;
|
||||
UInt<man*2> man2;
|
||||
uint i,c = 0;
|
||||
uint i,c;
|
||||
|
||||
if( IsNan() || ss2.IsNan() || ss2.IsZero() )
|
||||
return CheckCarry(1);
|
||||
|
@ -1049,9 +1055,7 @@ public:
|
|||
|
||||
i = man1.CompensationToLeft();
|
||||
|
||||
if( i )
|
||||
c += exponent.Sub(i);
|
||||
|
||||
c = exponent.Sub(i);
|
||||
c += exponent.Sub(ss2.exponent);
|
||||
|
||||
for(i=0 ; i<man ; ++i)
|
||||
|
@ -1072,8 +1076,8 @@ public:
|
|||
the remainder from a division
|
||||
|
||||
e.g.
|
||||
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
|
||||
-12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
|
||||
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
|
||||
-12.6 mod 3 = -0.6
|
||||
12.6 mod -3 = 0.6
|
||||
-12.6 mod -3 = -0.6
|
||||
|
||||
|
@ -1107,7 +1111,6 @@ public:
|
|||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
power this = this ^ pow
|
||||
(pow without a sign)
|
||||
|
@ -1125,7 +1128,7 @@ public:
|
|||
if( IsNan() )
|
||||
return 1;
|
||||
|
||||
if( pow.IsZero() && IsZero() )
|
||||
if(pow.IsZero() && IsZero())
|
||||
{
|
||||
// we don't define zero^zero
|
||||
SetNan();
|
||||
|
@ -1426,11 +1429,11 @@ public:
|
|||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next few parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
// we've added next few parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
}
|
||||
|
||||
// we set the denominator and the numerator for a next part of the formula
|
||||
|
@ -1592,11 +1595,11 @@ public:
|
|||
if( testing )
|
||||
{
|
||||
if( old_value == *this )
|
||||
// we've added next (step_test) parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
// we've added next (step_test) parts of the formula but the result
|
||||
// is still the same then we break the loop
|
||||
break;
|
||||
else
|
||||
old_value = *this;
|
||||
}
|
||||
|
||||
if( x1.Mul(x2) )
|
||||
|
@ -1766,7 +1769,7 @@ public:
|
|||
// MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'):
|
||||
// warning C4307: '*' : integral constant overflow
|
||||
// but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here
|
||||
#ifdef _MSC_VER
|
||||
#ifndef __GNUC__
|
||||
#pragma warning( disable: 4307 )
|
||||
#endif
|
||||
|
||||
|
@ -1782,7 +1785,7 @@ public:
|
|||
c += exponent.AddInt(man_diff, 0);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifndef __GNUC__
|
||||
#pragma warning( default: 4307 )
|
||||
#endif
|
||||
|
||||
|
@ -2007,7 +2010,7 @@ public:
|
|||
// error but I leave it at the moment as is
|
||||
TTMATH_ASSERT( sizeof(double) == 8 )
|
||||
|
||||
// I am not sure what will be on a platform which has
|
||||
// I am not sure what will be on a plaltform which has
|
||||
// a different endianness... but we use this library only
|
||||
// on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
|
||||
union
|
||||
|
@ -2172,7 +2175,7 @@ public:
|
|||
// then V=(-1)**S * 2 ** (-1022) * (0.F)
|
||||
// These are "unnormalized" values.
|
||||
|
||||
FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
|
||||
FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
|
||||
e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
|
||||
Standardizing();
|
||||
}
|
||||
|
@ -2650,7 +2653,7 @@ public:
|
|||
*/
|
||||
Big<exp,man> & operator=(const Big<exp,man> & value)
|
||||
{
|
||||
info = value.info;
|
||||
info = value.info;
|
||||
exponent = value.exponent;
|
||||
mantissa = value.mantissa;
|
||||
|
||||
|
@ -2667,6 +2670,18 @@ public:
|
|||
operator=(value);
|
||||
}
|
||||
|
||||
class LogHistory
|
||||
{
|
||||
public:
|
||||
Big<exp,man> val[15];
|
||||
|
||||
LogHistory()
|
||||
{
|
||||
for (int i = 0; i < 15; ++i)
|
||||
val[i].SetZero();
|
||||
}
|
||||
TTMATH_IMPLEMENT_THREADSAFE_OBJ
|
||||
};
|
||||
|
||||
/*!
|
||||
a method for converting the value into a string with a base equal 'base'
|
||||
|
@ -2724,7 +2739,7 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
if( base<2 || base>16 )
|
||||
if(base<2 || base>16)
|
||||
{
|
||||
result = error_overflow_msg;
|
||||
return 1;
|
||||
|
@ -2961,11 +2976,12 @@ private:
|
|||
// (LnSurrounding1() will return one immediately)
|
||||
uint c = Ln(x);
|
||||
|
||||
// warning! this 'static' is not thread safe
|
||||
static Big<exp,man> log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint index = base - 2;
|
||||
|
||||
if( log_history[index].IsZero() )
|
||||
static LogHistory log_history;
|
||||
TTMATH_USE_THREADSAFE_OBJ(log_history);
|
||||
|
||||
if( log_history.val[index].IsZero() )
|
||||
{
|
||||
// we don't have 'base' in 'log_history' then we calculate it now
|
||||
|
||||
|
@ -2983,14 +2999,14 @@ private:
|
|||
|
||||
// the next time we'll get the 'Ln(base)' from the history,
|
||||
// this 'log_history' can have (16-2+1) items max
|
||||
log_history[index] = temp;
|
||||
log_history.val[index] = temp;
|
||||
|
||||
c += Div(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've calculated the 'Ln(base)' beforehand and we're getting it now
|
||||
c += Div( log_history[index] );
|
||||
c += Div( log_history.val[index] );
|
||||
}
|
||||
|
||||
return (c==0)? 0 : 1;
|
||||
|
@ -3199,7 +3215,7 @@ private:
|
|||
an auxiliary method for converting into the string
|
||||
*/
|
||||
void ToString_SetCommaAndExponent_Normal_AddingZero(tt_string & new_man,
|
||||
Int<exp+1> & new_exp) const
|
||||
Int<exp+1> & new_exp) const
|
||||
{
|
||||
// we're adding zero characters at the end
|
||||
// 'i' will be smaller than 'when_scientific' (or equal)
|
||||
|
@ -3848,6 +3864,72 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AboutEqual(const Big<exp,man> & ss2, int nBitsToIgnore = 4) const
|
||||
{
|
||||
// we should check the mantissas beforehand because sometimes we can have
|
||||
// a mantissa set to zero but in the exponent something another value
|
||||
// (maybe we've forgotten about calling CorrectZero() ?)
|
||||
if( mantissa.IsZero())
|
||||
{
|
||||
if (ss2.mantissa.IsZero())
|
||||
return true;
|
||||
return(ss2.AboutEqual(*this,nBitsToIgnore));
|
||||
}
|
||||
|
||||
if (ss2.mantissa.IsZero())
|
||||
{
|
||||
return(this->exponent <= uint(2*(-sint(man*TTMATH_BITS_PER_UINT))+nBitsToIgnore));
|
||||
}
|
||||
|
||||
// exponents may not differ much!
|
||||
ttmath::Int<exp> expdiff(this->exponent - ss2.exponent);
|
||||
|
||||
// they may differ one if for example mantissa1=0x80000000, mantissa2=0xffffffff
|
||||
if (ttmath::Abs(expdiff) > 1)
|
||||
return(false);
|
||||
|
||||
// calculate the 'difference' mantissa
|
||||
ttmath::UInt<man> man1(this->mantissa);
|
||||
ttmath::UInt<man> man2(ss2.mantissa);
|
||||
ttmath::UInt<man> mandiff;
|
||||
|
||||
switch (expdiff.ToInt())
|
||||
{
|
||||
case +1:
|
||||
man2.Rcr(1,0);
|
||||
mandiff = man1;
|
||||
mandiff.Sub(man2);
|
||||
break;
|
||||
case -1:
|
||||
man1.Rcr(1,0);
|
||||
mandiff = man2;
|
||||
mandiff.Sub(man1);
|
||||
break;
|
||||
default:
|
||||
if (man2 > man1)
|
||||
{
|
||||
mandiff = man2;
|
||||
mandiff.Sub(man1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mandiff = man1;
|
||||
mandiff.Sub(man2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// faster to mask the bits!
|
||||
ASSERT(nBitsToIgnore < TTMATH_BITS_PER_UINT);
|
||||
|
||||
for (int n = man-1; n > 0; --n)
|
||||
{
|
||||
if (mandiff.table[n] != 0)
|
||||
return(false);
|
||||
}
|
||||
uint nMask = ~((1 << nBitsToIgnore) - 1);
|
||||
return((mandiff.table[0] & nMask) == 0);
|
||||
}
|
||||
|
||||
bool operator<(const Big<exp,man> & ss2) const
|
||||
{
|
||||
|
@ -3879,8 +3961,6 @@ public:
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool operator>(const Big<exp,man> & ss2) const
|
||||
{
|
||||
if( IsSign() && !ss2.IsSign() )
|
||||
|
@ -4253,6 +4333,9 @@ public:
|
|||
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
@ -1327,4 +1337,9 @@ public:
|
|||
|
||||
} // namespace
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
typedef unsigned long long int ulint;
|
||||
|
||||
/*!
|
||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||
*/
|
||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||
const uint TTMATH_UINT_HIGHEST_BIT = 0x80000000ul;
|
||||
|
||||
/*!
|
||||
the max value of the unsigned 32bit word (2^32 - 1)
|
||||
(all bits equal one)
|
||||
*/
|
||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||
const uint TTMATH_UINT_MAX_VALUE = 0xfffffffful;
|
||||
|
||||
/*!
|
||||
the number of words (32bit words on 32bit platform)
|
||||
which are kept in built-in variables for a Big<> type
|
||||
(these variables are defined in ttmathbig.h)
|
||||
*/
|
||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||
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,30 +171,28 @@ 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,7 +274,6 @@ namespace ttmath
|
|||
#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
|
||||
|
@ -406,12 +400,12 @@ namespace ttmath
|
|||
{
|
||||
public:
|
||||
|
||||
ReferenceError() : std::logic_error("reference error")
|
||||
ReferenceError() : std::logic_error ("reference error")
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceError(const tt_char * f, int l) :
|
||||
std::logic_error("reference error"), ExceptionInfo(f,l)
|
||||
std::logic_error ("reference error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -438,12 +432,12 @@ namespace ttmath
|
|||
{
|
||||
public:
|
||||
|
||||
RuntimeError() : std::runtime_error("internal error")
|
||||
RuntimeError() : std::runtime_error ("internal error")
|
||||
{
|
||||
}
|
||||
|
||||
RuntimeError(const tt_char * f, int l) :
|
||||
std::runtime_error("internal error"), ExceptionInfo(f,l)
|
||||
std::runtime_error ("internal error"), ExceptionInfo(f,l)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -476,6 +470,9 @@ namespace ttmath
|
|||
#define TTMATH_ASSERT(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_FILE, __LINE__);
|
||||
|
||||
#define TTMATH_VERIFY(expression) \
|
||||
if( !(expression) ) throw ttmath::RuntimeError(TTMATH_TEXT(__FILE__), __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||
|
@ -483,14 +480,20 @@ 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
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@
|
|||
|
||||
#include "ttmathtypes.h"
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief a namespace for the TTMath library
|
||||
|
@ -1969,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];
|
||||
|
@ -2286,7 +2288,7 @@ public:
|
|||
*/
|
||||
bool IsTheLowestBitSet() const
|
||||
{
|
||||
return (*table & 1) != 0;
|
||||
return (table[0] & 1) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2370,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)
|
||||
|
||||
|
@ -2380,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'));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3251,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);
|
||||
|
||||
|
@ -3276,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);
|
||||
|
@ -3319,6 +3318,10 @@ public:
|
|||
|
||||
} //namespace
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(default:4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
|
||||
#include "ttmathuint_x86.h"
|
||||
#include "ttmathuint_x86_64.h"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -36,14 +36,13 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef headerfilettmathuint_x86
|
||||
#define headerfilettmathuint_x86
|
||||
|
||||
|
||||
#ifndef TTMATH_NOASM
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
#pragma message("TTMATH_ASM32")
|
||||
|
||||
/*!
|
||||
\file ttmathuint_x86.h
|
||||
|
@ -66,7 +65,6 @@ namespace ttmath
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
adding ss2 to the this and adding carry if it's defined
|
||||
(this = this + ss2 + c)
|
||||
|
@ -85,46 +83,31 @@ namespace ttmath
|
|||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
// this part might be compiled with for example visual c
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
xor eax,eax // eax=0
|
||||
xor edx,edx // edx=0
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
sub eax,[c] // CF=c
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4]
|
||||
adc [ebx+edx*4],eax
|
||||
mov eax,[esi+edx*4+0]
|
||||
adc [ebx+edx*4+0],eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -154,7 +137,7 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::Add")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -188,14 +171,8 @@ namespace ttmath
|
|||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
|
@ -204,26 +181,21 @@ namespace ttmath
|
|||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
add [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -255,7 +227,7 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::AddInt")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -296,59 +268,47 @@ namespace ttmath
|
|||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint c;
|
||||
uint c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov edx, [index]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov eax, [x1]
|
||||
sub ecx, edx // max uints to add (value_size - index)
|
||||
|
||||
add [ebx+edx*4], eax
|
||||
inc edx
|
||||
dec ecx
|
||||
lea ecx, [ecx-1]
|
||||
|
||||
mov eax, [x2]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
adc [ebx+edx*4], eax
|
||||
adc [ebx+edx*4+4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 0
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
"push %%ecx \n"
|
||||
"push %%edx \n"
|
||||
|
||||
"subl %%edx, %%ecx \n"
|
||||
|
||||
"addl %%esi, (%%ebx,%%edx,4) \n"
|
||||
|
@ -376,7 +336,7 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -414,21 +374,19 @@ namespace ttmath
|
|||
// this part might be compiled with for example visual c
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
||||
mov esi, [ss1]
|
||||
mov ebx, [ss2]
|
||||
mov edi, [result]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax, [esi+edx*4]
|
||||
adc eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
|
@ -447,7 +405,7 @@ namespace ttmath
|
|||
adc eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
|
@ -455,8 +413,6 @@ namespace ttmath
|
|||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -529,40 +485,30 @@ namespace ttmath
|
|||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
|
||||
mov ecx,[b]
|
||||
|
||||
mov ebx,[p1]
|
||||
mov esi,[p2]
|
||||
|
||||
xor edx,edx // edx=0
|
||||
mov eax,[c]
|
||||
neg eax // CF=1 if rax!=0 , CF=0 if rax==0
|
||||
xor eax, eax
|
||||
mov edx, eax
|
||||
|
||||
sub eax, [c]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
mov eax,[esi+edx*4]
|
||||
sbb [ebx+edx*4],eax
|
||||
mov eax, [esi+edx*4]
|
||||
sbb [ebx+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -594,7 +540,7 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -629,14 +575,8 @@ namespace ttmath
|
|||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ecx, [b]
|
||||
sub ecx, [index]
|
||||
|
||||
|
@ -645,26 +585,21 @@ namespace ttmath
|
|||
|
||||
mov eax, [value]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
sub [ebx+edx*4], eax
|
||||
jnc ttmath_end
|
||||
|
||||
mov eax, 1
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
ttmath_end:
|
||||
setc al
|
||||
movzx edx, al
|
||||
mov [c], edx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -740,7 +675,6 @@ namespace ttmath
|
|||
*/
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
mov ecx, [ss2_size]
|
||||
xor edx, edx // edx = 0, cf = 0
|
||||
|
@ -754,7 +688,7 @@ namespace ttmath
|
|||
sbb eax, [ebx+edx*4]
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
|
@ -773,7 +707,7 @@ namespace ttmath
|
|||
sbb eax, ebx
|
||||
mov [edi+edx*4], eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1]
|
||||
dec ecx
|
||||
jnz ttmath_loop2
|
||||
|
||||
|
@ -781,8 +715,6 @@ namespace ttmath
|
|||
|
||||
ttmath_end:
|
||||
mov [c], ecx
|
||||
|
||||
popad
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -858,29 +790,25 @@ namespace ttmath
|
|||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, edx
|
||||
sub ecx, [c]
|
||||
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcl dword ptr [ebx+edx*4], 1
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -936,25 +864,22 @@ namespace ttmath
|
|||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push ecx
|
||||
xor ecx, ecx
|
||||
sub ecx, [c]
|
||||
|
||||
mov ebx, [p1]
|
||||
mov ecx, [c]
|
||||
neg ecx
|
||||
mov ecx, [b]
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rcr dword ptr [ebx+ecx*4-4], 1
|
||||
|
||||
dec ecx
|
||||
jnz ttmath_loop
|
||||
|
||||
adc ecx, ecx
|
||||
mov [c], ecx
|
||||
|
||||
pop ecx
|
||||
pop ebx
|
||||
setc al
|
||||
movzx eax, al
|
||||
mov [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -987,13 +912,6 @@ namespace ttmath
|
|||
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4731)
|
||||
//warning C4731: frame pointer register 'ebp' modified by inline assembly code
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
|
@ -1011,62 +929,47 @@ namespace ttmath
|
|||
{
|
||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
register sint b = value_size;
|
||||
register uint * p1 = table;
|
||||
register uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shr edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
|
||||
mov eax, [c]
|
||||
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
rol dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, ebp
|
||||
and eax, [mask]
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
|
||||
inc edx
|
||||
lea edx, [edx+1] // inc edx, but faster (no flags dependencies)
|
||||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
pop ebp // restoring ebp
|
||||
|
||||
and eax, 1
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
mov dword ptr [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1116,7 +1019,7 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::Rcl2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1141,43 +1044,37 @@ namespace ttmath
|
|||
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint mask;
|
||||
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [b]
|
||||
|
||||
mov ecx, 32
|
||||
sub ecx, [bits]
|
||||
mov edx, -1
|
||||
shl edx, cl
|
||||
mov [mask], edx
|
||||
|
||||
mov ecx, [bits]
|
||||
mov ebx, [p1]
|
||||
mov eax, [c]
|
||||
|
||||
mov ebp, edx // ebp = mask (modified ebp - don't read/write to variables)
|
||||
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx
|
||||
xor edx, edx // edx = 0
|
||||
mov esi, edx // old value = 0
|
||||
add edx, edi
|
||||
dec edx // edx is pointing at the end of the table (on last word)
|
||||
or eax, eax
|
||||
cmovnz esi, ebp // if(c) esi=mask else esi=0
|
||||
dec edx // edx - is pointing at the last word
|
||||
|
||||
mov eax, [c]
|
||||
or eax, eax
|
||||
cmovnz esi, [mask] // if c then old value = mask
|
||||
|
||||
ALIGN 16
|
||||
ttmath_loop:
|
||||
ror dword ptr [ebx+edx*4], cl
|
||||
|
||||
mov eax, [ebx+edx*4]
|
||||
and eax, ebp
|
||||
and eax, [mask]
|
||||
xor [ebx+edx*4], eax // clearing bits
|
||||
or [ebx+edx*4], esi // saving old value
|
||||
mov esi, eax
|
||||
|
@ -1186,18 +1083,10 @@ namespace ttmath
|
|||
dec edi
|
||||
jnz ttmath_loop
|
||||
|
||||
pop ebp // restoring ebp
|
||||
|
||||
rol eax, 1 // 31bit will be first
|
||||
rol eax, 1 // bit 31 will be bit 0
|
||||
and eax, 1
|
||||
mov [c], eax
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
mov dword ptr [c], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1250,14 +1139,10 @@ namespace ttmath
|
|||
|
||||
TTMATH_LOG("UInt::Rcr2")
|
||||
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (default : 4731)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this method returns the number of the highest set bit in one 32-bit word
|
||||
|
@ -1271,16 +1156,11 @@ namespace ttmath
|
|||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx,-1
|
||||
bsr eax,[x]
|
||||
cmovz eax,edx
|
||||
mov [result], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
mov [result], eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1328,20 +1208,14 @@ namespace ttmath
|
|||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push eax
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
|
||||
mov eax, [v]
|
||||
mov ebx, [bit]
|
||||
bts eax, ebx
|
||||
mov [v], eax
|
||||
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
|
||||
pop eax
|
||||
pop ebx
|
||||
setc bl
|
||||
movzx ebx, bl
|
||||
mov [old_bit], ebx
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1360,8 +1234,7 @@ namespace ttmath
|
|||
#endif
|
||||
|
||||
value = v;
|
||||
|
||||
return old_bit;
|
||||
return old_bit;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1392,17 +1265,11 @@ namespace ttmath
|
|||
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
|
||||
mov eax, [a]
|
||||
mul dword ptr [b]
|
||||
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
mov [result2_], edx
|
||||
mov [result1_], eax
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1465,18 +1332,12 @@ namespace ttmath
|
|||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
|
||||
mov edx, [a]
|
||||
mov eax, [b]
|
||||
div dword ptr [c]
|
||||
|
||||
mov [r_], eax
|
||||
mov [rest_], edx
|
||||
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -83,12 +103,15 @@ namespace ttmath
|
|||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#if defined(_M_X64)
|
||||
c = adc_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
|
||||
uint dummy, dummy2;
|
||||
/*
|
||||
this part should be compiled with gcc
|
||||
*/
|
||||
|
@ -108,7 +131,7 @@ namespace ttmath
|
|||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
@ -150,11 +173,15 @@ namespace ttmath
|
|||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#if defined(_M_X64)
|
||||
c = addindexed_x64(p1,b,index,value);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -173,7 +200,7 @@ namespace ttmath
|
|||
"setc %%al \n"
|
||||
"movzx %%al, %%rdx \n"
|
||||
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||
: "0" (index), "1" (value), "2" (b), "b" (p1)
|
||||
: "cc", "memory" );
|
||||
|
||||
|
@ -220,6 +247,30 @@ namespace ttmath
|
|||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||
#if 0
|
||||
{
|
||||
uint i, c;
|
||||
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
printf("add %Id + %Id\n",x1,x2);
|
||||
for(int i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
|
||||
c = AddTwoWords(table[index], x1, 0, &table[index]);
|
||||
c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
|
||||
|
||||
for(i=index+2 ; i<value_size && c ; ++i)
|
||||
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||
for(i=index ; i<value_size ; ++i)
|
||||
printf("%d: %Id\n",i,table[i]);
|
||||
printf(" -> %d\n",c);
|
||||
|
||||
TTMATH_LOG("UInt::AddTwoInts")
|
||||
|
||||
return c;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
@ -228,11 +279,22 @@ namespace ttmath
|
|||
TTMATH_ASSERT( index < value_size - 1 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#if defined(_M_X64)
|
||||
//printf("add %Id + %Id\n",x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//if (table[0] == 1265784741359897913) DebugBreak();
|
||||
c = addindexed2_x64(p1,b,index,x1,x2);
|
||||
//for(int i=index ; i<value_size ; ++i)
|
||||
// printf("%d: %Id\n",i,table[i]);
|
||||
//printf(" -> %d\n",c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -265,88 +327,7 @@ namespace ttmath
|
|||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method addes one vector to the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5+1
|
||||
4 3 4+3
|
||||
2 7 2+7
|
||||
6 6
|
||||
9 9
|
||||
of course the carry is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
// this part should be compiled with gcc
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"adc (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"adc %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::AddVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -369,16 +350,19 @@ namespace ttmath
|
|||
uint * p1 = table;
|
||||
const uint * p2 = ss2.table;
|
||||
|
||||
|
||||
// we don't have to use TTMATH_REFERENCE_ASSERT here
|
||||
// this algorithm doesn't require it
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#if defined(_M_X64)
|
||||
c = sbb_x64(p1,p2,b,c);
|
||||
#else
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
uint dummy, dummy2;
|
||||
uint dummy, dummy2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
|
||||
|
@ -396,9 +380,10 @@ namespace ttmath
|
|||
"adcq %%rcx, %%rcx \n"
|
||||
|
||||
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||
: "cc", "memory" );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::Sub")
|
||||
|
@ -432,15 +417,20 @@ namespace ttmath
|
|||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint c;
|
||||
uint dummy, dummy2;
|
||||
|
||||
TTMATH_ASSERT( index < value_size )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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"
|
||||
|
@ -464,100 +454,12 @@ namespace ttmath
|
|||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubInt")
|
||||
TTMATH_LOG("UInt64::SubInt")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this static method subtractes one vector from the other
|
||||
'ss1' is larger in size or equal to 'ss2'
|
||||
|
||||
ss1 points to the first (larger) vector
|
||||
ss2 points to the second vector
|
||||
ss1_size - size of the ss1 (and size of the result too)
|
||||
ss2_size - size of the ss2
|
||||
result - is the result vector (which has size the same as ss1: ss1_size)
|
||||
|
||||
Example: ss1_size is 5, ss2_size is 3
|
||||
ss1: ss2: result (output):
|
||||
5 1 5-1
|
||||
4 3 4-3
|
||||
2 7 2-7
|
||||
6 6-1 (the borrow from previous item)
|
||||
9 9
|
||||
return (carry): 0
|
||||
of course the carry (borrow) is propagated and will be returned from the last item
|
||||
(this method is used by the Karatsuba multiplication algorithm)
|
||||
*/
|
||||
template<uint value_size>
|
||||
uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
|
||||
{
|
||||
TTMATH_ASSERT( ss1_size >= ss2_size )
|
||||
|
||||
uint rest = ss1_size - ss2_size;
|
||||
uint c;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
/*
|
||||
the asm code is nearly the same as in AddVector
|
||||
only two instructions 'adc' are changed to 'sbb'
|
||||
*/
|
||||
uint dummy1, dummy2, dummy3;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"mov %%rdx, %%r8 \n"
|
||||
"xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
|
||||
"1: \n"
|
||||
"mov (%%rsi,%%rdx,8), %%rax \n"
|
||||
"sbb (%%rbx,%%rdx,8), %%rax \n"
|
||||
"mov %%rax, (%%rdi,%%rdx,8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 1b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n" // rcx has the cf state
|
||||
|
||||
"or %%r8, %%r8 \n"
|
||||
"jz 3f \n"
|
||||
|
||||
"xor %%rbx, %%rbx \n" // ebx = 0
|
||||
"neg %%rcx \n" // setting cf from rcx
|
||||
"mov %%r8, %%rcx \n" // rcx=rest and is != 0
|
||||
"2: \n"
|
||||
"mov (%%rsi, %%rdx, 8), %%rax \n"
|
||||
"sbb %%rbx, %%rax \n"
|
||||
"mov %%rax, (%%rdi, %%rdx, 8) \n"
|
||||
|
||||
"inc %%rdx \n"
|
||||
"dec %%rcx \n"
|
||||
"jnz 2b \n"
|
||||
|
||||
"adc %%rcx, %%rcx \n"
|
||||
"3: \n"
|
||||
|
||||
: "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
|
||||
: "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
TTMATH_LOG("UInt::SubVector")
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
this method moves all bits into the left hand side
|
||||
return value <- this <- c
|
||||
|
@ -578,9 +480,12 @@ namespace ttmath
|
|||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -632,9 +537,12 @@ namespace ttmath
|
|||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -687,9 +595,12 @@ namespace ttmath
|
|||
uint b = value_size;
|
||||
uint * p1 = table;
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -707,6 +618,7 @@ namespace ttmath
|
|||
|
||||
"xorq %%rdx, %%rdx \n"
|
||||
"movq %%rdx, %%rsi \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%r8, %%rsi \n"
|
||||
|
||||
|
@ -726,7 +638,7 @@ namespace ttmath
|
|||
"and $1, %%rax \n"
|
||||
|
||||
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||
: "%r8", "cc", "memory" );
|
||||
|
||||
#endif
|
||||
|
@ -758,14 +670,19 @@ namespace ttmath
|
|||
|
||||
sint b = value_size;
|
||||
uint * p1 = table;
|
||||
uint dummy, dummy2, dummy3;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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"
|
||||
|
@ -780,6 +697,7 @@ namespace ttmath
|
|||
"movq %%rdx, %%rsi \n"
|
||||
"addq %%rdi, %%rdx \n"
|
||||
"decq %%rdx \n"
|
||||
|
||||
"orq %%rax, %%rax \n"
|
||||
"cmovnz %%R8, %%rsi \n"
|
||||
|
||||
|
@ -787,7 +705,7 @@ namespace ttmath
|
|||
"rorq %%cl, (%%rbx,%%rdx,8) \n"
|
||||
|
||||
"movq (%%rbx,%%rdx,8), %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"andq %%R8, %%rax \n"
|
||||
"xorq %%rax, (%%rbx,%%rdx,8) \n"
|
||||
"orq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||
"movq %%rax, %%rsi \n"
|
||||
|
@ -820,11 +738,19 @@ namespace ttmath
|
|||
template<uint value_size>
|
||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||
{
|
||||
sint result;
|
||||
|
||||
register sint result;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -870,7 +796,15 @@ namespace ttmath
|
|||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -925,7 +859,11 @@ namespace ttmath
|
|||
uint result2_;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -955,6 +893,7 @@ namespace ttmath
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
/*!
|
||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||
|
@ -982,7 +921,13 @@ namespace ttmath
|
|||
TTMATH_ASSERT( c != 0 )
|
||||
|
||||
#ifndef __GNUC__
|
||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||
#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__
|
||||
|
@ -1002,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
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue