diff --git a/CHANGELOG b/CHANGELOG index a257158..ff5523d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,15 +1,7 @@ -Version 0.9.0 prerelease (2009.09.11): - * added: support for wide characters (wchar_t) - wide characters are used when macro TTMATH_USE_WCHAR is defined - this macro is defined automatically when there is macro UNICODE or _UNICODE defined - some types have been changed - char -> tt_char - std::string -> tt_string - std::ostringstream -> tt_ostringstream - std::ostream -> tt_ostream - std::istream -> tt_istream - normally tt_char is equal char but when you are using wide characters then tt_char will be wchar_t (and so on) - (all typedef's are in ttmathtypes.h) +Version 0.9.0 prerelease (2009.09.13): + * fixed: Big::operator>>(std::istream&, Big<> &) didn't recognize values + in scientific mode (with 'e' character) + * added: support for wide characters (wchar_t, std::wstring) * added: Big::IsInteger() returns true if the value is integer (without fraction) (NaN flag is not checked) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index a850786..df051d5 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -320,7 +320,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 tt_char*) on a 32bit platform) + // and they were set into Big<1,400> type (using operator=(const char*) 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)) @@ -2799,6 +2799,7 @@ public: } + /*! a method for converting the value into a string with a base equal 'base' @@ -2837,27 +2838,59 @@ public: 1 - if there was a carry (shoudn't be in a normal situation - if is that means there is somewhere an error in the library) */ - uint ToString( tt_string & result, + uint ToString( std::string & result, uint base = 10, bool always_scientific = false, sint when_scientific = 15, sint max_digit_after_comma = -1, bool remove_trailing_zeroes = true, - tt_char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const + char decimal_point = TTMATH_COMMA_CHARACTER_1 ) const { - static tt_char error_overflow_msg[] = TTMATH_TEXT("overflow"); - static tt_char error_nan_msg[] = TTMATH_TEXT("NaN"); + return ToStringBase(result, base, always_scientific, when_scientific, + max_digit_after_comma, remove_trailing_zeroes, decimal_point); + } + + + /*! + a method for converting the value into a string with a base equal 'base' + */ + uint ToString( std::wstring & result, + uint base = 10, + bool always_scientific = false, + sint when_scientific = 15, + sint max_digit_after_comma = -1, + bool remove_trailing_zeroes = true, + wchar_t decimal_point = TTMATH_COMMA_CHARACTER_1 ) const + { + return ToStringBase(result, base, always_scientific, when_scientific, + max_digit_after_comma, remove_trailing_zeroes, decimal_point); + } + +private: + + + template + uint ToStringBase( string_type & result, + uint base, + bool always_scientific, + sint when_scientific, + sint max_digit_after_comma, + bool remove_trailing_zeroes, + char_type decimal_point) const + { + static char error_overflow_msg[] = "overflow"; + static char error_nan_msg[] = "NaN"; result.erase(); if( IsNan() ) { - result = error_nan_msg; + Misc::AssignString(result, error_nan_msg); return 0; } if( base<2 || base>16 ) { - result = error_overflow_msg; + Misc::AssignString(result, error_overflow_msg); return 1; } @@ -2887,7 +2920,7 @@ public: if( ToString_CreateNewMantissaAndExponent(result, base, new_exp) ) { - result = error_overflow_msg; + Misc::AssignString(result, error_overflow_msg); return 1; } @@ -2898,7 +2931,7 @@ public: if( base!=2 && base!=4 && base!=8 && base!=16 ) if( ToString_RoundMantissa(result, base, new_exp, decimal_point) ) { - result = error_overflow_msg; + Misc::AssignString(result, error_overflow_msg); return 1; } @@ -2906,7 +2939,7 @@ public: when_scientific, max_digit_after_comma, remove_trailing_zeroes, decimal_point ) ) { - result = error_overflow_msg; + Misc::AssignString(result, error_overflow_msg); return 1; } @@ -2988,7 +3021,8 @@ 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( tt_string & new_man, uint base, + template + uint ToString_CreateNewMantissaAndExponent( string_type & new_man, uint base, Int & new_exp) const { uint c = 0; @@ -3233,7 +3267,8 @@ 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( tt_string & new_man, + template + uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man, Int & new_exp ) const { for( sint i=man-1 ; i>=0 ; --i ) @@ -3263,13 +3298,14 @@ 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(tt_string & new_man, uint base, Int & new_exp, tt_char decimal_point) const + template + uint ToString_RoundMantissa(string_type & new_man, uint base, Int & new_exp, char_type decimal_point) const { // we must have minimum two characters if( new_man.length() < 2 ) return 0; - tt_string::size_type i = new_man.length() - 1; + typename string_type::size_type i = new_man.length() - 1; // we're erasing the last character uint digit = UInt::CharToDigit( new_man[i] ); @@ -3290,7 +3326,8 @@ private: this method addes one into the new mantissa */ - void ToString_RoundMantissa_AddOneIntoMantissa(tt_string & new_man, uint base, tt_char decimal_point) const + template + void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, uint base, char_type decimal_point) const { if( new_man.empty() ) return; @@ -3314,7 +3351,7 @@ private: else was_carry = false; - new_man[i] = static_cast( UInt::DigitToChar(digit) ); + new_man[i] = static_cast( UInt::DigitToChar(digit) ); } if( i<0 && was_carry ) @@ -3328,13 +3365,14 @@ private: this method sets the comma operator and/or puts the exponent into the string */ - uint ToString_SetCommaAndExponent( tt_string & new_man, uint base, + template + uint ToString_SetCommaAndExponent( string_type & new_man, uint base, Int & new_exp, bool always_scientific, sint when_scientific, sint max_digit_after_comma, bool remove_trailing_zeroes, - tt_char decimal_point) const + char_type decimal_point) const { uint carry = 0; @@ -3373,13 +3411,14 @@ private: /*! an auxiliary method for converting into the string */ + template void ToString_SetCommaAndExponent_Normal( - tt_string & new_man, + string_type & new_man, uint base, Int & new_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - tt_char decimal_point) const + char_type decimal_point) const { if( !new_exp.IsSign() ) //if( new_exp >= 0 ) return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); @@ -3391,7 +3430,8 @@ private: /*! an auxiliary method for converting into the string */ - void ToString_SetCommaAndExponent_Normal_AddingZero(tt_string & new_man, + template + void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man, Int & new_exp) const { // we're adding zero characters at the end @@ -3410,13 +3450,14 @@ private: /*! an auxiliary method for converting into the string */ + template void ToString_SetCommaAndExponent_Normal_SetCommaInside( - tt_string & new_man, + string_type & new_man, uint base, Int & new_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - tt_char decimal_point) const + char_type decimal_point) const { // new_exp is < 0 @@ -3435,7 +3476,7 @@ private: // we're adding zero characters before the mantissa uint how_many = e - new_man_len; - tt_string man_temp(how_many+1, '0'); + string_type man_temp(how_many+1, '0'); man_temp.insert( man_temp.begin()+1, decimal_point); new_man.insert(0, man_temp); @@ -3448,12 +3489,13 @@ private: /*! an auxiliary method for converting into the string */ - void ToString_SetCommaAndExponent_Scientific( tt_string & new_man, + template + void ToString_SetCommaAndExponent_Scientific( string_type & new_man, uint base, Int & scientific_exp, sint max_digit_after_comma, bool remove_trailing_zeroes, - tt_char decimal_point) const + char_type decimal_point) const { if( new_man.empty() ) return; @@ -3473,10 +3515,10 @@ private: { // the 10 here is meant as the base 'base' // (no matter which 'base' we're using there'll always be 10 here) - new_man += TTMATH_TEXT("*10^"); + Misc::AddString(new_man, "*10^"); } - tt_string temp_exp; + string_type temp_exp; scientific_exp.ToString( temp_exp, base ); new_man += temp_exp; @@ -3486,11 +3528,12 @@ private: /*! an auxiliary method for converting into the string */ - void ToString_CorrectDigitsAfterComma( tt_string & new_man, + template + void ToString_CorrectDigitsAfterComma( string_type & new_man, uint base, sint max_digit_after_comma, bool remove_trailing_zeroes, - tt_char decimal_point) const + char_type decimal_point) const { if( max_digit_after_comma >= 0 ) ToString_CorrectDigitsAfterComma_Round(new_man, base, max_digit_after_comma, decimal_point); @@ -3503,9 +3546,10 @@ private: /*! an auxiliary method for converting into the string */ + template void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( - tt_string & new_man, - tt_char decimal_point) const + string_type & new_man, + char_type decimal_point) const { // minimum two characters if( new_man.length() < 2 ) @@ -3523,7 +3567,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) == tt_string::npos ) + if( new_man.find_last_of(decimal_point, i) == string_type::npos ) return; // if directly before the first zero is the comma operator @@ -3538,27 +3582,28 @@ private: /*! an auxiliary method for converting into the string */ + template void ToString_CorrectDigitsAfterComma_Round( - tt_string & new_man, + string_type & new_man, uint base, sint max_digit_after_comma, - tt_char decimal_point) const + char_type decimal_point) const { // first we're looking for the comma operator - tt_string::size_type index = new_man.find(decimal_point, 0); + typename string_type::size_type index = new_man.find(decimal_point, 0); - if( index == tt_string::npos ) + if( index == string_type::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 - tt_string::size_type after_comma = new_man.length() - index - 1; + typename string_type::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( tt_string::size_type(max_digit_after_comma) >= after_comma ) + if( static_cast(max_digit_after_comma) >= after_comma ) return; uint last_digit = UInt::CharToDigit( new_man[ index + max_digit_after_comma + 1 ], base ); @@ -3581,31 +3626,13 @@ private: -public: - +private: /*! - a method for converting a string into its value - - it returns 1 if the value will be too big -- we cannot pass it into the range - of our class Big (or if the base is incorrect) - - that means only digits before the comma operator can make this value too big, - all digits after the comma we can ignore - - 'source' - pointer to the string for parsing - 'const char*' or 'const wchar_t*' - - if 'after_source' is set that when this method finishes - it sets the pointer to the new first character after parsed value - - 'value_read' - if the pointer is provided that means the value_read will be true - only when a value has been actually read, there can be situation where only such - a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but - no value has been read (there are no digits) - on other words if 'value_read' is true -- there is at least one digit in the string + an auxiliary method for converting from a string */ - uint FromString(const tt_char * source, uint base = 10, const tt_char ** after_source = 0, bool * value_read = 0) + template + uint FromStringBase(const char_type * source, uint base = 10, const char_type ** after_source = 0, bool * value_read = 0) { bool is_sign; bool value_read_temp = false; @@ -3648,15 +3675,54 @@ public: -private: +public: + + /*! + a method for converting a string into its value + + it returns 1 if the value will be too big -- we cannot pass it into the range + of our class Big (or if the base is incorrect) + + that means only digits before the comma operator can make this value too big, + all digits after the comma we can ignore + + 'source' - pointer to the string for parsing + 'const char*' or 'const wchar_t*' + + if 'after_source' is set that when this method finishes + it sets the pointer to the new first character after parsed value + + 'value_read' - if the pointer is provided that means the value_read will be true + only when a value has been actually read, there can be situation where only such + a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but + no value has been read (there are no digits) + on other words if 'value_read' is true -- there is at least one digit in the string + */ + uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(source, base, after_source, value_read); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(source, base, after_source, value_read); + } + + +private: /*! we're testing whether the value is with the sign (this method is used from 'FromString_ReadPartScientific' too) */ - void FromString_TestSign( const tt_char * & source, bool & is_sign ) + template + void FromString_TestSign( const char_type * & source, bool & is_sign ) { UInt::SkipWhiteCharacters(source); @@ -3678,7 +3744,8 @@ private: /*! we're testing whether there's a comma operator */ - bool FromString_TestCommaOperator(const tt_char * & source) + template + bool FromString_TestCommaOperator(const char_type * & source) { if( (*source == TTMATH_COMMA_CHARACTER_1) || (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) @@ -3696,7 +3763,8 @@ private: this method reads the first part of a string (before the comma operator) */ - uint FromString_ReadPartBeforeComma( const tt_char * & source, uint base, bool & value_read ) + template + uint FromString_ReadPartBeforeComma( const char_type * & source, uint base, bool & value_read ) { sint character; Big temp; @@ -3725,7 +3793,8 @@ private: this method reads the second part of a string (after the comma operator) */ - uint FromString_ReadPartAfterComma( const tt_char * & source, uint base, bool & value_read ) + template + uint FromString_ReadPartAfterComma( const char_type * & source, uint base, bool & value_read ) { sint character; uint c = 0, index = 1; @@ -3783,12 +3852,13 @@ private: it is called when the base is 10 and some digits were read before */ - uint FromString_ReadScientificIfExists(const tt_char * & source) + template + uint FromString_ReadScientificIfExists(const char_type * & source) { uint c = 0; bool scientific_read = false; - const tt_char * before_scientific = source; + const char_type * before_scientific = source; if( FromString_TestScientific(source) ) c += FromString_ReadPartScientific( source, scientific_read ); @@ -3806,7 +3876,8 @@ private: this character is only allowed when we're using the base equals 10 */ - bool FromString_TestScientific(const tt_char * & source) + template + bool FromString_TestScientific(const char_type * & source) { UInt::SkipWhiteCharacters(source); @@ -3825,7 +3896,8 @@ 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 tt_char * & source, bool & scientific_read ) + template + uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read ) { uint c = 0; Big new_exponent, temp; @@ -3852,7 +3924,8 @@ private: this method reads the value of the extra exponent when scientific format is used (only when base == 10) */ - uint FromString_ReadPartScientific_ReadExponent( const tt_char * & source, Big & new_exponent, bool & scientific_read ) + template + uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big & new_exponent, bool & scientific_read ) { sint character; Big base, temp; @@ -3885,7 +3958,16 @@ public: /*! a method for converting a string into its value */ - uint FromString(const tt_string & string, uint base = 10) + uint FromString(const std::string & string, uint base = 10) + { + return FromString( string.c_str(), base ); + } + + + /*! + a method for converting a string into its value + */ + uint FromString(const std::wstring & string, uint base = 10) { return FromString( string.c_str(), base ); } @@ -3894,7 +3976,7 @@ public: /*! a constructor for converting a string into this class */ - Big(const tt_char * string) + Big(const char * string) { FromString( string ); } @@ -3903,7 +3985,25 @@ public: /*! a constructor for converting a string into this class */ - Big(const tt_string & string) + Big(const wchar_t * string) + { + FromString( string ); + } + + + /*! + a constructor for converting a string into this class + */ + Big(const std::string & string) + { + FromString( string.c_str() ); + } + + + /*! + a constructor for converting a string into this class + */ + Big(const std::wstring & string) { FromString( string.c_str() ); } @@ -3912,7 +4012,7 @@ public: /*! an operator= for converting a string into its value */ - Big & operator=(const tt_char * string) + Big & operator=(const char * string) { FromString( string ); @@ -3923,7 +4023,29 @@ public: /*! an operator= for converting a string into its value */ - Big & operator=(const tt_string & string) + Big & operator=(const wchar_t * string) + { + FromString( string ); + + return *this; + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const std::string & string) + { + FromString( string.c_str() ); + + return *this; + } + + + /*! + an operator= for converting a string into its value + */ + Big & operator=(const std::wstring & string) { FromString( string.c_str() ); @@ -4050,6 +4172,8 @@ public: */ bool AboutEqualWithoutSign(const Big & ss2, uint nBitsToIgnore) const { + /* not finished, should be added testing then exponents are different about one */ + // there is no sense to ignore the whole mantissas TTMATH_ASSERT( nBitsToIgnore < man*TTMATH_BITS_PER_UINT ) @@ -4444,14 +4568,15 @@ public: * */ - /*! - output for standard streams +private: - tt_ostream is either std::ostream or std::wostream + /*! + an auxiliary method for outputing to standard streams */ - friend tt_ostream & operator<<(tt_ostream & s, const Big & l) + template + static ostream_type & OutputToStream(ostream_type & s, const Big & l) { - tt_string ss; + string_type ss; l.ToString(ss); s << ss; @@ -4460,18 +4585,42 @@ public: } - /*! - input from standard streams +public: - tt_istream is either std::istream or std::wistream + + /*! + output to standard streams */ - friend tt_istream & operator>>(tt_istream & s, Big & l) + friend std::ostream & operator<<(std::ostream & s, const Big & l) { - tt_string ss; + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const Big & l) + { + return OutputToStream(s, l); + } + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + static istream_type & InputFromStream(istream_type & s, Big & l) + { + string_type ss; - // 'tt_char' for operator>> - tt_char z; + // char or wchar_t for operator>> + char_type z, old_z; bool was_comma = false; + bool was_e = false; + // operator>> omits white characters if they're set for ommiting s >> z; @@ -4481,25 +4630,44 @@ public: ss += z; s >> z; // we're reading a next character (white characters can be ommited) } + + old_z = 0; // we're reading only digits (base=10) and only one comma operator - for( ; s.good() ; z=static_cast(s.get()) ) + for( ; s.good() ; z=static_cast(s.get()) ) { if( z == TTMATH_COMMA_CHARACTER_1 || ( z == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) ) { - if( was_comma ) - // second comma operator + if( was_comma || was_e ) + // second comma operator or comma operator after 'e' character break; was_comma = true; } else + if( z == 'e' || z == 'E' ) + { + if( was_e ) + // second 'e' character + break; + + was_e = true; + } + else + if( z == '+' || z == '-' ) + { + if( old_z != 'e' && old_z != 'E' ) + // '+' or '-' is allowed only after 'e' character + break; + } + else if( UInt::CharToDigit(z, 10) < 0 ) break; - ss += z; + ss += z; + old_z = z; } // we're leaving the last read character @@ -4511,6 +4679,27 @@ public: return s; } + + +public: + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, Big & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, Big & l) + { + return InputFromStream(s, l); + } + }; diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index abb4355..32a2a2e 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -821,7 +821,16 @@ public: /*! a constructor for converting string to this class (with the base=10) */ - Int(const tt_char * s) + Int(const char * s) + { + FromString(s); + } + + + /*! + a constructor for converting string to this class (with the base=10) + */ + Int(const wchar_t * s) { FromString(s); } @@ -830,7 +839,16 @@ public: /*! a constructor for converting a string to this class (with the base=10) */ - Int(const tt_string & s) + Int(const std::string & s) + { + FromString( s.c_str() ); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + Int(const std::wstring & s) { FromString( s.c_str() ); } @@ -866,10 +884,13 @@ public: } +private: + /*! - this method converts the value to a string with a base equal 'b' + an auxiliary method for converting to a string */ - void ToString(tt_string & result, uint b = 10) const + template + void ToStringBase(string_type & result, uint b = 10) const { if( IsSign() ) { @@ -885,28 +906,33 @@ public: } } +public: + + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::string & result, uint b = 10) const + { + return ToStringBase(result, b); + } + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::wstring & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + +private: /*! - this method converts a string into its value - string is given either as 'const char *' or 'const wchar_t *' - - it returns carry=1 if the value will be too big or an incorrect base 'b' is given - - string is ended with a non-digit value, for example: - "-12" will be translated to -12 - as well as: - "- 12foo" will be translated to -12 too - - existing first white characters will be ommited - (between '-' and a first digit can be white characters too) - - after_source (if exists) is pointing at the end of the parsed string - - value_read (if exists) tells whether something has actually been read (at least one digit) + an auxiliary method for converting from a string */ - uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0) + template + uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) { bool is_sign = false; @@ -959,11 +985,54 @@ public: } +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 + + string is ended with a non-digit value, for example: + "-12" will be translated to -12 + as well as: + "- 12foo" will be translated to -12 too + + existing first white characters will be ommited + (between '-' and a first digit can be white characters too) + + after_source (if exists) is pointing at the end of the parsed string + + value_read (if exists) tells whether something has actually been read (at least one digit) + */ + uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + */ + uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + /*! 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 tt_string & s, uint b = 10) + uint FromString(const std::string & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + + + /*! + 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::wstring & s, uint b = 10) { return FromString( s.c_str(), b ); } @@ -972,7 +1041,7 @@ public: /*! this operator converts a string into its value (with base = 10) */ - Int & operator=(const tt_char * s) + Int & operator=(const char * s) { FromString(s); @@ -983,7 +1052,18 @@ public: /*! this operator converts a string into its value (with base = 10) */ - Int & operator=(const tt_string & s) + Int & operator=(const wchar_t * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const std::string & s) { FromString( s.c_str() ); @@ -991,6 +1071,15 @@ public: } + /*! + this operator converts a string into its value (with base = 10) + */ + Int & operator=(const std::wstring & s) + { + FromString( s.c_str() ); + + return *this; + } /*! @@ -1270,14 +1359,15 @@ public: * */ - /*! - output for standard streams +private: - tt_ostream is either std::ostream or std::wostream + /*! + an auxiliary method for outputing to standard streams */ - friend tt_ostream & operator<<(tt_ostream & s, const Int & l) + template + static ostream_type & OutputToStream(ostream_type & s, const Int & l) { - tt_string ss; + string_type ss; l.ToString(ss); s << ss; @@ -1286,17 +1376,41 @@ public: } - /*! - input from standard streams - tt_istream is either std::istream or std::wistream +public: + + + /*! + output to standard streams */ - friend tt_istream & operator>>(tt_istream & s, Int & l) + friend std::ostream & operator<<(std::ostream & s, const Int & l) { - tt_string ss; + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const Int & l) + { + return OutputToStream(s, l); + } + + + +private: + + /*! + an auxiliary method for converting from a string + */ + template + static istream_type & InputFromStream(istream_type & s, Int & l) + { + string_type ss; - // tt_char for operator>> - tt_char z; + // char or wchar_t for operator>> + char_type z; // operator>> omits white characters if they're set for ommiting s >> z; @@ -1311,7 +1425,7 @@ public: while( s.good() && UInt::CharToDigit(z, 10)>=0 ) { ss += z; - z = static_cast(s.get()); + z = static_cast(s.get()); } // we're leaving the last readed character @@ -1323,6 +1437,26 @@ public: return s; } + +public: + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, Int & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, Int & l) + { + return InputFromStream(s, l); + } + }; } // namespace diff --git a/ttmath/ttmathmisc.h b/ttmath/ttmathmisc.h new file mode 100644 index 0000000..8e5398d --- /dev/null +++ b/ttmath/ttmathmisc.h @@ -0,0 +1,155 @@ +/* + * 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 headerfilettmathmisc +#define headerfilettmathmisc + + +/*! + \file ttmathmisc.h + \brief some helpful functions +*/ + + +#include + + +namespace ttmath +{ + +/*! + some helpful functions +*/ +class Misc +{ +public: + + +/* + * + * AssignString(result, str) + * result = str + * + */ + +/*! + result = str +*/ +static void AssignString(std::string & result, const char * str) +{ + result = str; +} + + +/*! + result = str +*/ +static void AssignString(std::wstring & result, const char * str) +{ + result.clear(); + + for( ; *str ; ++str ) + result += *str; +} + + +/*! + result = str +*/ +static void AssignString(std::wstring & result, const std::string & str) +{ + return AssignString(result, str.c_str()); +} + + +/*! + result = str +*/ +static void AssignString(std::string & result, const wchar_t * str) +{ + result.clear(); + + for( ; *str ; ++str ) + result += static_cast(*str); +} + + +/*! + result = str +*/ +static void AssignString(std::string & result, const std::wstring & str) +{ + return AssignString(result, str.c_str()); +} + + +/* + * + * AddString(result, str) + * result += str + * + */ + + +/*! + result += str +*/ +static void AddString(std::string & result, const char * str) +{ + result += str; +} + + +/*! + result += str +*/ +static void AddString(std::wstring & result, const char * str) +{ + for( ; *str ; ++str ) + result += *str; +} + + + + + +}; // struct Misc + +} + + +#endif diff --git a/ttmath/ttmathobjects.h b/ttmath/ttmathobjects.h index d30991e..5fe343d 100644 --- a/ttmath/ttmathobjects.h +++ b/ttmath/ttmathobjects.h @@ -44,13 +44,13 @@ \brief Mathematic functions. */ -#include "ttmathtypes.h" - #include #include #include #include +#include "ttmathtypes.h" +#include "ttmathmisc.h" namespace ttmath @@ -74,19 +74,19 @@ public: struct Item { // name of a variable of a function - // (either std::string or std::wstring) - tt_string value; + // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) + std::string value; // number of parameters required by the function // (if there's a variable this 'param' is ignored) int param; Item() {} - Item(const tt_string & v, int p) : value(v), param(p) {} + Item(const std::string & 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; @@ -99,7 +99,7 @@ public: if 'can_be_digit' is true that means when the 'c' is a digit this method returns true otherwise it returns false */ - static bool CorrectCharacter(int c, bool can_be_digit) + static bool CorrectCharacter(wchar_t c, bool can_be_digit) { if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) return true; @@ -114,7 +114,8 @@ public: /*! this method returns true if the name can be as a name of an object */ - static bool IsNameCorrect(const tt_string & name) + template + static bool IsNameCorrect(const string_type & name) { if( name.empty() ) return false; @@ -122,7 +123,7 @@ public: if( !CorrectCharacter(name[0], false) ) return false; - tt_string::const_iterator i=name.begin(); + typename string_type::const_iterator i = name.begin(); for(++i ; i!=name.end() ; ++i) if( !CorrectCharacter(*i, true) ) @@ -135,7 +136,7 @@ public: /*! this method returns true if such an object is defined (name exists) */ - bool IsDefined(const tt_string & name) + bool IsDefined(const std::string & name) { Iterator i = table.find(name); @@ -147,10 +148,26 @@ public: } + /*! + this method returns true if such an object is defined (name exists) + */ + bool IsDefined(const std::wstring & name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return false; + + Misc::AssignString(str_tmp1, name); + + return IsDefined(str_tmp1); + } + + /*! this method adds one object (variable of function) into the table */ - ErrorCode Add(const tt_string & name, const tt_string & value, int param = 0) + ErrorCode Add(const std::string & name, const std::string & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -167,6 +184,23 @@ public: } + /*! + this method adds one object (variable of function) into the table + */ + ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + Misc::AssignString(str_tmp2, value); + + return Add(str_tmp1, str_tmp2, param); + } + + /*! this method returns 'true' if the table is empty */ @@ -207,7 +241,7 @@ public: /*! this method changes the value and the number of parameters for a specific object */ - ErrorCode EditValue(const tt_string & name, const tt_string & value, int param = 0) + ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -224,10 +258,27 @@ public: } + /*! + this method changes the value and the number of parameters for a specific object + */ + ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + Misc::AssignString(str_tmp2, value); + + return EditValue(str_tmp1, str_tmp2, param); + } + + /*! this method changes the name of a specific object */ - ErrorCode EditName(const tt_string & old_name, const tt_string & new_name) + ErrorCode EditName(const std::string & old_name, const std::string & new_name) { if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) return err_incorrect_name; @@ -255,10 +306,27 @@ public: } + /*! + this method changes the name of a specific object + */ + ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, old_name); + Misc::AssignString(str_tmp2, new_name); + + return EditName(str_tmp1, str_tmp2); + } + + /*! this method deletes an object */ - ErrorCode Delete(const tt_string & name) + ErrorCode Delete(const std::string & name) { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -274,10 +342,26 @@ public: } + /*! + this method deletes an object + */ + ErrorCode Delete(const std::wstring & name) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return Delete(str_tmp1); + } + + /*! this method gets the value of a specific object */ - ErrorCode GetValue(const tt_string & name, tt_string & value) const + ErrorCode GetValue(const std::string & name, std::string & value) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -296,11 +380,29 @@ public: } + /*! + this method gets the value of a specific object + */ + ErrorCode GetValue(const std::wstring & name, std::wstring & value) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + ErrorCode err = GetValue(str_tmp1, str_tmp2); + Misc::AssignString(value, str_tmp2); + + return err; + } + + /*! this method gets the value of a specific object (this version is used for not copying the whole string) */ - ErrorCode GetValue(const tt_string & name, const tt_char ** value) const + ErrorCode GetValue(const std::string & name, const char ** value) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -319,11 +421,28 @@ public: } + /*! + this method gets the value of a specific object + (this version is used for not copying the whole string) + */ + ErrorCode GetValue(const std::wstring & name, const char ** value) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return GetValue(str_tmp1, value); + } + + /*! this method gets the value and the number of parameters of a specific object */ - ErrorCode GetValueAndParam(const tt_string & name, tt_string & value, int * param) const + ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -344,12 +463,31 @@ public: } + /*! + this method gets the value and the number of parameters + of a specific object + */ + ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); + Misc::AssignString(value, str_tmp2); + + return err; + } + + /*! this method sets the value and the number of parameters of a specific object (this version is used for not copying the whole string) */ - ErrorCode GetValueAndParam(const tt_string & name, const tt_char ** value, int * param) const + ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; @@ -370,6 +508,25 @@ public: } + /*! + this method sets the value and the number of parameters + of a specific object + (this version is used for not copying the whole string + but in fact we make one copying during AssignString()) + */ + ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) + { + // we should check whether the name (in wide characters) are correct + // before calling AssignString() function + if( !IsNameCorrect(name) ) + return err_incorrect_name; + + Misc::AssignString(str_tmp1, name); + + return GetValueAndParam(str_tmp1, value, param); + } + + /*! this method returns a pointer into the table */ @@ -382,6 +539,7 @@ public: private: Table table; + std::string str_tmp1, str_tmp2; }; // end of class Objects diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index af5ac5f..547d031 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -52,6 +52,7 @@ #include "ttmath.h" #include "ttmathobjects.h" +#include "ttmathmisc.h" @@ -255,7 +256,7 @@ public: bool function; // if function is true - tt_string function_name; + std::string function_name; /* the sign of value @@ -314,7 +315,7 @@ ErrorCode error; when an error has occured it may be used to count the index of the wrong character */ -const tt_char * pstring; +const char * pstring; /*! @@ -351,7 +352,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 +363,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 +397,10 @@ typedef void (ValueType::*pfunction_var)(); table of mathematic functions this map consists of: - tt_string - function's name + std::string - function's name pfunction - pointer to specific function */ -typedef std::map FunctionsTable; +typedef std::map FunctionsTable; FunctionsTable functions_table; @@ -407,10 +408,10 @@ FunctionsTable functions_table; table of mathematic operators this map consists of: - tt_string - operators's name + std::string - operators's name MatOperator::Type - type of the operator */ -typedef std::map OperatorsTable; +typedef std::map OperatorsTable; OperatorsTable operators_table; @@ -418,10 +419,10 @@ OperatorsTable operators_table; table of mathematic variables this map consists of: - tt_string - variable's name + std::string - 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; @@ -455,7 +456,7 @@ void SkipWhiteCharacters() /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ -void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const tt_string & name) +void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) { if( variable ) { @@ -473,7 +474,7 @@ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, cons /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ -void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string & name) +void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) { if( variable ) visited_variables.insert( name ); @@ -485,7 +486,7 @@ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const tt_string /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ -void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_string & name) +void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) { if( variable ) visited_variables.erase( name ); @@ -504,7 +505,7 @@ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const tt_str (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 tt_string & name, const tt_char * new_string, +ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0) { RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); @@ -548,12 +549,12 @@ public: /*! this method returns the user-defined value of a variable */ -bool GetValueOfUserDefinedVariable(const tt_string & variable_name,ValueType & result) +bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) { if( !puser_variables ) return false; - const tt_char * string_value; + const char * string_value; if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) return false; @@ -567,7 +568,7 @@ return true; /*! this method returns the value of a local variable of a function */ -bool GetValueOfFunctionLocalVariable(const tt_string & variable_name, ValueType & result) +bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) { if( !pfunction_local_variables ) return false; @@ -589,7 +590,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 tt_string & variable_name) +ValueType GetValueOfVariable(const std::string & variable_name) { ValueType result; @@ -600,7 +601,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() ) @@ -1361,9 +1362,9 @@ void Avg(int sindex, int amount_of_args, ValueType & result) /*! we use such a method because 'wvsprintf' is not everywhere defined */ -void Sprintf(tt_char * buffer, int par) +void Sprintf(char * buffer, int par) { -char buf[30]; // char, not tt_char +char buf[30]; // char, not wchar_t etc. int i; #ifdef _MSC_VER @@ -1390,12 +1391,12 @@ int i; (look at the description in 'CallFunction(...)') */ -bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_of_args, int sindex) +bool GetValueOfUserDefinedFunction(const std::string & function_name, int amount_of_args, int sindex) { if( !puser_functions ) return false; - const tt_char * string_value; + const char * string_value; int param; if( puser_functions->GetValueAndParam(function_name, &string_value, ¶m) != err_ok ) @@ -1409,7 +1410,7 @@ bool GetValueOfUserDefinedFunction(const tt_string & function_name, int amount_o if( amount_of_args > 0 ) { - tt_char buffer[30]; + char buffer[30]; // x = x1 buffer[0] = 'x'; @@ -1443,7 +1444,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 tt_string & function_name, int amount_of_args, int sindex) +void CallFunction(const std::string & function_name, int amount_of_args, int sindex) { if( GetValueOfUserDefinedFunction(function_name, amount_of_args, sindex) ) return; @@ -1469,12 +1470,16 @@ void CallFunction(const tt_string & function_name, int amount_of_args, int sinde function_name - name of the function pf - pointer to the function (to the wrapper) */ -void InsertFunctionToTable(const tt_char * function_name, pfunction pf) +void InsertFunctionToTable(const char * function_name, pfunction pf) { - functions_table.insert( std::make_pair(tt_string(function_name), pf)); + std::string str; + Misc::AssignString(str, function_name); + + functions_table.insert( std::make_pair(str, pf) ); } + /*! inserting a function to the variables' table (this function returns value of variable) @@ -1482,9 +1487,12 @@ void InsertFunctionToTable(const tt_char * function_name, pfunction pf) variable_name - name of the function pf - pointer to the function */ -void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf) +void InsertVariableToTable(const char * variable_name, pfunction_var pf) { - variables_table.insert( std::make_pair(tt_string(variable_name), pf)); + std::string str; + Misc::AssignString(str, variable_name); + + variables_table.insert( std::make_pair(str, pf) ); } @@ -1493,65 +1501,65 @@ void InsertVariableToTable(const tt_char * variable_name, pfunction_var pf) */ void CreateFunctionsTable() { - InsertFunctionToTable(TTMATH_TEXT("gamma"), &Parser::Gamma); - InsertFunctionToTable(TTMATH_TEXT("factorial"), &Parser::Factorial); - InsertFunctionToTable(TTMATH_TEXT("abs"), &Parser::Abs); - InsertFunctionToTable(TTMATH_TEXT("sin"), &Parser::Sin); - InsertFunctionToTable(TTMATH_TEXT("cos"), &Parser::Cos); - InsertFunctionToTable(TTMATH_TEXT("tan"), &Parser::Tan); - InsertFunctionToTable(TTMATH_TEXT("tg"), &Parser::Tan); - InsertFunctionToTable(TTMATH_TEXT("cot"), &Parser::Cot); - InsertFunctionToTable(TTMATH_TEXT("ctg"), &Parser::Cot); - InsertFunctionToTable(TTMATH_TEXT("int"), &Parser::Int); - InsertFunctionToTable(TTMATH_TEXT("round"), &Parser::Round); - InsertFunctionToTable(TTMATH_TEXT("ln"), &Parser::Ln); - InsertFunctionToTable(TTMATH_TEXT("log"), &Parser::Log); - InsertFunctionToTable(TTMATH_TEXT("exp"), &Parser::Exp); - InsertFunctionToTable(TTMATH_TEXT("max"), &Parser::Max); - InsertFunctionToTable(TTMATH_TEXT("min"), &Parser::Min); - InsertFunctionToTable(TTMATH_TEXT("asin"), &Parser::ASin); - InsertFunctionToTable(TTMATH_TEXT("acos"), &Parser::ACos); - InsertFunctionToTable(TTMATH_TEXT("atan"), &Parser::ATan); - InsertFunctionToTable(TTMATH_TEXT("atg"), &Parser::ATan); - InsertFunctionToTable(TTMATH_TEXT("acot"), &Parser::ACot); - InsertFunctionToTable(TTMATH_TEXT("actg"), &Parser::ACot); - InsertFunctionToTable(TTMATH_TEXT("sgn"), &Parser::Sgn); - InsertFunctionToTable(TTMATH_TEXT("mod"), &Parser::Mod); - InsertFunctionToTable(TTMATH_TEXT("if"), &Parser::If); - InsertFunctionToTable(TTMATH_TEXT("or"), &Parser::Or); - InsertFunctionToTable(TTMATH_TEXT("and"), &Parser::And); - InsertFunctionToTable(TTMATH_TEXT("not"), &Parser::Not); - InsertFunctionToTable(TTMATH_TEXT("degtorad"), &Parser::DegToRad); - InsertFunctionToTable(TTMATH_TEXT("radtodeg"), &Parser::RadToDeg); - InsertFunctionToTable(TTMATH_TEXT("degtodeg"), &Parser::DegToDeg); - InsertFunctionToTable(TTMATH_TEXT("gradtorad"), &Parser::GradToRad); - InsertFunctionToTable(TTMATH_TEXT("radtograd"), &Parser::RadToGrad); - InsertFunctionToTable(TTMATH_TEXT("degtograd"), &Parser::DegToGrad); - InsertFunctionToTable(TTMATH_TEXT("gradtodeg"), &Parser::GradToDeg); - InsertFunctionToTable(TTMATH_TEXT("ceil"), &Parser::Ceil); - InsertFunctionToTable(TTMATH_TEXT("floor"), &Parser::Floor); - InsertFunctionToTable(TTMATH_TEXT("sqrt"), &Parser::Sqrt); - InsertFunctionToTable(TTMATH_TEXT("sinh"), &Parser::Sinh); - InsertFunctionToTable(TTMATH_TEXT("cosh"), &Parser::Cosh); - InsertFunctionToTable(TTMATH_TEXT("tanh"), &Parser::Tanh); - InsertFunctionToTable(TTMATH_TEXT("tgh"), &Parser::Tanh); - InsertFunctionToTable(TTMATH_TEXT("coth"), &Parser::Coth); - InsertFunctionToTable(TTMATH_TEXT("ctgh"), &Parser::Coth); - InsertFunctionToTable(TTMATH_TEXT("root"), &Parser::Root); - InsertFunctionToTable(TTMATH_TEXT("asinh"), &Parser::ASinh); - InsertFunctionToTable(TTMATH_TEXT("acosh"), &Parser::ACosh); - InsertFunctionToTable(TTMATH_TEXT("atanh"), &Parser::ATanh); - InsertFunctionToTable(TTMATH_TEXT("atgh"), &Parser::ATanh); - InsertFunctionToTable(TTMATH_TEXT("acoth"), &Parser::ACoth); - InsertFunctionToTable(TTMATH_TEXT("actgh"), &Parser::ACoth); - InsertFunctionToTable(TTMATH_TEXT("bitand"), &Parser::BitAnd); - InsertFunctionToTable(TTMATH_TEXT("bitor"), &Parser::BitOr); - InsertFunctionToTable(TTMATH_TEXT("bitxor"), &Parser::BitXor); - InsertFunctionToTable(TTMATH_TEXT("band"), &Parser::BitAnd); - InsertFunctionToTable(TTMATH_TEXT("bor"), &Parser::BitOr); - InsertFunctionToTable(TTMATH_TEXT("bxor"), &Parser::BitXor); - InsertFunctionToTable(TTMATH_TEXT("sum"), &Parser::Sum); - InsertFunctionToTable(TTMATH_TEXT("avg"), &Parser::Avg); + InsertFunctionToTable("gamma", &Parser::Gamma); + InsertFunctionToTable("factorial", &Parser::Factorial); + InsertFunctionToTable("abs", &Parser::Abs); + InsertFunctionToTable("sin", &Parser::Sin); + InsertFunctionToTable("cos", &Parser::Cos); + InsertFunctionToTable("tan", &Parser::Tan); + InsertFunctionToTable("tg", &Parser::Tan); + InsertFunctionToTable("cot", &Parser::Cot); + InsertFunctionToTable("ctg", &Parser::Cot); + InsertFunctionToTable("int", &Parser::Int); + InsertFunctionToTable("round", &Parser::Round); + InsertFunctionToTable("ln", &Parser::Ln); + InsertFunctionToTable("log", &Parser::Log); + InsertFunctionToTable("exp", &Parser::Exp); + InsertFunctionToTable("max", &Parser::Max); + InsertFunctionToTable("min", &Parser::Min); + InsertFunctionToTable("asin", &Parser::ASin); + InsertFunctionToTable("acos", &Parser::ACos); + InsertFunctionToTable("atan", &Parser::ATan); + InsertFunctionToTable("atg", &Parser::ATan); + InsertFunctionToTable("acot", &Parser::ACot); + InsertFunctionToTable("actg", &Parser::ACot); + InsertFunctionToTable("sgn", &Parser::Sgn); + InsertFunctionToTable("mod", &Parser::Mod); + InsertFunctionToTable("if", &Parser::If); + InsertFunctionToTable("or", &Parser::Or); + InsertFunctionToTable("and", &Parser::And); + InsertFunctionToTable("not", &Parser::Not); + InsertFunctionToTable("degtorad", &Parser::DegToRad); + InsertFunctionToTable("radtodeg", &Parser::RadToDeg); + InsertFunctionToTable("degtodeg", &Parser::DegToDeg); + InsertFunctionToTable("gradtorad", &Parser::GradToRad); + InsertFunctionToTable("radtograd", &Parser::RadToGrad); + InsertFunctionToTable("degtograd", &Parser::DegToGrad); + InsertFunctionToTable("gradtodeg", &Parser::GradToDeg); + InsertFunctionToTable("ceil", &Parser::Ceil); + InsertFunctionToTable("floor", &Parser::Floor); + InsertFunctionToTable("sqrt", &Parser::Sqrt); + InsertFunctionToTable("sinh", &Parser::Sinh); + InsertFunctionToTable("cosh", &Parser::Cosh); + InsertFunctionToTable("tanh", &Parser::Tanh); + InsertFunctionToTable("tgh", &Parser::Tanh); + InsertFunctionToTable("coth", &Parser::Coth); + InsertFunctionToTable("ctgh", &Parser::Coth); + InsertFunctionToTable("root", &Parser::Root); + InsertFunctionToTable("asinh", &Parser::ASinh); + InsertFunctionToTable("acosh", &Parser::ACosh); + InsertFunctionToTable("atanh", &Parser::ATanh); + InsertFunctionToTable("atgh", &Parser::ATanh); + InsertFunctionToTable("acoth", &Parser::ACoth); + InsertFunctionToTable("actgh", &Parser::ACoth); + InsertFunctionToTable("bitand", &Parser::BitAnd); + InsertFunctionToTable("bitor", &Parser::BitOr); + InsertFunctionToTable("bitxor", &Parser::BitXor); + InsertFunctionToTable("band", &Parser::BitAnd); + InsertFunctionToTable("bor", &Parser::BitOr); + InsertFunctionToTable("bxor", &Parser::BitXor); + InsertFunctionToTable("sum", &Parser::Sum); + InsertFunctionToTable("avg", &Parser::Avg); } @@ -1560,8 +1568,8 @@ void CreateFunctionsTable() */ void CreateVariablesTable() { - InsertVariableToTable(TTMATH_TEXT("pi"), &ValueType::SetPi); - InsertVariableToTable(TTMATH_TEXT("e"), &ValueType::SetE); + InsertVariableToTable("pi", &ValueType::SetPi); + InsertVariableToTable("e", &ValueType::SetE); } @@ -1587,7 +1595,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(tt_string & result) +bool ReadName(std::string & result) { int character; @@ -1604,7 +1612,7 @@ int character; do { - result += static_cast( character ); + result += static_cast( character ); character = * ++pstring; } while( (character>='a' && character<='z') || @@ -1659,7 +1667,7 @@ return false; */ bool ReadVariableOrFunction(Item & result) { -tt_string name; +std::string name; bool is_it_name_of_function = ReadName(name); if( is_it_name_of_function ) @@ -1688,7 +1696,7 @@ return is_it_name_of_function; */ void ReadValue(Item & result, int reading_base) { -const tt_char * new_stack_pointer; +const char * new_stack_pointer; bool value_read; uint carry = result.value.FromString(pstring, reading_base, &new_stack_pointer, &value_read); @@ -1861,9 +1869,9 @@ return 0; } -void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type) +void InsertOperatorToTable(const char * name, typename MatOperator::Type type) { - operators_table.insert( std::make_pair(tt_string(name), type) ); + operators_table.insert( std::make_pair(std::string(name), type) ); } @@ -1872,19 +1880,19 @@ void InsertOperatorToTable(const tt_char * name, typename MatOperator::Type type */ void CreateMathematicalOperatorsTable() { - InsertOperatorToTable(TTMATH_TEXT("||"), MatOperator::lor); - InsertOperatorToTable(TTMATH_TEXT("&&"), MatOperator::land); - InsertOperatorToTable(TTMATH_TEXT("!="), MatOperator::neq); - InsertOperatorToTable(TTMATH_TEXT("=="), MatOperator::eq); - InsertOperatorToTable(TTMATH_TEXT(">="), MatOperator::get); - InsertOperatorToTable(TTMATH_TEXT("<="), MatOperator::let); - InsertOperatorToTable(TTMATH_TEXT(">"), MatOperator::gt); - InsertOperatorToTable(TTMATH_TEXT("<"), MatOperator::lt); - InsertOperatorToTable(TTMATH_TEXT("-"), MatOperator::sub); - InsertOperatorToTable(TTMATH_TEXT("+"), MatOperator::add); - InsertOperatorToTable(TTMATH_TEXT("/"), MatOperator::div); - InsertOperatorToTable(TTMATH_TEXT("*"), MatOperator::mul); - InsertOperatorToTable(TTMATH_TEXT("^"), MatOperator::pow); + InsertOperatorToTable("||", MatOperator::lor); + InsertOperatorToTable("&&", MatOperator::land); + InsertOperatorToTable("!=", MatOperator::neq); + InsertOperatorToTable("==", MatOperator::eq); + InsertOperatorToTable(">=", MatOperator::get); + InsertOperatorToTable("<=", MatOperator::let); + InsertOperatorToTable(">", MatOperator::gt); + InsertOperatorToTable("<", MatOperator::lt); + InsertOperatorToTable("-", MatOperator::sub); + InsertOperatorToTable("+", MatOperator::add); + InsertOperatorToTable("/", MatOperator::div); + InsertOperatorToTable("*", MatOperator::mul); + InsertOperatorToTable("^", MatOperator::pow); } @@ -1894,12 +1902,12 @@ void CreateMathematicalOperatorsTable() e.g. true when str1="test" and str2="te" */ -bool IsSubstring(const tt_string & str1, const tt_string & str2) +bool IsSubstring(const std::string & str1, const std::string & str2) { if( str2.length() > str1.length() ) return false; - for(tt_string::size_type i=0 ; i + void PrintTable(ostream_type & output) const { // how many columns there'll be const int columns = 8; @@ -97,7 +96,7 @@ public: int c = 1; for(int i=value_size-1 ; i>=0 ; --i) { - output << TTMATH_TEXT("0x") << std::setfill('0'); + output << "0x" << std::setfill('0'); #ifdef TTMATH_PLATFORM32 output << std::setw(8); @@ -109,7 +108,7 @@ public: if( i>0 ) { - output << TTMATH_TEXT(", "); + output << ", "; if( ++c > columns ) { @@ -121,14 +120,15 @@ public: output << std::dec << std::endl; } - #endif - void PrintLog(const tt_char * msg, tt_ostream & output) const + + template + void PrintLog(const char_type * msg, ostream_type & output) const { output << msg << std::endl; for(uint i=0 ; i type = 10; - this constant 10 has the int type (signed int), if we don't give such + above "10" constant 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 tt_char*), operator=(uint) etc.) + (the UInt class has operator=(const char*), operator=(uint) etc.) */ UInt & operator=(sint i) { @@ -2621,18 +2621,38 @@ public: /*! a constructor for converting a string to this class (with the base=10) */ - UInt(const tt_char * s) + UInt(const char * s) { FromString(s); - TTMATH_LOG("UInt::UInt(const tt_char *)") + TTMATH_LOG("UInt::UInt(const char *)") } /*! a constructor for converting a string to this class (with the base=10) */ - UInt(const tt_string & s) + UInt(const wchar_t * s) + { + FromString(s); + + TTMATH_LOG("UInt::UInt(const wchar_t *)") + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const std::string & s) + { + FromString( s.c_str() ); + } + + + /*! + a constructor for converting a string to this class (with the base=10) + */ + UInt(const std::wstring & s) { FromString( s.c_str() ); } @@ -2695,13 +2715,16 @@ public: } +private: + /*! - this method converts the value to a string with a base equal 'b' + an auxiliary method for converting to a string */ - void ToString(tt_string & result, uint b = 10) const + template + void ToStringBase(string_type & result, uint b = 10) const { UInt temp( *this ); - tt_char character; + char character; uint rem; result.clear(); @@ -2712,7 +2735,7 @@ public: do { temp.DivInt(b, &rem); - character = static_cast( DigitToChar(rem) ); + character = static_cast( DigitToChar(rem) ); result.insert(result.begin(), character); } while( !temp.IsZero() ); @@ -2721,36 +2744,42 @@ public: } +public: + + /*! + this method converts the value to a string with a base equal 'b' + */ + void ToString(std::string & result, uint b = 10) const + { + return ToStringBase(result, b); + } + + void ToString(std::wstring & result, uint b = 10) const + { + return ToStringBase(result, b); + } + /* this method's ommiting any white characters from the string + char_type is char or wchar_t */ - static void SkipWhiteCharacters(const tt_char * & c) + template + static void SkipWhiteCharacters(const char_type * & c) { while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) ++c; } +private: + /*! - 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 - - string is ended with a non-digit value, for example: - "12" will be translated to 12 - as well as: - "12foo" will be translated to 12 too - - existing first white characters will be ommited - - if the value from s is too large the rest digits will be skipped - - after_source (if exists) is pointing at the end of the parsed string - - value_read (if exists) tells whether something has actually been read (at least one digit) + an auxiliary method for converting from a string */ - uint FromString(const tt_char * s, uint b = 10, const tt_char ** after_source = 0, bool * value_read = 0) + template + uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) { UInt base( b ); UInt temp; @@ -2794,28 +2823,70 @@ public: } +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 + + string is ended with a non-digit value, for example: + "12" will be translated to 12 + as well as: + "12foo" will be translated to 12 too + + existing first white characters will be ommited + + if the value from s is too large the rest digits will be skipped + + after_source (if exists) is pointing at the end of the parsed string + + value_read (if exists) tells whether something has actually been read (at least one digit) + */ + uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + + + /*! + this method converts a string into its value + */ + uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, b, after_source, value_read); + } + /*! 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 tt_string & s, uint b = 10) + uint FromString(const std::string & s, uint b = 10) { return FromString( s.c_str(), b ); } + /*! + 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::wstring & s, uint b = 10) + { + return FromString( s.c_str(), b ); + } + /*! this operator converts a string into its value (with base = 10) */ - UInt & operator=(const tt_char * s) + UInt & operator=(const char * s) { FromString(s); - TTMATH_LOG("UInt::operator=(const tt_char *)") - return *this; } @@ -2823,7 +2894,18 @@ public: /*! this operator converts a string into its value (with base = 10) */ - UInt & operator=(const tt_string & s) + UInt & operator=(const wchar_t * s) + { + FromString(s); + + return *this; + } + + + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const std::string & s) { FromString( s.c_str() ); @@ -2831,6 +2913,15 @@ public: } + /*! + this operator converts a string into its value (with base = 10) + */ + UInt & operator=(const std::wstring & s) + { + FromString( s.c_str() ); + + return *this; + } /*! @@ -3192,14 +3283,16 @@ public: */ - /*! - output for standard streams +private: - tt_ostream is either std::ostream or std::wostream + + /*! + an auxiliary method for outputing to standard streams */ - friend tt_ostream & operator<<(tt_ostream & s, const UInt & l) + template + static ostream_type & OutputToStream(ostream_type & s, const UInt & l) { - tt_string ss; + string_type ss; l.ToString(ss); s << ss; @@ -3208,18 +3301,39 @@ public: } +public: + /*! - input from standard streams - - tt_istream is either std::istream or std::wistream + output to standard streams */ - friend tt_istream & operator>>(tt_istream & s, UInt & l) + friend std::ostream & operator<<(std::ostream & s, const UInt & l) { - tt_string ss; + return OutputToStream(s, l); + } + + + /*! + output to standard streams + */ + friend std::wostream & operator<<(std::wostream & s, const UInt & l) + { + return OutputToStream(s, l); + } + + +private: + + /*! + an auxiliary method for reading from standard streams + */ + template + static istream_type & InputFromStream(istream_type & s, UInt & l) + { + string_type ss; - // tt_char for operator>> - tt_char z; + // char or wchar_t for operator>> + char_type z; // operator>> omits white characters if they're set for ommiting s >> z; @@ -3228,7 +3342,7 @@ public: while( s.good() && CharToDigit(z, 10)>=0 ) { ss += z; - z = static_cast(s.get()); + z = static_cast(s.get()); } // we're leaving the last read character @@ -3237,11 +3351,28 @@ public: l.FromString(ss); - TTMATH_LOG("UInt::operator>>") - return s; } +public: + + + /*! + input from standard streams + */ + friend std::istream & operator>>(std::istream & s, UInt & l) + { + return InputFromStream(s, l); + } + + + /*! + input from standard streams + */ + friend std::wistream & operator>>(std::wistream & s, UInt & l) + { + return InputFromStream(s, l); + } /*