Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
506840787a | |||
e58253a078 | |||
6862321fad | |||
2e192969b0 | |||
e8daa77d75 | |||
231164f6ea | |||
c51b2fdcc9 | |||
84f34ebe52 |
16
CHANGELOG
16
CHANGELOG
@@ -1,3 +1,19 @@
|
|||||||
|
Version 0.9.3 (2012.12.28):
|
||||||
|
* fixed: in Big::FromDouble(double value) (only 32 bit version)
|
||||||
|
buffer overflow in referencing to UInt<2>
|
||||||
|
this was used when 'value' was in so called "unnormalized" state
|
||||||
|
(E=0 and F is nonzero)
|
||||||
|
it produced incorrect mantissa (on about 8th decimal digit up)
|
||||||
|
* added: Parser::InitCGamma()
|
||||||
|
initializing coefficients used when calculating the gamma (or factorial) function
|
||||||
|
this speed up the next calculations
|
||||||
|
you don't have to call this method explicitly
|
||||||
|
these coefficients will be calculated when needed
|
||||||
|
* added: option 'group_digits' to Conv struct
|
||||||
|
you can set how many digits should be grouped
|
||||||
|
* changed: small optimizations in UInt::ToString() and Big::FromString()
|
||||||
|
|
||||||
|
|
||||||
Version 0.9.2 (2010.09.23):
|
Version 0.9.2 (2010.09.23):
|
||||||
* fixed: Big::Add() sometimes incorrectly rounded the last bit from its mantissa
|
* fixed: Big::Add() sometimes incorrectly rounded the last bit from its mantissa
|
||||||
* fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN
|
* fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2006-2010, Tomasz Sowa
|
Copyright (c) 2006-2012, 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
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
* Copyright (c) 2006-2012, 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
|
||||||
@@ -2832,10 +2832,14 @@ namespace ttmath
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
this is for convenience for the user
|
this is for convenience for the user
|
||||||
he can only use '#include <ttmath/ttmath.h>' even if he uses the parser
|
he can only use '#include <ttmath/ttmath.h>'
|
||||||
*/
|
*/
|
||||||
#include "ttmathparser.h"
|
#include "ttmathparser.h"
|
||||||
|
|
||||||
|
// Dec is not finished yet
|
||||||
|
//#include "ttmathdec.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
//warning C4127: conditional expression is constant
|
//warning C4127: conditional expression is constant
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
* Copyright (c) 2006-2012, 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
|
||||||
@@ -1571,7 +1571,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Big<exp, man> start(*this), start_temp;
|
Big<exp, man> start(*this);
|
||||||
Big<exp, man> result;
|
Big<exp, man> result;
|
||||||
result.SetOne();
|
result.SetOne();
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
@@ -1586,8 +1586,7 @@ public:
|
|||||||
if( pow.IsZero() )
|
if( pow.IsZero() )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
start_temp = start;
|
c += start.Mul(start);
|
||||||
c += start.Mul(start_temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*this = result;
|
*this = result;
|
||||||
@@ -1665,13 +1664,10 @@ public:
|
|||||||
if( pow.IsSign() )
|
if( pow.IsSign() )
|
||||||
pow.Abs();
|
pow.Abs();
|
||||||
|
|
||||||
Big<exp, man> start(*this), start_temp;
|
Big<exp, man> start(*this);
|
||||||
Big<exp, man> result;
|
Big<exp, man> result;
|
||||||
Big<exp, man> one;
|
Big<exp, man> one;
|
||||||
Int<exp> e_one;
|
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
|
|
||||||
e_one.SetOne();
|
|
||||||
one.SetOne();
|
one.SetOne();
|
||||||
result = one;
|
result = one;
|
||||||
|
|
||||||
@@ -1680,13 +1676,12 @@ public:
|
|||||||
if( pow.Mod2() )
|
if( pow.Mod2() )
|
||||||
c += result.Mul(start);
|
c += result.Mul(start);
|
||||||
|
|
||||||
c += pow.exponent.Sub( e_one ); // !! may use SubOne() here?
|
c += pow.exponent.SubOne();
|
||||||
|
|
||||||
if( pow < one )
|
if( pow < one )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
start_temp = start;
|
c += start.Mul(start);
|
||||||
c += start.Mul(start_temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*this = result;
|
*this = result;
|
||||||
@@ -2649,7 +2644,7 @@ public:
|
|||||||
|
|
||||||
FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
|
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[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4743,15 +4738,19 @@ private:
|
|||||||
typename string_type::size_type & index) const
|
typename string_type::size_type & index) const
|
||||||
{
|
{
|
||||||
typedef typename string_type::size_type StrSize;
|
typedef typename string_type::size_type StrSize;
|
||||||
uint group = 0;
|
|
||||||
|
uint group = 0;
|
||||||
StrSize i = index;
|
StrSize i = index;
|
||||||
|
uint group_digits = conv.group_digits;
|
||||||
|
|
||||||
|
if( group_digits < 1 )
|
||||||
|
group_digits = 1;
|
||||||
|
|
||||||
// adding group characters before the comma operator
|
// adding group characters before the comma operator
|
||||||
// i>0 because on the first position we don't put any additional grouping characters
|
// i>0 because on the first position we don't put any additional grouping characters
|
||||||
for( ; i>0 ; --i, ++group)
|
for( ; i>0 ; --i, ++group)
|
||||||
{
|
{
|
||||||
if( group >= 3 )
|
if( group >= group_digits )
|
||||||
{
|
{
|
||||||
group = 0;
|
group = 0;
|
||||||
new_man.insert(i, 1, static_cast<char_type>(conv.group));
|
new_man.insert(i, 1, static_cast<char_type>(conv.group));
|
||||||
@@ -4768,11 +4767,15 @@ private:
|
|||||||
void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
|
void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
|
||||||
typename string_type::size_type index) const
|
typename string_type::size_type index) const
|
||||||
{
|
{
|
||||||
uint group = 0;
|
uint group = 0;
|
||||||
|
uint group_digits = conv.group_digits;
|
||||||
|
|
||||||
|
if( group_digits < 1 )
|
||||||
|
group_digits = 1;
|
||||||
|
|
||||||
for( ; index<new_man.size() ; ++index, ++group)
|
for( ; index<new_man.size() ; ++index, ++group)
|
||||||
{
|
{
|
||||||
if( group >= 3 )
|
if( group >= group_digits )
|
||||||
{
|
{
|
||||||
group = 0;
|
group = 0;
|
||||||
new_man.insert(index, 1, static_cast<char_type>(conv.group));
|
new_man.insert(index, 1, static_cast<char_type>(conv.group));
|
||||||
@@ -5117,19 +5120,14 @@ private:
|
|||||||
uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
|
uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
|
||||||
{
|
{
|
||||||
sint character;
|
sint character;
|
||||||
uint c = 0, index = 1;
|
uint c = 0, power = 0;
|
||||||
Big<exp, man> sum, part, power, old_value, base_( conv.base );
|
UInt<1> power_;
|
||||||
|
Big<exp, man> sum, base_(conv.base);
|
||||||
|
|
||||||
// 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 'old_value' which GCC reports
|
|
||||||
// (in fact we will initialize it later when the condition 'testing' is fulfilled)
|
|
||||||
old_value.SetZero();
|
|
||||||
|
|
||||||
power.SetOne();
|
|
||||||
sum.SetZero();
|
sum.SetZero();
|
||||||
|
|
||||||
for( ; true ; ++source, ++index )
|
for( ; sum.exponent.IsSign() || sum.exponent.IsZero() ; ++source )
|
||||||
{
|
{
|
||||||
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
||||||
continue;
|
continue;
|
||||||
@@ -5141,30 +5139,13 @@ private:
|
|||||||
|
|
||||||
value_read = true;
|
value_read = true;
|
||||||
|
|
||||||
part = character;
|
|
||||||
|
|
||||||
if( power.Mul( base_ ) )
|
|
||||||
// there's no sens to add the next parts, but we can't report this
|
|
||||||
// as an error (this is only inaccuracy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( part.Div( power ) )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// every 5 iteration we make a test whether the value will be changed or not
|
|
||||||
// (character must be different from zero to this test)
|
|
||||||
bool testing = (character != 0 && (index % 5) == 0);
|
|
||||||
|
|
||||||
if( testing )
|
|
||||||
old_value = sum;
|
|
||||||
|
|
||||||
// there actually shouldn't be a carry here
|
// there actually shouldn't be a carry here
|
||||||
c += sum.Add( part );
|
c += sum.Mul(base_);
|
||||||
|
c += sum.Add(character);
|
||||||
|
power += 1;
|
||||||
|
|
||||||
if( testing && old_value == sum )
|
if( power == 0 )
|
||||||
// after adding 'part' the value has not been changed
|
c += 1;
|
||||||
// there's no sense to add any next parts
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we could break the parsing somewhere in the middle of the string,
|
// we could break the parsing somewhere in the middle of the string,
|
||||||
@@ -5172,6 +5153,9 @@ private:
|
|||||||
// we should set a correct value of 'source' now
|
// we should set a correct value of 'source' now
|
||||||
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
|
for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
|
||||||
|
|
||||||
|
power_ = power;
|
||||||
|
c += base_.Pow(power_);
|
||||||
|
c += sum.Div(base_);
|
||||||
c += Add(sum);
|
c += Add(sum);
|
||||||
|
|
||||||
return (c==0)? 0 : 1;
|
return (c==0)? 0 : 1;
|
||||||
|
419
ttmath/ttmathdec.h
Normal file
419
ttmath/ttmathdec.h
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of TTMath Bignum Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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 headerfilettmathdec
|
||||||
|
#define headerfilettmathdec
|
||||||
|
|
||||||
|
#include "ttmathtypes.h"
|
||||||
|
#include "ttmaththreads.h"
|
||||||
|
#include "ttmathuint.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
template<uint value_size, uint dec_digits>
|
||||||
|
class Dec
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
UInt<value_size> value;
|
||||||
|
unsigned char info;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sign
|
||||||
|
the mask of a bit from 'info' which means that there is a sign
|
||||||
|
(when the bit is set)
|
||||||
|
*/
|
||||||
|
#define TTMATH_DEC_SIGN 128
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Not a number
|
||||||
|
if this bit is set that there is not a valid number
|
||||||
|
*/
|
||||||
|
#define TTMATH_DEC_NAN 64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dec()
|
||||||
|
{
|
||||||
|
info = TTMATH_DEC_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dec(const char * s)
|
||||||
|
{
|
||||||
|
info = TTMATH_DEC_NAN;
|
||||||
|
FromString(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dec<value_size, dec_digits> & operator=(const char * s)
|
||||||
|
{
|
||||||
|
FromString(s);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0)
|
||||||
|
{
|
||||||
|
return FromStringBase(s, after_source, value_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ToString(std::string & result) const
|
||||||
|
{
|
||||||
|
ToStringBase(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method clears a specific bit in the 'info' variable
|
||||||
|
|
||||||
|
bit is one of:
|
||||||
|
*/
|
||||||
|
void ClearInfoBit(unsigned char bit)
|
||||||
|
{
|
||||||
|
info = info & (~bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets a specific bit in the 'info' variable
|
||||||
|
|
||||||
|
bit is one of:
|
||||||
|
|
||||||
|
*/
|
||||||
|
void SetInfoBit(unsigned char bit)
|
||||||
|
{
|
||||||
|
info = info | bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method returns true if a specific bit in the 'info' variable is set
|
||||||
|
|
||||||
|
bit is one of:
|
||||||
|
*/
|
||||||
|
bool IsInfoBit(unsigned char bit) const
|
||||||
|
{
|
||||||
|
return (info & bit) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsNan() const
|
||||||
|
{
|
||||||
|
return IsInfoBit(TTMATH_DEC_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsSign() const
|
||||||
|
{
|
||||||
|
return IsInfoBit(TTMATH_DEC_SIGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets the sign
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
-1 -> -1
|
||||||
|
2 -> -2
|
||||||
|
|
||||||
|
we do not check whether there is a zero or not, if you're using this method
|
||||||
|
you must be sure that the value is (or will be afterwards) different from zero
|
||||||
|
*/
|
||||||
|
void SetSign()
|
||||||
|
{
|
||||||
|
SetInfoBit(TTMATH_DEC_SIGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetNaN()
|
||||||
|
{
|
||||||
|
SetInfoBit(TTMATH_DEC_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Abs()
|
||||||
|
{
|
||||||
|
ClearInfoBit(TTMATH_DEC_SIGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint Add(const Dec<value_size, dec_digits> & arg)
|
||||||
|
{
|
||||||
|
uint c = 0;
|
||||||
|
|
||||||
|
if( IsSign() == arg.IsSign() )
|
||||||
|
{
|
||||||
|
c += value.Add(arg.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool is_sign;
|
||||||
|
|
||||||
|
if( value > arg.value )
|
||||||
|
{
|
||||||
|
is_sign = IsSign();
|
||||||
|
value.Sub(arg.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
is_sign = arg.IsSign();
|
||||||
|
UInt<value_size> temp(this->value);
|
||||||
|
value = arg.value;
|
||||||
|
value.Sub(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_sign ? SetSign() : Abs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
SetNaN();
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
uint Sub(const Dec<value_size, dec_digits> & arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TTMATH_MULTITHREADS
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
void SetMultipler(UInt<value_size> & result)
|
||||||
|
{
|
||||||
|
// this guardian is initialized before the program runs (static POD type)
|
||||||
|
static int guardian = 0;
|
||||||
|
static UInt<value_size> multipler;
|
||||||
|
|
||||||
|
if( guardian == 0 )
|
||||||
|
{
|
||||||
|
multipler = 10;
|
||||||
|
multipler.Pow(dec_digits);
|
||||||
|
guardian = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = multipler;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*/
|
||||||
|
void SetMultipler(UInt<value_size> & result)
|
||||||
|
{
|
||||||
|
// this guardian is initialized before the program runs (static POD type)
|
||||||
|
volatile static sig_atomic_t guardian = 0;
|
||||||
|
static UInt<value_size> * pmultipler;
|
||||||
|
|
||||||
|
// double-checked locking
|
||||||
|
if( guardian == 0 )
|
||||||
|
{
|
||||||
|
ThreadLock thread_lock;
|
||||||
|
|
||||||
|
// locking
|
||||||
|
if( thread_lock.Lock() )
|
||||||
|
{
|
||||||
|
static UInt<value_size> multipler;
|
||||||
|
|
||||||
|
if( guardian == 0 )
|
||||||
|
{
|
||||||
|
pmultipler = &multipler;
|
||||||
|
multipler = 10;
|
||||||
|
multipler.Pow(dec_digits);
|
||||||
|
guardian = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there was a problem with locking, we store the result directly in 'result' object
|
||||||
|
result = 10;
|
||||||
|
result.Pow(dec_digits);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// automatically unlocking
|
||||||
|
}
|
||||||
|
|
||||||
|
result = *pmultipler;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for converting from a string
|
||||||
|
*/
|
||||||
|
template<class char_type>
|
||||||
|
uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
|
||||||
|
{
|
||||||
|
UInt<value_size> multipler;
|
||||||
|
const char_type * after;
|
||||||
|
uint c = 0;
|
||||||
|
info = 0;
|
||||||
|
|
||||||
|
Misc::SkipWhiteCharacters(s);
|
||||||
|
|
||||||
|
if( *s == '-' )
|
||||||
|
{
|
||||||
|
s += 1;
|
||||||
|
SetSign();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( *s == '+' )
|
||||||
|
{
|
||||||
|
s += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += value.FromString(s, 10, &after, value_read);
|
||||||
|
|
||||||
|
if( after_source )
|
||||||
|
*after_source = after;
|
||||||
|
|
||||||
|
SetMultipler(multipler);
|
||||||
|
c += value.Mul(multipler);
|
||||||
|
|
||||||
|
if( *after == '.' )
|
||||||
|
c += FromStringBaseAfterComma(after+1, after_source);
|
||||||
|
|
||||||
|
if( c )
|
||||||
|
SetInfoBit(TTMATH_DEC_NAN);
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class char_type>
|
||||||
|
uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0)
|
||||||
|
{
|
||||||
|
UInt<value_size> temp;
|
||||||
|
UInt<value_size> multipler;
|
||||||
|
sint z;
|
||||||
|
uint c = 0;
|
||||||
|
size_t i = dec_digits;
|
||||||
|
|
||||||
|
SetMultipler(multipler);
|
||||||
|
|
||||||
|
for( ; i>0 && (z=Misc::CharToDigit(*s, 10)) != -1 ; --i, ++s )
|
||||||
|
{
|
||||||
|
multipler.DivInt(10);
|
||||||
|
temp.SetZero();
|
||||||
|
|
||||||
|
if( value_read )
|
||||||
|
*value_read = true;
|
||||||
|
|
||||||
|
if( c == 0 )
|
||||||
|
{
|
||||||
|
temp.table[0] = z;
|
||||||
|
c += temp.Mul(multipler);
|
||||||
|
c += value.Add(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i == 0 && (z=Misc::CharToDigit(*s, 10)) != -1 && z >= 5 )
|
||||||
|
c += value.AddOne();
|
||||||
|
|
||||||
|
if( after_source )
|
||||||
|
{
|
||||||
|
while( (z=Misc::CharToDigit(*s, 10)) != -1 )
|
||||||
|
s += 1;
|
||||||
|
|
||||||
|
*after_source = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class string_type>
|
||||||
|
void ToStringBase(string_type & result) const
|
||||||
|
{
|
||||||
|
if( IsNan() )
|
||||||
|
{
|
||||||
|
result = "NaN";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.ToStringBase(result, 10, IsSign());
|
||||||
|
|
||||||
|
if( dec_digits > 0 )
|
||||||
|
{
|
||||||
|
size_t size = result.size();
|
||||||
|
|
||||||
|
if( IsSign() && size > 0 )
|
||||||
|
size -= 1;
|
||||||
|
|
||||||
|
if( dec_digits >= size )
|
||||||
|
{
|
||||||
|
size_t zeroes = dec_digits - size + 1;
|
||||||
|
size_t start = IsSign() ? 1 : 0;
|
||||||
|
result.insert(start, zeroes, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
result.insert(result.end() - dec_digits, '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
* Copyright (c) 2006-2011, 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
|
||||||
@@ -1315,13 +1315,11 @@ private:
|
|||||||
{
|
{
|
||||||
Int<value_size> temp(*this);
|
Int<value_size> temp(*this);
|
||||||
temp.Abs();
|
temp.Abs();
|
||||||
|
temp.UInt<value_size>::ToStringBase(result, b, true);
|
||||||
temp.UInt<value_size>::ToString(result, b);
|
|
||||||
result.insert(result.begin(), '-');
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UInt<value_size>::ToString(result, b);
|
UInt<value_size>::ToStringBase(result, b, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2755,6 +2755,18 @@ bool Calculated()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
initializing coefficients used when calculating the gamma (or factorial) function
|
||||||
|
this speed up the next calculations
|
||||||
|
you don't have to call this method explicitly
|
||||||
|
these coefficients will be calculated when needed
|
||||||
|
*/
|
||||||
|
void InitCGamma()
|
||||||
|
{
|
||||||
|
cgamma.InitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
* Copyright (c) 2006-2012, 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
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 9
|
#define TTMATH_MINOR_VER 9
|
||||||
#define TTMATH_REVISION_VER 2
|
#define TTMATH_REVISION_VER 3
|
||||||
|
|
||||||
#define TTMATH_PRERELEASE_VER 0
|
#define TTMATH_PRERELEASE_VER 0
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
_M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
|
_M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
|
||||||
|
|
||||||
amd64 architecture:
|
amd64 architecture:
|
||||||
__x86_64__ defined by GNU C and Sun Studio
|
__x86_64__ defined by GNU C, CLANG (LLVM) and Sun Studio
|
||||||
_M_X64 defined by Visual Studio
|
_M_X64 defined by Visual Studio
|
||||||
|
|
||||||
asm version is available only for x86 or amd64 platforms
|
asm version is available only for x86 or amd64 platforms
|
||||||
@@ -134,7 +134,8 @@
|
|||||||
|
|
||||||
#if !defined _MSC_VER && !defined __GNUC__
|
#if !defined _MSC_VER && !defined __GNUC__
|
||||||
/*!
|
/*!
|
||||||
another compilers than MS VC or GCC by default use no asm version
|
another compilers than MS VC or GCC or CLANG (LLVM) by default use no asm version
|
||||||
|
(CLANG defines __GNUC__ too)
|
||||||
*/
|
*/
|
||||||
#define TTMATH_NOASM
|
#define TTMATH_NOASM
|
||||||
#endif
|
#endif
|
||||||
@@ -465,6 +466,13 @@ namespace ttmath
|
|||||||
uint group;
|
uint group;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
how many digits should be grouped (it is used if 'group' is non zero)
|
||||||
|
default: 3
|
||||||
|
*/
|
||||||
|
uint group_digits;
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
uint group_exp; // not implemented yet
|
uint group_exp; // not implemented yet
|
||||||
@@ -484,6 +492,7 @@ namespace ttmath
|
|||||||
comma = '.';
|
comma = '.';
|
||||||
comma2 = ',';
|
comma2 = ',';
|
||||||
group = 0;
|
group = 0;
|
||||||
|
group_digits = 3;
|
||||||
group_exp = 0;
|
group_exp = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2010, Tomasz Sowa
|
* Copyright (c) 2006-2011, 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
|
||||||
@@ -1260,9 +1260,18 @@ private:
|
|||||||
UInt<ss_size*2> res;
|
UInt<ss_size*2> res;
|
||||||
Mul2Big2<ss_size>(ss1, ss2, res);
|
Mul2Big2<ss_size>(ss1, ss2, res);
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
|
#endif
|
||||||
|
|
||||||
for(uint i=0 ; i<ss_size*2 ; ++i)
|
for(uint i=0 ; i<ss_size*2 ; ++i)
|
||||||
result[i] = res.table[i];
|
result[i] = res.table[i];
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1355,10 +1364,18 @@ private:
|
|||||||
|
|
||||||
Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
|
Mul3Big2<first_size>(temp.table, temp2.table, z1.table);
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
|
#endif
|
||||||
|
|
||||||
// clearing the rest of z1
|
// clearing the rest of z1
|
||||||
for(i=first_size*2 ; i<first_size*3 ; ++i)
|
for(i=first_size*2 ; i<first_size*3 ; ++i)
|
||||||
z1.table[i] = 0;
|
z1.table[i] = 0;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
if( xc )
|
if( xc )
|
||||||
{
|
{
|
||||||
@@ -1375,9 +1392,18 @@ private:
|
|||||||
|
|
||||||
if( xc && yc )
|
if( xc && yc )
|
||||||
{
|
{
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
|
#endif
|
||||||
|
|
||||||
for( i=first_size*2 ; i<first_size*3 ; ++i )
|
for( i=first_size*2 ; i<first_size*3 ; ++i )
|
||||||
if( ++z1.table[i] != 0 )
|
if( ++z1.table[i] != 0 )
|
||||||
break; // break if there was no carry
|
break; // break if there was no carry
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// z1 = z1 - z2
|
// z1 = z1 - z2
|
||||||
@@ -1396,11 +1422,20 @@ private:
|
|||||||
uint z1_size = result_size - first_size;
|
uint z1_size = result_size - first_size;
|
||||||
TTMATH_ASSERT( z1_size <= first_size*3 )
|
TTMATH_ASSERT( z1_size <= first_size*3 )
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
|
#endif
|
||||||
|
|
||||||
for(i=z1_size ; i<first_size*3 ; ++i)
|
for(i=z1_size ; i<first_size*3 ; ++i)
|
||||||
{
|
{
|
||||||
TTMATH_ASSERT( z1.table[i] == 0 )
|
TTMATH_ASSERT( z1.table[i] == 0 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
|
c = AddVector(result+first_size, z1.table, result_size-first_size, z1_size, result+first_size);
|
||||||
TTMATH_ASSERT(c==0)
|
TTMATH_ASSERT(c==0)
|
||||||
}
|
}
|
||||||
@@ -2370,7 +2405,7 @@ public:
|
|||||||
// we don't define zero^zero
|
// we don't define zero^zero
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
UInt<value_size> start(*this), start_temp;
|
UInt<value_size> start(*this);
|
||||||
UInt<value_size> result;
|
UInt<value_size> result;
|
||||||
result.SetOne();
|
result.SetOne();
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
@@ -2384,9 +2419,7 @@ public:
|
|||||||
if( pow.IsZero() )
|
if( pow.IsZero() )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
start_temp = start;
|
c += start.Mul(start);
|
||||||
// in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there)
|
|
||||||
c += start.Mul(start_temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*this = result;
|
*this = result;
|
||||||
@@ -2507,10 +2540,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool IsOnlyTheHighestBitSet() const
|
bool IsOnlyTheHighestBitSet() const
|
||||||
{
|
{
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||||
|
#endif
|
||||||
|
|
||||||
for(uint i=0 ; i<value_size-1 ; ++i)
|
for(uint i=0 ; i<value_size-1 ; ++i)
|
||||||
if( table[i] != 0 )
|
if( table[i] != 0 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
|
if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -3206,36 +3247,98 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
an auxiliary method for converting into the string
|
||||||
|
it returns the log (with the base 2) from x
|
||||||
|
where x is in <2;16>
|
||||||
|
*/
|
||||||
|
double ToStringLog2(uint x) const
|
||||||
|
{
|
||||||
|
static double log_tab[] = {
|
||||||
|
1.000000000000000000,
|
||||||
|
0.630929753571457437,
|
||||||
|
0.500000000000000000,
|
||||||
|
0.430676558073393050,
|
||||||
|
0.386852807234541586,
|
||||||
|
0.356207187108022176,
|
||||||
|
0.333333333333333333,
|
||||||
|
0.315464876785728718,
|
||||||
|
0.301029995663981195,
|
||||||
|
0.289064826317887859,
|
||||||
|
0.278942945651129843,
|
||||||
|
0.270238154427319741,
|
||||||
|
0.262649535037193547,
|
||||||
|
0.255958024809815489,
|
||||||
|
0.250000000000000000
|
||||||
|
};
|
||||||
|
|
||||||
|
if( x<2 || x>16 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return log_tab[x-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
an auxiliary method for converting to a string
|
an auxiliary method for converting to a string
|
||||||
|
it's used from Int::ToString() too (negative is set true then)
|
||||||
*/
|
*/
|
||||||
template<class string_type>
|
template<class string_type>
|
||||||
void ToStringBase(string_type & result, uint b = 10) const
|
void ToStringBase(string_type & result, uint b = 10, bool negative = false) const
|
||||||
{
|
{
|
||||||
UInt<value_size> temp( *this );
|
UInt<value_size> temp(*this);
|
||||||
|
uint rest, table_id, index, digits;
|
||||||
|
double digits_d;
|
||||||
char character;
|
char character;
|
||||||
uint rem;
|
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
if( b<2 || b>16 )
|
if( b<2 || b>16 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if( !FindLeadingBit(table_id, index) )
|
||||||
|
{
|
||||||
|
result = '0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( negative )
|
||||||
|
result = '-';
|
||||||
|
|
||||||
|
digits_d = table_id; // for not making an overflow in uint type
|
||||||
|
digits_d *= TTMATH_BITS_PER_UINT;
|
||||||
|
digits_d += index + 1;
|
||||||
|
digits_d *= ToStringLog2(b);
|
||||||
|
digits = static_cast<uint>(digits_d) + 3; // plus some epsilon
|
||||||
|
|
||||||
|
if( result.capacity() < digits )
|
||||||
|
result.reserve(digits);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
temp.DivInt(b, &rem);
|
temp.DivInt(b, &rest);
|
||||||
character = static_cast<char>( Misc::DigitToChar(rem) );
|
character = static_cast<char>(Misc::DigitToChar(rest));
|
||||||
result.insert(result.begin(), character);
|
result.insert(result.end(), character);
|
||||||
}
|
}
|
||||||
while( !temp.IsZero() );
|
while( !temp.IsZero() );
|
||||||
|
|
||||||
return;
|
size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true)
|
||||||
|
size_t i2 = result.size() - 1;
|
||||||
|
|
||||||
|
for( ; i1 < i2 ; ++i1, --i2 )
|
||||||
|
{
|
||||||
|
char tempc = static_cast<char>(result[i1]);
|
||||||
|
result[i1] = result[i2];
|
||||||
|
result[i2] = tempc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method converts the value to a string with a base equal 'b'
|
this method converts the value to a string with a base equal 'b'
|
||||||
@@ -3310,7 +3413,7 @@ private:
|
|||||||
{
|
{
|
||||||
temp.table[0] = z;
|
temp.table[0] = z;
|
||||||
|
|
||||||
c += Mul(base);
|
c += Mul(base); // !! IMPROVE ME: there can be used MulInt here
|
||||||
c += Add(temp);
|
c += Add(temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3976,7 +4079,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
following methods are defined in:
|
Following methods are defined in:
|
||||||
ttmathuint_x86.h
|
ttmathuint_x86.h
|
||||||
ttmathuint_x86_64.h
|
ttmathuint_x86_64.h
|
||||||
ttmathuint_noasm.h
|
ttmathuint_noasm.h
|
||||||
|
Reference in New Issue
Block a user