From c91bd24e985086ac56fe056ec3ef60bcae543902 Mon Sep 17 00:00:00 2001 From: Christian Kaiser Date: Wed, 6 May 2009 15:11:29 +0000 Subject: [PATCH] - 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 --- ttmath/ttmath.h | 1 + ttmath/ttmathbig.h | 133 ++-- ttmath/ttmathconfig.h | 70 +++ ttmath/ttmathint.h | 40 +- ttmath/ttmathobjects.h | 28 +- ttmath/ttmathparser.h | 100 +-- ttmath/ttmathtypes.h | 898 ++++++++++++++------------- ttmath/ttmathuint.h | 54 +- ttmath/ttmathuint_x86_64.h | 130 +++- ttmath/ttmathuint_x86_amd64_msvc.asm | 358 +++++++++++ 10 files changed, 1177 insertions(+), 635 deletions(-) create mode 100644 ttmath/ttmathconfig.h create mode 100644 ttmath/ttmathuint_x86_amd64_msvc.asm diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index d73e813..bec013a 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -45,6 +45,7 @@ \brief Mathematics functions. */ +#include "ttmathconfig.h" #include "ttmathbig.h" #include "ttmathobjects.h" diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index b99bd8b..be385b7 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -47,6 +47,10 @@ #include +#if defined(_MSC_VER) + #pragma warning(disable:4127) // conditional expression is constant +#endif + namespace ttmath { @@ -79,9 +83,9 @@ class Big public: -Int exponent; -UInt mantissa; -unsigned char info; +Int exponent; +UInt mantissa; +tchar_t info; /*! @@ -237,7 +241,7 @@ private: // 3101 digits were taken from this website // (later the digits were compared with: // 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 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // and on 64bit platform value 128 (256/2=128)) @@ -655,9 +659,7 @@ public: // there shouldn't be a carry here because // (1) (2) guarantee that the mantissa of this // is greater than or equal to the mantissa of the ss2 - uint c_temp = mantissa.Sub(ss2.mantissa); - - TTMATH_ASSERT( c_temp == 0 ) + TTMATH_ASSERT( mantissa.Sub(ss2.mantissa) == 0 ) } c += Standardizing(); @@ -2037,7 +2039,7 @@ public: // then V=(-1)**S * 2 ** (-1022) * (0.F) // These are "unnormalized" values. - FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul), + FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0, e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m); Standardizing(); } @@ -2540,18 +2542,18 @@ public: output: 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 */ - uint ToString( std::string & result, + uint ToString( tstr_t & result, uint base = 10, bool always_scientific = false, sint when_scientific = 15, sint max_digit_after_comma = -1, bool remove_trailing_zeroes = true, - char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const - { - static char error_overflow_msg[] = "overflow"; + tchar_t decimal_point = TTMATH_COMMA_CHARACTER_1 ) const + { + static tchar_t error_overflow_msg[] = TTMATH_TEXT("overflow"); result.erase(); if(base<2 || base>16) @@ -2562,7 +2564,7 @@ public: if( IsZero() ) { - result = "0"; + result = TTMATH_TEXT("0"); return 0; } @@ -2687,7 +2689,7 @@ private: but we need 'new'exp' as integer then we take: 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 & new_exp) const { uint c = 0; @@ -2870,7 +2872,7 @@ private: (we can make that speciality when the base is 4,8 or 16 as well but maybe in further time) */ - uint ToString_CreateNewMantissaAndExponent_Base2( std::string & new_man, + uint ToString_CreateNewMantissaAndExponent_Base2( tstr_t & new_man, Int & new_exp ) const { for( sint i=man-1 ; i>=0 ; --i ) @@ -2900,13 +2902,13 @@ private: this method roundes the last character from the new mantissa (it's used in systems where the base is different from 2) */ - uint ToString_RoundMantissa(std::string & new_man, uint base, Int & new_exp, char decimal_point) const + uint ToString_RoundMantissa(tstr_t & new_man, uint base, Int & new_exp, tchar_t decimal_point) const { // we must have minimum two characters if( new_man.length() < 2 ) 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 uint digit = UInt::CharToDigit( new_man[i] ); @@ -2927,7 +2929,7 @@ private: 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() ) return; @@ -2965,13 +2967,13 @@ private: this method sets the comma operator and/or puts the exponent into the string */ - uint ToString_SetCommaAndExponent( std::string & new_man, uint base, + uint ToString_SetCommaAndExponent( tstr_t & new_man, uint base, Int & new_exp, bool always_scientific, sint when_scientific, sint max_digit_after_comma, bool remove_trailing_zeroes, - char decimal_point) const + tchar_t decimal_point) const { uint carry = 0; @@ -3011,12 +3013,12 @@ private: an auxiliary method for converting into the string */ void ToString_SetCommaAndExponent_Normal( - std::string & new_man, + tstr_t & new_man, uint base, Int & new_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - char decimal_point) const + tchar_t decimal_point) const { if( !new_exp.IsSign() ) //if( new_exp >= 0 ) return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); @@ -3028,7 +3030,7 @@ private: /*! 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 & new_exp) const { // we're adding zero characters at the end @@ -3048,12 +3050,12 @@ private: an auxiliary method for converting into the string */ void ToString_SetCommaAndExponent_Normal_SetCommaInside( - std::string & new_man, + tstr_t & new_man, uint base, Int & new_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - char decimal_point) const + tchar_t decimal_point) const { // new_exp is < 0 @@ -3072,7 +3074,7 @@ private: // we're adding zero characters before the mantissa 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); new_man.insert(0, man_temp); @@ -3085,12 +3087,12 @@ private: /*! 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, Int & scientific_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - char decimal_point) const + tchar_t decimal_point) const { if( new_man.empty() ) return; @@ -3104,16 +3106,16 @@ private: new_man += 'e'; if( !scientific_exp.IsSign() ) - new_man += "+"; + new_man += TTMATH_TEXT("+"); } else { // the 10 here is meant as the base 'base' // (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 ); new_man += temp_exp; @@ -3123,11 +3125,11 @@ private: /*! an auxiliary method for converting into the string */ - void ToString_CorrectDigitsAfterComma( std::string & new_man, + void ToString_CorrectDigitsAfterComma( tstr_t & new_man, uint base, sint max_digit_after_comma, bool remove_trailing_zeroes, - char decimal_point) const + tchar_t decimal_point) const { if( max_digit_after_comma >= 0 ) 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 */ void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( - std::string & new_man, - char decimal_point) const + tstr_t & new_man, + tchar_t decimal_point) const { // minimum two characters if( new_man.length() < 2 ) @@ -3160,7 +3162,7 @@ private: // we must have a comma // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round // 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; // if directly before the first zero is the comma operator @@ -3176,26 +3178,26 @@ private: an auxiliary method for converting into the string */ void ToString_CorrectDigitsAfterComma_Round( - std::string & new_man, + tstr_t & new_man, uint base, sint max_digit_after_comma, - char decimal_point) const + tchar_t decimal_point) const { // 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) return; // 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 // 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) // 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; uint last_digit = UInt::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base ); @@ -3241,7 +3243,7 @@ public: no value has been read (there are no digits) on other words if 'value_read' is true -- there is at least one digit in the string */ - uint FromString(const char * source, uint base = 10, const char ** after_source = 0, 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 value_read_temp = false; @@ -3290,7 +3292,7 @@ private: (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::SkipWhiteCharacters(source); @@ -3312,7 +3314,7 @@ private: /*! 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) || (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) @@ -3330,7 +3332,7 @@ private: this method reads the first part of a string (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; Big temp; @@ -3359,7 +3361,7 @@ private: this method reads the second part of a string (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; uint c = 0, index = 1; @@ -3417,12 +3419,12 @@ private: 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; bool scientific_read = false; - const char * before_scientific = source; + const tchar_t * before_scientific = source; if( FromString_TestScientific(source) ) c += FromString_ReadPartScientific( source, scientific_read ); @@ -3440,7 +3442,7 @@ private: 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::SkipWhiteCharacters(source); @@ -3459,7 +3461,7 @@ private: 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 */ - uint FromString_ReadPartScientific( const char * & source, bool & scientific_read ) + uint FromString_ReadPartScientific( const tchar_t * & source, bool & scientific_read ) { uint c = 0; Big new_exponent, temp; @@ -3486,7 +3488,7 @@ private: this method reads the value of the extra exponent when scientific format is used (only when base == 10) */ - uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big & new_exponent, bool & scientific_read ) + uint FromString_ReadPartScientific_ReadExponent( const tchar_t * & source, Big & new_exponent, bool & scientific_read ) { sint character; Big base, temp; @@ -3519,7 +3521,7 @@ public: /*! 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 ); } @@ -3528,7 +3530,7 @@ public: /*! a constructor for converting a string into this class */ - Big(const char * string) + Big(const tchar_t * string) { FromString( string ); } @@ -3537,7 +3539,7 @@ public: /*! a constructor for converting a string into this class */ - Big(const std::string & string) + Big(const tstr_t & string) { FromString( string.c_str() ); } @@ -3546,7 +3548,7 @@ public: /*! an operator= for converting a string into its value */ - Big & operator=(const char * string) + Big & operator=(const tchar_t * string) { FromString( string ); @@ -3557,7 +3559,7 @@ public: /*! an operator= for converting a string into its value */ - Big & operator=(const std::string & string) + Big & operator=(const tstr_t & string) { FromString( string.c_str() ); @@ -3964,9 +3966,9 @@ public: * */ - friend std::ostream & operator<<(std::ostream & s, const Big & l) + friend tostrm_t & operator<<(tostrm_t & s, const Big & l) { - std::string ss; + tstr_t ss; l.ToString(ss); s << ss; @@ -3975,12 +3977,12 @@ public: } - friend std::istream & operator>>(std::istream & s, Big & l) + friend tistrm_t & operator>>(tistrm_t & s, Big & l) { - std::string ss; + tstr_t ss; - // 'char' for operator>> - unsigned char z; + // 'tchar_t' for operator>> + unsigned tchar_t z; bool was_comma = false; // 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 diff --git a/ttmath/ttmathconfig.h b/ttmath/ttmathconfig.h new file mode 100644 index 0000000..d6c3c62 --- /dev/null +++ b/ttmath/ttmathconfig.h @@ -0,0 +1,70 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the PNG licence. + * Author: Christian Kaiser + */ + +/* + 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 + +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 diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index b5c5f97..1f86498 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -47,6 +47,10 @@ #include "ttmathuint.h" +#if defined(_MSC_VER) + #pragma warning(disable:4127) // conditional expression is constant +#endif + namespace ttmath { @@ -641,8 +645,14 @@ public: // there can be a carry here when the size of this value is equal one word // and the 'value' has the highest bit set + #if defined(_MSC_VER) + #pragma warning(disable:4127) // conditional expression is constant + #endif if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) return 1; + #if defined(_MSC_VER) + #pragma warning(default:4127) // conditional expression is constant + #endif return 0; } @@ -821,7 +831,7 @@ public: /*! a constructor for converting string to this class (with the base=10) */ - Int(const char * s) + Int(const tchar_t * s) { FromString(s); } @@ -830,7 +840,7 @@ public: /*! a constructor for converting a string to this class (with the base=10) */ - Int(const std::string & s) + Int(const tstr_t & s) { FromString( s.c_str() ); } @@ -869,7 +879,7 @@ public: /*! this method converts the value to a string with a base equal 'b' */ - void ToString(std::string & result, uint b = 10) const + void ToString(tstr_t & result, uint b = 10) const { if( IsSign() ) { @@ -904,7 +914,7 @@ public: value_read (if exists) tells whether something has actually been read (at least one digit) */ - uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0) { bool is_sign = false; @@ -961,7 +971,7 @@ public: this method converts a string into its value it returns carry=1 if the value will be too big or an incorrect base 'b' is given */ - uint FromString(const std::string & s, uint b = 10) + uint FromString(const tstr_t & s, uint b = 10) { return FromString( s.c_str() ); } @@ -970,7 +980,7 @@ public: /*! this operator converts a string into its value (with base = 10) */ - Int & operator=(const char * s) + Int & operator=(const tchar_t * s) { FromString(s); @@ -981,7 +991,7 @@ public: /*! this operator converts a string into its value (with base = 10) */ - Int & operator=(const std::string & s) + Int & operator=(const tstr_t & s) { FromString( s.c_str() ); @@ -1268,9 +1278,9 @@ public: * */ - friend std::ostream & operator<<(std::ostream & s, const Int & l) + friend tostrm_t & operator<<(tostrm_t & s, const Int & l) { - std::string ss; + tstr_t ss; l.ToString(ss); s << ss; @@ -1280,12 +1290,12 @@ public: - friend std::istream & operator>>(std::istream & s, Int & l) + friend tistrm_t & operator>>(tistrm_t & s, Int & l) { - std::string ss; + tstr_t ss; - // char for operator>> - unsigned char z; + // tchar_t for operator>> + unsigned tchar_t z; // operator>> omits white characters if they're set for ommiting s >> z; @@ -1316,5 +1326,9 @@ public: } // namespace +#if defined(_MSC_VER) + #pragma warning(default:4127) // conditional expression is constant +#endif + #endif diff --git a/ttmath/ttmathobjects.h b/ttmath/ttmathobjects.h index 52acf9c..2dcdfad 100644 --- a/ttmath/ttmathobjects.h +++ b/ttmath/ttmathobjects.h @@ -73,18 +73,18 @@ public: struct Item { // name of a variable of a function - std::string value; + tstr_t value; // number of parameters required by the function // (if there's a variable this 'param' is ignored) int param; Item() {} - Item(const std::string & v, int p) : value(v), param(p) {} + Item(const tstr_t & v, int p) : value(v), param(p) {} }; // 'Table' is the type of our table - typedef std::map Table; + typedef std::map Table; typedef Table::iterator Iterator; 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 */ - static bool IsNameCorrect(const std::string & name) + static bool IsNameCorrect(const tstr_t & name) { if( name.empty() ) return false; @@ -120,7 +120,7 @@ public: if( !CorrectCharacter(name[0], false) ) return false; - std::string::const_iterator i=name.begin(); + tstr_t::const_iterator i=name.begin(); for(++i ; i!=name.end() ; ++i) if( !CorrectCharacter(*i, true) ) @@ -133,7 +133,7 @@ public: /*! 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); @@ -148,7 +148,7 @@ public: /*! this method adds one object (variable of function) into the table */ - ErrorCode Add(const std::string & name, const std::string & value, int param = 0) + ErrorCode Add(const tstr_t & name, const tstr_t & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -205,7 +205,7 @@ public: /*! this method changes the value and the number of parameters for a specific object */ - ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) + ErrorCode EditValue(const tstr_t & name, const tstr_t & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -225,7 +225,7 @@ public: /*! this method changes the name of a specific object */ - ErrorCode EditName(const std::string & old_name, const std::string & new_name) + ErrorCode EditName(const tstr_t & old_name, const tstr_t & new_name) { if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) return err_incorrect_name; @@ -256,7 +256,7 @@ public: /*! this method deletes an object */ - ErrorCode Delete(const std::string & name) + ErrorCode Delete(const tstr_t & name) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -275,7 +275,7 @@ public: /*! 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) ) return err_incorrect_name; @@ -298,7 +298,7 @@ public: this method gets the value of a specific object (this version is used for not copying the whole string) */ - ErrorCode GetValue(const std::string & name, const char ** value) const + ErrorCode GetValue(const tstr_t & name, const tchar_t ** value) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -321,7 +321,7 @@ public: this method gets the value and the number of parameters of a specific object */ - ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const + ErrorCode GetValueAndParam(const tstr_t & name, tstr_t & value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -347,7 +347,7 @@ public: of a specific object (this version is used for not copying the whole string) */ - ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const + ErrorCode GetValueAndParam(const tstr_t & name, const tchar_t ** value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index ac52542..e7505bf 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -256,7 +256,7 @@ public: bool function; // if function is true - std::string function_name; + tstr_t function_name; /* 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 */ -const char * pstring; +const tchar_t * pstring; /*! @@ -351,7 +351,7 @@ const Objects * puser_variables; const Objects * puser_functions; -typedef std::map FunctionLocalVariables; +typedef std::map FunctionLocalVariables; /*! a pointer to the local variables of a function @@ -362,13 +362,13 @@ const FunctionLocalVariables * pfunction_local_variables; /*! a temporary set using during parsing user defined variables */ -std::set visited_variables; +std::set visited_variables; /*! a temporary set using during parsing user defined functions */ -std::set visited_functions; +std::set visited_functions; @@ -396,10 +396,10 @@ typedef void (ValueType::*pfunction_var)(); table of mathematic functions this map consists of: - std::string - function's name + tstr_t - function's name pfunction - pointer to specific function */ -typedef std::map FunctionsTable; +typedef std::map FunctionsTable; FunctionsTable functions_table; @@ -407,10 +407,10 @@ FunctionsTable functions_table; table of mathematic operators this map consists of: - std::string - operators's name + tstr_t - operators's name MatOperator::Type - type of the operator */ -typedef std::map OperatorsTable; +typedef std::map OperatorsTable; OperatorsTable operators_table; @@ -418,10 +418,10 @@ OperatorsTable operators_table; table of mathematic variables 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 */ -typedef std::map VariablesTable; +typedef std::map VariablesTable; VariablesTable variables_table; @@ -456,7 +456,7 @@ void SkipWhiteCharacters() /*! 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 ) { @@ -474,7 +474,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ -void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) +void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tstr_t & name) { if( variable ) visited_variables.insert( name ); @@ -486,7 +486,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::stri /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ -void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) +void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tstr_t & name) { if( variable ) 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' 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_AddName(variable, name); @@ -548,12 +548,12 @@ public: /*! this method returns the user-defined value of a variable */ -bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) +bool GetValueOfUserDefinedVariable(const tstr_t & variable_name,ValueType & result) { if( !puser_variables ) return false; - const char * string_value; + const tchar_t * string_value; if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) return false; @@ -567,7 +567,7 @@ return true; /*! this method returns the value of a local variable of a function */ -bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) +bool GetValueOfFunctionLocalVariable(const tstr_t & variable_name, ValueType & result) { if( !pfunction_local_variables ) return false; @@ -589,7 +589,7 @@ return true; we make an object of type ValueType then call a method which sets the correct value in it and finally we'll return the object */ -ValueType GetValueOfVariable(const std::string & variable_name) +ValueType GetValueOfVariable(const tstr_t & variable_name) { ValueType result; @@ -600,7 +600,7 @@ ValueType result; return result; - typename std::map::iterator i = + typename std::map::iterator i = variables_table.find(variable_name); 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(...)') */ -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 ) return false; - const char * string_value; + const tchar_t * string_value; int param; if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok ) @@ -1357,7 +1357,7 @@ bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount if( amount_of_args > 0 ) { - char buffer[20]; + tchar_t buffer[20]; // x = x1 sprintf(buffer,"x"); @@ -1389,7 +1389,7 @@ return true; result will be stored in 'stack[sindex-1].value' (we don't have to set the correct type of this element, it'll be set later) */ -void CallFunction(const std::string & function_name, int amount_of_args, int sindex) +void CallFunction(const tstr_t & function_name, int amount_of_args, int sindex) { if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) return; @@ -1415,9 +1415,9 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin function_name - name of the function pf - pointer to the function (to the wrapper) */ -void InsertFunctionToTable(const char * function_name, pfunction pf) +void InsertFunctionToTable(const 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 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 a '(' character after a name that function returns 'true' */ -bool ReadName(std::string & result) +bool ReadName(tstr_t & result) { int character; @@ -1610,7 +1610,7 @@ return false; */ bool ReadVariableOrFunction(Item & result) { -std::string name; +tstr_t name; bool is_it_name_of_function = ReadName(name); if( is_it_name_of_function ) @@ -1639,7 +1639,7 @@ return is_it_name_of_function; */ void ReadValue(Item & result, int reading_base) { -const char * new_stack_pointer; +const tchar_t * new_stack_pointer; bool 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) ); } @@ -1823,19 +1823,19 @@ void InsertOperatorToTable(const std::string & name, typename MatOperator::Type */ void CreateMathematicalOperatorsTable() { - InsertOperatorToTable(std::string("||"), MatOperator::lor); - InsertOperatorToTable(std::string("&&"), MatOperator::land); - InsertOperatorToTable(std::string("!="), MatOperator::neq); - InsertOperatorToTable(std::string("=="), MatOperator::eq); - InsertOperatorToTable(std::string(">="), MatOperator::get); - InsertOperatorToTable(std::string("<="), MatOperator::let); - InsertOperatorToTable(std::string(">"), MatOperator::gt); - InsertOperatorToTable(std::string("<"), MatOperator::lt); - InsertOperatorToTable(std::string("-"), MatOperator::sub); - InsertOperatorToTable(std::string("+"), MatOperator::add); - InsertOperatorToTable(std::string("/"), MatOperator::div); - InsertOperatorToTable(std::string("*"), MatOperator::mul); - InsertOperatorToTable(std::string("^"), MatOperator::pow); + InsertOperatorToTable(tstr_t("||"), MatOperator::lor); + InsertOperatorToTable(tstr_t("&&"), MatOperator::land); + InsertOperatorToTable(tstr_t("!="), MatOperator::neq); + InsertOperatorToTable(tstr_t("=="), MatOperator::eq); + InsertOperatorToTable(tstr_t(">="), MatOperator::get); + InsertOperatorToTable(tstr_t("<="), MatOperator::let); + InsertOperatorToTable(tstr_t(">"), MatOperator::gt); + InsertOperatorToTable(tstr_t("<"), MatOperator::lt); + InsertOperatorToTable(tstr_t("-"), MatOperator::sub); + InsertOperatorToTable(tstr_t("+"), MatOperator::add); + InsertOperatorToTable(tstr_t("/"), MatOperator::div); + InsertOperatorToTable(tstr_t("*"), MatOperator::mul); + InsertOperatorToTable(tstr_t("^"), MatOperator::pow); } @@ -1845,12 +1845,12 @@ void CreateMathematicalOperatorsTable() e.g. true when str1="test" and str2="te" */ -bool IsSubstring(const std::string & str1, const std::string & str2) +bool IsSubstring(const tstr_t & str1, const tstr_t & str2) { if( str2.length() > str1.length() ) return false; - for(std::string::size_type i=0 ; i - */ - -/* - * Copyright (c) 2006-2009, Tomasz Sowa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name Tomasz Sowa nor the names of contributors to this - * project may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef headerfilettmathtypes -#define headerfilettmathtypes - -/*! - \file ttmathtypes.h - \brief constants used in the library - - As our library is written in header files (templates) we cannot use - constants like 'const int' etc. because we should have some source files - *.cpp to define this variables. Only what we can have are constants - defined by #define preprocessor macros. - - All macros are preceded by TTMATH_ prefix -*/ - - -#include -#include - - -/*! - the version of the library - - TTMATH_PRERELEASE_VER is either zero or one - if zero that means this is the release version of the library -*/ -#define TTMATH_MAJOR_VER 0 -#define TTMATH_MINOR_VER 8 -#define TTMATH_REVISION_VER 4 -#define TTMATH_PRERELEASE_VER 1 - - -/*! - TTMATH_DEBUG - this macro enables further testing during writing your code - you don't have to define it in a release mode - - 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 - is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) - - 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 - gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp - 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 -*/ -#ifndef TTMATH_RELEASE - #define TTMATH_DEBUG -#endif - - - -namespace ttmath -{ - -#if !defined _M_X64 && !defined __x86_64__ - - /*! - we're using a 32bit platform - */ - #define TTMATH_PLATFORM32 - -#else - - /*! - we're using a 64bit platform - */ - #define TTMATH_PLATFORM64 - -#endif - - - -#ifdef TTMATH_PLATFORM32 - - /*! - on 32bit platforms one word (uint, sint) will be equal 32bits - */ - typedef unsigned int uint; - typedef signed int sint; - - - /*! - this type is twice bigger than uint - (64bit on a 32bit platforms) - - although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long) - but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it - - this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined - */ - typedef unsigned long long int ulint; - - /*! - how many bits there are in the uint type - */ - #define TTMATH_BITS_PER_UINT 32u - - /*! - the mask for the highest bit in the unsigned 32bit word (2^31) - */ - #define TTMATH_UINT_HIGHEST_BIT 2147483648u - - /*! - the max value of the unsigned 32bit word (2^32 - 1) - (all bits equal one) - */ - #define TTMATH_UINT_MAX_VALUE 4294967295u - - /*! - the number of words (32bit words on 32bit platform) - which are kept in built-in variables for a Big<> type - (these variables are defined in ttmathbig.h) - */ - #define TTMATH_BUILTIN_VARIABLES_SIZE 256u - -#else - - /*! - on 64bit platforms one word (uint, sint) will be equal 64bits - */ - typedef unsigned long uint; - typedef signed long sint; - - /*! - on 64bit platform we do not define ulint - sizeof(long long) is 8 (64bit) but we need 128bit - - on 64 bit platform (when there is defined TTMATH_NOASM macro) - methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit - */ - //typedef unsigned long long int ulint; - - /*! - how many bits there are in the uint type - */ - #define TTMATH_BITS_PER_UINT 64ul - - /*! - the mask for the highest bit in the unsigned 64bit word (2^63) - */ - #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul - - /*! - the max value of the unsigned 64bit word (2^64 - 1) - (all bits equal one) - */ - #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul - - /*! - the number of words (64bit words on 64bit platforms) - which are kept in built-in variables for a Big<> type - (these variables are defined in ttmathbig.h) - */ - #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul - -#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 - - if you don't want it just put 0 there e.g. - #define TTMATH_COMMA_CHARACTER_2 0 - then only TTMATH_COMMA_CHARACTER_1 will be used - - 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. - - note! there'll not be so many iterations, iterations are stopped when - 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 - */ - enum ErrorCode - { - err_ok = 0, - err_nothing_has_read, - err_unknown_character, - err_unexpected_final_bracket, - err_stack_not_clear, - err_unknown_variable, - err_division_by_zero, - err_interrupt, - err_overflow, - err_unknown_function, - err_unknown_operator, - err_unexpected_semicolon_operator, - err_improper_amount_of_arguments, - err_improper_argument, - err_unexpected_end, - err_internal_error, - err_incorrect_name, - err_incorrect_value, - err_variable_exists, - err_variable_loop, - err_functions_loop, - err_must_be_only_one_value, - 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 - the 'stop object', if the method WasStopSignal() of this - object returns true that means we should break the calculating - and return - */ - 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 - */ - class ExceptionInfo - { - const char * file; - int line; - - public: - ExceptionInfo() : file(0), line(0) {} - ExceptionInfo(const char * f, int l) : file(f), line(l) {} - - std::string Where() const - { - if( !file ) - return "unknown"; - - std::ostringstream result; - result << file << ":" << 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 - - If you compile with gcc you can get a small benefit - from using method Where() (it returns std::string with - the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT - was used) - - What is the 'reference' error? - Some kind of methods use a reference as their argument to another object, - and the another object not always can be the same which is calling, e.g. - Big<1,2> foo(10); - foo.Mul(foo); // this is incorrect - above method Mul is making something more with 'this' object and - 'this' cannot be passed as the argument because the result will be undefined - - macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem - - note! some methods can use 'this' object as the argument - for example this code is correct: - UInt<2> foo(10); - foo.Add(foo); - but there are only few methods which can do that - */ - class ReferenceError : public std::logic_error, ExceptionInfo - { - public: - - ReferenceError() : std::logic_error ("reference error") - { - } - - ReferenceError(const char * f, int l) : - std::logic_error ("reference error"), ExceptionInfo(f,l) - { - } - - std::string 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 - - if you compile with gcc you can get a small benefit - from using method Where() (it returns std::string with - the name and the line of a file where the macro TTMATH_ASSERT - was used) - */ - class RuntimeError : public std::runtime_error, ExceptionInfo - { - public: - - RuntimeError() : std::runtime_error ("internal error") - { - } - - RuntimeError(const char * f, int l) : - std::runtime_error ("internal error"), ExceptionInfo(f,l) - { - } - - std::string Where() const - { - return ExceptionInfo::Where(); - } - }; - - - - /*! - look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG - */ - #ifdef TTMATH_DEBUG - - #if defined(__FILE__) && defined(__LINE__) - - #define TTMATH_REFERENCE_ASSERT(expression) \ - if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); - - #define TTMATH_ASSERT(expression) \ - if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); - - #else - - #define TTMATH_REFERENCE_ASSERT(expression) \ - if( &(expression) == this ) throw ReferenceError(); - - #define TTMATH_ASSERT(expression) \ - if( !(expression) ) throw RuntimeError(); - #endif - - #else - #define TTMATH_REFERENCE_ASSERT(expression) - #define TTMATH_ASSERT(expression) - #endif - - - - #ifdef TTMATH_DEBUG_LOG - - #define TTMATH_LOG(msg) \ - PrintLog(msg, std::cout); - - #else - - #define TTMATH_LOG(msg) - - #endif - - -} // namespace - - -#endif +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2006-2009, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef headerfilettmathtypes +#define headerfilettmathtypes + +/*! + \file ttmathtypes.h + \brief constants used in the library + + As our library is written in header files (templates) we cannot use + constants like 'const int' etc. because we should have some source files + *.cpp to define this variables. Only what we can have are constants + defined by #define preprocessor macros. + + All macros are preceded by TTMATH_ prefix +*/ + + +#include +#include + + +/*! + the version of the library + + TTMATH_PRERELEASE_VER is either zero or one + if zero that means this is the release version of the library +*/ +#define TTMATH_MAJOR_VER 0 +#define TTMATH_MINOR_VER 8 +#define TTMATH_REVISION_VER 4 +#define TTMATH_PRERELEASE_VER 1 + + +/*! + TTMATH_DEBUG + this macro enables further testing during writing your code + you don't have to define it in a release mode + + 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 + is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) + + 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 + gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp + 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 +*/ +#ifndef TTMATH_RELEASE + #define TTMATH_DEBUG +#endif + + + +namespace ttmath +{ + +#if !defined _M_X64 && !defined __x86_64__ + + /*! + we're using a 32bit platform + */ + #define TTMATH_PLATFORM32 + +#else + + /*! + we're using a 64bit platform + */ + #define TTMATH_PLATFORM64 + +#endif + + + +#ifdef TTMATH_PLATFORM32 + + /*! + on 32bit platforms one word (uint, sint) will be equal 32bits + */ + typedef unsigned int uint; + typedef signed int sint; + + + /*! + this type is twice bigger than uint + (64bit on a 32bit platforms) + + although C++ Standard - ANSI ISO IEC 14882:2003 doesn't define such a type (long long) + but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it + + this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined + */ + typedef unsigned long long int ulint; + + /*! + how many bits there are in the uint type + */ + #define TTMATH_BITS_PER_UINT 32u + + /*! + the mask for the highest bit in the unsigned 32bit word (2^31) + */ + #define TTMATH_UINT_HIGHEST_BIT 2147483648u + + /*! + the max value of the unsigned 32bit word (2^32 - 1) + (all bits equal one) + */ + #define TTMATH_UINT_MAX_VALUE 4294967295u + + /*! + the number of words (32bit words on 32bit platform) + which are kept in built-in variables for a Big<> type + (these variables are defined in ttmathbig.h) + */ + #define TTMATH_BUILTIN_VARIABLES_SIZE 256u + +#else + + /*! + on 64bit platforms one word (uint, sint) will be equal 64bits + */ + #if defined(_MSC_VER) + typedef unsigned __int64 uint; + typedef signed __int64 sint; + #else + typedef unsigned long long uint; + typedef signed long long sint; + #endif + /*! + on 64bit platform we do not define ulint + sizeof(long long) is 8 (64bit) but we need 128bit + + on 64 bit platform (when there is defined TTMATH_NOASM macro) + methods UInt::MulTwoWords and UInt::DivTwoWords are using other algorithms than those on 32 bit + */ + //typedef unsigned long long int ulint; + + /*! + how many bits there are in the uint type + */ + #define TTMATH_BITS_PER_UINT 64ul + + /*! + the mask for the highest bit in the unsigned 64bit word (2^63) + */ + #define TTMATH_UINT_HIGHEST_BIT 0x8000000000000000ul + + /*! + the max value of the unsigned 64bit word (2^64 - 1) + (all bits equal one) + */ + #define TTMATH_UINT_MAX_VALUE 0xfffffffffffffffful + + /*! + the number of words (64bit words on 64bit platforms) + which are kept in built-in variables for a Big<> type + (these variables are defined in ttmathbig.h) + */ + #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul + +#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 + + if you don't want it just put 0 there e.g. + #define TTMATH_COMMA_CHARACTER_2 0 + then only TTMATH_COMMA_CHARACTER_1 will be used + + 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. + + note! there'll not be so many iterations, iterations are stopped when + 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 + */ + enum ErrorCode + { + err_ok = 0, + err_nothing_has_read, + err_unknown_character, + err_unexpected_final_bracket, + err_stack_not_clear, + err_unknown_variable, + err_division_by_zero, + err_interrupt, + err_overflow, + err_unknown_function, + err_unknown_operator, + err_unexpected_semicolon_operator, + err_improper_amount_of_arguments, + err_improper_argument, + err_unexpected_end, + err_internal_error, + err_incorrect_name, + err_incorrect_value, + err_variable_exists, + err_variable_loop, + err_functions_loop, + err_must_be_only_one_value, + 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 + the 'stop object', if the method WasStopSignal() of this + object returns true that means we should break the calculating + and return + */ + 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 + */ + class ExceptionInfo + { + const tchar_t * file; + int line; + + public: + ExceptionInfo() : file(0), line(0) {} + ExceptionInfo(const tchar_t * f, int l) : file(f), line(l) {} + + tstr_t Where() const + { + if( !file ) + return(TTMATH_TEXT("unknown")); + + 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 + + If you compile with gcc you can get a small benefit + from using method Where() (it returns tstr_t with + the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT + was used) + + What is the 'reference' error? + Some kind of methods use a reference as their argument to another object, + and the another object not always can be the same which is calling, e.g. + Big<1,2> foo(10); + foo.Mul(foo); // this is incorrect + above method Mul is making something more with 'this' object and + 'this' cannot be passed as the argument because the result will be undefined + + macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem + + note! some methods can use 'this' object as the argument + for example this code is correct: + UInt<2> foo(10); + foo.Add(foo); + but there are only few methods which can do that + */ + class ReferenceError : public std::logic_error, ExceptionInfo + { + public: + + ReferenceError() : std::logic_error ("reference error") + { + } + + ReferenceError(const tchar_t * f, int l) : + std::logic_error ("reference error"), ExceptionInfo(f,l) + { + } + + 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 + + if you compile with gcc you can get a small benefit + from using method Where() (it returns tstr_t with + the name and the line of a file where the macro TTMATH_ASSERT + was used) + */ + class RuntimeError : public std::runtime_error, ExceptionInfo + { + public: + + RuntimeError() : std::runtime_error ("internal error") + { + } + + RuntimeError(const tchar_t * f, int l) : + std::runtime_error ("internal error"), ExceptionInfo(f,l) + { + } + + 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__) + + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); + + #else + + #define TTMATH_REFERENCE_ASSERT(expression) \ + if( &(expression) == this ) throw ReferenceError(); + + #define TTMATH_ASSERT(expression) \ + if( !(expression) ) throw RuntimeError(); + #endif + + #else + #define TTMATH_REFERENCE_ASSERT(expression) + #define TTMATH_ASSERT(expression) + #endif + + + + #ifdef TTMATH_DEBUG_LOG + + #define TTMATH_LOG(msg) \ + PrintLog(msg, std::cout); + + #else + + #define TTMATH_LOG(msg) + + #endif + + +} // namespace + + +#endif diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index 61e773e..8604e00 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -50,7 +50,9 @@ #include "ttmathtypes.h" - +#if defined(_MSC_VER) + #pragma warning(disable:4127) // conditional expression is constant +#endif /*! \brief a namespace for the TTMath library @@ -84,7 +86,7 @@ public: 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 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; @@ -1473,7 +1475,7 @@ private: bool Div2_DivisorGreaterOrEqual( const UInt & divisor, UInt * remainder, uint table_id, uint index, - uint divisor_table_id, uint divisor_index ) + uint /*divisor_table_id*/, uint divisor_index ) { if( divisor_index > index ) { @@ -1604,7 +1606,7 @@ private: for(uint i = j+1 ; i (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 operators and constructors the compiler will not compile the program, because it has to make a conversion and doesn't know into which type - (the UInt class has operator=(const char*), operator=(uint) etc.) + (the UInt class has operator=(const tchar_t*), operator=(uint) etc.) */ UInt & operator=(sint i) { @@ -2256,18 +2258,18 @@ public: /*! a constructor for converting a string to this class (with the base=10) */ - UInt(const char * s) + UInt(const tchar_t * 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) */ - UInt(const std::string & s) + UInt(const tstr_t & s) { FromString( s.c_str() ); } @@ -2332,10 +2334,10 @@ public: /*! this method converts the value to a string with a base equal 'b' */ - void ToString(std::string & result, uint b = 10) const + void ToString(tstr_t & result, uint b = 10) const { UInt temp( *this ); - char character; + tchar_t character; uint rem; result.clear(); @@ -2360,7 +2362,7 @@ public: /* 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') ) ++c; @@ -2384,7 +2386,7 @@ public: value_read (if exists) tells whether something has actually been read (at least one digit) */ - uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + uint FromString(const tchar_t * s, uint b = 10, const tchar_t ** after_source = 0, bool * value_read = 0) { UInt base( b ); UInt temp; @@ -2434,7 +2436,7 @@ public: (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) */ - uint FromString(const std::string & s, uint b = 10) + uint FromString(const tstr_t & s, uint b = 10) { return FromString( s.c_str(), b ); } @@ -2444,11 +2446,11 @@ public: /*! this operator converts a string into its value (with base = 10) */ - UInt & operator=(const char * s) + UInt & operator=(const tchar_t * s) { FromString(s); - TTMATH_LOG("UInt::operator=(const char *)") + TTMATH_LOG("UInt::operator=(const tchar_t *)") return *this; } @@ -2457,7 +2459,7 @@ public: /*! this operator converts a string into its value (with base = 10) */ - UInt & operator=(const std::string & s) + UInt & operator=(const tstr_t & s) { FromString( s.c_str() ); @@ -2825,9 +2827,9 @@ public: * */ - friend std::ostream & operator<<(std::ostream & s, const UInt & l) + friend tostrm_t & operator<<(tostrm_t & s, const UInt & l) { - std::string ss; + tstr_t ss; l.ToString(ss); s << ss; @@ -2837,12 +2839,12 @@ public: - friend std::istream & operator>>(std::istream & s, UInt & l) + friend tistrm_t & operator>>(tistrm_t & s, UInt & l) { - std::string ss; + tstr_t ss; - // char for operator>> - unsigned char z; + // tchar_t for operator>> + tchar_t z; // operator>> omits white characters if they're set for ommiting s >> z; @@ -2925,6 +2927,10 @@ public: } //namespace +#if defined(_MSC_VER) + #pragma warning(default:4127) // conditional expression is constant +#endif + #include "ttmathuint_x86.h" #include "ttmathuint_x86_64.h" diff --git a/ttmath/ttmathuint_x86_64.h b/ttmath/ttmathuint_x86_64.h index 4ddf437..6e405be 100644 --- a/ttmath/ttmathuint_x86_64.h +++ b/ttmath/ttmathuint_x86_64.h @@ -41,9 +41,9 @@ #ifndef TTMATH_NOASM +#pragma message("ASM code included") #ifdef TTMATH_PLATFORM64 - /*! \file ttmathuint_x86_64.h \brief template class UInt with assembler code for 64bit x86_64 processors @@ -55,6 +55,24 @@ namespace ttmath { + #if defined(_M_IX64) + #include + + extern "C" + { + uint __fastcall adc_x64(uint* p1, const uint* p2, uint nSize, uint c); + uint __fastcall addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); + uint __fastcall addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); + uint __fastcall sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); + uint __fastcall subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); + uint __fastcall rcl_x64(uint* p1, uint nSize, uint nLowestBit); + uint __fastcall rcr_x64(uint* p1, uint nSize, uint nLowestBit); + uint __fastcall div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); + uint __fastcall rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); + uint __fastcall rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); + }; + #endif + /*! * * basic mathematic functions @@ -78,16 +96,20 @@ namespace ttmath uint b = value_size; uint * p1 = table; const uint * p2 = ss2.table; - uint dummy, dummy2; // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ - #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 #ifdef __GNUC__ + uint dummy, dummy2; /* this part should be compiled with gcc */ @@ -145,15 +167,19 @@ namespace ttmath uint b = value_size; uint * p1 = table; uint c; - uint dummy, dummy2; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_M_IX64) + c = addindexed_x64(p1,b,index,value); + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ + uint dummy, dummy2; __asm__ __volatile__( @@ -223,15 +249,20 @@ namespace ttmath uint b = value_size; uint * p1 = table; uint c; - uint dummy, dummy2; TTMATH_ASSERT( index < value_size - 1 ) #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #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 #ifdef __GNUC__ + uint dummy, dummy2; + __asm__ __volatile__( "subq %%rdx, %%rcx \n" @@ -284,16 +315,21 @@ namespace ttmath uint b = value_size; uint * p1 = table; const uint * p2 = ss2.table; - uint dummy, dummy2; // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ - #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 #ifdef __GNUC__ + uint dummy, dummy2; + __asm__ __volatile__( "xorq %%rdx, %%rdx \n" @@ -347,15 +383,20 @@ namespace ttmath uint b = value_size; uint * p1 = table; uint c; - uint dummy, dummy2; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_M_IX64) + c = subindexed_x64(p1,b,index,value); + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ + uint dummy, dummy2; + __asm__ __volatile__( "subq %%rdx, %%rcx \n" @@ -404,13 +445,18 @@ namespace ttmath { sint b = value_size; uint * p1 = table; - uint dummy, dummy2; #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 #ifdef __GNUC__ + uint dummy, dummy2; + __asm__ __volatile__( "xorq %%rdx, %%rdx \n" // rdx=0 @@ -456,13 +502,18 @@ namespace ttmath { sint b = value_size; uint * p1 = table; - uint dummy; #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 #ifdef __GNUC__ + uint dummy; + __asm__ __volatile__( "neg %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 @@ -509,13 +560,18 @@ namespace ttmath uint b = value_size; uint * p1 = table; - uint dummy, dummy2, dummy3; #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #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 #ifdef __GNUC__ + uint dummy, dummy2, dummy3; + __asm__ __volatile__( "movq %%rcx, %%rsi \n" @@ -580,14 +636,19 @@ namespace ttmath sint b = value_size; uint * p1 = table; - uint dummy, dummy2, dummy3; #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_M_IX64) + c = rcr2_x64(p1,b,bits,c); + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ + uint dummy, dummy2, dummy3; + __asm__ __volatile__( "movq %%rcx, %%rsi \n" @@ -646,7 +707,16 @@ namespace ttmath register sint result; #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_MSC_VER) + unsigned long nIndex(0); + + if (_BitScanReverse64(&nIndex,x) == 0) + result = -1; + else + result = nIndex; + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ @@ -691,7 +761,11 @@ namespace ttmath #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 #ifdef __GNUC__ @@ -747,7 +821,11 @@ namespace ttmath register uint result2_; #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_MSC_VER) + result1_ = _umul128(a,b,&result2_); + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ @@ -804,7 +882,13 @@ namespace ttmath TTMATH_ASSERT( c != 0 ) #ifndef __GNUC__ - #error "another compiler than GCC is currently not supported in 64bit mode" + #if defined(_MSC_VER) + div_x64(&a,&b,c); + r_ = a; + rest_ = b; + #else + #error "another compiler than GCC is currently not supported in 64bit mode" + #endif #endif #ifdef __GNUC__ diff --git a/ttmath/ttmathuint_x86_amd64_msvc.asm b/ttmath/ttmathuint_x86_amd64_msvc.asm new file mode 100644 index 0000000..f94c7d0 --- /dev/null +++ b/ttmath/ttmathuint_x86_amd64_msvc.asm @@ -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