- support for MS specific code (__int64 etc) and warnings

- support for AMD64 assembler (not thoroughly tested)
- support for UNICODE I/O (strings and streams)

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@132 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Christian Kaiser 2009-05-06 15:11:29 +00:00
parent cbc12db22f
commit c91bd24e98
10 changed files with 1177 additions and 635 deletions

View File

@ -45,6 +45,7 @@
\brief Mathematics functions. \brief Mathematics functions.
*/ */
#include "ttmathconfig.h"
#include "ttmathbig.h" #include "ttmathbig.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"

View File

@ -47,6 +47,10 @@
#include <iostream> #include <iostream>
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace ttmath namespace ttmath
{ {
@ -79,9 +83,9 @@ class Big
public: public:
Int<exp> exponent; Int<exp> exponent;
UInt<man> mantissa; UInt<man> mantissa;
unsigned char info; tchar_t info;
/*! /*!
@ -237,7 +241,7 @@ private:
// 3101 digits were taken from this website // 3101 digits were taken from this website
// (later the digits were compared with: // (later the digits were compared with:
// http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html ) // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
// and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform) // and they were set into Big<1,400> type (using operator=(const tchar_t*) on a 32bit platform)
// and then the first 256 words were taken into this table // and then the first 256 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 256,
// and on 64bit platform value 128 (256/2=128)) // and on 64bit platform value 128 (256/2=128))
@ -655,9 +659,7 @@ public:
// there shouldn't be a carry here because // there shouldn't be a carry here because
// (1) (2) guarantee that the mantissa of this // (1) (2) guarantee that the mantissa of this
// is greater than or equal to the mantissa of the ss2 // is greater than or equal to the mantissa of the ss2
uint c_temp = mantissa.Sub(ss2.mantissa); TTMATH_ASSERT( mantissa.Sub(ss2.mantissa) == 0 )
TTMATH_ASSERT( c_temp == 0 )
} }
c += Standardizing(); c += Standardizing();
@ -2037,7 +2039,7 @@ public:
// then V=(-1)**S * 2 ** (-1022) * (0.F) // then V=(-1)**S * 2 ** (-1022) * (0.F)
// These are "unnormalized" values. // These are "unnormalized" values.
FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul), FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m); e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
Standardizing(); Standardizing();
} }
@ -2540,18 +2542,18 @@ public:
output: output:
return value: return value:
0 - ok and 'result' will be an object of type std::string which holds the value 0 - ok and 'result' will be an object of type tstr_t which holds the value
1 - if there was a carry 1 - if there was a carry
*/ */
uint ToString( std::string & result, uint ToString( tstr_t & result,
uint base = 10, uint base = 10,
bool always_scientific = false, bool always_scientific = false,
sint when_scientific = 15, sint when_scientific = 15,
sint max_digit_after_comma = -1, sint max_digit_after_comma = -1,
bool remove_trailing_zeroes = true, bool remove_trailing_zeroes = true,
char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const tchar_t decimal_point = TTMATH_COMMA_CHARACTER_1 ) const
{ {
static char error_overflow_msg[] = "overflow"; static tchar_t error_overflow_msg[] = TTMATH_TEXT("overflow");
result.erase(); result.erase();
if(base<2 || base>16) if(base<2 || base>16)
@ -2562,7 +2564,7 @@ public:
if( IsZero() ) if( IsZero() )
{ {
result = "0"; result = TTMATH_TEXT("0");
return 0; return 0;
} }
@ -2687,7 +2689,7 @@ private:
but we need 'new'exp' as integer then we take: but we need 'new'exp' as integer then we take:
new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x new_exp = [log base (2^exponent)] + 1 <- where [x] means integer value from x
*/ */
uint ToString_CreateNewMantissaAndExponent( std::string & new_man, uint base, uint ToString_CreateNewMantissaAndExponent( tstr_t & new_man, uint base,
Int<exp+1> & new_exp) const Int<exp+1> & new_exp) const
{ {
uint c = 0; uint c = 0;
@ -2870,7 +2872,7 @@ private:
(we can make that speciality when the base is 4,8 or 16 as well (we can make that speciality when the base is 4,8 or 16 as well
but maybe in further time) but maybe in further time)
*/ */
uint ToString_CreateNewMantissaAndExponent_Base2( std::string & new_man, uint ToString_CreateNewMantissaAndExponent_Base2( tstr_t & new_man,
Int<exp+1> & new_exp ) const Int<exp+1> & new_exp ) const
{ {
for( sint i=man-1 ; i>=0 ; --i ) for( sint i=man-1 ; i>=0 ; --i )
@ -2900,13 +2902,13 @@ private:
this method roundes the last character from the new mantissa this method roundes the last character from the new mantissa
(it's used in systems where the base is different from 2) (it's used in systems where the base is different from 2)
*/ */
uint ToString_RoundMantissa(std::string & new_man, uint base, Int<exp+1> & new_exp, char decimal_point) const uint ToString_RoundMantissa(tstr_t & new_man, uint base, Int<exp+1> & new_exp, tchar_t decimal_point) const
{ {
// we must have minimum two characters // we must have minimum two characters
if( new_man.length() < 2 ) if( new_man.length() < 2 )
return 0; return 0;
std::string::size_type i = new_man.length() - 1; tstr_t::size_type i = new_man.length() - 1;
// we're erasing the last character // we're erasing the last character
uint digit = UInt<man>::CharToDigit( new_man[i] ); uint digit = UInt<man>::CharToDigit( new_man[i] );
@ -2927,7 +2929,7 @@ private:
this method addes one into the new mantissa this method addes one into the new mantissa
*/ */
void ToString_RoundMantissa_AddOneIntoMantissa(std::string & new_man, uint base, char decimal_point) const void ToString_RoundMantissa_AddOneIntoMantissa(tstr_t & new_man, uint base, tchar_t decimal_point) const
{ {
if( new_man.empty() ) if( new_man.empty() )
return; return;
@ -2965,13 +2967,13 @@ private:
this method sets the comma operator and/or puts the exponent this method sets the comma operator and/or puts the exponent
into the string into the string
*/ */
uint ToString_SetCommaAndExponent( std::string & new_man, uint base, uint ToString_SetCommaAndExponent( tstr_t & new_man, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
bool always_scientific, bool always_scientific,
sint when_scientific, sint when_scientific,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
char decimal_point) const tchar_t decimal_point) const
{ {
uint carry = 0; uint carry = 0;
@ -3011,12 +3013,12 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal( void ToString_SetCommaAndExponent_Normal(
std::string & new_man, tstr_t & new_man,
uint base, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
char decimal_point) const tchar_t decimal_point) const
{ {
if( !new_exp.IsSign() ) //if( new_exp >= 0 ) if( !new_exp.IsSign() ) //if( new_exp >= 0 )
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
@ -3028,7 +3030,7 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal_AddingZero(std::string & new_man, void ToString_SetCommaAndExponent_Normal_AddingZero(tstr_t & new_man,
Int<exp+1> & new_exp) const Int<exp+1> & new_exp) const
{ {
// we're adding zero characters at the end // we're adding zero characters at the end
@ -3048,12 +3050,12 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Normal_SetCommaInside( void ToString_SetCommaAndExponent_Normal_SetCommaInside(
std::string & new_man, tstr_t & new_man,
uint base, uint base,
Int<exp+1> & new_exp, Int<exp+1> & new_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
char decimal_point) const tchar_t decimal_point) const
{ {
// new_exp is < 0 // new_exp is < 0
@ -3072,7 +3074,7 @@ private:
// we're adding zero characters before the mantissa // we're adding zero characters before the mantissa
uint how_many = e - new_man_len; uint how_many = e - new_man_len;
std::string man_temp(how_many+1, '0'); tstr_t man_temp(how_many+1, '0');
man_temp.insert( man_temp.begin()+1, decimal_point); man_temp.insert( man_temp.begin()+1, decimal_point);
new_man.insert(0, man_temp); new_man.insert(0, man_temp);
@ -3085,12 +3087,12 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_SetCommaAndExponent_Scientific( std::string & new_man, void ToString_SetCommaAndExponent_Scientific( tstr_t & new_man,
uint base, uint base,
Int<exp+1> & scientific_exp, Int<exp+1> & scientific_exp,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
char decimal_point) const tchar_t decimal_point) const
{ {
if( new_man.empty() ) if( new_man.empty() )
return; return;
@ -3104,16 +3106,16 @@ private:
new_man += 'e'; new_man += 'e';
if( !scientific_exp.IsSign() ) if( !scientific_exp.IsSign() )
new_man += "+"; new_man += TTMATH_TEXT("+");
} }
else else
{ {
// the 10 here is meant as the base 'base' // the 10 here is meant as the base 'base'
// (no matter which 'base' we're using there'll always be 10 here) // (no matter which 'base' we're using there'll always be 10 here)
new_man += "*10^"; new_man += TTMATH_TEXT("*10^");
} }
std::string temp_exp; tstr_t temp_exp;
scientific_exp.ToString( temp_exp, base ); scientific_exp.ToString( temp_exp, base );
new_man += temp_exp; new_man += temp_exp;
@ -3123,11 +3125,11 @@ private:
/*! /*!
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma( std::string & new_man, void ToString_CorrectDigitsAfterComma( tstr_t & new_man,
uint base, uint base,
sint max_digit_after_comma, sint max_digit_after_comma,
bool remove_trailing_zeroes, bool remove_trailing_zeroes,
char decimal_point) const tchar_t decimal_point) const
{ {
if( max_digit_after_comma >= 0 ) if( max_digit_after_comma >= 0 )
ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point); ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point);
@ -3141,8 +3143,8 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
std::string & new_man, tstr_t & new_man,
char decimal_point) const tchar_t decimal_point) const
{ {
// minimum two characters // minimum two characters
if( new_man.length() < 2 ) if( new_man.length() < 2 )
@ -3160,7 +3162,7 @@ private:
// we must have a comma // we must have a comma
// (the comma can be removed by ToString_CorrectDigitsAfterComma_Round // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
// which is called before) // which is called before)
if( new_man.find_last_of(decimal_point, i) == std::string::npos ) if( new_man.find_last_of(decimal_point, i) == tstr_t::npos )
return; return;
// if directly before the first zero is the comma operator // if directly before the first zero is the comma operator
@ -3176,26 +3178,26 @@ private:
an auxiliary method for converting into the string an auxiliary method for converting into the string
*/ */
void ToString_CorrectDigitsAfterComma_Round( void ToString_CorrectDigitsAfterComma_Round(
std::string & new_man, tstr_t & new_man,
uint base, uint base,
sint max_digit_after_comma, sint max_digit_after_comma,
char decimal_point) const tchar_t decimal_point) const
{ {
// first we're looking for the comma operator // first we're looking for the comma operator
std::string::size_type index = new_man.find(decimal_point, 0); tstr_t::size_type index = new_man.find(decimal_point, 0);
if( index == std::string::npos ) if( index == tstr_t::npos )
// nothing was found (actually there can't be this situation) // nothing was found (actually there can't be this situation)
return; return;
// we're calculating how many digits there are at the end (after the comma) // we're calculating how many digits there are at the end (after the comma)
// 'after_comma' will be greater than zero because at the end // 'after_comma' will be greater than zero because at the end
// we have at least one digit // we have at least one digit
std::string::size_type after_comma = new_man.length() - index - 1; tstr_t::size_type after_comma = new_man.length() - index - 1;
// if 'max_digit_after_comma' is greater than 'after_comma' (or equal) // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
// we don't have anything for cutting // we don't have anything for cutting
if( std::string::size_type(max_digit_after_comma) >= after_comma ) if( tstr_t::size_type(max_digit_after_comma) >= after_comma )
return; return;
uint last_digit = UInt<man>::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base ); uint last_digit = UInt<man>::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base );
@ -3241,7 +3243,7 @@ public:
no value has been read (there are no digits) 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 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, bool * value_read = 0) uint FromString(const tchar_t * source, uint base = 10, const tchar_t ** after_source = 0, bool * value_read = 0)
{ {
bool is_sign; bool is_sign;
bool value_read_temp = false; bool value_read_temp = false;
@ -3290,7 +3292,7 @@ private:
(this method is used from 'FromString_ReadPartScientific' too) (this method is used from 'FromString_ReadPartScientific' too)
*/ */
void FromString_TestSign( const char * & source, bool & is_sign ) void FromString_TestSign( const tchar_t * & source, bool & is_sign )
{ {
UInt<man>::SkipWhiteCharacters(source); UInt<man>::SkipWhiteCharacters(source);
@ -3312,7 +3314,7 @@ private:
/*! /*!
we're testing whether there's a comma operator we're testing whether there's a comma operator
*/ */
bool FromString_TestCommaOperator(const char * & source) bool FromString_TestCommaOperator(const tchar_t * & source)
{ {
if( (*source == TTMATH_COMMA_CHARACTER_1) || if( (*source == TTMATH_COMMA_CHARACTER_1) ||
(*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
@ -3330,7 +3332,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, bool & value_read ) uint FromString_ReadPartBeforeComma( const tchar_t * & source, uint base, bool & value_read )
{ {
sint character; sint character;
Big<exp, man> temp; Big<exp, man> temp;
@ -3359,7 +3361,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, bool & value_read ) uint FromString_ReadPartAfterComma( const tchar_t * & source, uint base, bool & value_read )
{ {
sint character; sint character;
uint c = 0, index = 1; uint c = 0, index = 1;
@ -3417,12 +3419,12 @@ private:
it is called when the base is 10 and some digits were read before it is called when the base is 10 and some digits were read before
*/ */
int FromString_ReadScientificIfExists(const char * & source) int FromString_ReadScientificIfExists(const tchar_t * & source)
{ {
int c = 0; int c = 0;
bool scientific_read = false; bool scientific_read = false;
const char * before_scientific = source; const tchar_t * before_scientific = source;
if( FromString_TestScientific(source) ) if( FromString_TestScientific(source) )
c += FromString_ReadPartScientific( source, scientific_read ); c += FromString_ReadPartScientific( source, scientific_read );
@ -3440,7 +3442,7 @@ private:
this character is only allowed when we're using the base equals 10 this character is only allowed when we're using the base equals 10
*/ */
bool FromString_TestScientific(const char * & source) bool FromString_TestScientific(const tchar_t * & source)
{ {
UInt<man>::SkipWhiteCharacters(source); UInt<man>::SkipWhiteCharacters(source);
@ -3459,7 +3461,7 @@ 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, bool & scientific_read ) uint FromString_ReadPartScientific( const tchar_t * & source, bool & scientific_read )
{ {
uint c = 0; uint c = 0;
Big<exp, man> new_exponent, temp; Big<exp, man> new_exponent, temp;
@ -3486,7 +3488,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, bool & scientific_read ) uint FromString_ReadPartScientific_ReadExponent( const tchar_t * & source, Big<exp, man> & new_exponent, bool & scientific_read )
{ {
sint character; sint character;
Big<exp, man> base, temp; Big<exp, man> base, temp;
@ -3519,7 +3521,7 @@ public:
/*! /*!
a method for converting a string into its value a method for converting a string into its value
*/ */
uint FromString(const std::string & string, uint base = 10) uint FromString(const tstr_t & string, uint base = 10)
{ {
return FromString( string.c_str(), base ); return FromString( string.c_str(), base );
} }
@ -3528,7 +3530,7 @@ public:
/*! /*!
a constructor for converting a string into this class a constructor for converting a string into this class
*/ */
Big(const char * string) Big(const tchar_t * string)
{ {
FromString( string ); FromString( string );
} }
@ -3537,7 +3539,7 @@ public:
/*! /*!
a constructor for converting a string into this class a constructor for converting a string into this class
*/ */
Big(const std::string & string) Big(const tstr_t & string)
{ {
FromString( string.c_str() ); FromString( string.c_str() );
} }
@ -3546,7 +3548,7 @@ public:
/*! /*!
an operator= for converting a string into its value an operator= for converting a string into its value
*/ */
Big<exp, man> & operator=(const char * string) Big<exp, man> & operator=(const tchar_t * string)
{ {
FromString( string ); FromString( string );
@ -3557,7 +3559,7 @@ public:
/*! /*!
an operator= for converting a string into its value an operator= for converting a string into its value
*/ */
Big<exp, man> & operator=(const std::string & string) Big<exp, man> & operator=(const tstr_t & string)
{ {
FromString( string.c_str() ); FromString( string.c_str() );
@ -3964,9 +3966,9 @@ public:
* *
*/ */
friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l) friend tostrm_t & operator<<(tostrm_t & s, const Big<exp,man> & l)
{ {
std::string ss; tstr_t ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -3975,12 +3977,12 @@ public:
} }
friend std::istream & operator>>(std::istream & s, Big<exp,man> & l) friend tistrm_t & operator>>(tistrm_t & s, Big<exp,man> & l)
{ {
std::string ss; tstr_t ss;
// 'char' for operator>> // 'tchar_t' for operator>>
unsigned char z; unsigned tchar_t z;
bool was_comma = false; bool was_comma = false;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
@ -4023,6 +4025,9 @@ public:
}; };
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
} // namespace } // namespace

70
ttmath/ttmathconfig.h Normal file
View File

@ -0,0 +1,70 @@
/*
* This file is a part of TTMath Bignum Library
* and is distributed under the PNG licence.
* Author: Christian Kaiser <chk@online.de>
*/
/*
Copyright (c) 2009 Christian Kaiser
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef headerfilettmathmathttconfig
#define headerfilettmathmathttconfig
#pragma once
#include <sstream>
namespace ttmath
{
#if defined(_MSC_VER)
#if defined(_UNICODE)
typedef wchar_t tchar_t;
typedef std::wstring tstr_t;
typedef std::wostringstream tostrstrm_t;
typedef std::wostream tostrm_t;
typedef std::wistream tistrm_t;
#else
typedef unsigned char tchar_t;
typedef std::string tstr_t;
typedef std::ostringstream tostrstrm_t;
typedef std::ostream tostrm_t;
typedef std::istream tistrm_t;
#endif
#if defined(_UNICODE)
#define __TEXT(quote) L ## quote
#else
#define __TEXT(quote) quote
#endif
#define TTMATH_TEXT(quote) __TEXT(quote)
#else
typedef unsigned char tchar_t;
typedef std::string tstr_t;
typedef std::ostringstream tostrstrm_t;
typedef std::ostream tostrm_t;
typedef std::istream tistrm_t;
#endif
} // namespace
#endif // headerfilettmathmathttconfig

View File

@ -47,6 +47,10 @@
#include "ttmathuint.h" #include "ttmathuint.h"
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
namespace ttmath namespace ttmath
{ {
@ -641,8 +645,14 @@ public:
// there can be a carry here when the size of this value is equal one word // there can be a carry here when the size of this value is equal one word
// and the 'value' has the highest bit set // and the 'value' has the highest bit set
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 )
return 1; return 1;
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
return 0; return 0;
} }
@ -821,7 +831,7 @@ public:
/*! /*!
a constructor for converting string to this class (with the base=10) a constructor for converting string to this class (with the base=10)
*/ */
Int(const char * s) Int(const tchar_t * s)
{ {
FromString(s); FromString(s);
} }
@ -830,7 +840,7 @@ public:
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
Int(const std::string & s) Int(const tstr_t & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
} }
@ -869,7 +879,7 @@ 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'
*/ */
void ToString(std::string & result, uint b = 10) const void ToString(tstr_t & result, uint b = 10) const
{ {
if( IsSign() ) if( IsSign() )
{ {
@ -904,7 +914,7 @@ public:
value_read (if exists) tells whether something has actually been read (at least one digit) value_read (if exists) tells whether something has actually been read (at least one digit)
*/ */
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0)
{ {
bool is_sign = false; bool is_sign = false;
@ -961,7 +971,7 @@ public:
this method converts a string into its value this method converts a string into its value
it returns carry=1 if the value will be too big or an incorrect base 'b' is given it returns carry=1 if the value will be too big or an incorrect base 'b' is given
*/ */
uint FromString(const std::string & s, uint b = 10) uint FromString(const tstr_t & s, uint b = 10)
{ {
return FromString( s.c_str() ); return FromString( s.c_str() );
} }
@ -970,7 +980,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const char * s) Int<value_size> & operator=(const tchar_t * s)
{ {
FromString(s); FromString(s);
@ -981,7 +991,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
Int<value_size> & operator=(const std::string & s) Int<value_size> & operator=(const tstr_t & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
@ -1268,9 +1278,9 @@ public:
* *
*/ */
friend std::ostream & operator<<(std::ostream & s, const Int<value_size> & l) friend tostrm_t & operator<<(tostrm_t & s, const Int<value_size> & l)
{ {
std::string ss; tstr_t ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -1280,12 +1290,12 @@ public:
friend std::istream & operator>>(std::istream & s, Int<value_size> & l) friend tistrm_t & operator>>(tistrm_t & s, Int<value_size> & l)
{ {
std::string ss; tstr_t ss;
// char for operator>> // tchar_t for operator>>
unsigned char z; unsigned tchar_t z;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
s >> z; s >> z;
@ -1316,5 +1326,9 @@ public:
} // namespace } // namespace
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
#endif #endif

View File

@ -73,18 +73,18 @@ public:
struct Item struct Item
{ {
// name of a variable of a function // name of a variable of a function
std::string value; tstr_t value;
// number of parameters required by the function // number of parameters required by the function
// (if there's a variable this 'param' is ignored) // (if there's a variable this 'param' is ignored)
int param; int param;
Item() {} Item() {}
Item(const std::string & v, int p) : value(v), param(p) {} Item(const tstr_t & v, int p) : value(v), param(p) {}
}; };
// 'Table' is the type of our table // 'Table' is the type of our table
typedef std::map<std::string, Item> Table; typedef std::map<tstr_t, Item> Table;
typedef Table::iterator Iterator; typedef Table::iterator Iterator;
typedef Table::const_iterator CIterator; typedef Table::const_iterator CIterator;
@ -112,7 +112,7 @@ public:
/*! /*!
this method returns true if the name can be as a name of an object this method returns true if the name can be as a name of an object
*/ */
static bool IsNameCorrect(const std::string & name) static bool IsNameCorrect(const tstr_t & name)
{ {
if( name.empty() ) if( name.empty() )
return false; return false;
@ -120,7 +120,7 @@ public:
if( !CorrectCharacter(name[0], false) ) if( !CorrectCharacter(name[0], false) )
return false; return false;
std::string::const_iterator i=name.begin(); tstr_t::const_iterator i=name.begin();
for(++i ; i!=name.end() ; ++i) for(++i ; i!=name.end() ; ++i)
if( !CorrectCharacter(*i, true) ) if( !CorrectCharacter(*i, true) )
@ -133,7 +133,7 @@ public:
/*! /*!
this method returns true if such an object is defined (name exists) this method returns true if such an object is defined (name exists)
*/ */
bool IsDefined(const std::string & name) bool IsDefined(const tstr_t & name)
{ {
Iterator i = table.find(name); Iterator i = table.find(name);
@ -148,7 +148,7 @@ public:
/*! /*!
this method adds one object (variable of function) into the table this method adds one object (variable of function) into the table
*/ */
ErrorCode Add(const std::string & name, const std::string & value, int param = 0) ErrorCode Add(const tstr_t & name, const tstr_t & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -205,7 +205,7 @@ public:
/*! /*!
this method changes the value and the number of parameters for a specific object this method changes the value and the number of parameters for a specific object
*/ */
ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) ErrorCode EditValue(const tstr_t & name, const tstr_t & value, int param = 0)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -225,7 +225,7 @@ public:
/*! /*!
this method changes the name of a specific object this method changes the name of a specific object
*/ */
ErrorCode EditName(const std::string & old_name, const std::string & new_name) ErrorCode EditName(const tstr_t & old_name, const tstr_t & new_name)
{ {
if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) )
return err_incorrect_name; return err_incorrect_name;
@ -256,7 +256,7 @@ public:
/*! /*!
this method deletes an object this method deletes an object
*/ */
ErrorCode Delete(const std::string & name) ErrorCode Delete(const tstr_t & name)
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -275,7 +275,7 @@ public:
/*! /*!
this method gets the value of a specific object this method gets the value of a specific object
*/ */
ErrorCode GetValue(const std::string & name, std::string & value) const ErrorCode GetValue(const tstr_t & name, tstr_t & value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -298,7 +298,7 @@ public:
this method gets the value of a specific object this method gets the value of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValue(const std::string & name, const char ** value) const ErrorCode GetValue(const tstr_t & name, const tchar_t ** value) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -321,7 +321,7 @@ public:
this method gets the value and the number of parameters this method gets the value and the number of parameters
of a specific object of a specific object
*/ */
ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const ErrorCode GetValueAndParam(const tstr_t & name, tstr_t & value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;
@ -347,7 +347,7 @@ public:
of a specific object of a specific object
(this version is used for not copying the whole string) (this version is used for not copying the whole string)
*/ */
ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const ErrorCode GetValueAndParam(const tstr_t & name, const tchar_t ** value, int * param) const
{ {
if( !IsNameCorrect(name) ) if( !IsNameCorrect(name) )
return err_incorrect_name; return err_incorrect_name;

View File

@ -256,7 +256,7 @@ public:
bool function; bool function;
// if function is true // if function is true
std::string function_name; tstr_t function_name;
/* /*
the sign of value the sign of value
@ -310,11 +310,11 @@ ErrorCode error;
/*! /*!
pointer to the currently reading char pointer to the currently reading tchar_t
when an error has occured it may be used to count the index of the wrong character when an error has occured it may be used to count the index of the wrong character
*/ */
const char * pstring; const tchar_t * pstring;
/*! /*!
@ -351,7 +351,7 @@ const Objects * puser_variables;
const Objects * puser_functions; const Objects * puser_functions;
typedef std::map<std::string, ValueType> FunctionLocalVariables; typedef std::map<tstr_t, ValueType> FunctionLocalVariables;
/*! /*!
a pointer to the local variables of a function a pointer to the local variables of a function
@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables;
/*! /*!
a temporary set using during parsing user defined variables a temporary set using during parsing user defined variables
*/ */
std::set<std::string> visited_variables; std::set<tstr_t> visited_variables;
/*! /*!
a temporary set using during parsing user defined functions a temporary set using during parsing user defined functions
*/ */
std::set<std::string> visited_functions; std::set<tstr_t> visited_functions;
@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)();
table of mathematic functions table of mathematic functions
this map consists of: this map consists of:
std::string - function's name tstr_t - function's name
pfunction - pointer to specific function pfunction - pointer to specific function
*/ */
typedef std::map<std::string, pfunction> FunctionsTable; typedef std::map<tstr_t, pfunction> FunctionsTable;
FunctionsTable functions_table; FunctionsTable functions_table;
@ -407,10 +407,10 @@ FunctionsTable functions_table;
table of mathematic operators table of mathematic operators
this map consists of: this map consists of:
std::string - operators's name tstr_t - operators's name
MatOperator::Type - type of the operator MatOperator::Type - type of the operator
*/ */
typedef std::map<std::string, typename MatOperator::Type> OperatorsTable; typedef std::map<tstr_t, typename MatOperator::Type> OperatorsTable;
OperatorsTable operators_table; OperatorsTable operators_table;
@ -418,10 +418,10 @@ OperatorsTable operators_table;
table of mathematic variables table of mathematic variables
this map consists of: this map consists of:
std::string - variable's name tstr_t - variable's name
pfunction_var - pointer to specific function which returns value of variable pfunction_var - pointer to specific function which returns value of variable
*/ */
typedef std::map<std::string, pfunction_var> VariablesTable; typedef std::map<tstr_t, pfunction_var> VariablesTable;
VariablesTable variables_table; VariablesTable variables_table;
@ -456,7 +456,7 @@ void SkipWhiteCharacters()
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tstr_t & name)
{ {
if( variable ) if( variable )
{ {
@ -474,7 +474,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tstr_t & name)
{ {
if( variable ) if( variable )
visited_variables.insert( name ); visited_variables.insert( name );
@ -486,7 +486,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri
/*! /*!
an auxiliary method for RecurrenceParsingVariablesOrFunction(...) an auxiliary method for RecurrenceParsingVariablesOrFunction(...)
*/ */
void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tstr_t & name)
{ {
if( variable ) if( variable )
visited_variables.erase( name ); visited_variables.erase( name );
@ -505,7 +505,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::s
(there can be a recurrence here therefore we're using 'visited_variables' (there can be a recurrence here therefore we're using 'visited_variables'
and 'visited_functions' sets to make a stop condition) and 'visited_functions' sets to make a stop condition)
*/ */
ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0) ValueType RecurrenceParsingVariablesOrFunction(bool variable, const tstr_t & name, const tchar_t * new_string, FunctionLocalVariables * local_variables = 0)
{ {
RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name);
RecurrenceParsingVariablesOrFunction_AddName(variable, name); RecurrenceParsingVariablesOrFunction_AddName(variable, name);
@ -548,12 +548,12 @@ public:
/*! /*!
this method returns the user-defined value of a variable this method returns the user-defined value of a variable
*/ */
bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) bool GetValueOfUserDefinedVariable(const tstr_t & variable_name,ValueType & result)
{ {
if( !puser_variables ) if( !puser_variables )
return false; return false;
const char * string_value; const tchar_t * string_value;
if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) if( puser_variables->GetValue(variable_name, &string_value) != err_ok )
return false; return false;
@ -567,7 +567,7 @@ return true;
/*! /*!
this method returns the value of a local variable of a function this method returns the value of a local variable of a function
*/ */
bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) bool GetValueOfFunctionLocalVariable(const tstr_t & variable_name, ValueType & result)
{ {
if( !pfunction_local_variables ) if( !pfunction_local_variables )
return false; return false;
@ -589,7 +589,7 @@ return true;
we make an object of type ValueType then call a method which we make an object of type ValueType then call a method which
sets the correct value in it and finally we'll return the object sets the correct value in it and finally we'll return the object
*/ */
ValueType GetValueOfVariable(const std::string & variable_name) ValueType GetValueOfVariable(const tstr_t & variable_name)
{ {
ValueType result; ValueType result;
@ -600,7 +600,7 @@ ValueType result;
return result; return result;
typename std::map<std::string, pfunction_var>::iterator i = typename std::map<tstr_t, pfunction_var>::iterator i =
variables_table.find(variable_name); variables_table.find(variable_name);
if( i == variables_table.end() ) if( i == variables_table.end() )
@ -1338,12 +1338,12 @@ void Avg(int sindex, int amount_of_args, ValueType & result)
(look at the description in 'CallFunction(...)') (look at the description in 'CallFunction(...)')
*/ */
bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex) bool GetValueOfUserDefinedFunction(const tstr_t & function_name, int amount_of_args, int sindex)
{ {
if( !puser_functions ) if( !puser_functions )
return false; return false;
const char * string_value; const tchar_t * string_value;
int param; int param;
if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok ) if( puser_functions->GetValueAndParam(function_name, &string_value, &param) != err_ok )
@ -1357,7 +1357,7 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount
if( amount_of_args > 0 ) if( amount_of_args > 0 )
{ {
char buffer[20]; tchar_t buffer[20];
// x = x1 // x = x1
sprintf(buffer,"x"); sprintf(buffer,"x");
@ -1389,7 +1389,7 @@ return true;
result will be stored in 'stack[sindex-1].value' result will be stored in 'stack[sindex-1].value'
(we don't have to set the correct type of this element, it'll be set later) (we don't have to set the correct type of this element, it'll be set later)
*/ */
void CallFunction(const std::string & function_name, int amount_of_args, int sindex) void CallFunction(const tstr_t & function_name, int amount_of_args, int sindex)
{ {
if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) )
return; return;
@ -1415,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 char * function_name, pfunction pf) void InsertFunctionToTable(const tchar_t * function_name, pfunction pf)
{ {
functions_table.insert( std::make_pair(std::string(function_name), pf)); functions_table.insert( std::make_pair(tstr_t(function_name), pf));
} }
@ -1428,9 +1428,9 @@ void InsertFunctionToTable(const char * function_name, pfunction pf)
variable_name - name of the function variable_name - name of the function
pf - pointer to the function pf - pointer to the function
*/ */
void InsertVariableToTable(const char * variable_name, pfunction_var pf) void InsertVariableToTable(const tchar_t * variable_name, pfunction_var pf)
{ {
variables_table.insert( std::make_pair(std::string(variable_name), pf)); variables_table.insert( std::make_pair(tstr_t(variable_name), pf));
} }
@ -1538,7 +1538,7 @@ return c;
what should be returned is tested just by a '(' character that means if there's what should be returned is tested just by a '(' character that means if there's
a '(' character after a name that function returns 'true' a '(' character after a name that function returns 'true'
*/ */
bool ReadName(std::string & result) bool ReadName(tstr_t & result)
{ {
int character; int character;
@ -1610,7 +1610,7 @@ return false;
*/ */
bool ReadVariableOrFunction(Item & result) bool ReadVariableOrFunction(Item & result)
{ {
std::string name; tstr_t name;
bool is_it_name_of_function = ReadName(name); bool is_it_name_of_function = ReadName(name);
if( is_it_name_of_function ) if( is_it_name_of_function )
@ -1639,7 +1639,7 @@ return is_it_name_of_function;
*/ */
void ReadValue(Item & result, int reading_base) void ReadValue(Item & result, int reading_base)
{ {
const char * new_stack_pointer; const tchar_t * new_stack_pointer;
bool value_read; bool value_read;
int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read); int carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read);
@ -1812,7 +1812,7 @@ return 0;
} }
void InsertOperatorToTable(const std::string & name, typename MatOperator::Type type) void InsertOperatorToTable(const tstr_t & name, typename MatOperator::Type type)
{ {
operators_table.insert( std::make_pair(name, type) ); operators_table.insert( std::make_pair(name, type) );
} }
@ -1823,19 +1823,19 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type
*/ */
void CreateMathematicalOperatorsTable() void CreateMathematicalOperatorsTable()
{ {
InsertOperatorToTable(std::string("||"), MatOperator::lor); InsertOperatorToTable(tstr_t("||"), MatOperator::lor);
InsertOperatorToTable(std::string("&&"), MatOperator::land); InsertOperatorToTable(tstr_t("&&"), MatOperator::land);
InsertOperatorToTable(std::string("!="), MatOperator::neq); InsertOperatorToTable(tstr_t("!="), MatOperator::neq);
InsertOperatorToTable(std::string("=="), MatOperator::eq); InsertOperatorToTable(tstr_t("=="), MatOperator::eq);
InsertOperatorToTable(std::string(">="), MatOperator::get); InsertOperatorToTable(tstr_t(">="), MatOperator::get);
InsertOperatorToTable(std::string("<="), MatOperator::let); InsertOperatorToTable(tstr_t("<="), MatOperator::let);
InsertOperatorToTable(std::string(">"), MatOperator::gt); InsertOperatorToTable(tstr_t(">"), MatOperator::gt);
InsertOperatorToTable(std::string("<"), MatOperator::lt); InsertOperatorToTable(tstr_t("<"), MatOperator::lt);
InsertOperatorToTable(std::string("-"), MatOperator::sub); InsertOperatorToTable(tstr_t("-"), MatOperator::sub);
InsertOperatorToTable(std::string("+"), MatOperator::add); InsertOperatorToTable(tstr_t("+"), MatOperator::add);
InsertOperatorToTable(std::string("/"), MatOperator::div); InsertOperatorToTable(tstr_t("/"), MatOperator::div);
InsertOperatorToTable(std::string("*"), MatOperator::mul); InsertOperatorToTable(tstr_t("*"), MatOperator::mul);
InsertOperatorToTable(std::string("^"), MatOperator::pow); InsertOperatorToTable(tstr_t("^"), MatOperator::pow);
} }
@ -1845,12 +1845,12 @@ void CreateMathematicalOperatorsTable()
e.g. e.g.
true when str1="test" and str2="te" true when str1="test" and str2="te"
*/ */
bool IsSubstring(const std::string & str1, const std::string & str2) bool IsSubstring(const tstr_t & str1, const tstr_t & str2)
{ {
if( str2.length() > str1.length() ) if( str2.length() > str1.length() )
return false; return false;
for(std::string::size_type i=0 ; i<str2.length() ; ++i) for(tstr_t::size_type i=0 ; i<str2.length() ; ++i)
if( str1[i] != str2[i] ) if( str1[i] != str2[i] )
return false; return false;
@ -1863,7 +1863,7 @@ return true;
*/ */
void ReadMathematicalOperator(Item & result) void ReadMathematicalOperator(Item & result)
{ {
std::string oper; tstr_t oper;
typename OperatorsTable::iterator iter_old, iter_new; typename OperatorsTable::iterator iter_old, iter_new;
iter_old = operators_table.end(); iter_old = operators_table.end();
@ -2510,7 +2510,7 @@ void SetFactorialMax(const ValueType & m)
/*! /*!
the main method using for parsing string the main method using for parsing string
*/ */
ErrorCode Parse(const char * str) ErrorCode Parse(const tchar_t * str)
{ {
stack_index = 0; stack_index = 0;
pstring = str; pstring = str;

View File

@ -1,447 +1,451 @@
/* /*
* This file is a part of TTMath Bignum 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-2009, 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
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright notice, * * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name Tomasz Sowa nor the names of contributors to this * * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived * project may be used to endorse or promote products derived
* from this software without specific prior written permission. * from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef headerfilettmathtypes #ifndef headerfilettmathtypes
#define headerfilettmathtypes #define headerfilettmathtypes
/*! /*!
\file ttmathtypes.h \file ttmathtypes.h
\brief constants used in the library \brief constants used in the library
As our library is written in header files (templates) we cannot use As our library is written in header files (templates) we cannot use
constants like 'const int' etc. because we should have some source files constants like 'const int' etc. because we should have some source files
*.cpp to define this variables. Only what we can have are constants *.cpp to define this variables. Only what we can have are constants
defined by #define preprocessor macros. defined by #define preprocessor macros.
All macros are preceded by TTMATH_ prefix All macros are preceded by TTMATH_ prefix
*/ */
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
/*! /*!
the version of the library the version of the library
TTMATH_PRERELEASE_VER is either zero or one TTMATH_PRERELEASE_VER is either zero or one
if zero that means this is the release version of the library if zero that means this is the release version of the library
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 4 #define TTMATH_REVISION_VER 4
#define TTMATH_PRERELEASE_VER 1 #define TTMATH_PRERELEASE_VER 1
/*! /*!
TTMATH_DEBUG TTMATH_DEBUG
this macro enables further testing during writing your code this macro enables further testing during writing your code
you don't have to define it in a release mode you don't have to define it in a release mode
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
are set as well and these macros can throw an exception if a condition in it are set as well and these macros can throw an exception if a condition in it
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
TTMATH_RELEASE TTMATH_RELEASE
if you are confident that your code is perfect you can define TTMATH_RELEASE if you are confident that your code is perfect you can define TTMATH_RELEASE
macro for example by using -D option in gcc macro for example by using -D option in gcc
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 automatically if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
*/ */
#ifndef TTMATH_RELEASE #ifndef TTMATH_RELEASE
#define TTMATH_DEBUG #define TTMATH_DEBUG
#endif #endif
namespace ttmath namespace ttmath
{ {
#if !defined _M_X64 && !defined __x86_64__ #if !defined _M_X64 && !defined __x86_64__
/*! /*!
we're using a 32bit platform we're using a 32bit platform
*/ */
#define TTMATH_PLATFORM32 #define TTMATH_PLATFORM32
#else #else
/*! /*!
we're using a 64bit platform we're using a 64bit platform
*/ */
#define TTMATH_PLATFORM64 #define TTMATH_PLATFORM64
#endif #endif
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
/*! /*!
on 32bit platforms one word (uint, sint) will be equal 32bits on 32bit platforms one word (uint, sint) will be equal 32bits
*/ */
typedef unsigned int uint; typedef unsigned int uint;
typedef signed int sint; typedef signed int sint;
/*! /*!
this type is twice bigger than uint this type is twice bigger than uint
(64bit on a 32bit platforms) (64bit on a 32bit platforms)
although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long) 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 but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
*/ */
typedef unsigned long long int ulint; typedef unsigned long long int ulint;
/*! /*!
how many bits there are in the uint type how many bits there are in the uint type
*/ */
#define TTMATH_BITS_PER_UINT 32u #define TTMATH_BITS_PER_UINT 32u
/*! /*!
the mask for the highest bit in the unsigned 32bit word (2^31) the mask for the highest bit in the unsigned 32bit word (2^31)
*/ */
#define TTMATH_UINT_HIGHEST_BIT 2147483648u #define TTMATH_UINT_HIGHEST_BIT 2147483648u
/*! /*!
the max value of the unsigned 32bit word (2^32 - 1) the max value of the unsigned 32bit word (2^32 - 1)
(all bits equal one) (all bits equal one)
*/ */
#define TTMATH_UINT_MAX_VALUE 4294967295u #define TTMATH_UINT_MAX_VALUE 4294967295u
/*! /*!
the number of words (32bit words on 32bit platform) the number of words (32bit words on 32bit platform)
which are kept in built-in variables for a Big<> type which are kept in built-in variables for a Big<> type
(these variables are defined in ttmathbig.h) (these variables are defined in ttmathbig.h)
*/ */
#define TTMATH_BUILTIN_VARIABLES_SIZE 256u #define TTMATH_BUILTIN_VARIABLES_SIZE 256u
#else #else
/*! /*!
on 64bit platforms one word (uint, sint) will be equal 64bits on 64bit platforms one word (uint, sint) will be equal 64bits
*/ */
typedef unsigned long uint; #if defined(_MSC_VER)
typedef signed long sint; typedef unsigned __int64 uint;
typedef signed __int64 sint;
/*! #else
on 64bit platform we do not define ulint typedef unsigned long long uint;
sizeof(long long) is 8 (64bit) but we need 128bit typedef signed long long sint;
#endif
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 on 64bit platform we do not define ulint
*/ sizeof(long long) is 8 (64bit) but we need 128bit
//typedef unsigned long long int ulint;
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
how many bits there are in the uint type */
*/ //typedef unsigned long long int ulint;
#define TTMATH_BITS_PER_UINT 64ul
/*!
/*! how many bits there are in the uint type
the mask for the highest bit in the unsigned 64bit word (2^63) */
*/ #define TTMATH_BITS_PER_UINT 64ul
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
/*!
/*! the mask for the highest bit in the unsigned 64bit word (2^63)
the max value of the unsigned 64bit word (2^64 - 1) */
(all bits equal one) #define TTMATH_UINT_HIGHEST_BIT 0x8000000000000000ul
*/
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul /*!
the max value of the unsigned 64bit word (2^64 - 1)
/*! (all bits equal one)
the number of words (64bit words on 64bit platforms) */
which are kept in built-in variables for a Big<> type #define TTMATH_UINT_MAX_VALUE 0xfffffffffffffffful
(these variables are defined in ttmathbig.h)
*/ /*!
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul the number of words (64bit words on 64bit platforms)
which are kept in built-in variables for a Big<> type
#endif (these variables are defined in ttmathbig.h)
} */
#define TTMATH_BUILTIN_VARIABLES_SIZE 128ul
#endif
/*! }
characters which represent the comma operator
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function)
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character /*!
that means you can input values for example 1.2345 and 1,2345 as well characters which represent the comma operator
if you don't want it just put 0 there e.g. TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing (default, can be overwritten in ToString() function)
#define TTMATH_COMMA_CHARACTER_2 0 TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
then only TTMATH_COMMA_CHARACTER_1 will be used that means you can input values for example 1.2345 and 1,2345 as well
don't put there any special character which is used by the parser if you don't want it just put 0 there e.g.
(for example a semicolon ';' shouldn't be there) #define TTMATH_COMMA_CHARACTER_2 0
*/ then only TTMATH_COMMA_CHARACTER_1 will be used
#define TTMATH_COMMA_CHARACTER_1 '.'
#define TTMATH_COMMA_CHARACTER_2 ',' don't put there any special character which is used by the parser
(for example a semicolon ';' shouldn't be there)
*/
#define TTMATH_COMMA_CHARACTER_1 '.'
/*! #define TTMATH_COMMA_CHARACTER_2 ','
this variable defines how many iterations are performed
during some kind of calculating when we're making any long formulas
(for example Taylor series)
/*!
it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. this variable defines how many iterations are performed
during some kind of calculating when we're making any long formulas
note! there'll not be so many iterations, iterations are stopped when (for example Taylor series)
there is no sense to continue calculating (for example when the result
still remains unchanged after adding next series and we know that the next it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc.
series are smaller than previous ones)
*/ note! there'll not be so many iterations, iterations are stopped when
#define TTMATH_ARITHMETIC_MAX_LOOP 10000 there is no sense to continue calculating (for example when the result
still remains unchanged after adding next series and we know that the next
series are smaller than previous ones)
*/
#define TTMATH_ARITHMETIC_MAX_LOOP 10000
namespace ttmath
{
/*!
error codes namespace ttmath
*/ {
enum ErrorCode
{ /*!
err_ok = 0, error codes
err_nothing_has_read, */
err_unknown_character, enum ErrorCode
err_unexpected_final_bracket, {
err_stack_not_clear, err_ok = 0,
err_unknown_variable, err_nothing_has_read,
err_division_by_zero, err_unknown_character,
err_interrupt, err_unexpected_final_bracket,
err_overflow, err_stack_not_clear,
err_unknown_function, err_unknown_variable,
err_unknown_operator, err_division_by_zero,
err_unexpected_semicolon_operator, err_interrupt,
err_improper_amount_of_arguments, err_overflow,
err_improper_argument, err_unknown_function,
err_unexpected_end, err_unknown_operator,
err_internal_error, err_unexpected_semicolon_operator,
err_incorrect_name, err_improper_amount_of_arguments,
err_incorrect_value, err_improper_argument,
err_variable_exists, err_unexpected_end,
err_variable_loop, err_internal_error,
err_functions_loop, err_incorrect_name,
err_must_be_only_one_value, err_incorrect_value,
err_object_exists, err_variable_exists,
err_unknown_object, err_variable_loop,
err_still_calculating, err_functions_loop,
err_too_big_factorial, err_must_be_only_one_value,
err_in_short_form_used_function err_object_exists,
}; err_unknown_object,
err_still_calculating,
err_too_big_factorial,
/*! err_in_short_form_used_function
this simple class can be used in multithreading model };
(you can write your own class derived from this one)
for example: in some functions like Factorial() /*!
/at the moment only Factorial/ you can give a pointer to this simple class can be used in multithreading model
the 'stop object', if the method WasStopSignal() of this (you can write your own class derived from this one)
object returns true that means we should break the calculating
and return for example: in some functions like Factorial()
*/ /at the moment only Factorial/ you can give a pointer to
class StopCalculating the 'stop object', if the method WasStopSignal() of this
{ object returns true that means we should break the calculating
public: and return
virtual bool WasStopSignal() const volatile { return false; } */
virtual ~StopCalculating(){} class StopCalculating
}; {
public:
virtual bool WasStopSignal() const volatile { return false; }
/*! virtual ~StopCalculating(){}
a small class which is useful when compiling with gcc };
object of this type holds the name and the line of a file
in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used /*!
*/ a small class which is useful when compiling with gcc
class ExceptionInfo
{ object of this type holds the name and the line of a file
const char * file; in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used
int line; */
class ExceptionInfo
public: {
ExceptionInfo() : file(0), line(0) {} const tchar_t * file;
ExceptionInfo(const char * f, int l) : file(f), line(l) {} int line;
std::string Where() const public:
{ ExceptionInfo() : file(0), line(0) {}
if( !file ) ExceptionInfo(const tchar_t * f, int l) : file(f), line(l) {}
return "unknown";
tstr_t Where() const
std::ostringstream result; {
result << file << ":" << line; if( !file )
return(TTMATH_TEXT("unknown"));
return result.str();
} tostrstrm_t result;
}; result << file << TTMATH_TEXT(":") << line;
return result.str();
/*! }
A small class used for reporting 'reference' errors };
In the library is used macro TTMATH_REFERENCE_ASSERT which
can throw an exception of this type /*!
A small class used for reporting 'reference' errors
If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with In the library is used macro TTMATH_REFERENCE_ASSERT which
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT can throw an exception of this type
was used)
If you compile with gcc you can get a small benefit
What is the 'reference' error? from using method Where() (it returns tstr_t with
Some kind of methods use a reference as their argument to another object, the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
and the another object not always can be the same which is calling, e.g. was used)
Big<1,2> foo(10);
foo.Mul(foo); // this is incorrect What is the 'reference' error?
above method Mul is making something more with 'this' object and Some kind of methods use a reference as their argument to another object,
'this' cannot be passed as the argument because the result will be undefined and the another object not always can be the same which is calling, e.g.
Big<1,2> foo(10);
macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem foo.Mul(foo); // this is incorrect
above method Mul is making something more with 'this' object and
note! some methods can use 'this' object as the argument 'this' cannot be passed as the argument because the result will be undefined
for example this code is correct:
UInt<2> foo(10); macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem
foo.Add(foo);
but there are only few methods which can do that note! some methods can use 'this' object as the argument
*/ for example this code is correct:
class ReferenceError : public std::logic_error, ExceptionInfo UInt<2> foo(10);
{ foo.Add(foo);
public: but there are only few methods which can do that
*/
ReferenceError() : std::logic_error ("reference error") class ReferenceError : public std::logic_error, ExceptionInfo
{ {
} public:
ReferenceError(const char * f, int l) : ReferenceError() : std::logic_error ("reference error")
std::logic_error ("reference error"), ExceptionInfo(f,l) {
{ }
}
ReferenceError(const tchar_t * f, int l) :
std::string Where() const std::logic_error ("reference error"), ExceptionInfo(f,l)
{ {
return ExceptionInfo::Where(); }
}
}; tstr_t Where() const
{
return ExceptionInfo::Where();
/*! }
a small class used for reporting errors };
in the library is used macro TTMATH_ASSERT which
(if the condition in it is false) throw an exception /*!
of this type a small class used for reporting errors
if you compile with gcc you can get a small benefit in the library is used macro TTMATH_ASSERT which
from using method Where() (it returns std::string with (if the condition in it is false) throw an exception
the name and the line of a file where the macro TTMATH_ASSERT of this type
was used)
*/ if you compile with gcc you can get a small benefit
class RuntimeError : public std::runtime_error, ExceptionInfo from using method Where() (it returns tstr_t with
{ the name and the line of a file where the macro TTMATH_ASSERT
public: was used)
*/
RuntimeError() : std::runtime_error ("internal error") class RuntimeError : public std::runtime_error, ExceptionInfo
{ {
} public:
RuntimeError(const char * f, int l) : RuntimeError() : std::runtime_error ("internal error")
std::runtime_error ("internal error"), ExceptionInfo(f,l) {
{ }
}
RuntimeError(const tchar_t * f, int l) :
std::string Where() const std::runtime_error ("internal error"), ExceptionInfo(f,l)
{ {
return ExceptionInfo::Where(); }
}
}; tstr_t Where() const
{
return ExceptionInfo::Where();
}
/*! };
look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
*/
#ifdef TTMATH_DEBUG
/*!
#if defined(__FILE__) && defined(__LINE__) look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
*/
#define TTMATH_REFERENCE_ASSERT(expression) \ #ifdef TTMATH_DEBUG
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
#if defined(__FILE__) && defined(__LINE__)
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); #define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
#else
#define TTMATH_ASSERT(expression) \
#define TTMATH_REFERENCE_ASSERT(expression) \ if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
if( &(expression) == this ) throw ReferenceError();
#else
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw RuntimeError(); #define TTMATH_REFERENCE_ASSERT(expression) \
#endif if( &(expression) == this ) throw ReferenceError();
#else #define TTMATH_ASSERT(expression) \
#define TTMATH_REFERENCE_ASSERT(expression) if( !(expression) ) throw RuntimeError();
#define TTMATH_ASSERT(expression) #endif
#endif
#else
#define TTMATH_REFERENCE_ASSERT(expression)
#define TTMATH_ASSERT(expression)
#ifdef TTMATH_DEBUG_LOG #endif
#define TTMATH_LOG(msg) \
PrintLog(msg, std::cout);
#ifdef TTMATH_DEBUG_LOG
#else
#define TTMATH_LOG(msg) \
#define TTMATH_LOG(msg) PrintLog(msg, std::cout);
#endif #else
#define TTMATH_LOG(msg)
} // namespace
#endif
#endif
} // namespace
#endif

View File

@ -50,7 +50,9 @@
#include "ttmathtypes.h" #include "ttmathtypes.h"
#if defined(_MSC_VER)
#pragma warning(disable:4127) // conditional expression is constant
#endif
/*! /*!
\brief a namespace for the TTMath library \brief a namespace for the TTMath library
@ -84,7 +86,7 @@ public:
it prints the table in a nice form of several columns it prints the table in a nice form of several columns
*/ */
void PrintTable(std::ostream & output) const void PrintTable(tostrm_t & output) const
{ {
// how many columns there'll be // how many columns there'll be
const int columns = 8; const int columns = 8;
@ -118,7 +120,7 @@ public:
} }
void PrintLog(const char * msg, std::ostream & output) const void PrintLog(const tchar_t * msg, tostrm_t & output) const
{ {
output << msg << std::endl; output << msg << std::endl;
@ -1473,7 +1475,7 @@ private:
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor, bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
UInt<value_size> * remainder, UInt<value_size> * remainder,
uint table_id, uint index, uint table_id, uint index,
uint divisor_table_id, uint divisor_index ) uint /*divisor_table_id*/, uint divisor_index )
{ {
if( divisor_index > index ) if( divisor_index > index )
{ {
@ -1604,7 +1606,7 @@ private:
for(uint i = j+1 ; i<value_size ; ++i) for(uint i = j+1 ; i<value_size ; ++i)
q.table[i] = 0; q.table[i] = 0;
while( true ) for (;;)
{ {
u1 = table[j+n-1]; u1 = table[j+n-1];
u0 = table[j+n-2]; u0 = table[j+n-2];
@ -2005,7 +2007,7 @@ public:
/*! /*!
this method converts a digit into a char this method converts a digit into a tchar_t
digit should be from <0,F> digit should be from <0,F>
(we don't have to get a base) (we don't have to get a base)
@ -2141,7 +2143,7 @@ public:
this constant 10 has the int type (signed int), if we don't give such this constant 10 has the int type (signed int), if we don't give such
operators and constructors the compiler will not compile the program, operators and constructors the compiler will not compile the program,
because it has to make a conversion and doesn't know into which type because it has to make a conversion and doesn't know into which type
(the UInt class has operator=(const char*), operator=(uint) etc.) (the UInt class has operator=(const tchar_t*), operator=(uint) etc.)
*/ */
UInt<value_size> & operator=(sint i) UInt<value_size> & operator=(sint i)
{ {
@ -2256,18 +2258,18 @@ public:
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
UInt(const char * s) UInt(const tchar_t * s)
{ {
FromString(s); FromString(s);
TTMATH_LOG("UInt::UInt(const char *)") TTMATH_LOG("UInt::UInt(const tchar_t *)")
} }
/*! /*!
a constructor for converting a string to this class (with the base=10) a constructor for converting a string to this class (with the base=10)
*/ */
UInt(const std::string & s) UInt(const tstr_t & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
} }
@ -2332,10 +2334,10 @@ 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'
*/ */
void ToString(std::string & result, uint b = 10) const void ToString(tstr_t & result, uint b = 10) const
{ {
UInt<value_size> temp( *this ); UInt<value_size> temp( *this );
char character; tchar_t character;
uint rem; uint rem;
result.clear(); result.clear();
@ -2360,7 +2362,7 @@ public:
/* /*
this method's ommiting any white characters from the string this method's ommiting any white characters from the string
*/ */
static void SkipWhiteCharacters(const char * & c) static void SkipWhiteCharacters(const tchar_t * & c)
{ {
while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') )
++c; ++c;
@ -2384,7 +2386,7 @@ public:
value_read (if exists) tells whether something has actually been read (at least one digit) value_read (if exists) tells whether something has actually been read (at least one digit)
*/ */
uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0)
{ {
UInt<value_size> base( b ); UInt<value_size> base( b );
UInt<value_size> temp; UInt<value_size> temp;
@ -2434,7 +2436,7 @@ public:
(it returns carry=1 if the value will be too big or an incorrect base 'b' is given) (it returns carry=1 if the value will be too big or an incorrect base 'b' is given)
*/ */
uint FromString(const std::string & s, uint b = 10) uint FromString(const tstr_t & s, uint b = 10)
{ {
return FromString( s.c_str(), b ); return FromString( s.c_str(), b );
} }
@ -2444,11 +2446,11 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
UInt<value_size> & operator=(const char * s) UInt<value_size> & operator=(const tchar_t * s)
{ {
FromString(s); FromString(s);
TTMATH_LOG("UInt::operator=(const char *)") TTMATH_LOG("UInt::operator=(const tchar_t *)")
return *this; return *this;
} }
@ -2457,7 +2459,7 @@ public:
/*! /*!
this operator converts a string into its value (with base = 10) this operator converts a string into its value (with base = 10)
*/ */
UInt<value_size> & operator=(const std::string & s) UInt<value_size> & operator=(const tstr_t & s)
{ {
FromString( s.c_str() ); FromString( s.c_str() );
@ -2825,9 +2827,9 @@ public:
* *
*/ */
friend std::ostream & operator<<(std::ostream & s, const UInt<value_size> & l) friend tostrm_t & operator<<(tostrm_t & s, const UInt<value_size> & l)
{ {
std::string ss; tstr_t ss;
l.ToString(ss); l.ToString(ss);
s << ss; s << ss;
@ -2837,12 +2839,12 @@ public:
friend std::istream & operator>>(std::istream & s, UInt<value_size> & l) friend tistrm_t & operator>>(tistrm_t & s, UInt<value_size> & l)
{ {
std::string ss; tstr_t ss;
// char for operator>> // tchar_t for operator>>
unsigned char z; tchar_t z;
// operator>> omits white characters if they're set for ommiting // operator>> omits white characters if they're set for ommiting
s >> z; s >> z;
@ -2925,6 +2927,10 @@ public:
} //namespace } //namespace
#if defined(_MSC_VER)
#pragma warning(default:4127) // conditional expression is constant
#endif
#include "ttmathuint_x86.h" #include "ttmathuint_x86.h"
#include "ttmathuint_x86_64.h" #include "ttmathuint_x86_64.h"

View File

@ -41,9 +41,9 @@
#ifndef TTMATH_NOASM #ifndef TTMATH_NOASM
#pragma message("ASM code included")
#ifdef TTMATH_PLATFORM64 #ifdef TTMATH_PLATFORM64
/*! /*!
\file ttmathuint_x86_64.h \file ttmathuint_x86_64.h
\brief template class UInt<uint> with assembler code for 64bit x86_64 processors \brief template class UInt<uint> with assembler code for 64bit x86_64 processors
@ -55,6 +55,24 @@
namespace ttmath namespace ttmath
{ {
#if defined(_M_IX64)
#include <intrin.h>
extern "C"
{
uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit);
uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
};
#endif
/*! /*!
* *
* basic mathematic functions * basic mathematic functions
@ -78,16 +96,20 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
const uint * p2 = ss2.table; const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = adc_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
/* /*
this part should be compiled with gcc this part should be compiled with gcc
*/ */
@ -145,15 +167,19 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = addindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
@ -223,15 +249,20 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size - 1 ) TTMATH_ASSERT( index < value_size - 1 )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = addindexed2_x64(p1,b,index,x2,x1);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"subq %%rdx, %%rcx \n" "subq %%rdx, %%rcx \n"
@ -284,16 +315,21 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
const uint * p2 = ss2.table; const uint * p2 = ss2.table;
uint dummy, dummy2;
// we don't have to use TTMATH_REFERENCE_ASSERT here // we don't have to use TTMATH_REFERENCE_ASSERT here
// this algorithm doesn't require it // this algorithm doesn't require it
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = sbb_x64(p1,p2,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" "xorq %%rdx, %%rdx \n"
@ -347,15 +383,20 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint c; uint c;
uint dummy, dummy2;
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = subindexed_x64(p1,b,index,value);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"subq %%rdx, %%rcx \n" "subq %%rdx, %%rcx \n"
@ -404,13 +445,18 @@ namespace ttmath
{ {
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = rcl_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2;
__asm__ __volatile__( __asm__ __volatile__(
"xorq %%rdx, %%rdx \n" // rdx=0 "xorq %%rdx, %%rdx \n" // rdx=0
@ -456,13 +502,18 @@ namespace ttmath
{ {
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = rcr_x64(p1,b,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy;
__asm__ __volatile__( __asm__ __volatile__(
"neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
@ -509,13 +560,18 @@ namespace ttmath
uint b = value_size; uint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = rcl2_x64(p1,b,bits,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__( __asm__ __volatile__(
"movq %%rcx, %%rsi \n" "movq %%rcx, %%rsi \n"
@ -580,14 +636,19 @@ namespace ttmath
sint b = value_size; sint b = value_size;
uint * p1 = table; uint * p1 = table;
uint dummy, dummy2, dummy3;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_M_IX64)
c = rcr2_x64(p1,b,bits,c);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
uint dummy, dummy2, dummy3;
__asm__ __volatile__( __asm__ __volatile__(
"movq %%rcx, %%rsi \n" "movq %%rcx, %%rsi \n"
@ -646,7 +707,16 @@ namespace ttmath
register sint result; register sint result;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_MSC_VER)
unsigned long nIndex(0);
if (_BitScanReverse64(&nIndex,x) == 0)
result = -1;
else
result = nIndex;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@ -691,7 +761,11 @@ namespace ttmath
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_MSC_VER)
old_bit = _bittestandset((long*)&value,bit) != 0;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@ -747,7 +821,11 @@ namespace ttmath
register uint result2_; register uint result2_;
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_MSC_VER)
result1_ = _umul128(a,b,&result2_);
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@ -804,7 +882,13 @@ namespace ttmath
TTMATH_ASSERT( c != 0 ) TTMATH_ASSERT( c != 0 )
#ifndef __GNUC__ #ifndef __GNUC__
#error "another compiler than GCC is currently not supported in 64bit mode" #if defined(_MSC_VER)
div_x64(&a,&b,c);
r_ = a;
rest_ = b;
#else
#error "another compiler than GCC is currently not supported in 64bit mode"
#endif
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__

View File

@ -0,0 +1,358 @@
PUBLIC adc_x64
PUBLIC addindexed_x64
PUBLIC addindexed2_x64
PUBLIC sbb_x64
PUBLIC subindexed_x64
PUBLIC rcl_x64
PUBLIC rcr_x64
PUBLIC rcl2_x64
PUBLIC rcr2_x64
public div_x64
;
; "rax, rcx, rdx, r8-r11 are volatile."
; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile."
;
.CODE
ALIGN 8
;----------------------------------------
adc_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nSize
; r9 = nCarry
xor rax, rax
mov r11, 0
sub rax, r9 ; sets CARRY if r9 != 0
loop1:
mov rax,qword ptr [rdx + r11 * 8]
adc qword ptr [rcx + r11 * 8], rax
inc r11
dec r8
jnz loop1
setc al
movzx rax, al
ret
adc_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
addindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
sub rdx, r8 ; rdx = remaining count of uints
loop1:
add qword ptr [rcx + r8 * 8], r9
jnc done
inc r8
mov r9, 1
dec rdx
jnz loop1
done:
setc al
movzx rax, al
ret
addindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
addindexed2_x64 PROC
; rcx = p1
; rdx = b
; r8 = nPos
; r9 = nValue1
; [esp+0x28] = nValue2
mov r11, rcx ; table
sub rdx, r8 ; rdx = remaining count of uints
mov r10, [esp+028h] ; r10 = nValue2
add qword ptr [r11 + r8 * 8], r10
inc r8
loop1:
adc qword ptr [r11 + r8 * 8], r9
jnc done
inc r8
mov r9, 0 ; set to 0 -> cy still set!
dec rdx
jnz loop1
done:
setc al
movzx rax, al
ret
addindexed2_x64 ENDP
;----------------------------------------
ALIGN 8
ALIGN 8
;----------------------------------------
sbb_x64 PROC
; rcx = p1
; rdx = p2
; r8 = nCount
; r9 = nCarry
xor rax, rax
mov r11, 0
sub rax, r9 ; sets CARRY if r9 != 0
loop1:
mov rax,qword ptr [rdx + r11 * 8]
sbb qword ptr [rcx + r11 * 8], rax
inc r11
dec r8
jnz loop1
setc al
movzx rax, al
ret
sbb_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
subindexed_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nPos
; r9 = nValue
sub rdx, r8 ; rdx = remaining count of uints
loop1:
sub qword ptr [rcx + r8 * 8], r9
jnc done
inc r8
mov r9, 1
dec rdx
jnz loop1
done:
setc al
movzx rax, al
ret
subindexed_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcl_x64 PROC
; rcx = p1
; rdx = b
; r8 = nLowestBit
mov r11, rcx ; table
xor r10, r10
neg r8 ; CY set if r8 <> 0
loop1:
rcl qword ptr [r11 + r10 * 8], 1
inc r10
dec rdx
jnz loop1
setc al
movzx rax, al
ret
rcl_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcr_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = nLowestBit
xor r10, r10
neg r8 ; CY set if r8 <> 0
loop1:
rcr qword ptr -8[rcx + rdx * 8], 1
dec rdx
jnz loop1
setc al
movzx rax, al
ret
rcr_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
div_x64 PROC
; rcx = &Hi
; rdx = &Lo
; r8 = nDiv
mov r11, rcx
mov r10, rdx
mov rdx, qword ptr [r11]
mov rax, qword ptr [r10]
div r8
mov qword ptr [r10], rdx ; remainder
mov qword ptr [r11], rax ; value
ret
div_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcl2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shr r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rax ; r9 = index (0..nSize-1)
loop1:
rol qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
inc r9
dec rdx
jnz loop1
and rax, 1
ret
rcl2_x64 ENDP
;----------------------------------------
ALIGN 8
;----------------------------------------
rcr2_x64 PROC
; rcx = p1
; rdx = nSize
; r8 = bits
; r9 = c
mov r10, rcx ; r10 = p1
xor rax, rax
mov rcx, 64
sub rcx, r8
mov r11, -1
shl r11, cl ; r11 = mask
mov rcx, r8 ; rcx = count of bits
mov rbx, rax ; rbx = old value = 0
or r9, r9
cmovnz rbx, r11 ; if (c) then old value = mask
mov r9, rdx ; r9 = index (0..nSize-1)
dec r9
loop1:
ror qword ptr [r10+r9*8], cl
mov rax, qword ptr [r10+r9*8]
and rax, r11
xor qword ptr [r10+r9*8], rax
or qword ptr [r10+r9*8], rbx
mov rbx, rax
dec r9
dec rdx
jnz loop1
rol rax, 1
and rax, 1
ret
rcr2_x64 ENDP
END