From 6862321fadecdb5f5b6e5814931558d7545d7031 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 4 Feb 2012 16:26:11 +0000 Subject: [PATCH] added: ttmath/ttmathdec.h starting work on a Decimal template type git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@381 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmath.h | 4 +- ttmath/ttmathdec.h | 419 ++++++++++++++++++++++++++++++++++++++++++++ ttmath/ttmathuint.h | 7 +- 3 files changed, 426 insertions(+), 4 deletions(-) create mode 100644 ttmath/ttmathdec.h diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 37c971f..f862b8b 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -2832,9 +2832,11 @@ namespace ttmath /*! this is for convenience for the user - he can only use '#include ' even if he uses the parser + he can only use '#include ' */ #include "ttmathparser.h" +#include "ttmathdec.h" + #ifdef _MSC_VER diff --git a/ttmath/ttmathdec.h b/ttmath/ttmathdec.h new file mode 100644 index 0000000..92d3e39 --- /dev/null +++ b/ttmath/ttmathdec.h @@ -0,0 +1,419 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfilettmathdec +#define headerfilettmathdec + +#include "ttmathtypes.h" +#include "ttmaththreads.h" +#include "ttmathuint.h" + + + +namespace ttmath +{ + +template +class Dec +{ +public: + + UInt value; + unsigned char info; + + + /*! + Sign + the mask of a bit from 'info' which means that there is a sign + (when the bit is set) + */ + #define TTMATH_DEC_SIGN 128 + + + /*! + Not a number + if this bit is set that there is not a valid number + */ + #define TTMATH_DEC_NAN 64 + + + + + Dec() + { + info = TTMATH_DEC_NAN; + } + + + Dec(const char * s) + { + info = TTMATH_DEC_NAN; + FromString(s); + } + + + Dec & operator=(const char * s) + { + FromString(s); + + return *this; + } + + + uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, after_source, value_read); + } + + + void ToString(std::string & result) const + { + ToStringBase(result); + } + + + /*! + this method clears a specific bit in the 'info' variable + + bit is one of: + */ + void ClearInfoBit(unsigned char bit) + { + info = info & (~bit); + } + + + /*! + this method sets a specific bit in the 'info' variable + + bit is one of: + + */ + void SetInfoBit(unsigned char bit) + { + info = info | bit; + } + + + /*! + this method returns true if a specific bit in the 'info' variable is set + + bit is one of: + */ + bool IsInfoBit(unsigned char bit) const + { + return (info & bit) != 0; + } + + + bool IsNan() const + { + return IsInfoBit(TTMATH_DEC_NAN); + } + + + bool IsSign() const + { + return IsInfoBit(TTMATH_DEC_SIGN); + } + + + /*! + this method sets the sign + + e.g. + -1 -> -1 + 2 -> -2 + + we do not check whether there is a zero or not, if you're using this method + you must be sure that the value is (or will be afterwards) different from zero + */ + void SetSign() + { + SetInfoBit(TTMATH_DEC_SIGN); + } + + + void SetNaN() + { + SetInfoBit(TTMATH_DEC_NAN); + } + + + void Abs() + { + ClearInfoBit(TTMATH_DEC_SIGN); + } + + + + uint Add(const Dec & arg) + { + uint c = 0; + + if( IsSign() == arg.IsSign() ) + { + c += value.Add(arg.value); + } + else + { + bool is_sign; + + if( value > arg.value ) + { + is_sign = IsSign(); + value.Sub(arg.value); + } + else + { + is_sign = arg.IsSign(); + UInt temp(this->value); + value = arg.value; + value.Sub(temp); + } + + is_sign ? SetSign() : Abs(); + } + + if( c ) + SetNaN(); + + return (c==0)? 0 : 1; + } + +/* + uint Sub(const Dec & arg) + { + } +*/ + +private: + + + + + + +#ifndef TTMATH_MULTITHREADS + + /*! + */ + void SetMultipler(UInt & result) + { + // this guardian is initialized before the program runs (static POD type) + static int guardian = 0; + static UInt multipler; + + if( guardian == 0 ) + { + multipler = 10; + multipler.Pow(dec_digits); + guardian = 1; + } + + result = multipler; + } + +#else + + /*! + */ + void SetMultipler(UInt & result) + { + // this guardian is initialized before the program runs (static POD type) + volatile static sig_atomic_t guardian = 0; + static UInt * pmultipler; + + // double-checked locking + if( guardian == 0 ) + { + ThreadLock thread_lock; + + // locking + if( thread_lock.Lock() ) + { + static UInt multipler; + + if( guardian == 0 ) + { + pmultipler = &multipler; + multipler = 10; + multipler.Pow(dec_digits); + guardian = 1; + } + } + else + { + // there was a problem with locking, we store the result directly in 'result' object + result = 10; + result.Pow(dec_digits); + + return; + } + + // automatically unlocking + } + + result = *pmultipler; + } + +#endif + + + + /*! + an auxiliary method for converting from a string + */ + template + uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) + { + UInt multipler; + const char_type * after; + uint c = 0; + info = 0; + + Misc::SkipWhiteCharacters(s); + + if( *s == '-' ) + { + s += 1; + SetSign(); + } + else + if( *s == '+' ) + { + s += 1; + } + + c += value.FromString(s, 10, &after, value_read); + + if( after_source ) + *after_source = after; + + SetMultipler(multipler); + c += value.Mul(multipler); + + if( *after == '.' ) + c += FromStringBaseAfterComma(after+1, after_source); + + if( c ) + SetInfoBit(TTMATH_DEC_NAN); + + return (c==0)? 0 : 1; + } + + + template + uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) + { + UInt temp; + UInt multipler; + sint z; + uint c = 0; + size_t i = dec_digits; + + SetMultipler(multipler); + + for( ; i>0 && (z=Misc::CharToDigit(*s, 10)) != -1 ; --i, ++s ) + { + multipler.DivInt(10); + temp.SetZero(); + + if( value_read ) + *value_read = true; + + if( c == 0 ) + { + temp.table[0] = z; + c += temp.Mul(multipler); + c += value.Add(temp); + } + } + + if( i == 0 && (z=Misc::CharToDigit(*s, 10)) != -1 && z >= 5 ) + c += value.AddOne(); + + if( after_source ) + { + while( (z=Misc::CharToDigit(*s, 10)) != -1 ) + s += 1; + + *after_source = s; + } + + return c; + } + + + + template + void ToStringBase(string_type & result) const + { + if( IsNan() ) + { + result = "NaN"; + return; + } + + value.ToStringBase(result, 10, IsSign()); + + if( dec_digits > 0 ) + { + size_t size = result.size(); + + if( IsSign() && size > 0 ) + size -= 1; + + if( dec_digits >= size ) + { + size_t zeroes = dec_digits - size + 1; + size_t start = IsSign() ? 1 : 0; + result.insert(start, zeroes, '0'); + } + + result.insert(result.end() - dec_digits, '.'); + } + } + + + +}; + + +} // namespace + +#endif diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index d0f6df1..2365bf5 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -3238,6 +3238,9 @@ protected: } +public: + + /*! an auxiliary method for converting to a string it's used from Int::ToString() too (negative is set true then) @@ -3294,8 +3297,6 @@ protected: -public: - /*! this method converts the value to a string with a base equal 'b' */ @@ -3369,7 +3370,7 @@ private: { temp.table[0] = z; - c += Mul(base); + c += Mul(base); // !! IMPROVE ME: there can be used MulInt here c += Add(temp); } }