Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
3231780a85 | |||
1bae0d6cb8 | |||
277dd72fb6 | |||
a7a7eb7808 | |||
e665f91682 | |||
85945b2bb0 | |||
1efe39686b | |||
d8b829f4c5 | |||
fca1bc1a33 | |||
c65857297b | |||
f530635262 | |||
9327b4ebd4 | |||
d695785cbb | |||
85d1b87ac0 | |||
bfdc6d3df3 | |||
5668fbecf5 | |||
3899b8631c | |||
460608859c | |||
978815f12d | |||
404727f3de | |||
4aebe9aa18 | |||
e18201ba35 | |||
5b24101a83 | |||
6da0386a2d | |||
c7c859fc76 | |||
1d81dc75ff | |||
712bfc9c3b | |||
91e7badb62 | |||
cfd719cca2 | |||
f1115a2ce9 | |||
ca51020fe6 | |||
f8f324f98f | |||
cdd95f602c |
120
CHANGELOG
120
CHANGELOG
@@ -1,3 +1,123 @@
|
|||||||
|
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
|
||||||
|
(now the method returns one)
|
||||||
|
* fixed: the problem with GCC optimization on x86_64
|
||||||
|
sometimes when using -O2 or -O3 GCC doesn't set correctly
|
||||||
|
the stack pointer (actually the stack is used for other things)
|
||||||
|
and you can't use instructions like push/pop in assembler code.
|
||||||
|
All the asm code in x86_64 have been rewritten, now instructions
|
||||||
|
push/pop are not used, other thing which have access to stack
|
||||||
|
(like "m" (mask) constraints in Rcl2 and Rcr2) have also gone away,
|
||||||
|
now the library works well with -O2 and -O3 and the asm code
|
||||||
|
is a little faster
|
||||||
|
* added: UInt::PrintLog(const char * msg, std::ostream & output)
|
||||||
|
used (for debugging purposes) by macro TTMATH_LOG(msg)
|
||||||
|
(it is used in nearly all methods in UInt class)
|
||||||
|
* added: macro TTMATH_DEBUG_LOG: when defined then TTMATH_LOG()
|
||||||
|
put some debug information (to std::cout)
|
||||||
|
* added: ttmathuint_x86.h, ttmathuint_x86_64.h, ttmathuint_noasm.h,
|
||||||
|
all the methods which are using assembler code have been
|
||||||
|
rewritten to no-asm forms, now we have:
|
||||||
|
1. asm for x86 file: ttmathuint_x86.h
|
||||||
|
2. asm for x86_64 file: ttmathuint_x86_64.h
|
||||||
|
3. no asm file: ttmathuint_noasm.h
|
||||||
|
(it's used when macro TTMATH_NOASM is defined)
|
||||||
|
The third form can be used on x86 and x86_64 as well and
|
||||||
|
on other platforms with a little effort.
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.8.3 (2009.04.06):
|
||||||
|
* fixed: RclMoveAllWords() and RcrMoveAllWords() sometimes didn't return
|
||||||
|
the proper carry, (when 'bits' was greater than or equal to 'value_size')
|
||||||
|
this had impact on Rcl() and Rcr(), they also returned the wrong carry
|
||||||
|
* fixed: UInt::Div() didn't return a correct result when the divisor was equal 1
|
||||||
|
there was an error in UInt::DivInt() - when the divisor was 1 it returned
|
||||||
|
zero and the carry was set
|
||||||
|
* fixed: there was a TTMATH_REREFENCE_ASSERT error in Big::PowUInt() caused by: start.Mul(start)
|
||||||
|
* fixed: Big::Add incorrectly rounded 'this' when both exponents were equal
|
||||||
|
it caused that sometimes when adding a zero the result has changed
|
||||||
|
this had impact among other things on FromString() method
|
||||||
|
"0,8" had different binary representation from "0,80"
|
||||||
|
* fixed: template Big::FromBig(const Big<another_exp, another_man> & another)
|
||||||
|
didn't correctly set the exponent (when the mantisses had different size -
|
||||||
|
when 'man' was different from 'another_man')
|
||||||
|
this had impact on operator= too
|
||||||
|
sample:
|
||||||
|
Big<2,3> a = 100;
|
||||||
|
Big<3,5> b;
|
||||||
|
b = a; // b had a wrong value
|
||||||
|
* fixed: Big::Pow(const Big<exp, man> & pow)
|
||||||
|
it's using PowInt() only when pow.exponent is in range (-man*TTMATH_BITS_PER_UINT; 0]
|
||||||
|
previously the powering 'hung' on an input like this: "(1+ 1e-10000) ^ 10e100000000"
|
||||||
|
(there was 10e100000000 iterations in PowInt())
|
||||||
|
* fixed: in function DegToRad(const ValueType & x, ErrorCode * err = 0) it is better
|
||||||
|
to make division first and then mutliplication -- the result is more
|
||||||
|
accurate especially when x is: 90,180,270 or 360
|
||||||
|
* fixed: the parser didn't correctly treat operators for changing the base
|
||||||
|
(radix) -- operators '#' and '&', e.g.:
|
||||||
|
'#sin(1)' was equal '0' -- there was a zero from '#' and then
|
||||||
|
it was multipied by 'sin(1)'
|
||||||
|
the parser didn't check whether Big::FromString() has actually
|
||||||
|
read a proper value -- the method Big::FromString() didn't have
|
||||||
|
something to report such a situation
|
||||||
|
* fixed: Big::FromString() when the base is 10, the method reads the scientific
|
||||||
|
part only if such a part it correctly supplied, e.g:
|
||||||
|
'1234e10', '1234e+10', '1234e-5'
|
||||||
|
previous '1234e' was treated as: '1234e0' (now parsing stops on 'e' and
|
||||||
|
the 'e' can be parsed by other parsers, e.g. the mathematical
|
||||||
|
parser -- now in the parser would be: '1234e' = '1234 * e' = '3354,3597...' )
|
||||||
|
* changed: renamed: Big::PowUInt(UInt<pow_size> pow) -> Big::Pow(UInt<pow_size> pow)
|
||||||
|
it returns 2 when there is: 0^0
|
||||||
|
* changed: renamed: Big::PowInt(Int<pow_size> pow) -> Big::Pow(Int<pow_size> pow)
|
||||||
|
it returns 2 when there is: 0^0 or 0^(-something)
|
||||||
|
* changed: renamed: Big::PowBUInt() -> PowUInt(), Big::PowBInt() -> Big::PowInt()
|
||||||
|
they return 2 when the arguments are incorrect (like above)
|
||||||
|
* changed: UInt::SetBitInWord(uint & value, uint bit) is taking the first argument by a reference now,
|
||||||
|
the specific bit is set in the 'value' and the method returns the last state of the bit (zero or one)
|
||||||
|
* changed: UInt::SetBit(uint bit_index) - it's using TTMATH_ASSERT now
|
||||||
|
* changed: the size of built-in variables (constants) in ttmathbig.h
|
||||||
|
now they consist of 256 32bit words
|
||||||
|
macro TTMATH_BUILTIN_VARIABLES_SIZE is equal: 256u on a 32bit platform and 128ul on a 64bit platform
|
||||||
|
* changed: the asm code in ttmathuint.h and ttmathuint64.h has been completely rewritten
|
||||||
|
now UInt<> is faster about 15-30% than UInt<> from 0.8.2
|
||||||
|
this has impact on Big<> too - it's faster about 10% now
|
||||||
|
* changed: in the parser: the form with operators '#' and '&' is as follows:
|
||||||
|
[-|+][#|&]numeric_value
|
||||||
|
previous was: [-|+][#|&][-|+]numeric_value
|
||||||
|
* changed: in the parser: the short form of multiplication has the same
|
||||||
|
priority as the normal multiplication, e.g.:
|
||||||
|
'2x^3' = 2 * (x^3)
|
||||||
|
previous the priority was greater than powering priority
|
||||||
|
previous: '2x^3' = (2*x) ^ 3
|
||||||
|
* added: UInt::GetBit(uint bit_index) - returning the state of the specific bit
|
||||||
|
* added: Big::operator=(double) and Big::Big(double)
|
||||||
|
* added: UInt::Pow(UInt<value_size> pow) and Int::Pow(Int<value_size> pow)
|
||||||
|
* added: global template functions in ttmath.h:
|
||||||
|
ValueType GradToRad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
ValueType DegToGrad(const ValueType & d, const ValueType & m,
|
||||||
|
const ValueType & s, ErrorCode * err = 0)
|
||||||
|
ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
* added: Parser::SetDegRadGrad(int angle) - 0 deg, 1 rad (default), 2 grad
|
||||||
|
this affects following functions (in the parser only): sin, cos, tan, cot,
|
||||||
|
asin, acos, atan, acot
|
||||||
|
* added: functions to the parser: gradtorad(grad), radtograd(rad), degtograd(deg),
|
||||||
|
degtograd(d,m,s), gradtodeg(grad)
|
||||||
|
* added: UInt::FromString, added a parametr 'after_source'
|
||||||
|
which is pointing at the end of the parsed string
|
||||||
|
* added: Int::FromString(): parameter 'const char ** after_source = 0'
|
||||||
|
if exists it's pointing at the end of the parsed string
|
||||||
|
* added: to UInt::FromString(), Int::FromString(), Big::FromString():
|
||||||
|
parameter 'bool * value_read = 0' - (if exists) tells
|
||||||
|
whether something has actually been read (at least one digit)
|
||||||
|
* added: Objects::IsDefined(const std::string & name)
|
||||||
|
returning true if such an object is defined
|
||||||
|
* removed: Big::FromString() this method doesn't longer recognize operators
|
||||||
|
for changing the base ('#' and '&')
|
||||||
|
|
||||||
|
|
||||||
Version 0.8.2 (2008.06.18):
|
Version 0.8.2 (2008.06.18):
|
||||||
* added: UInt::BitNot2() this method has been proposed by
|
* added: UInt::BitNot2() this method has been proposed by
|
||||||
Arek <kmicicc AnTispam users.sourceforge.net>
|
Arek <kmicicc AnTispam users.sourceforge.net>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2006-2008, Tomasz Sowa
|
Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
4
README
4
README
@@ -21,6 +21,6 @@ This means only C++ developers can use this library and one thing they have
|
|||||||
to do is to use 'include' directive of the preprocessor. How big the
|
to do is to use 'include' directive of the preprocessor. How big the
|
||||||
values can be is set directly in the source code by the programmer.
|
values can be is set directly in the source code by the programmer.
|
||||||
|
|
||||||
Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
Project pages: http://ttmath.slimaczek.pl
|
Project pages: http://www.ttmath.org
|
||||||
http://sourceforge.net/projects/ttmath
|
http://sourceforge.net/projects/ttmath
|
||||||
|
27
constgen/Makefile
Normal file
27
constgen/Makefile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
o = main.o
|
||||||
|
CC = g++
|
||||||
|
CFLAGS = -s -O2 -DCONSTANTSGENERATOR
|
||||||
|
name = gen
|
||||||
|
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
all: $(name)
|
||||||
|
|
||||||
|
$(name): $(o)
|
||||||
|
$(CC) -o $(name) $(CFLAGS) $(o)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main.o: main.cpp
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f *.s
|
||||||
|
rm -f $(name)
|
||||||
|
rm -f $(name).exe
|
126
constgen/main.cpp
Normal file
126
constgen/main.cpp
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
this simple program is used to make constants which then are put into ttmathbig.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../ttmath/ttmath.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
void CalcPi()
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> pi;
|
||||||
|
|
||||||
|
// 3100 digits after commna, taken from: http://zenwerx.com/pi.php
|
||||||
|
pi = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||||
|
"8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196"
|
||||||
|
"4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273"
|
||||||
|
"7245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094"
|
||||||
|
"3305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912"
|
||||||
|
"9833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132"
|
||||||
|
"0005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235"
|
||||||
|
"4201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859"
|
||||||
|
"5024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303"
|
||||||
|
"5982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"
|
||||||
|
"3809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151"
|
||||||
|
"5574857242454150695950829533116861727855889075098381754637464939319255060400927701671139009848824012"
|
||||||
|
"8583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912"
|
||||||
|
"9331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279"
|
||||||
|
"6782354781636009341721641219924586315030286182974555706749838505494588586926995690927210797509302955"
|
||||||
|
"3211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000"
|
||||||
|
"8164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333"
|
||||||
|
"4547762416862518983569485562099219222184272550254256887671790494601653466804988627232791786085784383"
|
||||||
|
"8279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863"
|
||||||
|
"0674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009"
|
||||||
|
"9465764078951269468398352595709825822620522489407726719478268482601476990902640136394437455305068203"
|
||||||
|
"4962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382"
|
||||||
|
"6868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388"
|
||||||
|
"4390451244136549762780797715691435997700129616089441694868555848406353422072225828488648158456028506"
|
||||||
|
"0168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125"
|
||||||
|
"1507606947945109659609402522887971089314566913686722874894056010150330861792868092087476091782493858"
|
||||||
|
"9009714909675985261365549781893129784821682998948722658804857564014270477555132379641451523746234364"
|
||||||
|
"5428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344"
|
||||||
|
"0374200731057853906219838744780847848968332144571386875194350643021845319104848100537061468067491927"
|
||||||
|
"8191197939952061419663428754440643745123718192179998391015919561814675142691239748940907186494231961"
|
||||||
|
"5679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215";
|
||||||
|
|
||||||
|
std::cout << "---------------- PI ----------------" << std::endl;
|
||||||
|
pi.mantissa.PrintTable(std::cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CalcE()
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> e;
|
||||||
|
ttmath::uint steps;
|
||||||
|
|
||||||
|
// macro CONSTANTSGENERATOR has to be defined
|
||||||
|
e.ExpSurrounding0(1, &steps);
|
||||||
|
std::cout << "---------------- e ----------------" << std::endl;
|
||||||
|
e.mantissa.PrintTable(std::cout);
|
||||||
|
|
||||||
|
std::cout << "ExpSurrounding0(1): " << steps << " iterations" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CalcLn(int x)
|
||||||
|
{
|
||||||
|
ttmath::Big<1,400> ln;
|
||||||
|
ttmath::uint steps;
|
||||||
|
|
||||||
|
// macro CONSTANTSGENERATOR has to be defined
|
||||||
|
ln.LnSurrounding1(x, &steps);
|
||||||
|
std::cout << "---------------- ln(" << x << ") ----------------" << std::endl;
|
||||||
|
ln.mantissa.PrintTable(std::cout);
|
||||||
|
|
||||||
|
std::cout << "LnSurrounding1(" << x << "): " << steps << " iterations" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CalcPi();
|
||||||
|
CalcE();
|
||||||
|
CalcLn(2);
|
||||||
|
CalcLn(10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -32,20 +32,21 @@ MyBig atemp;
|
|||||||
if( !atemp.Add(b) )
|
if( !atemp.Add(b) )
|
||||||
std::cout << "a + b = " << atemp << std::endl;
|
std::cout << "a + b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a + b = (carry) " << atemp << std::endl;
|
std::cout << "a + b = (carry)" << std::endl;
|
||||||
|
// it have no sense to print 'atemp' (it's undefined)
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Sub(b) )
|
if( !atemp.Sub(b) )
|
||||||
std::cout << "a - b = " << atemp << std::endl;
|
std::cout << "a - b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a - b = (carry) " << atemp << std::endl;
|
std::cout << "a - b = (carry)" << std::endl;
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Mul(b) )
|
if( !atemp.Mul(b) )
|
||||||
std::cout << "a * b = " << atemp << std::endl;
|
std::cout << "a * b = " << atemp << std::endl;
|
||||||
else
|
else
|
||||||
std::cout << "a * b = (carry: the result is too big) " << std::endl;
|
std::cout << "a * b = (carry)" << std::endl;
|
||||||
// it have no sense to print 'atemp' (it's undefined)
|
|
||||||
|
|
||||||
atemp = a;
|
atemp = a;
|
||||||
if( !atemp.Div(b) )
|
if( !atemp.Div(b) )
|
||||||
@@ -68,9 +69,8 @@ MyBig a,b;
|
|||||||
// 'a' will have the max value which can be held in this type
|
// 'a' will have the max value which can be held in this type
|
||||||
a.SetMax();
|
a.SetMax();
|
||||||
|
|
||||||
// at the moment conversions from double (or float etc.) are not supported
|
// conversion from double
|
||||||
// you cannot do that: b = 456.32f
|
b = 456.32;
|
||||||
b = "456.32";
|
|
||||||
|
|
||||||
// Look at the value 'a' and the product from a+b and a-b
|
// Look at the value 'a' and the product from a+b and a-b
|
||||||
// Don't worry this is the nature of floating point numbers
|
// Don't worry this is the nature of floating point numbers
|
||||||
@@ -89,9 +89,9 @@ a * b = 12193540837712.2708
|
|||||||
a / b = 0.0012499665458095765
|
a / b = 0.0012499665458095765
|
||||||
Calculating with a carry
|
Calculating with a carry
|
||||||
a = 1.624801256070839555e+646457012
|
a = 1.624801256070839555e+646457012
|
||||||
b = 456.32
|
b = 456.31999999999999
|
||||||
a + b = 1.624801256070839555e+646457012
|
a + b = 1.624801256070839555e+646457012
|
||||||
a - b = 1.624801256070839555e+646457012
|
a - b = 1.624801256070839555e+646457012
|
||||||
a * b = (carry: the result is too big)
|
a * b = (carry)
|
||||||
a / b = 3.56066193914542329e+646457009
|
a / b = 3.56066193914542334e+646457009
|
||||||
*/
|
*/
|
||||||
|
31
tests/Makefile
Normal file
31
tests/Makefile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
CC = g++
|
||||||
|
o = main.o uinttest.o
|
||||||
|
CFLAGS = -Wall -O2 -s
|
||||||
|
ttmath = ..
|
||||||
|
name = tests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) -I$(ttmath) $<
|
||||||
|
|
||||||
|
|
||||||
|
all: $(name)
|
||||||
|
|
||||||
|
|
||||||
|
$(name): $(o)
|
||||||
|
$(CC) -o $(name) $(CFLAGS) -I$(ttmath) $(o)
|
||||||
|
|
||||||
|
|
||||||
|
main.o: main.cpp uinttest.h
|
||||||
|
uinttest.o: uinttest.cpp uinttest.h
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f $(name)
|
||||||
|
rm -f $(name).exe
|
||||||
|
|
||||||
|
|
68
tests/main.cpp
Normal file
68
tests/main.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ttmath/ttmath.h>
|
||||||
|
#include "uinttest.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char uint_tests_file[] = "tests.uint32";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void test_uint()
|
||||||
|
{
|
||||||
|
UIntTest test;
|
||||||
|
|
||||||
|
test.set_file_name(uint_tests_file);
|
||||||
|
test.go();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace ttmath;
|
||||||
|
|
||||||
|
|
||||||
|
test_uint();
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
92
tests/tests.uint32
Normal file
92
tests/tests.uint32
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Add
|
||||||
|
|
||||||
|
# min_bits max_bits a b result carry
|
||||||
|
add 32 0 0 0 0 0
|
||||||
|
add 32 0 1 1 2 0
|
||||||
|
add 32 0 2342234 3563456 5905690 0
|
||||||
|
add 32 0 254455 3453435 3707890 0
|
||||||
|
add 32 0 4294967295 0 4294967295 0
|
||||||
|
add 32 32 4294967295 1 0 1
|
||||||
|
add 32 32 4294967295 0 4294967295 0
|
||||||
|
add 64 64 18446744073709551615 1 0 1
|
||||||
|
add 64 64 18446744073709551615 0 18446744073709551615 0
|
||||||
|
add 96 96 79228162514264337593543950335 1 0 1
|
||||||
|
add 96 96 79228162514264337593543950335 0 79228162514264337593543950335 0
|
||||||
|
add 128 128 340282366920938463463374607431768211455 1 0 1
|
||||||
|
add 128 128 340282366920938463463374607431768211455 0 340282366920938463463374607431768211455 0
|
||||||
|
add 160 160 1461501637330902918203684832716283019655932542975 1 0 1
|
||||||
|
add 160 160 1461501637330902918203684832716283019655932542975 0 1461501637330902918203684832716283019655932542975 0
|
||||||
|
add 192 192 6277101735386680763835789423207666416102355444464034512895 1 0 1
|
||||||
|
add 192 192 6277101735386680763835789423207666416102355444464034512895 0 6277101735386680763835789423207666416102355444464034512895 0
|
||||||
|
|
||||||
|
|
||||||
|
# AddInt
|
||||||
|
|
||||||
|
# min_bits max_bits bits_per_int a b(int) index result carry
|
||||||
|
addint 32 0 32 0 0 0 0 0
|
||||||
|
addint 32 0 32 1000 2000 0 3000 0
|
||||||
|
addint 64 0 32 562342345 1423445 1 6113650284997065 0
|
||||||
|
addint 64 0 32 5342342455 3423553423 0 8765895878 0
|
||||||
|
addint 96 0 32 478895734 46756734 2 862509505820513898647477878 0
|
||||||
|
addint 128 0 32 27370506140054471803784984408165997441 24543 3 27372450636847059393422542757339093889 0
|
||||||
|
addint 128 128 32 340282366841711102552375003685868034945 2234543 3 177038656721750864719686733515479937 1
|
||||||
|
addint 160 160 32 1461501637330902918124457471805283415910032366465 3 3 158457126631793409034731674497 1
|
||||||
|
addint 192 0 32 6277101735386680763835789423128439055191355840718134336385 3354 1 6277101735386680763835789423128439055191355855123454647169 0
|
||||||
|
addint 192 192 32 6277101735386680763835789423128439055191355840718134336385 3354 5 4901876491607848387655079701569502248322251848964993 1
|
||||||
|
|
||||||
|
addint 64 0 64 0 0 0 0 0
|
||||||
|
addint 64 0 64 5342342 345534234 0 350876576 0
|
||||||
|
addint 64 0 64 5342342455 34235534234 0 39577876689 0
|
||||||
|
addint 64 64 64 18446744073709550615 2000 0 999 1
|
||||||
|
addint 128 0 64 42895062544824211012058135 3453234 0 42895062544824211015511369 0
|
||||||
|
addint 128 0 64 42895062544824211012058135 456234234 1 8458931214807741031021280279 0
|
||||||
|
addint 128 128 64 340282366920938426569886460012664978455 45623 1 804702316727431770143767 1
|
||||||
|
addint 192 192 64 6277101735386680763835789423207666379208867297044931279895 45623234 1 841563227924816702308613143 1
|
||||||
|
addint 192 192 64 6277101735386679588840776445207152040176347835149297122327 45623234 2 15523607057094857017675614218510090830281178135 1
|
||||||
|
addint 192 192 64 6277101735386680763835789423207666416102355444464034512895 1 0 0 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# AddTwoInts
|
||||||
|
# a the value
|
||||||
|
# c lower word
|
||||||
|
# b higher word
|
||||||
|
# index - index of the lower (c) word
|
||||||
|
# if there is a carry the result is skipped
|
||||||
|
|
||||||
|
# min_bits max_bits bits_per_int a b(int) c(int) index result carry
|
||||||
|
addtwoints 64 0 32 0 0 0 0 0 0
|
||||||
|
addtwoints 64 0 32 23542345 3453245 2356252356 0 14831576719870221 0
|
||||||
|
addtwoints 64 64 32 4563456879824345332 3453245255 3673623543 0 0 1
|
||||||
|
addtwoints 96 0 32 345345634564352344231 1231354534 345324551 1 22714482299528678798871855271 0
|
||||||
|
addtwoints 96 96 32 33333336690445123453645645123 4241542514 145235414 1 0 1
|
||||||
|
addtwoints 128 0 32 921345787234870984751756 2356245656 3423623455 2 186681013820253010515426931265335245452 0
|
||||||
|
addtwoints 128 128 32 259817508127340892734075234234345345346 3452345324 452354345 2 0 1
|
||||||
|
addtwoints 160 0 32 458674036702857083457018457034 435236456 1451234242 1 466702732224470435083940719562 0
|
||||||
|
addtwoints 160 0 32 258672084570198475012875019876674534523452543562 935245345 736765636 3 576919584276960743542382023227664277469907669578 0
|
||||||
|
addtwoints 192 0 32 2398670187501982374012837086745045 3253453245 234567536 4 4754927244626858434362642830810490464530603685767816794581 0
|
||||||
|
addtwoints 192 192 32 1734564564356435667546738087098769876387468736123143453646 3456345245 3256347435 4 0 1
|
||||||
|
|
||||||
|
|
||||||
|
addtwoints 128 0 64 0 0 0 0 0 0
|
||||||
|
addtwoints 128 0 64 14513452345 234512412345 8473567534 0 4325990452636459442359440119399 0
|
||||||
|
addtwoints 128 128 64 325434534534536347567567356714513452345 4324546234512412345 8473567534 0 0 1
|
||||||
|
addtwoints 192 0 64 8786356223462562562561234 4356879827345 34745638455 1 1482569380039046311960318103044992688410168990618834 0
|
||||||
|
addtwoints 192 0 64 875687458745872039847234234048572306857602 12341234356 3472568734534 1 4199505313073142510985676024483326499863441546882 0
|
||||||
|
addtwoints 192 192 64 6234554767823878635622346242564564564564564564562562561234 457644356879827345 34844576655 1 0 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
424
tests/uinttest.cpp
Normal file
424
tests/uinttest.cpp
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "uinttest.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::set_file_name(const std::string & f)
|
||||||
|
{
|
||||||
|
file_name = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::read_uint(uuint & result)
|
||||||
|
{
|
||||||
|
UInt<1> temp;
|
||||||
|
|
||||||
|
int c = temp.FromString(pline, 10, &pline);
|
||||||
|
|
||||||
|
result = temp.ToUInt();
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
std::cerr << " carry from reading uint" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::read_uint(UInt<type_size> & result)
|
||||||
|
{
|
||||||
|
int c = result.FromString(pline, 10, &pline);
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
std::cerr << " carry from UInt<>::FromString()" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_minmax_bits(int type_size)
|
||||||
|
{
|
||||||
|
uuint min_bits;
|
||||||
|
uuint max_bits;
|
||||||
|
|
||||||
|
read_uint(min_bits);
|
||||||
|
read_uint(max_bits);
|
||||||
|
|
||||||
|
if( min_bits != 0 && type_size * TTMATH_BITS_PER_UINT < (unsigned int)min_bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( max_bits != 0 && type_size * TTMATH_BITS_PER_UINT > (unsigned int)max_bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_minmax_bits_bitperint(int type_size)
|
||||||
|
{
|
||||||
|
if( !check_minmax_bits(type_size) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uuint bits;
|
||||||
|
|
||||||
|
read_uint(bits);
|
||||||
|
|
||||||
|
if( TTMATH_BITS_PER_UINT != bits )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_end()
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
|
||||||
|
if( *pline!='#' && *pline!= 0 )
|
||||||
|
{
|
||||||
|
std::cerr << "syntax error" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::check_result_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if( new_carry != carry )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect carry: " << new_carry << " (expected: " << carry << ")" << std::endl;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( new_result != result )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect result: " << new_result << " (expected: " << result << ")" << std::endl;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool UIntTest::check_result_or_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry)
|
||||||
|
{
|
||||||
|
if( new_carry != carry )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect carry: " << new_carry << " (expected: " << carry << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( new_carry == 1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( new_result != result )
|
||||||
|
{
|
||||||
|
std::cerr << "Incorrect result: " << new_result << " (expected: " << result << ")" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_add()
|
||||||
|
{
|
||||||
|
UInt<type_size> a,b,result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
uuint carry;
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] Add<" << type_size << ">: ";
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.Add(b);
|
||||||
|
|
||||||
|
if( check_result_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_addint()
|
||||||
|
{
|
||||||
|
UInt<type_size> a, result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits_bitperint(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
uuint b, index, carry;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(index);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] AddInt<" << type_size << ">: ";
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.AddInt(b, index);
|
||||||
|
|
||||||
|
if( check_result_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
void UIntTest::test_addtwoints()
|
||||||
|
{
|
||||||
|
UInt<type_size> a, result, new_result;
|
||||||
|
|
||||||
|
if( !check_minmax_bits_bitperint(type_size) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::cerr << '[' << row << "] AddTwoInts<" << type_size << ">: ";
|
||||||
|
|
||||||
|
uuint b, c, index, carry;
|
||||||
|
|
||||||
|
read_uint(a);
|
||||||
|
read_uint(b);
|
||||||
|
read_uint(c);
|
||||||
|
read_uint(index);
|
||||||
|
read_uint(result);
|
||||||
|
|
||||||
|
read_uint(carry);
|
||||||
|
|
||||||
|
|
||||||
|
if( !check_end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( index >= type_size - 1 )
|
||||||
|
{
|
||||||
|
std::cerr << "index too large" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
new_result = a;
|
||||||
|
int new_carry = new_result.AddTwoInts(b, c, index);
|
||||||
|
|
||||||
|
if( check_result_or_carry(result, new_result, carry, new_carry) )
|
||||||
|
std::cerr << "ok" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int UIntTest::upper_char(int c)
|
||||||
|
{
|
||||||
|
if( c>='a' && c<='z' )
|
||||||
|
return c - 'a' + 'A';
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::is_white(int c)
|
||||||
|
{
|
||||||
|
if( c==' ' || c=='\t' || c==13 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::skip_white_characters()
|
||||||
|
{
|
||||||
|
while( is_white(*pline) )
|
||||||
|
++pline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::read_method()
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
|
||||||
|
if( *pline == '#' )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
method.clear();
|
||||||
|
|
||||||
|
for(int c = upper_char(*pline) ; c>='A'&& c<='Z' ; c = upper_char(*pline) )
|
||||||
|
{
|
||||||
|
method += c;
|
||||||
|
++pline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( method.empty() )
|
||||||
|
{
|
||||||
|
skip_white_characters();
|
||||||
|
if( *pline == 0 )
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << '[' << row << "] ";
|
||||||
|
std::cerr << "syntax error" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::test_method()
|
||||||
|
{
|
||||||
|
const char * p = pline;
|
||||||
|
|
||||||
|
if( method == "ADD" )
|
||||||
|
{
|
||||||
|
pline = p; test_add<1>();
|
||||||
|
pline = p; test_add<2>();
|
||||||
|
pline = p; test_add<3>();
|
||||||
|
pline = p; test_add<4>();
|
||||||
|
pline = p; test_add<5>();
|
||||||
|
pline = p; test_add<6>();
|
||||||
|
pline = p; test_add<7>();
|
||||||
|
pline = p; test_add<8>();
|
||||||
|
pline = p; test_add<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( method == "ADDINT" )
|
||||||
|
{
|
||||||
|
pline = p; test_addint<1>();
|
||||||
|
pline = p; test_addint<2>();
|
||||||
|
pline = p; test_addint<3>();
|
||||||
|
pline = p; test_addint<4>();
|
||||||
|
pline = p; test_addint<5>();
|
||||||
|
pline = p; test_addint<6>();
|
||||||
|
pline = p; test_addint<7>();
|
||||||
|
pline = p; test_addint<8>();
|
||||||
|
pline = p; test_addint<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( method == "ADDTWOINTS" )
|
||||||
|
{
|
||||||
|
pline = p; test_addtwoints<1>();
|
||||||
|
pline = p; test_addtwoints<2>();
|
||||||
|
pline = p; test_addtwoints<3>();
|
||||||
|
pline = p; test_addtwoints<4>();
|
||||||
|
pline = p; test_addtwoints<5>();
|
||||||
|
pline = p; test_addtwoints<6>();
|
||||||
|
pline = p; test_addtwoints<7>();
|
||||||
|
pline = p; test_addtwoints<8>();
|
||||||
|
pline = p; test_addtwoints<9>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << '[' << row << "] ";
|
||||||
|
std::cerr << "method " << method << " is not supported" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool UIntTest::check_line()
|
||||||
|
{
|
||||||
|
std::getline(file, line);
|
||||||
|
|
||||||
|
pline = line.c_str();
|
||||||
|
|
||||||
|
if( read_method() )
|
||||||
|
test_method();
|
||||||
|
|
||||||
|
|
||||||
|
if( file.eof() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UIntTest::go()
|
||||||
|
{
|
||||||
|
file.open(file_name.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
if( !file )
|
||||||
|
{
|
||||||
|
std::cerr << "I can't open the input file" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
row = 1;
|
||||||
|
|
||||||
|
while( check_line() )
|
||||||
|
++row;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
105
tests/uinttest.h
Normal file
105
tests/uinttest.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef headerfileuinttest
|
||||||
|
#define headerfileuinttest
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <ttmath/ttmath.h>
|
||||||
|
|
||||||
|
using namespace ttmath;
|
||||||
|
typedef ttmath::uint uuint;
|
||||||
|
|
||||||
|
|
||||||
|
class UIntTest
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string file_name;
|
||||||
|
|
||||||
|
// current line from the file
|
||||||
|
std::string line;
|
||||||
|
const char * pline;
|
||||||
|
|
||||||
|
std::ifstream file;
|
||||||
|
|
||||||
|
|
||||||
|
std::string method;
|
||||||
|
|
||||||
|
int row;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set_file_name(const std::string & f);
|
||||||
|
|
||||||
|
void go();
|
||||||
|
|
||||||
|
bool read_uint(uuint & result);
|
||||||
|
|
||||||
|
template<uuint type_size>
|
||||||
|
bool read_uint(UInt<type_size> & result);
|
||||||
|
|
||||||
|
|
||||||
|
template<uuint type_size> void test_add();
|
||||||
|
template<uuint type_size> void test_addint();
|
||||||
|
template<uuint type_size> void test_addtwoints();
|
||||||
|
|
||||||
|
template<uuint type_size> bool check_result_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry);
|
||||||
|
|
||||||
|
template<uuint type_size> bool check_result_or_carry(const ttmath::UInt<type_size> & result, const ttmath::UInt<type_size> & new_result,
|
||||||
|
int carry, int new_carry);
|
||||||
|
|
||||||
|
int upper_char(int c);
|
||||||
|
bool is_white(int c);
|
||||||
|
void skip_white_characters();
|
||||||
|
bool read_method();
|
||||||
|
void test_method();
|
||||||
|
bool check_line();
|
||||||
|
|
||||||
|
bool check_minmax_bits(int type_size);
|
||||||
|
bool check_minmax_bits_bitperint(int type_size);
|
||||||
|
bool check_end();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
151
ttmath/ttmath.h
151
ttmath/ttmath.h
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -53,6 +53,13 @@
|
|||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* functions defined here are used only with Big<> types
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
@@ -416,7 +423,7 @@ namespace ttmath
|
|||||||
if( c )
|
if( c )
|
||||||
// Sin is from <-1,1> and cannot make an overflow
|
// Sin is from <-1,1> and cannot make an overflow
|
||||||
// but the carry can be from the Taylor series
|
// but the carry can be from the Taylor series
|
||||||
// (then we only breaks our calculations)
|
// (then we only break our calculations)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( addition )
|
if( addition )
|
||||||
@@ -1347,7 +1354,7 @@ namespace ttmath
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* functions for converting between degrees and radians
|
* functions for converting between degrees, radians and gradians
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -1361,14 +1368,18 @@ namespace ttmath
|
|||||||
template<class ValueType>
|
template<class ValueType>
|
||||||
ValueType DegToRad(const ValueType & x, ErrorCode * err = 0)
|
ValueType DegToRad(const ValueType & x, ErrorCode * err = 0)
|
||||||
{
|
{
|
||||||
ValueType result, delimiter;
|
ValueType result, temp;
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
|
|
||||||
result.SetPi();
|
result = x;
|
||||||
c += result.Mul(x);
|
|
||||||
|
|
||||||
delimiter = 180;
|
// it is better to make division first and then multiplication
|
||||||
c += result.Div(delimiter);
|
// the result is more accurate especially when x is: 90,180,270 or 360
|
||||||
|
temp = 180;
|
||||||
|
c += result.Div(temp);
|
||||||
|
|
||||||
|
temp.SetPi();
|
||||||
|
c += result.Mul(temp);
|
||||||
|
|
||||||
if( err )
|
if( err )
|
||||||
*err = c ? err_overflow : err_ok;
|
*err = c ? err_overflow : err_ok;
|
||||||
@@ -1468,6 +1479,128 @@ namespace ttmath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this function converts gradians to radians
|
||||||
|
|
||||||
|
it returns: x * pi / 200
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType GradToRad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType result, temp;
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
result = x;
|
||||||
|
|
||||||
|
// it is better to make division first and then multiplication
|
||||||
|
// the result is more accurate especially when x is: 100,200,300 or 400
|
||||||
|
temp = 200;
|
||||||
|
c += result.Div(temp);
|
||||||
|
|
||||||
|
temp.SetPi();
|
||||||
|
c += result.Mul(temp);
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this function converts radians to gradians
|
||||||
|
|
||||||
|
it returns: x * 200 / pi
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType result, delimiter;
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
result = 200;
|
||||||
|
c += result.Mul(x);
|
||||||
|
|
||||||
|
delimiter.SetPi();
|
||||||
|
c += result.Div(delimiter);
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this function converts degrees to gradians
|
||||||
|
|
||||||
|
it returns: x * 200 / 180
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType result, temp;
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
result = x;
|
||||||
|
|
||||||
|
temp = 200;
|
||||||
|
c += result.Mul(temp);
|
||||||
|
|
||||||
|
temp = 180;
|
||||||
|
c += result.Div(temp);
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this function converts degrees in the long format to gradians
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s,
|
||||||
|
ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType temp_deg = DegToDeg(d,m,s,err);
|
||||||
|
|
||||||
|
if( err && *err!=err_ok )
|
||||||
|
return temp_deg;
|
||||||
|
|
||||||
|
return DegToGrad(temp_deg, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this function converts degrees to gradians
|
||||||
|
|
||||||
|
it returns: x * 180 / 200
|
||||||
|
*/
|
||||||
|
template<class ValueType>
|
||||||
|
ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0)
|
||||||
|
{
|
||||||
|
ValueType result, temp;
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
result = x;
|
||||||
|
|
||||||
|
temp = 180;
|
||||||
|
c += result.Mul(temp);
|
||||||
|
|
||||||
|
temp = 200;
|
||||||
|
c += result.Div(temp);
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = c ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* another functions
|
* another functions
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -212,20 +212,35 @@ private:
|
|||||||
0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
|
0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
|
||||||
0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
|
0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
|
||||||
0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
|
0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
|
||||||
0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646df // (last one was: 0x602646de)
|
0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de,
|
||||||
// 0xc9751e76, ...
|
0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831,
|
||||||
// (the last word was rounded up because the next one is 0xc9751e76 -- first bit is one 0xc..)
|
0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b,
|
||||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03,
|
||||||
|
0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3,
|
||||||
|
0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8,
|
||||||
|
0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0,
|
||||||
|
0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee,
|
||||||
|
0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c,
|
||||||
|
0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466,
|
||||||
|
0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9,
|
||||||
|
0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd,
|
||||||
|
0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d,
|
||||||
|
0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1,
|
||||||
|
0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7,
|
||||||
|
0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df,
|
||||||
|
0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52
|
||||||
|
//0x86d44014, ...
|
||||||
|
// (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..)
|
||||||
|
// 256 32bit words for the mantissa -- about 2464 valid decimal digits
|
||||||
};
|
};
|
||||||
|
// the value of PI is comming from the website http://zenwerx.com/pi.php
|
||||||
// the value of PI is comming from the website "Paul's 8192 Digits of Pi"
|
// 3101 digits were taken from this website
|
||||||
// http://www.escape.com/~paulg53/math/pi/8192.html
|
// (later the digits were compared with:
|
||||||
// 2999 digits were taken from this website
|
// http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
|
||||||
// (later they were compared with http://zenwerx.com/pi.php)
|
// and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform)
|
||||||
// and they were set into Big<1,300> type (using operator=(const char*) on 32bit platform)
|
// and then the first 256 words were taken into this table
|
||||||
// and then the first 128 words were taken into this table
|
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
|
||||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
// and on 64bit platform value 128 (256/2=128))
|
||||||
// and on 64bit platform value 64 (128/2=64))
|
|
||||||
|
|
||||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
|
||||||
}
|
}
|
||||||
@@ -288,17 +303,34 @@ public:
|
|||||||
0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
|
0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
|
||||||
0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
|
0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
|
||||||
0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
|
0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
|
||||||
0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a
|
0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a,
|
||||||
//0x23ba4442,...
|
0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a,
|
||||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910,
|
||||||
|
0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3,
|
||||||
|
0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6,
|
||||||
|
0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e,
|
||||||
|
0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403,
|
||||||
|
0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1,
|
||||||
|
0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64,
|
||||||
|
0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829,
|
||||||
|
0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282,
|
||||||
|
0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74,
|
||||||
|
0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b,
|
||||||
|
0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457,
|
||||||
|
0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e,
|
||||||
|
0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e,
|
||||||
|
0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749
|
||||||
|
// 0x2fe26dd4, ...
|
||||||
|
// 256 32bit words for the mantissa -- about 2464 valid decimal digits
|
||||||
};
|
};
|
||||||
|
|
||||||
// above value was calculated using Big<1,300> on 32bit platform
|
// above value was calculated using Big<1,400> type on a 32bit platform
|
||||||
// and then the first 128 words were taken,
|
// and then the first 256 words were taken,
|
||||||
// the calculating was made by using ExpSurrounding0(1) method
|
// the calculating was made by using ExpSurrounding0(1) method
|
||||||
// which took 1110 iterations
|
// which took 1420 iterations
|
||||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
// (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil)
|
||||||
// and on 64bit platform value 64 (128/2=64))
|
// (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(int));
|
||||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||||
@@ -328,18 +360,35 @@ public:
|
|||||||
0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
|
0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
|
||||||
0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
|
0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
|
||||||
0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
|
0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
|
||||||
0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd9 // (last one was: 0xc8daadd8)
|
0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8,
|
||||||
// 0x85db6ab0, ...
|
0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c,
|
||||||
// (the last word was rounded up because the next one is 0x85db6ab0 -- first bit is one 0x8..)
|
0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f,
|
||||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00,
|
||||||
|
0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783,
|
||||||
|
0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8,
|
||||||
|
0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a,
|
||||||
|
0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda,
|
||||||
|
0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8,
|
||||||
|
0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527,
|
||||||
|
0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7,
|
||||||
|
0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca,
|
||||||
|
0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb,
|
||||||
|
0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab,
|
||||||
|
0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797,
|
||||||
|
0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6,
|
||||||
|
0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992
|
||||||
|
//0xcbb9ac40, ...
|
||||||
|
// (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..)
|
||||||
|
// 256 32bit words for the mantissa -- about 2464 valid decimal digits
|
||||||
};
|
};
|
||||||
|
|
||||||
// above value was calculated using Big<1,300> on 32bit platform
|
// above value was calculated using Big<1,400> type on a 32bit platform
|
||||||
// and then the first 128 words were taken,
|
// and then the first 256 words were taken,
|
||||||
// the calculating was made by using LnSurrounding1(2) method
|
// the calculating was made by using LnSurrounding1(2) method
|
||||||
// which took 3030 iterations
|
// which took 4035 iterations
|
||||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
// (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html)
|
||||||
// and on 64bit platform value 64 (128/2=64))
|
// (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(int));
|
||||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
||||||
@@ -379,21 +428,38 @@ public:
|
|||||||
0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
|
0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
|
||||||
0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
|
0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
|
||||||
0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
|
0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
|
||||||
0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f9 // (last one was: 0xba83c7f8)
|
0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8,
|
||||||
///0xfb5f06c3, ...
|
0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022,
|
||||||
//(the last word was rounded up because the next one is 0xfb5f06c3 -- first bit is one 0xf..)
|
0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f,
|
||||||
// 128 32bit words for the mantissa -- about 1232 valid digits (decimal)
|
0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31,
|
||||||
|
0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766,
|
||||||
|
0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84,
|
||||||
|
0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8,
|
||||||
|
0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8,
|
||||||
|
0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f,
|
||||||
|
0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6,
|
||||||
|
0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c,
|
||||||
|
0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73,
|
||||||
|
0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7,
|
||||||
|
0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68,
|
||||||
|
0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d,
|
||||||
|
0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687,
|
||||||
|
0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347
|
||||||
|
// 0xb4a638ef, ...
|
||||||
|
//(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..)
|
||||||
|
// 256 32bit words for the mantissa -- about 2464 valid digits (decimal)
|
||||||
};
|
};
|
||||||
|
|
||||||
// above value was calculated using Big<1,300> on 32bit platform
|
// above value was calculated using Big<1,400> type on a 32bit platform
|
||||||
// and then the first 128 32bit words were taken,
|
// and then the first 256 32bit words were taken,
|
||||||
// the calculating was made by using LnSurrounding1(10) method
|
// the calculating was made by using LnSurrounding1(10) method
|
||||||
// which took 16555 iterations
|
// which took 22080 iterations
|
||||||
|
// (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html)
|
||||||
// (the formula used in LnSurrounding1(x) converges badly when
|
// (the formula used in LnSurrounding1(x) converges badly when
|
||||||
// the x is greater than one but in fact we can use it, only the
|
// the x is greater than one but in fact we can use it, only the
|
||||||
// number of iterations will be greater)
|
// number of iterations will be greater)
|
||||||
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 128,
|
// (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
|
||||||
// and on 64bit platform value 64 (128/2=64))
|
// 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(int));
|
||||||
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||||
@@ -561,9 +627,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( exp_offset > mantissa_size_in_bits )
|
if( exp_offset >= mantissa_size_in_bits )
|
||||||
{
|
{
|
||||||
// the second value is too short for taking into consideration in the sum
|
// the second value is too small for taking into consideration in the sum
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -572,13 +638,6 @@ public:
|
|||||||
// (2) moving 'exp_offset' times
|
// (2) moving 'exp_offset' times
|
||||||
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// (3)
|
|
||||||
// exp_offset == mantissa_size_in_bits
|
|
||||||
// we're rounding 'this' about one (up or down depending on a ss2 sign)
|
|
||||||
ss2.mantissa.SetOne();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( IsSign() == ss2.IsSign() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
@@ -594,8 +653,8 @@ public:
|
|||||||
{
|
{
|
||||||
// values have different signs
|
// values have different signs
|
||||||
// there shouldn't be a carry here because
|
// there shouldn't be a carry here because
|
||||||
// (1) (2) and (3) guarantee that the mantissa of this
|
// (1) (2) guarantee that the mantissa of this
|
||||||
// is greater than the mantissa of the ss2
|
// is greater than or equal to the mantissa of the ss2
|
||||||
uint c_temp = mantissa.Sub(ss2.mantissa);
|
uint c_temp = mantissa.Sub(ss2.mantissa);
|
||||||
|
|
||||||
TTMATH_ASSERT( c_temp == 0 )
|
TTMATH_ASSERT( c_temp == 0 )
|
||||||
@@ -653,7 +712,7 @@ public:
|
|||||||
|
|
||||||
if( exp_offset >= mantissa_size_in_bits )
|
if( exp_offset >= mantissa_size_in_bits )
|
||||||
{
|
{
|
||||||
// the second value is too short
|
// the second value is too small
|
||||||
SetZero();
|
SetZero();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -700,7 +759,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( exp_offset >= mantissa_size_in_bits )
|
if( exp_offset >= mantissa_size_in_bits )
|
||||||
// the second value is too short
|
// the second value is too small
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
||||||
@@ -745,7 +804,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( exp_offset >= mantissa_size_in_bits )
|
if( exp_offset >= mantissa_size_in_bits )
|
||||||
// the second value is too short
|
// the second value is too small
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
// exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
|
||||||
@@ -944,7 +1003,7 @@ public:
|
|||||||
-12.6 mod -3 = -0.6
|
-12.6 mod -3 = -0.6
|
||||||
|
|
||||||
it means:
|
it means:
|
||||||
in other words: this(old) = ss2 * q + this(new)(result)
|
in other words: this(old) = ss2 * q + this(new -- result)
|
||||||
*/
|
*/
|
||||||
uint Mod(const Big<exp, man> & ss2)
|
uint Mod(const Big<exp, man> & ss2)
|
||||||
{
|
{
|
||||||
@@ -966,18 +1025,23 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ pow
|
power this = this ^ pow
|
||||||
pow without a sign
|
(pow without a sign)
|
||||||
|
|
||||||
binary algorithm (r-to-l)
|
binary algorithm (r-to-l)
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments (0^0)
|
||||||
*/
|
*/
|
||||||
template<uint pow_size>
|
template<uint pow_size>
|
||||||
uint PowUInt(UInt<pow_size> pow)
|
uint Pow(UInt<pow_size> pow)
|
||||||
{
|
{
|
||||||
if(pow.IsZero() && IsZero())
|
if(pow.IsZero() && IsZero())
|
||||||
// we don't define zero^zero
|
// we don't define zero^zero
|
||||||
return 1;
|
return 2;
|
||||||
|
|
||||||
Big<exp, man> start(*this);
|
Big<exp, man> start(*this), start_temp;
|
||||||
Big<exp, man> result;
|
Big<exp, man> result;
|
||||||
result.SetOne();
|
result.SetOne();
|
||||||
|
|
||||||
@@ -987,7 +1051,8 @@ public:
|
|||||||
if( result.Mul(start) )
|
if( result.Mul(start) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( start.Mul(start) )
|
start_temp = start;
|
||||||
|
if( start.Mul(start_temp) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
pow.Rcr(1);
|
pow.Rcr(1);
|
||||||
@@ -1001,27 +1066,31 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ pow
|
power this = this ^ pow
|
||||||
p can be with a sign
|
|
||||||
p can be negative
|
p can be negative
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments 0^0 or 0^(-something)
|
||||||
*/
|
*/
|
||||||
template<uint pow_size>
|
template<uint pow_size>
|
||||||
uint PowInt(Int<pow_size> pow)
|
uint Pow(Int<pow_size> pow)
|
||||||
{
|
{
|
||||||
if( !pow.IsSign() )
|
if( !pow.IsSign() )
|
||||||
return PowUInt(pow);
|
return Pow( UInt<pow_size>(pow) );
|
||||||
|
|
||||||
|
|
||||||
if( IsZero() )
|
if( IsZero() )
|
||||||
// if 'p' is negative then
|
// if 'p' is negative then
|
||||||
// 'this' must be different from zero
|
// 'this' must be different from zero
|
||||||
return 1;
|
return 2;
|
||||||
|
|
||||||
if( pow.ChangeSign() )
|
if( pow.ChangeSign() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Big<exp, man> t(*this);
|
Big<exp, man> t(*this);
|
||||||
if( t.PowUInt(pow) )
|
uint c_temp = t.Pow( UInt<pow_size>(pow) );
|
||||||
return 1;
|
if( c_temp > 0 )
|
||||||
|
return c_temp;
|
||||||
|
|
||||||
SetOne();
|
SetOne();
|
||||||
if( Div(t) )
|
if( Div(t) )
|
||||||
@@ -1032,33 +1101,40 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns true if 'this' mod 2 is equal one
|
this method returns: 'this' mod 2
|
||||||
|
(either zero or one)
|
||||||
|
|
||||||
|
this method is much faster than using Mod( object_with_value_two )
|
||||||
*/
|
*/
|
||||||
bool Mod2() const
|
uint Mod2() const
|
||||||
{
|
{
|
||||||
if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
|
if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
sint exp_int = exponent.ToInt();
|
sint exp_int = exponent.ToInt();
|
||||||
// 'exp_int' is negative (or zero), we set its as positive
|
// 'exp_int' is negative (or zero), we set it as positive
|
||||||
exp_int = -exp_int;
|
exp_int = -exp_int;
|
||||||
|
|
||||||
// !!! here we'll use a new method (method for testing a bit)
|
return mantissa.GetBit(exp_int);
|
||||||
uint value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
|
|
||||||
value >>= (uint(exp_int) % TTMATH_BITS_PER_UINT);
|
|
||||||
|
|
||||||
return bool(value & 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ abs([pow])
|
power this = this ^ abs([pow])
|
||||||
pow without a sign and without a fraction
|
pow is treated as a value without a sign and without a fraction
|
||||||
|
if pow has a sign then the method pow.Abs() is used
|
||||||
|
if pow has a fraction the fraction is skipped (not used in calculation)
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments (0^0)
|
||||||
*/
|
*/
|
||||||
uint PowBUInt(Big<exp, man> pow)
|
uint PowUInt(Big<exp, man> pow)
|
||||||
{
|
{
|
||||||
if( pow.IsZero() && IsZero() )
|
if( pow.IsZero() && IsZero() )
|
||||||
return 1;
|
return 2;
|
||||||
|
|
||||||
if( pow.IsSign() )
|
if( pow.IsSign() )
|
||||||
pow.Abs();
|
pow.Abs();
|
||||||
@@ -1070,7 +1146,7 @@ public:
|
|||||||
|
|
||||||
e_one.SetOne();
|
e_one.SetOne();
|
||||||
one.SetOne();
|
one.SetOne();
|
||||||
result.SetOne();
|
result = one;
|
||||||
|
|
||||||
while( pow >= one )
|
while( pow >= one )
|
||||||
{
|
{
|
||||||
@@ -1093,24 +1169,30 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ [pow]
|
power this = this ^ [pow]
|
||||||
pow without a fraction
|
pow is treated as a value without a fraction
|
||||||
pow can be negative
|
pow can be negative
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments 0^0 or 0^(-something)
|
||||||
*/
|
*/
|
||||||
uint PowBInt(const Big<exp, man> & pow)
|
uint PowInt(const Big<exp, man> & pow)
|
||||||
{
|
{
|
||||||
TTMATH_REFERENCE_ASSERT( pow )
|
TTMATH_REFERENCE_ASSERT( pow )
|
||||||
|
|
||||||
if( !pow.IsSign() )
|
if( !pow.IsSign() )
|
||||||
return PowBUInt(pow);
|
return PowUInt(pow);
|
||||||
|
|
||||||
if( IsZero() )
|
if( IsZero() )
|
||||||
// if 'pow' is negative then
|
// if 'pow' is negative then
|
||||||
// 'this' must be different from zero
|
// 'this' must be different from zero
|
||||||
return 1;
|
return 2;
|
||||||
|
|
||||||
Big<exp, man> temp(*this);
|
Big<exp, man> temp(*this);
|
||||||
if( temp.PowBUInt(pow) )
|
uint c_temp = temp.PowUInt(pow);
|
||||||
return 1;
|
if( c_temp > 0 )
|
||||||
|
return c_temp;
|
||||||
|
|
||||||
SetOne();
|
SetOne();
|
||||||
if( Div(temp) )
|
if( Div(temp) )
|
||||||
@@ -1122,13 +1204,13 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ pow
|
power this = this ^ pow
|
||||||
this *must* be greater than zero (this > 0)
|
this must be greater than zero (this > 0)
|
||||||
pow can be negative and with fraction
|
pow can be negative and with fraction
|
||||||
|
|
||||||
return values:
|
return values:
|
||||||
0 - ok
|
0 - ok
|
||||||
1 - carry
|
1 - carry
|
||||||
2 - incorrect argument ('this')
|
2 - incorrect argument ('this' <= 0)
|
||||||
*/
|
*/
|
||||||
uint PowFrac(const Big<exp, man> & pow)
|
uint PowFrac(const Big<exp, man> & pow)
|
||||||
{
|
{
|
||||||
@@ -1147,6 +1229,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
power this = this ^ pow
|
power this = this ^ pow
|
||||||
pow can be negative and with fraction
|
pow can be negative and with fraction
|
||||||
@@ -1171,14 +1254,14 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Big<exp, man> pow_frac( pow );
|
if( pow.exponent>-int(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
|
||||||
pow_frac.RemainFraction();
|
{
|
||||||
|
Big<exp, man> pow_frac( pow );
|
||||||
|
pow_frac.RemainFraction();
|
||||||
|
|
||||||
if( pow_frac.IsZero() )
|
if( pow_frac.IsZero() )
|
||||||
return PowBInt( pow );
|
return PowInt( pow );
|
||||||
|
}
|
||||||
// pow is with fraction (not integer)
|
|
||||||
// result = e^(pow * ln(this) ) where 'this' must be greater than 0
|
|
||||||
|
|
||||||
return PowFrac(pow);
|
return PowFrac(pow);
|
||||||
}
|
}
|
||||||
@@ -1186,12 +1269,16 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
#ifdef CONSTANTSGENERATOR
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Exponent this = exp(x) = e^x where x is in (-1,1)
|
Exponent this = exp(x) = e^x where x is in (-1,1)
|
||||||
|
|
||||||
we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ...
|
we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ...
|
||||||
*/
|
*/
|
||||||
void ExpSurrounding0(const Big<exp,man> & x)
|
void ExpSurrounding0(const Big<exp,man> & x, uint * steps = 0)
|
||||||
{
|
{
|
||||||
TTMATH_REFERENCE_ASSERT( x )
|
TTMATH_REFERENCE_ASSERT( x )
|
||||||
|
|
||||||
@@ -1204,22 +1291,20 @@ private:
|
|||||||
denominator.SetOne();
|
denominator.SetOne();
|
||||||
denominator_i.SetOne();
|
denominator_i.SetOne();
|
||||||
|
|
||||||
// this is only to avoid getting a warning about an uninitialized object
|
|
||||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
|
||||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
|
||||||
old_value.info = 0;
|
|
||||||
|
|
||||||
// every 'step_test' times we make a test
|
// every 'step_test' times we make a test
|
||||||
const uint step_test = 5;
|
const uint step_test = 5;
|
||||||
|
uint i;
|
||||||
|
old_value = *this;
|
||||||
|
|
||||||
// we begin from 1 in order to not testing at the start
|
// we begin from 1 in order to not testing at the beginning
|
||||||
for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
#ifdef CONSTANTSGENERATOR
|
||||||
|
for(i=1 ; true ; ++i)
|
||||||
|
#else
|
||||||
|
for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
bool testing = ((i % step_test) == 0);
|
bool testing = ((i % step_test) == 0);
|
||||||
|
|
||||||
if( testing )
|
|
||||||
old_value = *this;
|
|
||||||
|
|
||||||
next_part = numerator;
|
next_part = numerator;
|
||||||
|
|
||||||
if( next_part.Div( denominator ) )
|
if( next_part.Div( denominator ) )
|
||||||
@@ -1232,9 +1317,12 @@ private:
|
|||||||
Add( next_part );
|
Add( next_part );
|
||||||
|
|
||||||
if( testing && old_value==*this )
|
if( testing && old_value==*this )
|
||||||
// we've added a next part of the formula but the result
|
// we've added next few parts of the formula but the result
|
||||||
// is still the same then we break the loop
|
// is still the same then we break the loop
|
||||||
break;
|
break;
|
||||||
|
else
|
||||||
|
old_value = *this;
|
||||||
|
|
||||||
|
|
||||||
// we set the denominator and the numerator for a next part of the formula
|
// we set the denominator and the numerator for a next part of the formula
|
||||||
if( denominator_i.Add(one) )
|
if( denominator_i.Add(one) )
|
||||||
@@ -1247,10 +1335,11 @@ private:
|
|||||||
if( numerator.Mul(x) )
|
if( numerator.Mul(x) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( steps )
|
||||||
|
*steps = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
@@ -1318,7 +1407,7 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpSurrounding0(m);
|
ExpSurrounding0(m);
|
||||||
c += PowBUInt(e_);
|
c += PowUInt(e_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
@@ -1329,13 +1418,17 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
#ifdef CONSTANTSGENERATOR
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Natural logarithm this = ln(x) where x in range <1,2)
|
Natural logarithm this = ln(x) where x in range <1,2)
|
||||||
|
|
||||||
we're using the formula:
|
we're using the formula:
|
||||||
ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
|
ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
|
||||||
*/
|
*/
|
||||||
void LnSurrounding1(const Big<exp,man> & x)
|
void LnSurrounding1(const Big<exp,man> & x, uint * steps = 0)
|
||||||
{
|
{
|
||||||
Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x);
|
Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x);
|
||||||
|
|
||||||
@@ -1360,16 +1453,19 @@ private:
|
|||||||
denominator.SetOne();
|
denominator.SetOne();
|
||||||
SetZero();
|
SetZero();
|
||||||
|
|
||||||
// this is only to avoid getting a warning about an uninitialized object
|
old_value = *this;
|
||||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
|
||||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
|
||||||
old_value.info = 0;
|
|
||||||
|
|
||||||
// every 'step_test' times we make a test
|
// every 'step_test' times we make a test
|
||||||
const uint step_test = 5;
|
const uint step_test = 5;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONSTANTSGENERATOR
|
||||||
|
for(i=1 ; true ; ++i)
|
||||||
|
#else
|
||||||
// we begin from 1 in order to not testing at the beginning
|
// we begin from 1 in order to not testing at the beginning
|
||||||
for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
bool testing = ((i % step_test) == 0);
|
bool testing = ((i % step_test) == 0);
|
||||||
|
|
||||||
@@ -1381,9 +1477,6 @@ private:
|
|||||||
// it means there are too many parts of the formula
|
// it means there are too many parts of the formula
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( testing )
|
|
||||||
old_value = *this;
|
|
||||||
|
|
||||||
// there shouldn't be a carry here
|
// there shouldn't be a carry here
|
||||||
Add(next_part);
|
Add(next_part);
|
||||||
|
|
||||||
@@ -1391,6 +1484,8 @@ private:
|
|||||||
// we've added next (step_test) parts of the formula but the result
|
// we've added next (step_test) parts of the formula but the result
|
||||||
// is still the same then we break the loop
|
// is still the same then we break the loop
|
||||||
break;
|
break;
|
||||||
|
else
|
||||||
|
old_value = *this;
|
||||||
|
|
||||||
if( x1.Mul(x2) )
|
if( x1.Mul(x2) )
|
||||||
// if there is a carry here the result we return as good
|
// if there is a carry here the result we return as good
|
||||||
@@ -1403,6 +1498,9 @@ private:
|
|||||||
// this = this * 2
|
// this = this * 2
|
||||||
// ( there can't be a carry here because we calculate the logarithm between <1,2) )
|
// ( there can't be a carry here because we calculate the logarithm between <1,2) )
|
||||||
exponent.AddOne();
|
exponent.AddOne();
|
||||||
|
|
||||||
|
if( steps )
|
||||||
|
*steps = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1427,8 +1525,6 @@ public:
|
|||||||
0 - ok
|
0 - ok
|
||||||
1 - overflow
|
1 - overflow
|
||||||
2 - incorrect argument (x<=0)
|
2 - incorrect argument (x<=0)
|
||||||
|
|
||||||
parts: look at the LnSurrounding1() method
|
|
||||||
*/
|
*/
|
||||||
uint Ln(const Big<exp,man> & x)
|
uint Ln(const Big<exp,man> & x)
|
||||||
{
|
{
|
||||||
@@ -1460,7 +1556,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Logarithm with a base 'base' -- this = Log(x) with a base 'base'
|
Logarithm from 'x' with a 'base'
|
||||||
|
|
||||||
we're using the formula:
|
we're using the formula:
|
||||||
Log(x) with 'base' = ln(x) / ln(base)
|
Log(x) with 'base' = ln(x) / ln(base)
|
||||||
@@ -1470,12 +1566,6 @@ public:
|
|||||||
1 - overflow
|
1 - overflow
|
||||||
2 - incorrect argument (x<=0)
|
2 - incorrect argument (x<=0)
|
||||||
3 - incorrect base (a<=0 lub a=1)
|
3 - incorrect base (a<=0 lub a=1)
|
||||||
|
|
||||||
|
|
||||||
parts: look at the LnSurrounding1() method
|
|
||||||
we pass this value only into 'ln(x)' method
|
|
||||||
because if we passed 'parts' into 'ln(base)' as well then
|
|
||||||
the error (after dividing) would be too great
|
|
||||||
*/
|
*/
|
||||||
uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
|
uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
|
||||||
{
|
{
|
||||||
@@ -1502,7 +1592,6 @@ public:
|
|||||||
// there can be only a carry
|
// there can be only a carry
|
||||||
uint c = Ln(x);
|
uint c = Ln(x);
|
||||||
|
|
||||||
// we don't pass the 'parts' here (the error after dividing would be to great)
|
|
||||||
c += denominator.Ln(base);
|
c += denominator.Ln(base);
|
||||||
c += Div(denominator);
|
c += Div(denominator);
|
||||||
|
|
||||||
@@ -1514,7 +1603,7 @@ public:
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* convertion methods
|
* converting methods
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1532,6 +1621,7 @@ public:
|
|||||||
|
|
||||||
uint man_len_min = (man < another_man)? man : another_man;
|
uint man_len_min = (man < another_man)? man : another_man;
|
||||||
uint i;
|
uint i;
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
for( i = 0 ; i<man_len_min ; ++i )
|
for( i = 0 ; i<man_len_min ; ++i )
|
||||||
mantissa.table[man-1-i] = another.mantissa.table[another_man-1-i];
|
mantissa.table[man-1-i] = another.mantissa.table[another_man-1-i];
|
||||||
@@ -1539,10 +1629,34 @@ public:
|
|||||||
for( ; i<man ; ++i )
|
for( ; i<man ; ++i )
|
||||||
mantissa.table[man-1-i] = 0;
|
mantissa.table[man-1-i] = 0;
|
||||||
|
|
||||||
// mantissa is standardized
|
|
||||||
//c += Standardizing();
|
|
||||||
|
|
||||||
return 0;
|
// 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 a situation here
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#pragma warning( disable: 4307 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( man > another_man )
|
||||||
|
{
|
||||||
|
uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT;
|
||||||
|
c += exponent.SubInt(man_diff, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( man < another_man )
|
||||||
|
{
|
||||||
|
uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT;
|
||||||
|
c += exponent.AddInt(man_diff, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#pragma warning( default: 4307 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero)
|
||||||
|
CorrectZero();
|
||||||
|
|
||||||
|
return (c == 0 )? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1760,7 +1874,7 @@ public:
|
|||||||
// error but I leave it at the moment as is
|
// error but I leave it at the moment as is
|
||||||
TTMATH_ASSERT( sizeof(double) == 8 )
|
TTMATH_ASSERT( sizeof(double) == 8 )
|
||||||
|
|
||||||
// I am not sure what will be on a plaltform which has
|
// I am not sure what will be on a platform which has
|
||||||
// a different endianness... but we use this library only
|
// a different endianness... but we use this library only
|
||||||
// on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
|
// on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
|
||||||
union
|
union
|
||||||
@@ -1793,7 +1907,7 @@ public:
|
|||||||
// where "1.F" is intended to represent the binary number
|
// where "1.F" is intended to represent the binary number
|
||||||
// created by prefixing F with an implicit leading 1 and a binary point.
|
// created by prefixing F with an implicit leading 1 and a binary point.
|
||||||
|
|
||||||
FromDouble_SetExpAndMan(bool(temp.u[1] & 0x80000000u),
|
FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
|
||||||
e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
|
e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
|
||||||
m1, m2);
|
m1, m2);
|
||||||
|
|
||||||
@@ -1815,7 +1929,7 @@ public:
|
|||||||
m.table[0] = m2;
|
m.table[0] = m2;
|
||||||
uint moved = m.CompensationToLeft();
|
uint moved = m.CompensationToLeft();
|
||||||
|
|
||||||
FromDouble_SetExpAndMan(bool(temp.u[1] & 0x80000000u),
|
FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
|
||||||
e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
|
e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
|
||||||
m.table[1], m.table[2]);
|
m.table[1], m.table[2]);
|
||||||
}
|
}
|
||||||
@@ -1906,7 +2020,7 @@ public:
|
|||||||
// where "1.F" is intended to represent the binary number
|
// where "1.F" is intended to represent the binary number
|
||||||
// created by prefixing F with an implicit leading 1 and a binary point.
|
// created by prefixing F with an implicit leading 1 and a binary point.
|
||||||
|
|
||||||
FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
|
FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
|
||||||
e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
|
e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
|
||||||
0x8000000000000000ul, m);
|
0x8000000000000000ul, m);
|
||||||
|
|
||||||
@@ -2118,6 +2232,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an operator= for converting 'double' to this class
|
||||||
|
*/
|
||||||
|
Big<exp, man> & operator=(double value)
|
||||||
|
{
|
||||||
|
FromDouble(value);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a constructor for converting 'sint' to this class
|
a constructor for converting 'sint' to this class
|
||||||
*/
|
*/
|
||||||
@@ -2135,6 +2260,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
a constructor for converting 'double' to this class
|
||||||
|
*/
|
||||||
|
Big(double value)
|
||||||
|
{
|
||||||
|
FromDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -3091,39 +3225,48 @@ public:
|
|||||||
a method for converting a string into its value
|
a method for converting a string into its value
|
||||||
|
|
||||||
it returns 1 if the value will be too big -- we cannot pass it into the range
|
it returns 1 if the value will be too big -- we cannot pass it into the range
|
||||||
of our class Big<exp,man>
|
of our class Big<exp,man> (or if the base is incorrect)
|
||||||
|
|
||||||
that means only digits before the comma operator can make this value too big,
|
that means only digits before the comma operator can make this value too big,
|
||||||
all digits after the comma we can ignore
|
all digits after the comma we can ignore
|
||||||
|
|
||||||
'source' - pointer to the string for parsing
|
'source' - pointer to the string for parsing
|
||||||
|
|
||||||
if 'after_source' is set that when this method have finished its job
|
if 'after_source' is set that when this method finishes
|
||||||
it set the pointer to the new first character after parsed value
|
it sets the pointer to the new first character after parsed value
|
||||||
|
|
||||||
|
'value_read' - if the pointer is provided that means the value_read will be true
|
||||||
|
only when a value has been actually read, there can be situation where only such
|
||||||
|
a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
|
||||||
|
no value has been read (there are no digits)
|
||||||
|
on other words if 'value_read' is true -- there is at least one digit in the string
|
||||||
*/
|
*/
|
||||||
uint FromString(const char * source, uint base = 10, const char ** after_source = 0)
|
uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||||
{
|
{
|
||||||
bool is_sign;
|
bool is_sign;
|
||||||
|
bool value_read_temp = false;
|
||||||
|
|
||||||
if( base<2 || base>16 )
|
if( base<2 || base>16 )
|
||||||
{
|
{
|
||||||
if( after_source )
|
if( after_source )
|
||||||
*after_source = source;
|
*after_source = source;
|
||||||
|
|
||||||
|
if( value_read )
|
||||||
|
*value_read = value_read_temp;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetZero();
|
SetZero();
|
||||||
FromString_TestNewBase( source, base );
|
|
||||||
FromString_TestSign( source, is_sign );
|
FromString_TestSign( source, is_sign );
|
||||||
|
|
||||||
uint c = FromString_ReadPartBeforeComma( source, base );
|
uint c = FromString_ReadPartBeforeComma( source, base, value_read_temp );
|
||||||
|
|
||||||
if( FromString_TestCommaOperator(source) )
|
if( FromString_TestCommaOperator(source) )
|
||||||
c += FromString_ReadPartAfterComma( source, base );
|
c += FromString_ReadPartAfterComma( source, base, value_read_temp );
|
||||||
|
|
||||||
if( base==10 && FromString_TestScientific(source) )
|
if( value_read_temp && base == 10 )
|
||||||
c += FromString_ReadPartScientific( source );
|
c += FromString_ReadScientificIfExists( source );
|
||||||
|
|
||||||
if( is_sign && !IsZero() )
|
if( is_sign && !IsZero() )
|
||||||
ChangeSign();
|
ChangeSign();
|
||||||
@@ -3131,6 +3274,9 @@ public:
|
|||||||
if( after_source )
|
if( after_source )
|
||||||
*after_source = source;
|
*after_source = source;
|
||||||
|
|
||||||
|
if( value_read )
|
||||||
|
*value_read = value_read_temp;
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3139,30 +3285,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
we're testing whether a user wants to change the base
|
|
||||||
|
|
||||||
if there's a '#' character it means that the user wants the base to be 16,
|
|
||||||
if '&' the base will be 2
|
|
||||||
*/
|
|
||||||
void FromString_TestNewBase( const char * & source, uint & base )
|
|
||||||
{
|
|
||||||
UInt<man>::SkipWhiteCharacters(source);
|
|
||||||
|
|
||||||
if( *source == '#' )
|
|
||||||
{
|
|
||||||
base = 16;
|
|
||||||
++source;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if( *source == '&' )
|
|
||||||
{
|
|
||||||
base = 2;
|
|
||||||
++source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
we're testing whether the value is with the sign
|
we're testing whether the value is with the sign
|
||||||
|
|
||||||
@@ -3208,7 +3330,7 @@ private:
|
|||||||
this method reads the first part of a string
|
this method reads the first part of a string
|
||||||
(before the comma operator)
|
(before the comma operator)
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartBeforeComma( const char * & source, uint base )
|
uint FromString_ReadPartBeforeComma( const char * & source, uint base, bool & value_read )
|
||||||
{
|
{
|
||||||
sint character;
|
sint character;
|
||||||
Big<exp, man> temp;
|
Big<exp, man> temp;
|
||||||
@@ -3218,6 +3340,8 @@ private:
|
|||||||
|
|
||||||
for( ; (character=UInt<man>::CharToDigit(*source, base)) != -1 ; ++source )
|
for( ; (character=UInt<man>::CharToDigit(*source, base)) != -1 ; ++source )
|
||||||
{
|
{
|
||||||
|
value_read = true;
|
||||||
|
|
||||||
temp = character;
|
temp = character;
|
||||||
|
|
||||||
if( Mul(base_) )
|
if( Mul(base_) )
|
||||||
@@ -3235,7 +3359,7 @@ private:
|
|||||||
this method reads the second part of a string
|
this method reads the second part of a string
|
||||||
(after the comma operator)
|
(after the comma operator)
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartAfterComma( const char * & source, uint base )
|
uint FromString_ReadPartAfterComma( const char * & source, uint base, bool & value_read )
|
||||||
{
|
{
|
||||||
sint character;
|
sint character;
|
||||||
uint c = 0, index = 1;
|
uint c = 0, index = 1;
|
||||||
@@ -3243,15 +3367,16 @@ private:
|
|||||||
|
|
||||||
// we don't remove any white characters here
|
// we don't remove any white characters here
|
||||||
|
|
||||||
// this is only to avoid getting a warning about an uninitialized object
|
// this is only to avoid getting a warning about an uninitialized object 'old_value' which GCC reports
|
||||||
// gcc 4.1.2 reports: 'old_value.info' may be used uninitialized in this function
|
|
||||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
||||||
old_value.info = 0;
|
old_value.SetZero();
|
||||||
|
|
||||||
power.SetOne();
|
power.SetOne();
|
||||||
|
|
||||||
for( ; (character=UInt<man>::CharToDigit(*source, base)) != -1 ; ++source, ++index )
|
for( ; (character=UInt<man>::CharToDigit(*source, base)) != -1 ; ++source, ++index )
|
||||||
{
|
{
|
||||||
|
value_read = true;
|
||||||
|
|
||||||
part = character;
|
part = character;
|
||||||
|
|
||||||
if( power.Mul( base_ ) )
|
if( power.Mul( base_ ) )
|
||||||
@@ -3287,6 +3412,29 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method checks whether there is a scientific part: [e|E][-|+]value
|
||||||
|
|
||||||
|
it is called when the base is 10 and some digits were read before
|
||||||
|
*/
|
||||||
|
int FromString_ReadScientificIfExists(const char * & source)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
bool scientific_read = false;
|
||||||
|
const char * before_scientific = source;
|
||||||
|
|
||||||
|
if( FromString_TestScientific(source) )
|
||||||
|
c += FromString_ReadPartScientific( source, scientific_read );
|
||||||
|
|
||||||
|
if( !scientific_read )
|
||||||
|
source = before_scientific;
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
we're testing whether is there the character 'e'
|
we're testing whether is there the character 'e'
|
||||||
|
|
||||||
@@ -3311,21 +3459,24 @@ private:
|
|||||||
this method reads the exponent (after 'e' character) when there's a scientific
|
this method reads the exponent (after 'e' character) when there's a scientific
|
||||||
format of value and only when we're using the base equals 10
|
format of value and only when we're using the base equals 10
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartScientific( const char * & source )
|
uint FromString_ReadPartScientific( const char * & source, bool & scientific_read )
|
||||||
{
|
{
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
Big<exp, man> new_exponent, temp;
|
Big<exp, man> new_exponent, temp;
|
||||||
bool was_sign = false;
|
bool was_sign = false;
|
||||||
|
|
||||||
FromString_TestSign( source, was_sign );
|
FromString_TestSign( source, was_sign );
|
||||||
FromString_ReadPartScientific_ReadExponent( source, new_exponent );
|
c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read );
|
||||||
|
|
||||||
if( was_sign )
|
if( scientific_read )
|
||||||
new_exponent.ChangeSign();
|
{
|
||||||
|
if( was_sign )
|
||||||
|
new_exponent.ChangeSign();
|
||||||
|
|
||||||
temp = 10;
|
temp = 10;
|
||||||
c += temp.PowBInt( new_exponent );
|
c += temp.Pow( new_exponent );
|
||||||
c += Mul(temp);
|
c += Mul(temp);
|
||||||
|
}
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
}
|
}
|
||||||
@@ -3335,7 +3486,7 @@ private:
|
|||||||
this method reads the value of the extra exponent when scientific format is used
|
this method reads the value of the extra exponent when scientific format is used
|
||||||
(only when base == 10)
|
(only when base == 10)
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big<exp, man> & new_exponent )
|
uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big<exp, man> & new_exponent, bool & scientific_read )
|
||||||
{
|
{
|
||||||
sint character;
|
sint character;
|
||||||
Big<exp, man> base, temp;
|
Big<exp, man> base, temp;
|
||||||
@@ -3347,6 +3498,8 @@ private:
|
|||||||
|
|
||||||
for( ; (character=UInt<man>::CharToDigit(*source, 10)) != -1 ; ++source )
|
for( ; (character=UInt<man>::CharToDigit(*source, 10)) != -1 ; ++source )
|
||||||
{
|
{
|
||||||
|
scientific_read = true;
|
||||||
|
|
||||||
temp = character;
|
temp = character;
|
||||||
|
|
||||||
if( new_exponent.Mul(base) )
|
if( new_exponent.Mul(base) )
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -469,6 +469,70 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
power this = this ^ pow
|
||||||
|
this can be negative
|
||||||
|
pow is >= 0
|
||||||
|
*/
|
||||||
|
uint Pow2(const Int<value_size> & pow)
|
||||||
|
{
|
||||||
|
bool was_sign = IsSign();
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
if( was_sign )
|
||||||
|
c += Abs();
|
||||||
|
|
||||||
|
uint c_temp = UInt<value_size>::Pow(pow);
|
||||||
|
if( c_temp > 0 )
|
||||||
|
return c_temp; // c_temp can be: 0, 1 or 2
|
||||||
|
|
||||||
|
if( was_sign && (pow.table[0] & 1) == 1 )
|
||||||
|
// negative value to the power of odd number is negative
|
||||||
|
c += ChangeSign();
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
power this = this ^ pow
|
||||||
|
|
||||||
|
return values:
|
||||||
|
0 - ok
|
||||||
|
1 - carry
|
||||||
|
2 - incorrect arguments 0^0 or 0^(-something)
|
||||||
|
*/
|
||||||
|
uint Pow(Int<value_size> pow)
|
||||||
|
{
|
||||||
|
if( !pow.IsSign() )
|
||||||
|
return Pow2(pow);
|
||||||
|
|
||||||
|
if( UInt<value_size>::IsZero() )
|
||||||
|
// if 'p' is negative then
|
||||||
|
// 'this' must be different from zero
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if( pow.ChangeSign() )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
Int<value_size> t(*this);
|
||||||
|
uint c_temp = t.Pow2(pow);
|
||||||
|
if( c_temp > 0 )
|
||||||
|
return c_temp;
|
||||||
|
|
||||||
|
UInt<value_size>::SetOne();
|
||||||
|
if( Div(t) )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
@@ -583,7 +647,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// converting from Int
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the default assignment operator
|
the default assignment operator
|
||||||
@@ -650,7 +714,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// converting from UInt
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this operator converts an UInt<another_size> type to this class
|
this operator converts an UInt<another_size> type to this class
|
||||||
@@ -696,7 +759,7 @@ public:
|
|||||||
FromUInt(u);
|
FromUInt(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
#ifdef TTMATH_PLATFORM64
|
||||||
@@ -836,8 +899,12 @@ public:
|
|||||||
|
|
||||||
existing first white characters will be ommited
|
existing first white characters will be ommited
|
||||||
(between '-' and a first digit can be white characters too)
|
(between '-' and a first digit can be white characters too)
|
||||||
|
|
||||||
|
after_source (if exists) is pointing at the end of the parsed string
|
||||||
|
|
||||||
|
value_read (if exists) tells whether something has actually been read (at least one digit)
|
||||||
*/
|
*/
|
||||||
uint FromString(const char * s, uint b = 10)
|
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0)
|
||||||
{
|
{
|
||||||
bool is_sign = false;
|
bool is_sign = false;
|
||||||
|
|
||||||
@@ -854,7 +921,7 @@ public:
|
|||||||
UInt<value_size>::SkipWhiteCharacters(++s);
|
UInt<value_size>::SkipWhiteCharacters(++s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( UInt<value_size>::FromString(s,b) )
|
if( UInt<value_size>::FromString(s,b,after_source,value_read) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( is_sign )
|
if( is_sign )
|
||||||
@@ -865,12 +932,15 @@ public:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
the reference to mmin will be automatically converted to the reference
|
the reference to mmin will be automatically converted to the reference
|
||||||
to a UInt type
|
to UInt type
|
||||||
(this value can be equal mmin -- look at a description in ChangeSign())
|
(this value can be equal mmin -- look at a description in ChangeSign())
|
||||||
*/
|
*/
|
||||||
if( UInt<value_size>::operator>( mmin ) )
|
if( UInt<value_size>::operator>( mmin ) )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it)
|
||||||
|
*/
|
||||||
ChangeSign();
|
ChangeSign();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -130,6 +130,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if such an object is defined (name exists)
|
||||||
|
*/
|
||||||
|
bool IsDefined(const std::string & name)
|
||||||
|
{
|
||||||
|
Iterator i = table.find(name);
|
||||||
|
|
||||||
|
if( i != table.end() )
|
||||||
|
// we have this object in our table
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method adds one object (variable of function) into the table
|
this method adds one object (variable of function) into the table
|
||||||
*/
|
*/
|
||||||
@@ -258,7 +273,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value of a specific object
|
this method gets the value of a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValue(const std::string & name, std::string & value) const
|
ErrorCode GetValue(const std::string & name, std::string & value) const
|
||||||
{
|
{
|
||||||
@@ -280,7 +295,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value of a specific object
|
this method gets the value of a specific object
|
||||||
(this version is used for not copying the whole string)
|
(this version is used for not copying the whole string)
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValue(const std::string & name, const char ** value) const
|
ErrorCode GetValue(const std::string & name, const char ** value) const
|
||||||
@@ -303,7 +318,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets the value and the number of parameters
|
this method gets the value and the number of parameters
|
||||||
of a specific object
|
of a specific object
|
||||||
*/
|
*/
|
||||||
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -61,14 +61,14 @@ namespace ttmath
|
|||||||
/*!
|
/*!
|
||||||
\brief Mathematical parser
|
\brief Mathematical parser
|
||||||
|
|
||||||
let x will be an input string means an expression for converting:
|
let x will be an input string meaning an expression for converting:
|
||||||
|
|
||||||
x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
|
x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]...
|
||||||
where:
|
where:
|
||||||
an operator can be:
|
an operator can be:
|
||||||
^ (pow) (almost the heighest priority, look below at 'short mul')
|
^ (pow) (the heighest priority)
|
||||||
|
|
||||||
* (mul)
|
* (mul) (or multiplication without an operator -- short mul)
|
||||||
/ (div) (* and / have the same priority)
|
/ (div) (* and / have the same priority)
|
||||||
|
|
||||||
+ (add)
|
+ (add)
|
||||||
@@ -86,14 +86,22 @@ namespace ttmath
|
|||||||
|| (logical or) (the lowest priority)
|
|| (logical or) (the lowest priority)
|
||||||
|
|
||||||
short mul:
|
short mul:
|
||||||
or if the second Value (Var below) is either a variable or function there cannot be
|
if the second Value (Var below) is either a variable or function there might not be
|
||||||
an operator between them, e.g.
|
an operator between them, e.g.
|
||||||
[+|-]ValueVar is treated as [+|-]Value * Var and the multiplication
|
"[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication
|
||||||
has the greatest priority: 2^3m equals 2^(3*m)
|
has the same priority as a normal multiplication:
|
||||||
|
4x = 4 * x
|
||||||
|
2^3m = (2^3)* m
|
||||||
|
6h^3 = 6 * (h^3)
|
||||||
|
2sin(pi) = 2 * sin(pi)
|
||||||
|
etc.
|
||||||
|
|
||||||
|
Value can be:
|
||||||
and Value can be:
|
constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&]
|
||||||
constant e.g. 100
|
# - hex
|
||||||
|
& - bin
|
||||||
|
sample: #10 = 16
|
||||||
|
&10 = 2
|
||||||
variable e.g. pi
|
variable e.g. pi
|
||||||
another expression between brackets e.g (x)
|
another expression between brackets e.g (x)
|
||||||
function e.g. sin(x)
|
function e.g. sin(x)
|
||||||
@@ -112,7 +120,11 @@ namespace ttmath
|
|||||||
for separating parameters
|
for separating parameters
|
||||||
"1 < 2" (the result will be: 1)
|
"1 < 2" (the result will be: 1)
|
||||||
"4 < 3" (the result will be: 0)
|
"4 < 3" (the result will be: 0)
|
||||||
"2+x" (of course if the variable 'x' is defined)
|
"2+x" (of course if the variable 'x' is defined)
|
||||||
|
"4x+10"
|
||||||
|
"#20+10" = 32 + 10 = 42
|
||||||
|
"10 ^ -&101" = 10 ^ -5 = 0.00001
|
||||||
|
"8 * -&10" = 8 * -2 = -16
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
we can also use a semicolon for separating any 'x' input strings
|
we can also use a semicolon for separating any 'x' input strings
|
||||||
@@ -137,7 +149,7 @@ private:
|
|||||||
pow (^)
|
pow (^)
|
||||||
and 'shortmul' used when there is no any operators between
|
and 'shortmul' used when there is no any operators between
|
||||||
a first parameter and a variable or function
|
a first parameter and a variable or function
|
||||||
(the 'shortmul' has the greatest priority e.g. '5^3m' equals '5^(3*m)' )
|
(the 'shortmul' has the same priority as the normal multiplication )
|
||||||
*/
|
*/
|
||||||
class MatOperator
|
class MatOperator
|
||||||
{
|
{
|
||||||
@@ -182,6 +194,7 @@ private:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case mul:
|
case mul:
|
||||||
|
case shortmul:
|
||||||
case div:
|
case div:
|
||||||
priority = 12;
|
priority = 12;
|
||||||
break;
|
break;
|
||||||
@@ -190,10 +203,6 @@ private:
|
|||||||
priority = 14;
|
priority = 14;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case shortmul:
|
|
||||||
priority = 20;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Error( err_internal_error );
|
Error( err_internal_error );
|
||||||
break;
|
break;
|
||||||
@@ -309,11 +318,21 @@ const char * pstring;
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the base of the mathematic system (for example it may be '10')
|
the base (radix) of the mathematic system (for example it may be '10')
|
||||||
*/
|
*/
|
||||||
int base;
|
int base;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
|
||||||
|
0 - deg
|
||||||
|
1 - rad (default)
|
||||||
|
2 - grad
|
||||||
|
*/
|
||||||
|
int deg_rad_grad;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a pointer to an object which tell us whether we should stop calculating or not
|
a pointer to an object which tell us whether we should stop calculating or not
|
||||||
*/
|
*/
|
||||||
@@ -406,7 +425,6 @@ typedef std::map<std::string, pfunction_var> VariablesTable;
|
|||||||
VariablesTable variables_table;
|
VariablesTable variables_table;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
you can't calculate the factorial if the argument is greater than 'factorial_max'
|
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
|
default value is zero which means there are not any limitations
|
||||||
@@ -423,8 +441,6 @@ static void Error(ErrorCode code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method skips the white character from the string
|
this method skips the white character from the string
|
||||||
|
|
||||||
@@ -437,7 +453,6 @@ void SkipWhiteCharacters()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
@@ -467,6 +482,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
|
|||||||
visited_functions.insert( name );
|
visited_functions.insert( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
|
||||||
*/
|
*/
|
||||||
@@ -478,6 +494,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
|
|||||||
visited_functions.erase( name );
|
visited_functions.erase( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method returns the value of a variable or function
|
this method returns the value of a variable or function
|
||||||
by creating a new instance of the mathematical parser
|
by creating a new instance of the mathematical parser
|
||||||
@@ -612,7 +629,53 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
'silnia' in polish language
|
used by: sin,cos,tan,cot
|
||||||
|
*/
|
||||||
|
ValueType ConvertAngleToRad(const ValueType & input)
|
||||||
|
{
|
||||||
|
if( deg_rad_grad == 1 ) // rad
|
||||||
|
return input;
|
||||||
|
|
||||||
|
ValueType result;
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( deg_rad_grad == 0 ) // deg
|
||||||
|
result = ttmath::DegToRad(input, &err);
|
||||||
|
else // grad
|
||||||
|
result = ttmath::GradToRad(input, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
used by: asin,acos,atan,acot
|
||||||
|
*/
|
||||||
|
ValueType ConvertRadToAngle(const ValueType & input)
|
||||||
|
{
|
||||||
|
if( deg_rad_grad == 1 ) // rad
|
||||||
|
return input;
|
||||||
|
|
||||||
|
ValueType result;
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( deg_rad_grad == 0 ) // deg
|
||||||
|
result = ttmath::RadToDeg(input, &err);
|
||||||
|
else // grad
|
||||||
|
result = ttmath::RadToGrad(input, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
factorial
|
||||||
result = 1 * 2 * 3 * 4 * .... * x
|
result = 1 * 2 * 3 * 4 * .... * x
|
||||||
*/
|
*/
|
||||||
void Factorial(int sindex, int amount_of_args, ValueType & result)
|
void Factorial(int sindex, int amount_of_args, ValueType & result)
|
||||||
@@ -645,7 +708,7 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
|
|||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
result = ttmath::Sin(stack[sindex].value);
|
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cos(int sindex, int amount_of_args, ValueType & result)
|
void Cos(int sindex, int amount_of_args, ValueType & result)
|
||||||
@@ -653,7 +716,7 @@ void Cos(int sindex, int amount_of_args, ValueType & result)
|
|||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
result = ttmath::Cos(stack[sindex].value);
|
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tan(int sindex, int amount_of_args, ValueType & result)
|
void Tan(int sindex, int amount_of_args, ValueType & result)
|
||||||
@@ -662,7 +725,7 @@ void Tan(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
ErrorCode err;
|
ErrorCode err;
|
||||||
result = ttmath::Tan(stack[sindex].value, &err);
|
result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err);
|
||||||
|
|
||||||
if(err != err_ok)
|
if(err != err_ok)
|
||||||
Error( err );
|
Error( err );
|
||||||
@@ -674,7 +737,7 @@ void Cot(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
ErrorCode err;
|
ErrorCode err;
|
||||||
result = ttmath::Cot(stack[sindex].value, &err);
|
result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err);
|
||||||
|
|
||||||
if(err != err_ok)
|
if(err != err_ok)
|
||||||
Error( err );
|
Error( err );
|
||||||
@@ -779,10 +842,12 @@ void ASin(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
ErrorCode err;
|
ErrorCode err;
|
||||||
result = ttmath::ASin(stack[sindex].value, &err);
|
ValueType temp = ttmath::ASin(stack[sindex].value, &err);
|
||||||
|
|
||||||
if(err != err_ok)
|
if(err != err_ok)
|
||||||
Error( err );
|
Error( err );
|
||||||
|
|
||||||
|
result = ConvertRadToAngle(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -792,10 +857,12 @@ void ACos(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
ErrorCode err;
|
ErrorCode err;
|
||||||
result = ttmath::ACos(stack[sindex].value, &err);
|
ValueType temp = ttmath::ACos(stack[sindex].value, &err);
|
||||||
|
|
||||||
if(err != err_ok)
|
if(err != err_ok)
|
||||||
Error( err );
|
Error( err );
|
||||||
|
|
||||||
|
result = ConvertRadToAngle(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -804,7 +871,7 @@ void ATan(int sindex, int amount_of_args, ValueType & result)
|
|||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
result = ttmath::ATan(stack[sindex].value);
|
result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -813,7 +880,7 @@ void ACot(int sindex, int amount_of_args, ValueType & result)
|
|||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
Error( err_improper_amount_of_arguments );
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
result = ttmath::ACot(stack[sindex].value);
|
result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -954,6 +1021,72 @@ void DegToDeg(int sindex, int amount_of_args, ValueType & result)
|
|||||||
Error( err );
|
Error( err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GradToRad(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
result = ttmath::GradToRad(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RadToGrad(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
result = ttmath::RadToGrad(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DegToGrad(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( amount_of_args == 1 )
|
||||||
|
{
|
||||||
|
result = ttmath::DegToGrad(stack[sindex].value, &err);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( amount_of_args == 3 )
|
||||||
|
{
|
||||||
|
result = ttmath::DegToGrad( stack[sindex].value, stack[sindex+2].value,
|
||||||
|
stack[sindex+4].value, &err);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GradToDeg(int sindex, int amount_of_args, ValueType & result)
|
||||||
|
{
|
||||||
|
ErrorCode err;
|
||||||
|
|
||||||
|
if( amount_of_args != 1 )
|
||||||
|
Error( err_improper_amount_of_arguments );
|
||||||
|
|
||||||
|
result = ttmath::GradToDeg(stack[sindex].value, &err);
|
||||||
|
|
||||||
|
if( err != err_ok )
|
||||||
|
Error( err );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Ceil(int sindex, int amount_of_args, ValueType & result)
|
void Ceil(int sindex, int amount_of_args, ValueType & result)
|
||||||
{
|
{
|
||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
@@ -1282,9 +1415,9 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin
|
|||||||
function_name - name of the function
|
function_name - name of the function
|
||||||
pf - pointer to the function (to the wrapper)
|
pf - pointer to the function (to the wrapper)
|
||||||
*/
|
*/
|
||||||
void InsertFunctionToTable(const std::string & function_name, pfunction pf)
|
void InsertFunctionToTable(const char * function_name, pfunction pf)
|
||||||
{
|
{
|
||||||
functions_table.insert( std::make_pair(function_name, pf));
|
functions_table.insert( std::make_pair(std::string(function_name), pf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1295,9 +1428,9 @@ void InsertFunctionToTable(const std::string & function_name, pfunction pf)
|
|||||||
variable_name - name of the function
|
variable_name - name of the function
|
||||||
pf - pointer to the function
|
pf - pointer to the function
|
||||||
*/
|
*/
|
||||||
void InsertVariableToTable(const std::string & variable_name, pfunction_var pf)
|
void InsertVariableToTable(const char * variable_name, pfunction_var pf)
|
||||||
{
|
{
|
||||||
variables_table.insert( std::make_pair(variable_name, pf));
|
variables_table.insert( std::make_pair(std::string(variable_name), pf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1309,60 +1442,64 @@ void CreateFunctionsTable()
|
|||||||
/*
|
/*
|
||||||
names of functions should consist of small letters
|
names of functions should consist of small letters
|
||||||
*/
|
*/
|
||||||
InsertFunctionToTable(std::string("factorial"), &Parser<ValueType>::Factorial);
|
InsertFunctionToTable("factorial", &Parser<ValueType>::Factorial);
|
||||||
InsertFunctionToTable(std::string("abs"), &Parser<ValueType>::Abs);
|
InsertFunctionToTable("abs", &Parser<ValueType>::Abs);
|
||||||
InsertFunctionToTable(std::string("sin"), &Parser<ValueType>::Sin);
|
InsertFunctionToTable("sin", &Parser<ValueType>::Sin);
|
||||||
InsertFunctionToTable(std::string("cos"), &Parser<ValueType>::Cos);
|
InsertFunctionToTable("cos", &Parser<ValueType>::Cos);
|
||||||
InsertFunctionToTable(std::string("tan"), &Parser<ValueType>::Tan);
|
InsertFunctionToTable("tan", &Parser<ValueType>::Tan);
|
||||||
InsertFunctionToTable(std::string("tg"), &Parser<ValueType>::Tan);
|
InsertFunctionToTable("tg", &Parser<ValueType>::Tan);
|
||||||
InsertFunctionToTable(std::string("cot"), &Parser<ValueType>::Cot);
|
InsertFunctionToTable("cot", &Parser<ValueType>::Cot);
|
||||||
InsertFunctionToTable(std::string("ctg"), &Parser<ValueType>::Cot);
|
InsertFunctionToTable("ctg", &Parser<ValueType>::Cot);
|
||||||
InsertFunctionToTable(std::string("int"), &Parser<ValueType>::Int);
|
InsertFunctionToTable("int", &Parser<ValueType>::Int);
|
||||||
InsertFunctionToTable(std::string("round"), &Parser<ValueType>::Round);
|
InsertFunctionToTable("round", &Parser<ValueType>::Round);
|
||||||
InsertFunctionToTable(std::string("ln"), &Parser<ValueType>::Ln);
|
InsertFunctionToTable("ln", &Parser<ValueType>::Ln);
|
||||||
InsertFunctionToTable(std::string("log"), &Parser<ValueType>::Log);
|
InsertFunctionToTable("log", &Parser<ValueType>::Log);
|
||||||
InsertFunctionToTable(std::string("exp"), &Parser<ValueType>::Exp);
|
InsertFunctionToTable("exp", &Parser<ValueType>::Exp);
|
||||||
InsertFunctionToTable(std::string("max"), &Parser<ValueType>::Max);
|
InsertFunctionToTable("max", &Parser<ValueType>::Max);
|
||||||
InsertFunctionToTable(std::string("min"), &Parser<ValueType>::Min);
|
InsertFunctionToTable("min", &Parser<ValueType>::Min);
|
||||||
InsertFunctionToTable(std::string("asin"), &Parser<ValueType>::ASin);
|
InsertFunctionToTable("asin", &Parser<ValueType>::ASin);
|
||||||
InsertFunctionToTable(std::string("acos"), &Parser<ValueType>::ACos);
|
InsertFunctionToTable("acos", &Parser<ValueType>::ACos);
|
||||||
InsertFunctionToTable(std::string("atan"), &Parser<ValueType>::ATan);
|
InsertFunctionToTable("atan", &Parser<ValueType>::ATan);
|
||||||
InsertFunctionToTable(std::string("atg"), &Parser<ValueType>::ATan);
|
InsertFunctionToTable("atg", &Parser<ValueType>::ATan);
|
||||||
InsertFunctionToTable(std::string("acot"), &Parser<ValueType>::ACot);
|
InsertFunctionToTable("acot", &Parser<ValueType>::ACot);
|
||||||
InsertFunctionToTable(std::string("actg"), &Parser<ValueType>::ACot);
|
InsertFunctionToTable("actg", &Parser<ValueType>::ACot);
|
||||||
InsertFunctionToTable(std::string("sgn"), &Parser<ValueType>::Sgn);
|
InsertFunctionToTable("sgn", &Parser<ValueType>::Sgn);
|
||||||
InsertFunctionToTable(std::string("mod"), &Parser<ValueType>::Mod);
|
InsertFunctionToTable("mod", &Parser<ValueType>::Mod);
|
||||||
InsertFunctionToTable(std::string("if"), &Parser<ValueType>::If);
|
InsertFunctionToTable("if", &Parser<ValueType>::If);
|
||||||
InsertFunctionToTable(std::string("or"), &Parser<ValueType>::Or);
|
InsertFunctionToTable("or", &Parser<ValueType>::Or);
|
||||||
InsertFunctionToTable(std::string("and"), &Parser<ValueType>::And);
|
InsertFunctionToTable("and", &Parser<ValueType>::And);
|
||||||
InsertFunctionToTable(std::string("not"), &Parser<ValueType>::Not);
|
InsertFunctionToTable("not", &Parser<ValueType>::Not);
|
||||||
InsertFunctionToTable(std::string("degtorad"), &Parser<ValueType>::DegToRad);
|
InsertFunctionToTable("degtorad", &Parser<ValueType>::DegToRad);
|
||||||
InsertFunctionToTable(std::string("radtodeg"), &Parser<ValueType>::RadToDeg);
|
InsertFunctionToTable("radtodeg", &Parser<ValueType>::RadToDeg);
|
||||||
InsertFunctionToTable(std::string("degtodeg"), &Parser<ValueType>::DegToDeg);
|
InsertFunctionToTable("degtodeg", &Parser<ValueType>::DegToDeg);
|
||||||
InsertFunctionToTable(std::string("ceil"), &Parser<ValueType>::Ceil);
|
InsertFunctionToTable("gradtorad", &Parser<ValueType>::GradToRad);
|
||||||
InsertFunctionToTable(std::string("floor"), &Parser<ValueType>::Floor);
|
InsertFunctionToTable("radtograd", &Parser<ValueType>::RadToGrad);
|
||||||
InsertFunctionToTable(std::string("sqrt"), &Parser<ValueType>::Sqrt);
|
InsertFunctionToTable("degtograd", &Parser<ValueType>::DegToGrad);
|
||||||
InsertFunctionToTable(std::string("sinh"), &Parser<ValueType>::Sinh);
|
InsertFunctionToTable("gradtodeg", &Parser<ValueType>::GradToDeg);
|
||||||
InsertFunctionToTable(std::string("cosh"), &Parser<ValueType>::Cosh);
|
InsertFunctionToTable("ceil", &Parser<ValueType>::Ceil);
|
||||||
InsertFunctionToTable(std::string("tanh"), &Parser<ValueType>::Tanh);
|
InsertFunctionToTable("floor", &Parser<ValueType>::Floor);
|
||||||
InsertFunctionToTable(std::string("tgh"), &Parser<ValueType>::Tanh);
|
InsertFunctionToTable("sqrt", &Parser<ValueType>::Sqrt);
|
||||||
InsertFunctionToTable(std::string("coth"), &Parser<ValueType>::Coth);
|
InsertFunctionToTable("sinh", &Parser<ValueType>::Sinh);
|
||||||
InsertFunctionToTable(std::string("ctgh"), &Parser<ValueType>::Coth);
|
InsertFunctionToTable("cosh", &Parser<ValueType>::Cosh);
|
||||||
InsertFunctionToTable(std::string("root"), &Parser<ValueType>::Root);
|
InsertFunctionToTable("tanh", &Parser<ValueType>::Tanh);
|
||||||
InsertFunctionToTable(std::string("asinh"), &Parser<ValueType>::ASinh);
|
InsertFunctionToTable("tgh", &Parser<ValueType>::Tanh);
|
||||||
InsertFunctionToTable(std::string("acosh"), &Parser<ValueType>::ACosh);
|
InsertFunctionToTable("coth", &Parser<ValueType>::Coth);
|
||||||
InsertFunctionToTable(std::string("atanh"), &Parser<ValueType>::ATanh);
|
InsertFunctionToTable("ctgh", &Parser<ValueType>::Coth);
|
||||||
InsertFunctionToTable(std::string("atgh"), &Parser<ValueType>::ATanh);
|
InsertFunctionToTable("root", &Parser<ValueType>::Root);
|
||||||
InsertFunctionToTable(std::string("acoth"), &Parser<ValueType>::ACoth);
|
InsertFunctionToTable("asinh", &Parser<ValueType>::ASinh);
|
||||||
InsertFunctionToTable(std::string("actgh"), &Parser<ValueType>::ACoth);
|
InsertFunctionToTable("acosh", &Parser<ValueType>::ACosh);
|
||||||
InsertFunctionToTable(std::string("bitand"), &Parser<ValueType>::BitAnd);
|
InsertFunctionToTable("atanh", &Parser<ValueType>::ATanh);
|
||||||
InsertFunctionToTable(std::string("bitor"), &Parser<ValueType>::BitOr);
|
InsertFunctionToTable("atgh", &Parser<ValueType>::ATanh);
|
||||||
InsertFunctionToTable(std::string("bitxor"), &Parser<ValueType>::BitXor);
|
InsertFunctionToTable("acoth", &Parser<ValueType>::ACoth);
|
||||||
InsertFunctionToTable(std::string("band"), &Parser<ValueType>::BitAnd);
|
InsertFunctionToTable("actgh", &Parser<ValueType>::ACoth);
|
||||||
InsertFunctionToTable(std::string("bor"), &Parser<ValueType>::BitOr);
|
InsertFunctionToTable("bitand", &Parser<ValueType>::BitAnd);
|
||||||
InsertFunctionToTable(std::string("bxor"), &Parser<ValueType>::BitXor);
|
InsertFunctionToTable("bitor", &Parser<ValueType>::BitOr);
|
||||||
InsertFunctionToTable(std::string("sum"), &Parser<ValueType>::Sum);
|
InsertFunctionToTable("bitxor", &Parser<ValueType>::BitXor);
|
||||||
InsertFunctionToTable(std::string("avg"), &Parser<ValueType>::Avg);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1374,8 +1511,8 @@ void CreateVariablesTable()
|
|||||||
/*
|
/*
|
||||||
names of variables should consist of small letters
|
names of variables should consist of small letters
|
||||||
*/
|
*/
|
||||||
InsertVariableToTable(std::string("pi"), &ValueType::SetPi);
|
InsertVariableToTable("pi", &ValueType::SetPi);
|
||||||
InsertVariableToTable(std::string("e"), &ValueType::SetE);
|
InsertVariableToTable("e", &ValueType::SetE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1500,15 +1637,19 @@ return is_it_name_of_function;
|
|||||||
/*!
|
/*!
|
||||||
we're reading a numerical value directly from the string
|
we're reading a numerical value directly from the string
|
||||||
*/
|
*/
|
||||||
void ReadValue(Item & result)
|
void ReadValue(Item & result, int reading_base)
|
||||||
{
|
{
|
||||||
const char * new_stack_pointer;
|
const char * new_stack_pointer;
|
||||||
|
bool value_read;
|
||||||
|
|
||||||
int carry = result.value.FromString(pstring, base, &new_stack_pointer);
|
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
|
||||||
pstring = new_stack_pointer;
|
pstring = new_stack_pointer;
|
||||||
|
|
||||||
if( carry )
|
if( carry )
|
||||||
Error( err_overflow );
|
Error( err_overflow );
|
||||||
|
|
||||||
|
if( !value_read )
|
||||||
|
Error( err_unknown_character );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1537,6 +1678,24 @@ return c;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too)
|
||||||
|
*/
|
||||||
|
bool ValueStarts(int character, int base)
|
||||||
|
{
|
||||||
|
if( character == TTMATH_COMMA_CHARACTER_1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( TTMATH_COMMA_CHARACTER_2 != 0 && character == TTMATH_COMMA_CHARACTER_2 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( CharToDigit(character, base) != -1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
we're reading the item
|
we're reading the item
|
||||||
|
|
||||||
@@ -1596,19 +1755,33 @@ int character;
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( character=='#' || character=='&' ||
|
if( character == '#' )
|
||||||
character==TTMATH_COMMA_CHARACTER_1 ||
|
|
||||||
(character==TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0) ||
|
|
||||||
CharToDigit(character, base)!=-1 )
|
|
||||||
{
|
{
|
||||||
/*
|
++pstring;
|
||||||
warning:
|
SkipWhiteCharacters();
|
||||||
if we're using for example the base equal 16
|
|
||||||
we can find a first character like 'e' that is not e=2.71..
|
// after '#' character we do not allow '-' or '+' (can be white characters)
|
||||||
but the value 14, for this case we must use something like var::e for variables
|
if( ValueStarts(*pstring, 16) )
|
||||||
(not implemented yet)
|
ReadValue( result, 16 );
|
||||||
*/
|
else
|
||||||
ReadValue( result );
|
Error( err_unknown_character );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( character == '&' )
|
||||||
|
{
|
||||||
|
++pstring;
|
||||||
|
SkipWhiteCharacters();
|
||||||
|
|
||||||
|
// after '&' character we do not allow '-' or '+' (can be white characters)
|
||||||
|
if( ValueStarts(*pstring, 2) )
|
||||||
|
ReadValue( result, 2 );
|
||||||
|
else
|
||||||
|
Error( err_unknown_character );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( ValueStarts(character, base) )
|
||||||
|
{
|
||||||
|
ReadValue( result, base );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( character>='a' && character<='z' )
|
if( character>='a' && character<='z' )
|
||||||
@@ -1911,9 +2084,9 @@ void TryRollingUpStack()
|
|||||||
*/
|
*/
|
||||||
int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp)
|
int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp)
|
||||||
{
|
{
|
||||||
int kod = ReadValueVariableOrFunction( temp );
|
int code = ReadValueVariableOrFunction( temp );
|
||||||
|
|
||||||
if( kod == 0 )
|
if( code == 0 )
|
||||||
{
|
{
|
||||||
if( stack_index < stack.size() )
|
if( stack_index < stack.size() )
|
||||||
stack[stack_index] = temp;
|
stack[stack_index] = temp;
|
||||||
@@ -1923,13 +2096,13 @@ int kod = ReadValueVariableOrFunction( temp );
|
|||||||
++stack_index;
|
++stack_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( kod == 2 )
|
if( code == 2 )
|
||||||
// there was a final bracket, we didn't push it into the stack
|
// there was a final bracket, we didn't push it into the stack
|
||||||
// (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next)
|
// (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next)
|
||||||
kod = 0;
|
code = 0;
|
||||||
|
|
||||||
|
|
||||||
return kod;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2218,6 +2391,7 @@ Parser(): default_stack_size(100)
|
|||||||
puser_functions = 0;
|
puser_functions = 0;
|
||||||
pfunction_local_variables = 0;
|
pfunction_local_variables = 0;
|
||||||
base = 10;
|
base = 10;
|
||||||
|
deg_rad_grad = 1;
|
||||||
error = err_ok;
|
error = err_ok;
|
||||||
factorial_max.SetZero();
|
factorial_max.SetZero();
|
||||||
|
|
||||||
@@ -2237,6 +2411,7 @@ Parser<ValueType> & operator=(const Parser<ValueType> & p)
|
|||||||
puser_functions = p.puser_functions;
|
puser_functions = p.puser_functions;
|
||||||
pfunction_local_variables = 0;
|
pfunction_local_variables = 0;
|
||||||
base = p.base;
|
base = p.base;
|
||||||
|
deg_rad_grad = p.deg_rad_grad;
|
||||||
error = err_ok;
|
error = err_ok;
|
||||||
factorial_max = p.factorial_max;
|
factorial_max = p.factorial_max;
|
||||||
|
|
||||||
@@ -2274,6 +2449,18 @@ void SetBase(int b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot
|
||||||
|
0 - deg
|
||||||
|
1 - rad (default)
|
||||||
|
2 - grad
|
||||||
|
*/
|
||||||
|
void SetDegRadGrad(int angle)
|
||||||
|
{
|
||||||
|
if( angle >= 0 || angle <= 2 )
|
||||||
|
deg_rad_grad = angle;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets a pointer to the object which tell us whether we should stop
|
this method sets a pointer to the object which tell us whether we should stop
|
||||||
calculations
|
calculations
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* 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.
|
* and is distributed under the (new) BSD licence.
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 8
|
#define TTMATH_MINOR_VER 8
|
||||||
#define TTMATH_REVISION_VER 2
|
#define TTMATH_REVISION_VER 4
|
||||||
#define TTMATH_PRERELEASE_VER 0
|
#define TTMATH_PRERELEASE_VER 0
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
||||||
or by defining this macro in your code before using any header files of this library
|
or by defining this macro in your code before using any header files of this library
|
||||||
|
|
||||||
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set
|
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
|
||||||
*/
|
*/
|
||||||
#ifndef TTMATH_RELEASE
|
#ifndef TTMATH_RELEASE
|
||||||
#define TTMATH_DEBUG
|
#define TTMATH_DEBUG
|
||||||
@@ -120,6 +120,20 @@ namespace ttmath
|
|||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
typedef signed int sint;
|
typedef signed int sint;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this type is twice bigger than uint
|
||||||
|
(64bit on a 32bit platforms)
|
||||||
|
|
||||||
|
although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long)
|
||||||
|
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
|
||||||
|
|
||||||
|
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
|
||||||
|
but only on a 32bit platform
|
||||||
|
*/
|
||||||
|
#ifdef TTMATH_NOASM
|
||||||
|
typedef unsigned long long int ulint;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
how many bits there are in the uint type
|
how many bits there are in the uint type
|
||||||
*/
|
*/
|
||||||
@@ -141,7 +155,7 @@ namespace ttmath
|
|||||||
which are kept in built-in variables for a Big<> type
|
which are kept in built-in variables for a Big<> type
|
||||||
(these variables are defined in ttmathbig.h)
|
(these variables are defined in ttmathbig.h)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 128u
|
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -151,6 +165,15 @@ namespace ttmath
|
|||||||
typedef unsigned long uint;
|
typedef unsigned long uint;
|
||||||
typedef signed long sint;
|
typedef signed long sint;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
on 64bit platform we do not define ulint
|
||||||
|
sizeof(long long) is 8 (64bit) but we need 128bit
|
||||||
|
|
||||||
|
on 64 bit platform (when there is defined TTMATH_NOASM macro)
|
||||||
|
methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit
|
||||||
|
*/
|
||||||
|
//typedef unsigned long long int ulint;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
how many bits there are in the uint type
|
how many bits there are in the uint type
|
||||||
*/
|
*/
|
||||||
@@ -172,7 +195,7 @@ namespace ttmath
|
|||||||
which are kept in built-in variables for a Big<> type
|
which are kept in built-in variables for a Big<> type
|
||||||
(these variables are defined in ttmathbig.h)
|
(these variables are defined in ttmathbig.h)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_BUILTIN_VARIABLES_SIZE 64ul
|
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -407,6 +430,19 @@ namespace ttmath
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_DEBUG_LOG
|
||||||
|
|
||||||
|
#define TTMATH_LOG(msg) \
|
||||||
|
PrintLog(msg, std::cout);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TTMATH_LOG(msg)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
1817
ttmath/ttmathuint.h
1817
ttmath/ttmathuint.h
File diff suppressed because it is too large
Load Diff
@@ -1,985 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of TTMath Mathematical Library
|
|
||||||
* and is distributed under the (new) BSD licence.
|
|
||||||
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2006-2008, Tomasz Sowa
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
|
||||||
* project may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
||||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file ttmathuint.h
|
|
||||||
\brief template class UInt<uint> for 64bit processors
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
|
||||||
{
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* basic mathematic functions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef TTMATH_PLATFORM64
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
in 64bit platforms we must define additional operators and contructors
|
|
||||||
in order to allow a user initializing the objects in this way:
|
|
||||||
UInt<...> type = 20;
|
|
||||||
or
|
|
||||||
UInt<...> type;
|
|
||||||
type = 30;
|
|
||||||
|
|
||||||
decimal constants such as 20, 30 etc. are integer literal of type int,
|
|
||||||
if the value is greater it can even be long int,
|
|
||||||
0 is an octal integer of type int
|
|
||||||
(ISO 14882 p2.13.1 Integer literals)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this operator converts the unsigned int type to this class
|
|
||||||
|
|
||||||
***this operator is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size> & UInt<value_size>::operator=(unsigned int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
a constructor for converting the unsigned int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size>::UInt(unsigned int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
an operator for converting the signed int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
|
|
||||||
look at the description of UInt::operator=(sint)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size> & UInt<value_size>::operator=(signed int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
a constructor for converting the signed int to this class
|
|
||||||
|
|
||||||
***this constructor is created only on a 64bit platform***
|
|
||||||
it takes one argument of 32bit
|
|
||||||
|
|
||||||
look at the description of UInt::operator=(sint)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
UInt<value_size>::UInt(signed int i)
|
|
||||||
{
|
|
||||||
FromUInt(uint(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method copies the value stored in an another table
|
|
||||||
(warning: first values in temp_table are the highest words -- it's different
|
|
||||||
from our table)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
we copy as many words as it is possible
|
|
||||||
|
|
||||||
if temp_table_len is bigger than value_size we'll try to round
|
|
||||||
the lowest word from table depending on the last not used bit in temp_table
|
|
||||||
(this rounding isn't a perfect rounding -- look at the description below)
|
|
||||||
|
|
||||||
and if temp_table_len is smaller than value_size we'll clear the rest words
|
|
||||||
in the table
|
|
||||||
|
|
||||||
warning: we're using 'temp_table' as a pointer at 32bit words
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
void UInt<value_size>::SetFromTable(const unsigned int * temp_table, uint temp_table_len)
|
|
||||||
{
|
|
||||||
uint temp_table_index = 0;
|
|
||||||
sint i; // 'i' with a sign
|
|
||||||
|
|
||||||
for(i=value_size-1 ; i>=0 && temp_table_index<temp_table_len; --i, ++temp_table_index)
|
|
||||||
{
|
|
||||||
table[i] = uint(temp_table[ temp_table_index ]) << 32;
|
|
||||||
|
|
||||||
++temp_table_index;
|
|
||||||
|
|
||||||
if( temp_table_index<temp_table_len )
|
|
||||||
table[i] |= temp_table[ temp_table_index ];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// rounding mantissa
|
|
||||||
if( temp_table_index < temp_table_len )
|
|
||||||
{
|
|
||||||
if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
very simply rounding
|
|
||||||
if the bit from not used last word from temp_table is set to one
|
|
||||||
we're rouding the lowest word in the table
|
|
||||||
|
|
||||||
in fact there should be a normal addition but
|
|
||||||
we don't use Add() or AddTwoInts() because these methods
|
|
||||||
can set a carry and then there'll be a small problem
|
|
||||||
for optimization
|
|
||||||
*/
|
|
||||||
if( table[0] != TTMATH_UINT_MAX_VALUE )
|
|
||||||
++table[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleaning the rest of the mantissa
|
|
||||||
for( ; i >= 0 ; --i)
|
|
||||||
table[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adding ss2 to the this and adding carry if it's defined
|
|
||||||
(this = this + ss2 + c)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
|
||||||
function returns carry (1) (if it was)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
/*
|
|
||||||
this part should be compiled with gcc
|
|
||||||
*/
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"subq %%rsi, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"movq (%%rbx),%%rax \n"
|
|
||||||
"adcq (%%rdx),%%rax \n"
|
|
||||||
"movq %%rax,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
"movq %%rax, %%rsi \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=S" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adds one word (at a specific position)
|
|
||||||
and returns a carry (if it was)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
|
|
||||||
if we've got (value_size=3):
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30;
|
|
||||||
table[2] = 5;
|
|
||||||
and we call:
|
|
||||||
AddInt(2,1)
|
|
||||||
then it'll be:
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30 + 2;
|
|
||||||
table[2] = 5;
|
|
||||||
|
|
||||||
of course if there was a carry from table[3] it would be returned
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::AddInt(uint value, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq %%rsi, %%rdx \n"
|
|
||||||
"clc \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (value)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method adds only two unsigned words to the existing value
|
|
||||||
and these words begin on the 'index' position
|
|
||||||
(it's used in the multiplication algorithm 2)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
|
||||||
x1 - lower word, x2 - higher word
|
|
||||||
|
|
||||||
for example if we've got value_size equal 4 and:
|
|
||||||
table[0] = 3
|
|
||||||
table[1] = 4
|
|
||||||
table[2] = 5
|
|
||||||
table[3] = 6
|
|
||||||
then let
|
|
||||||
x1 = 10
|
|
||||||
x2 = 20
|
|
||||||
and
|
|
||||||
index = 1
|
|
||||||
|
|
||||||
the result of this method will be:
|
|
||||||
table[0] = 3
|
|
||||||
table[1] = 4 + x1 = 14
|
|
||||||
table[2] = 5 + x2 = 25
|
|
||||||
table[3] = 6
|
|
||||||
|
|
||||||
and no carry at the end of table[3]
|
|
||||||
|
|
||||||
(of course if there was a carry in table[2](5+20) then
|
|
||||||
this carry would be passed to the table[3] etc.)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"addq %%rsi, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdi, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"dec %%rcx \n"
|
|
||||||
"dec %%rcx \n"
|
|
||||||
"jz 2f \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"adcq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (x1), "D" (x2)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method's subtracting ss2 from the 'this' and subtracting
|
|
||||||
carry if it has been defined
|
|
||||||
(this = this - ss2 - c)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
c must be zero or one (might be a bigger value than 1)
|
|
||||||
function returns carry (1) (if it was)
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint * p2 = const_cast<uint*>(ss2.table);
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"subq %%rsi, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"movq (%%rbx),%%rax \n"
|
|
||||||
"sbbq (%%rdx),%%rax \n"
|
|
||||||
"movq %%rax,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
"inc %%rdx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
"movq %%rax, %%rsi \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=S" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method subtracts one word (at a specific position)
|
|
||||||
and returns a carry (if it was)
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
if we've got (value_size=3):
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30;
|
|
||||||
table[2] = 5;
|
|
||||||
and we call:
|
|
||||||
SubInt(2,1)
|
|
||||||
then it'll be:
|
|
||||||
table[0] = 10;
|
|
||||||
table[1] = 30 - 2;
|
|
||||||
table[2] = 5;
|
|
||||||
|
|
||||||
of course if there was a carry from table[3] it would be returned
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::SubInt(uint value, uint index)
|
|
||||||
{
|
|
||||||
register uint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
register uint c;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
"push %%rdx \n"
|
|
||||||
|
|
||||||
"subq %%rdx, %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
|
||||||
|
|
||||||
"movq %%rsi, %%rdx \n"
|
|
||||||
"clc \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
"movq (%%rbx), %%rax \n"
|
|
||||||
"sbbq %%rdx, %%rax \n"
|
|
||||||
"movq %%rax, (%%rbx) \n"
|
|
||||||
|
|
||||||
"jnc 2f \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"movq $0, %%rax \n"
|
|
||||||
"adcq %%rax,%%rax \n"
|
|
||||||
|
|
||||||
"pop %%rdx \n"
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
: "=a" (c)
|
|
||||||
: "c" (b), "d" (index), "b" (p1), "S" (value)
|
|
||||||
: "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method moves all bits into the left hand side
|
|
||||||
return value <- this <- c
|
|
||||||
|
|
||||||
the lowest *bits* will be held the 'c' and
|
|
||||||
the state of one additional bit (on the left hand side)
|
|
||||||
will be returned
|
|
||||||
|
|
||||||
for example:
|
|
||||||
let this is 001010000
|
|
||||||
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
|
||||||
{
|
|
||||||
if( bits == 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
|
||||||
|
|
||||||
register sint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rsi \n"
|
|
||||||
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
"xorq %%rax,%%rax \n"
|
|
||||||
"subq %%rdx,%%rax \n"
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"rclq $1,(%%rbx) \n"
|
|
||||||
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
"inc %%rbx \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
"decq %%rsi \n"
|
|
||||||
|
|
||||||
"jnz 2b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx, %%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rsi \n"
|
|
||||||
|
|
||||||
: "=d" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method moves all bits into the right hand side
|
|
||||||
C -> this -> return value
|
|
||||||
|
|
||||||
the highest *bits* will be held the 'c' and
|
|
||||||
the state of one additional bit (on the right hand side)
|
|
||||||
will be returned
|
|
||||||
|
|
||||||
for example:
|
|
||||||
let this is 000000010
|
|
||||||
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
|
||||||
{
|
|
||||||
if( bits == 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
|
||||||
|
|
||||||
register sint b = value_size;
|
|
||||||
register uint * p1 = table;
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"push %%rsi \n"
|
|
||||||
|
|
||||||
|
|
||||||
"2: \n"
|
|
||||||
|
|
||||||
|
|
||||||
"push %%rbx \n"
|
|
||||||
"push %%rcx \n"
|
|
||||||
|
|
||||||
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
|
||||||
|
|
||||||
"xorq %%rax, %%rax \n"
|
|
||||||
"subq %%rdx, %%rax \n"
|
|
||||||
|
|
||||||
"1: \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
"dec %%rbx \n"
|
|
||||||
|
|
||||||
"rcrq $1,(%%rbx) \n"
|
|
||||||
|
|
||||||
"loop 1b \n"
|
|
||||||
|
|
||||||
"pop %%rcx \n"
|
|
||||||
"pop %%rbx \n"
|
|
||||||
|
|
||||||
"decq %%rsi \n"
|
|
||||||
|
|
||||||
"jnz 2b \n"
|
|
||||||
|
|
||||||
"movq $0, %%rdx \n"
|
|
||||||
"adcq %%rdx,%%rdx \n"
|
|
||||||
|
|
||||||
"pop %%rsi \n"
|
|
||||||
|
|
||||||
: "=d" (c)
|
|
||||||
: "0" (c), "c" (b), "b" (p1), "S" (bits)
|
|
||||||
: "%rax", "cc", "memory" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
this method returns the number of the highest set bit in one 32-bit word
|
|
||||||
if the 'x' is zero this method returns '-1'
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
|
||||||
{
|
|
||||||
register sint result;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
|
|
||||||
"bsrq %%rbx, %%rax \n"
|
|
||||||
"jnz 1f \n"
|
|
||||||
"movq $-1, %%rax \n"
|
|
||||||
"1: \n"
|
|
||||||
|
|
||||||
: "=a" (result)
|
|
||||||
: "b" (x)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method sets a special bit in the 'value'
|
|
||||||
and returns the result
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
bit is from <0,31>
|
|
||||||
|
|
||||||
e.g.
|
|
||||||
SetBitInWord(0,0) = 1
|
|
||||||
SetBitInWord(0,2) = 4
|
|
||||||
SetBitInWord(10, 8) = 266
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
uint UInt<value_size>::SetBitInWord(uint value, uint bit)
|
|
||||||
{
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"btsq %%rbx,%%rax \n"
|
|
||||||
|
|
||||||
: "=a" (value)
|
|
||||||
: "0" (value), "b" (bit)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* Multiplication
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
multiplication: result2:result1 = a * b
|
|
||||||
result2 - higher word
|
|
||||||
result1 - lower word of the result
|
|
||||||
|
|
||||||
this methos never returns a carry
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
it is an auxiliary method for version two of the multiplication algorithm
|
|
||||||
*/
|
|
||||||
template<uint value_size>
|
|
||||||
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
we must use these temporary variables in order to inform the compilator
|
|
||||||
that value pointed with result1 and result2 has changed
|
|
||||||
|
|
||||||
this has no effect in visual studio but it's usefull when
|
|
||||||
using gcc and options like -O
|
|
||||||
*/
|
|
||||||
register uint result1_;
|
|
||||||
register uint result2_;
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"mulq %%rdx \n"
|
|
||||||
|
|
||||||
: "=a" (result1_), "=d" (result2_)
|
|
||||||
: "0" (a), "1" (b)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
*result1 = result1_;
|
|
||||||
*result2 = result2_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* Division
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
|
||||||
r = a:b / c and rest - remainder
|
|
||||||
|
|
||||||
***this method is created only on a 64bit platform***
|
|
||||||
|
|
||||||
*
|
|
||||||
* WARNING:
|
|
||||||
* if r (one word) is too small for the result or c is equal zero
|
|
||||||
* there'll be a hardware interruption (0)
|
|
||||||
* and probably the end of your program
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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_;
|
|
||||||
/*
|
|
||||||
these variables have similar meaning like those in
|
|
||||||
the multiplication algorithm MulTwoWords
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#error "another compiler than GCC is currently not supported in 64bit mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
__asm__ __volatile__(
|
|
||||||
|
|
||||||
"divq %%rcx \n"
|
|
||||||
|
|
||||||
: "=a" (r_), "=d" (rest_)
|
|
||||||
: "d" (a), "a" (b), "c" (c)
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
*r = r_;
|
|
||||||
*rest = rest_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} //namespace
|
|
857
ttmath/ttmathuint_noasm.h
Normal file
857
ttmath/ttmathuint_noasm.h
Normal file
@@ -0,0 +1,857 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfilettmathuint_noasm
|
||||||
|
#define headerfilettmathuint_noasm
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_NOASM
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmathuint_noasm.h
|
||||||
|
\brief template class UInt<uint> with methods without any assembler code
|
||||||
|
|
||||||
|
this file is included at the end of ttmathuint.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adding ss2 to the this and adding carry if it's defined
|
||||||
|
(this = this + ss2 + c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt_noasm::Add")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
AddInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 + 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size )
|
||||||
|
|
||||||
|
|
||||||
|
c = AddTwoWords(table[index], value, 0, &table[index]);
|
||||||
|
|
||||||
|
for(i=index+1 ; i<value_size && c ; ++i)
|
||||||
|
c = AddTwoWords(table[i], 0, c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt_noasm::AddInt")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds only two unsigned words to the existing value
|
||||||
|
and these words begin on the 'index' position
|
||||||
|
(it's used in the multiplication algorithm 2)
|
||||||
|
|
||||||
|
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
||||||
|
x1 - lower word, x2 - higher word
|
||||||
|
|
||||||
|
for example if we've got value_size equal 4 and:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4
|
||||||
|
table[2] = 5
|
||||||
|
table[3] = 6
|
||||||
|
then let
|
||||||
|
x1 = 10
|
||||||
|
x2 = 20
|
||||||
|
and
|
||||||
|
index = 1
|
||||||
|
|
||||||
|
the result of this method will be:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4 + x1 = 14
|
||||||
|
table[2] = 5 + x2 = 25
|
||||||
|
table[3] = 6
|
||||||
|
|
||||||
|
and no carry at the end of table[3]
|
||||||
|
|
||||||
|
(of course if there was a carry in table[2](5+20) then
|
||||||
|
this carry would be passed to the table[3] etc.)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size - 1 )
|
||||||
|
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::AddTwoInts")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 method's subtracting ss2 from the 'this' and subtracting
|
||||||
|
carry if it has been defined
|
||||||
|
(this = this - ss2 - c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt_noasm::Sub")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method subtracts one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
SubInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 - 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
uint i, c;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size )
|
||||||
|
|
||||||
|
|
||||||
|
c = SubTwoWords(table[index], value, 0, &table[index]);
|
||||||
|
|
||||||
|
for(i=index+1 ; i<value_size && c ; ++i)
|
||||||
|
c = SubTwoWords(table[i], 0, c, &table[i]);
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt_noasm::SubInt")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2_one(uint c)
|
||||||
|
{
|
||||||
|
uint i, new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = 1;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
{
|
||||||
|
new_c = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
table[i] = (table[i] << 1) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcl2_one")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
c -> this -> return value
|
||||||
|
|
||||||
|
the highest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2_one(uint c)
|
||||||
|
{
|
||||||
|
sint i; // signed i
|
||||||
|
uint new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_HIGHEST_BIT;
|
||||||
|
|
||||||
|
for(i=sint(value_size)-1 ; i>=0 ; --i)
|
||||||
|
{
|
||||||
|
new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0;
|
||||||
|
table[i] = (table[i] >> 1) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcr2_one")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint move = TTMATH_BITS_PER_UINT - bits;
|
||||||
|
uint i, new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_MAX_VALUE >> move;
|
||||||
|
|
||||||
|
for(i=0 ; i<value_size ; ++i)
|
||||||
|
{
|
||||||
|
new_c = table[i] >> move;
|
||||||
|
table[i] = (table[i] << bits) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt::Rcl2")
|
||||||
|
|
||||||
|
return (c & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
C -> this -> return value
|
||||||
|
|
||||||
|
the highest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint move = TTMATH_BITS_PER_UINT - bits;
|
||||||
|
sint i; // signed
|
||||||
|
uint new_c;
|
||||||
|
|
||||||
|
if( c != 0 )
|
||||||
|
c = TTMATH_UINT_MAX_VALUE << move;
|
||||||
|
|
||||||
|
for(i=value_size-1 ; i>=0 ; --i)
|
||||||
|
{
|
||||||
|
new_c = table[i] << move;
|
||||||
|
table[i] = (table[i] >> bits) | c;
|
||||||
|
c = new_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcr2")
|
||||||
|
|
||||||
|
return (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this method returns the number of the highest set bit in x
|
||||||
|
if the 'x' is zero this method returns '-1'
|
||||||
|
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||||
|
{
|
||||||
|
if( x == 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint bit = TTMATH_BITS_PER_UINT - 1;
|
||||||
|
|
||||||
|
while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 )
|
||||||
|
{
|
||||||
|
x = x << 1;
|
||||||
|
--bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets a special bit in the 'value'
|
||||||
|
and returns the last state of the bit (zero or one)
|
||||||
|
|
||||||
|
bit is from <0,63>
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
uint x = 100;
|
||||||
|
uint bit = SetBitInWord(x, 3);
|
||||||
|
now: x = 108 and bit = 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint mask = 1;
|
||||||
|
|
||||||
|
if( bit > 1 )
|
||||||
|
mask = mask << bit;
|
||||||
|
|
||||||
|
uint last = value & mask;
|
||||||
|
value = value | mask;
|
||||||
|
|
||||||
|
return (last != 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Multiplication
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result_high:result_low = a * b
|
||||||
|
result_high - higher word of the result
|
||||||
|
result_low - lower word of the result
|
||||||
|
|
||||||
|
this methos never returns a carry
|
||||||
|
this method is used in the second version of the multiplication algorithms
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
|
||||||
|
{
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
/*
|
||||||
|
on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace
|
||||||
|
this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit
|
||||||
|
*/
|
||||||
|
|
||||||
|
union uint_
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint low; // 32 bits
|
||||||
|
uint high; // 32 bits
|
||||||
|
} u_;
|
||||||
|
|
||||||
|
ulint u; // 64 bits
|
||||||
|
} res;
|
||||||
|
|
||||||
|
res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits
|
||||||
|
|
||||||
|
*result_high = res.u_.high;
|
||||||
|
*result_low = res.u_.low;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
64 bits platforms
|
||||||
|
|
||||||
|
we don't have a native type which has 128 bits
|
||||||
|
then we're splitting 'a' and 'b' to 4 parts (high and low halves)
|
||||||
|
and using 4 multiplications (with additions and carry correctness)
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint_ a_;
|
||||||
|
uint_ b_;
|
||||||
|
uint_ res_high1, res_high2;
|
||||||
|
uint_ res_low1, res_low2;
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
|
||||||
|
/*
|
||||||
|
the multiplication is as follows (schoolbook algorithm with O(n^2) ):
|
||||||
|
|
||||||
|
32 bits 32 bits
|
||||||
|
|
||||||
|
+--------------------------------+
|
||||||
|
| a_.u_.high | a_.u_.low |
|
||||||
|
+--------------------------------+
|
||||||
|
| b_.u_.high | b_.u_.low |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
| res_high1.u | res_low1.u |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
| res_high2.u | res_low2.u |
|
||||||
|
+--------------------------------+--------------------------------+
|
||||||
|
|
||||||
|
64 bits 64 bits
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
uint_ temp;
|
||||||
|
|
||||||
|
res_low1.u = uint(b_.u_.low) * uint(a_.u_.low);
|
||||||
|
|
||||||
|
temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high);
|
||||||
|
res_low1.u_.high = temp.u_.low;
|
||||||
|
res_high1.u_.low = temp.u_.high;
|
||||||
|
res_high1.u_.high = 0;
|
||||||
|
|
||||||
|
res_low2.u_.low = 0;
|
||||||
|
temp.u = uint(b_.u_.high) * uint(a_.u_.low);
|
||||||
|
res_low2.u_.high = temp.u_.low;
|
||||||
|
|
||||||
|
res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high);
|
||||||
|
|
||||||
|
uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u);
|
||||||
|
AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here
|
||||||
|
|
||||||
|
*result_high = res_high2.u;
|
||||||
|
*result_low = res_low2.u;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Division
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||||
|
r = a:b / c and rest - remainder
|
||||||
|
|
||||||
|
*
|
||||||
|
* WARNING:
|
||||||
|
* the c has to be suitably large for the result being keeped in one word,
|
||||||
|
* if c is equal zero there'll be a hardware interruption (0)
|
||||||
|
* and probably the end of your program
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
|
||||||
|
{
|
||||||
|
// (a < c ) for the result to be one word
|
||||||
|
TTMATH_ASSERT( c != 0 && a < c )
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM32
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint low; // 32 bits
|
||||||
|
uint high; // 32 bits
|
||||||
|
} u_;
|
||||||
|
|
||||||
|
ulint u; // 64 bits
|
||||||
|
} ab;
|
||||||
|
|
||||||
|
ab.u_.high = a;
|
||||||
|
ab.u_.low = b;
|
||||||
|
|
||||||
|
*r = uint(ab.u / c);
|
||||||
|
*rest = uint(ab.u % c);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint_ c_;
|
||||||
|
c_.u = c;
|
||||||
|
|
||||||
|
|
||||||
|
if( a == 0 )
|
||||||
|
{
|
||||||
|
*r = b / c;
|
||||||
|
*rest = b % c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( c_.u_.high == 0 )
|
||||||
|
{
|
||||||
|
// higher half of 'c' is zero
|
||||||
|
// then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c')
|
||||||
|
uint_ a_, b_, res_, temp1, temp2;
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
|
||||||
|
temp1.u_.high = a_.u_.low;
|
||||||
|
temp1.u_.low = b_.u_.high;
|
||||||
|
|
||||||
|
res_.u_.high = temp1.u / c;
|
||||||
|
temp2.u_.high = temp1.u % c;
|
||||||
|
temp2.u_.low = b_.u_.low;
|
||||||
|
|
||||||
|
res_.u_.low = temp2.u / c;
|
||||||
|
*rest = temp2.u % c;
|
||||||
|
|
||||||
|
*r = res_.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DivTwoWords2(a, b, c, r, rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method is available only on 64bit platforms
|
||||||
|
|
||||||
|
the same algorithm like the third division algorithm in ttmathuint.h
|
||||||
|
but now with the radix=2^32
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest)
|
||||||
|
{
|
||||||
|
// a is not zero
|
||||||
|
// c_.u_.high is not zero
|
||||||
|
|
||||||
|
uint_ a_, b_, c_, u_, q_;
|
||||||
|
unsigned int u3; // 32 bit
|
||||||
|
|
||||||
|
a_.u = a;
|
||||||
|
b_.u = b;
|
||||||
|
c_.u = c;
|
||||||
|
|
||||||
|
// normalizing
|
||||||
|
uint d = DivTwoWordsNormalize(a_, b_, c_);
|
||||||
|
|
||||||
|
// loop from j=1 to j=0
|
||||||
|
// the first step (for j=2) is skipped because our result is only in one word,
|
||||||
|
// (first 'q' were 0 and nothing would be changed)
|
||||||
|
u_.u_.high = a_.u_.high;
|
||||||
|
u_.u_.low = a_.u_.low;
|
||||||
|
u3 = b_.u_.high;
|
||||||
|
q_.u_.high = DivTwoWordsCalculate(u_, u3, c_);
|
||||||
|
MultiplySubtract(u_, u3, q_.u_.high, c_);
|
||||||
|
|
||||||
|
u_.u_.high = u_.u_.low;
|
||||||
|
u_.u_.low = u3;
|
||||||
|
u3 = b_.u_.low;
|
||||||
|
q_.u_.low = DivTwoWordsCalculate(u_, u3, c_);
|
||||||
|
MultiplySubtract(u_, u3, q_.u_.low, c_);
|
||||||
|
|
||||||
|
*r = q_.u;
|
||||||
|
|
||||||
|
// unnormalizing for the remainder
|
||||||
|
u_.u_.high = u_.u_.low;
|
||||||
|
u_.u_.low = u3;
|
||||||
|
*rest = DivTwoWordsUnnormalize(u_.u, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_)
|
||||||
|
{
|
||||||
|
uint d = 0;
|
||||||
|
|
||||||
|
for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
|
||||||
|
{
|
||||||
|
c_.u = c_.u << 1;
|
||||||
|
|
||||||
|
uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b'
|
||||||
|
|
||||||
|
b_.u = b_.u << 1;
|
||||||
|
a_.u = a_.u << 1; // carry bits from 'a' are simply skipped
|
||||||
|
|
||||||
|
if( bc )
|
||||||
|
a_.u = a_.u | 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d)
|
||||||
|
{
|
||||||
|
if( d == 0 )
|
||||||
|
return u;
|
||||||
|
|
||||||
|
u = u >> d;
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
unsigned int UInt<value_size>::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_)
|
||||||
|
{
|
||||||
|
bool next_test;
|
||||||
|
uint_ qp_, rp_, temp_;
|
||||||
|
|
||||||
|
qp_.u = u_.u / uint(v_.u_.high);
|
||||||
|
rp_.u = u_.u % uint(v_.u_.high);
|
||||||
|
|
||||||
|
TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 )
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bool decrease = false;
|
||||||
|
|
||||||
|
if( qp_.u_.high == 1 )
|
||||||
|
decrease = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp_.u_.high = rp_.u_.low;
|
||||||
|
temp_.u_.low = u3;
|
||||||
|
|
||||||
|
if( qp_.u * uint(v_.u_.low) > temp_.u )
|
||||||
|
decrease = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_test = false;
|
||||||
|
|
||||||
|
if( decrease )
|
||||||
|
{
|
||||||
|
--qp_.u;
|
||||||
|
rp_.u += v_.u_.high;
|
||||||
|
|
||||||
|
if( rp_.u_.high == 0 )
|
||||||
|
next_test = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( next_test );
|
||||||
|
|
||||||
|
return qp_.u_.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_)
|
||||||
|
{
|
||||||
|
uint_ temp_;
|
||||||
|
|
||||||
|
uint res_high;
|
||||||
|
uint res_low;
|
||||||
|
|
||||||
|
MulTwoWords(v_.u, q, &res_high, &res_low);
|
||||||
|
|
||||||
|
uint_ sub_res_high_;
|
||||||
|
uint_ sub_res_low_;
|
||||||
|
|
||||||
|
temp_.u_.high = u_.u_.low;
|
||||||
|
temp_.u_.low = u3;
|
||||||
|
|
||||||
|
uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u);
|
||||||
|
|
||||||
|
temp_.u_.high = 0;
|
||||||
|
temp_.u_.low = u_.u_.high;
|
||||||
|
c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u);
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
{
|
||||||
|
--q;
|
||||||
|
|
||||||
|
c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u);
|
||||||
|
AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u);
|
||||||
|
}
|
||||||
|
|
||||||
|
u_.u_.high = sub_res_high_.u_.low;
|
||||||
|
u_.u_.low = sub_res_low_.u_.high;
|
||||||
|
u3 = sub_res_low_.u_.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ifdef TTMATH_NOASM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1279
ttmath/ttmathuint_x86.h
Normal file
1279
ttmath/ttmathuint_x86.h
Normal file
File diff suppressed because it is too large
Load Diff
834
ttmath/ttmathuint_x86_64.h
Normal file
834
ttmath/ttmathuint_x86_64.h
Normal file
@@ -0,0 +1,834 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef headerfilettmathuint_x86_64
|
||||||
|
#define headerfilettmathuint_x86_64
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TTMATH_NOASM
|
||||||
|
#ifdef TTMATH_PLATFORM64
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmathuint_x86_64.h
|
||||||
|
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors
|
||||||
|
|
||||||
|
this file is included at the end of ttmathuint.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* basic mathematic functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adding ss2 to the this and adding carry if it's defined
|
||||||
|
(this = this + ss2 + c)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
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__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"movq (%%rsi,%%rdx,8), %%rax \n"
|
||||||
|
"adcq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"adcq %%rcx, %%rcx \n"
|
||||||
|
|
||||||
|
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||||
|
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Add")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
AddInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 + 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
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"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"addq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"movq $1, %%rax \n"
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
"setc %%al \n"
|
||||||
|
"movzx %%al, %%rdx \n"
|
||||||
|
|
||||||
|
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||||
|
: "a" (value), "c" (b), "0" (index), "b" (p1)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::AddInt")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds only two unsigned words to the existing value
|
||||||
|
and these words begin on the 'index' position
|
||||||
|
(it's used in the multiplication algorithm 2)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
||||||
|
x1 - lower word, x2 - higher word
|
||||||
|
|
||||||
|
for example if we've got value_size equal 4 and:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4
|
||||||
|
table[2] = 5
|
||||||
|
table[3] = 6
|
||||||
|
then let
|
||||||
|
x1 = 10
|
||||||
|
x2 = 20
|
||||||
|
and
|
||||||
|
index = 1
|
||||||
|
|
||||||
|
the result of this method will be:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4 + x1 = 14
|
||||||
|
table[2] = 5 + x2 = 25
|
||||||
|
table[3] = 6
|
||||||
|
|
||||||
|
and no carry at the end of table[3]
|
||||||
|
|
||||||
|
(of course if there was a carry in table[2](5+20) then
|
||||||
|
this carry would be passed to the table[3] etc.)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
|
||||||
|
{
|
||||||
|
uint b = value_size;
|
||||||
|
uint * p1 = table;
|
||||||
|
uint c;
|
||||||
|
uint dummy, dummy2;
|
||||||
|
|
||||||
|
TTMATH_ASSERT( index < value_size - 1 )
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"addq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"adcq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"mov $0, %%rax \n"
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
"setc %%al \n"
|
||||||
|
"movzx %%al, %%rax \n"
|
||||||
|
|
||||||
|
: "=a" (c), "=c" (dummy), "=d" (dummy2)
|
||||||
|
: "1" (b), "2" (index), "b" (p1), "S" (x1), "0" (x2)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::AddTwoInts")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method's subtracting ss2 from the 'this' and subtracting
|
||||||
|
carry if it has been defined
|
||||||
|
(this = this - ss2 - c)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
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__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"xorq %%rdx, %%rdx \n"
|
||||||
|
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"movq (%%rsi,%%rdx,8), %%rax \n"
|
||||||
|
"sbbq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"adcq %%rcx, %%rcx \n"
|
||||||
|
|
||||||
|
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||||
|
: "0" (b), "1" (c), "b" (p1), "S" (p2)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Sub")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method subtracts one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
SubInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 - 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[2] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
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"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"subq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"movq $1, %%rax \n"
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
"setc %%al \n"
|
||||||
|
"movzx %%al, %%rdx \n"
|
||||||
|
|
||||||
|
: "=d" (c), "=a" (dummy), "=c" (dummy2)
|
||||||
|
: "1" (value), "2" (b), "0" (index), "b" (p1)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::SubInt")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2_one(uint c)
|
||||||
|
{
|
||||||
|
sint b = value_size;
|
||||||
|
uint * p1 = table;
|
||||||
|
uint dummy, dummy2;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"xorq %%rdx, %%rdx \n" // rdx=0
|
||||||
|
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"rclq $1, (%%rbx, %%rdx, 8) \n"
|
||||||
|
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"adcq %%rcx, %%rcx \n"
|
||||||
|
|
||||||
|
: "=c" (c), "=a" (dummy), "=d" (dummy2)
|
||||||
|
: "1" (c), "0" (b), "b" (p1)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcl2_one")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
c -> this -> return value
|
||||||
|
|
||||||
|
the highest *bit* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2_one(uint c)
|
||||||
|
{
|
||||||
|
sint b = value_size;
|
||||||
|
uint * p1 = table;
|
||||||
|
uint dummy;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"rcrq $1, -8(%%rbx, %%rcx, 8) \n"
|
||||||
|
|
||||||
|
"decq %%rcx \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"adcq %%rcx, %%rcx \n"
|
||||||
|
|
||||||
|
: "=c" (c), "=a" (dummy)
|
||||||
|
: "1" (c), "0" (b), "b" (p1)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcr2_one")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the left hand side
|
||||||
|
return value <- this <- c
|
||||||
|
|
||||||
|
the lowest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the left hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 001010000
|
||||||
|
after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint b = value_size;
|
||||||
|
uint * p1 = table;
|
||||||
|
uint dummy, dummy2, dummy3;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"movq %%rcx, %%rsi \n"
|
||||||
|
"movq $64, %%rcx \n"
|
||||||
|
"subq %%rsi, %%rcx \n"
|
||||||
|
"movq $-1, %%rdx \n"
|
||||||
|
"shrq %%cl, %%rdx \n"
|
||||||
|
"movq %%rdx, %%r8 \n"
|
||||||
|
"movq %%rsi, %%rcx \n"
|
||||||
|
|
||||||
|
"xorq %%rdx, %%rdx \n"
|
||||||
|
"movq %%rdx, %%rsi \n"
|
||||||
|
|
||||||
|
"orq %%rax, %%rax \n"
|
||||||
|
"cmovnz %%r8, %%rsi \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"rolq %%cl, (%%rbx,%%rdx,8) \n"
|
||||||
|
|
||||||
|
"movq (%%rbx,%%rdx,8), %%rax \n"
|
||||||
|
"andq %%r8, %%rax \n"
|
||||||
|
"xorq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
"orq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||||
|
"movq %%rax, %%rsi \n"
|
||||||
|
|
||||||
|
"incq %%rdx \n"
|
||||||
|
"decq %%rdi \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"and $1, %%rax \n"
|
||||||
|
|
||||||
|
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||||
|
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||||
|
: "%r8", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcl2")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moves all bits into the right hand side
|
||||||
|
C -> this -> return value
|
||||||
|
|
||||||
|
the highest *bits* will be held the 'c' and
|
||||||
|
the state of one additional bit (on the right hand side)
|
||||||
|
will be returned
|
||||||
|
|
||||||
|
for example:
|
||||||
|
let this is 000000010
|
||||||
|
after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr2(uint bits, uint c)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
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"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"movq %%rcx, %%rsi \n"
|
||||||
|
"movq $64, %%rcx \n"
|
||||||
|
"subq %%rsi, %%rcx \n"
|
||||||
|
"movq $-1, %%rdx \n"
|
||||||
|
"shlq %%cl, %%rdx \n"
|
||||||
|
"movq %%rdx, %%R8 \n"
|
||||||
|
"movq %%rsi, %%rcx \n"
|
||||||
|
|
||||||
|
"xorq %%rdx, %%rdx \n"
|
||||||
|
"movq %%rdx, %%rsi \n"
|
||||||
|
"addq %%rdi, %%rdx \n"
|
||||||
|
"decq %%rdx \n"
|
||||||
|
|
||||||
|
"orq %%rax, %%rax \n"
|
||||||
|
"cmovnz %%R8, %%rsi \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"rorq %%cl, (%%rbx,%%rdx,8) \n"
|
||||||
|
|
||||||
|
"movq (%%rbx,%%rdx,8), %%rax \n"
|
||||||
|
"andq %%R8, %%rax \n"
|
||||||
|
"xorq %%rax, (%%rbx,%%rdx,8) \n"
|
||||||
|
"orq %%rsi, (%%rbx,%%rdx,8) \n"
|
||||||
|
"movq %%rax, %%rsi \n"
|
||||||
|
|
||||||
|
"decq %%rdx \n"
|
||||||
|
"decq %%rdi \n"
|
||||||
|
"jnz 1b \n"
|
||||||
|
|
||||||
|
"rolq $1, %%rax \n"
|
||||||
|
"andq $1, %%rax \n"
|
||||||
|
|
||||||
|
: "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
|
||||||
|
: "0" (c), "1" (b), "b" (p1), "c" (bits)
|
||||||
|
: "%r8", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TTMATH_LOG("UInt64::Rcr2")
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this method returns the number of the highest set bit in one 64-bit word
|
||||||
|
if the 'x' is zero this method returns '-1'
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||||
|
{
|
||||||
|
register sint result;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"bsrq %1, %0 \n"
|
||||||
|
"jnz 1f \n"
|
||||||
|
"movq $-1, %0 \n"
|
||||||
|
"1: \n"
|
||||||
|
|
||||||
|
: "=R" (result)
|
||||||
|
: "R" (x)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets a special bit in the 'value'
|
||||||
|
and returns the last state of the bit (zero or one)
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
bit is from <0,63>
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
uint x = 100;
|
||||||
|
uint bit = SetBitInWord(x, 3);
|
||||||
|
now: x = 108 and bit = 0
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
|
||||||
|
{
|
||||||
|
TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
|
||||||
|
|
||||||
|
uint old_bit;
|
||||||
|
uint v = value;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"btsq %%rbx, %%rax \n"
|
||||||
|
|
||||||
|
"setc %%bl \n"
|
||||||
|
"movzx %%bl, %%rbx \n"
|
||||||
|
|
||||||
|
: "=a" (v), "=b" (old_bit)
|
||||||
|
: "0" (v), "1" (bit)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
value = v;
|
||||||
|
|
||||||
|
return old_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Multiplication
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result_high:result_low = a * b
|
||||||
|
result_high - higher word of the result
|
||||||
|
result_low - lower word of the result
|
||||||
|
|
||||||
|
this methos never returns a carry
|
||||||
|
this method is used in the second version of the multiplication algorithms
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
we must use these temporary variables in order to inform the compilator
|
||||||
|
that value pointed with result1 and result2 has changed
|
||||||
|
|
||||||
|
this has no effect in visual studio but it's usefull when
|
||||||
|
using gcc and options like -O
|
||||||
|
*/
|
||||||
|
register uint result1_;
|
||||||
|
register uint result2_;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"mulq %%rdx \n"
|
||||||
|
|
||||||
|
: "=a" (result1_), "=d" (result2_)
|
||||||
|
: "0" (a), "1" (b)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
*result_low = result1_;
|
||||||
|
*result_high = result2_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Division
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||||
|
r = a:b / c and rest - remainder
|
||||||
|
|
||||||
|
***this method is created only on a 64bit platform***
|
||||||
|
|
||||||
|
*
|
||||||
|
* WARNING:
|
||||||
|
* if r (one word) is too small for the result or c is equal zero
|
||||||
|
* there'll be a hardware interruption (0)
|
||||||
|
* and probably the end of your program
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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_;
|
||||||
|
/*
|
||||||
|
these variables have similar meaning like those in
|
||||||
|
the multiplication algorithm MulTwoWords
|
||||||
|
*/
|
||||||
|
|
||||||
|
TTMATH_ASSERT( c != 0 )
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"divq %%rcx \n"
|
||||||
|
|
||||||
|
: "=a" (r_), "=d" (rest_)
|
||||||
|
: "d" (a), "a" (b), "c" (c)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
*r = r_;
|
||||||
|
*rest = rest_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ifdef TTMATH_PLATFORM64
|
||||||
|
#endif //ifndef TTMATH_NOASM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user