Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more
Diff: ttmathdec.h
- Revision:
- 0:04a9f72bbca7
diff -r 000000000000 -r 04a9f72bbca7 ttmathdec.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ttmathdec.h Tue Jul 30 18:43:48 2013 +0000 @@ -0,0 +1,420 @@ +/* + * This file is a part of TTMath Bignum Library + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa <t.sowa@ttmath.org> + */ + +/* + * Copyright (c) 2012, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfilettmathdec +#define headerfilettmathdec + +#include "ttmathtypes.h" +#include "ttmaththreads.h" +#include "ttmathuint.h" + + + +namespace ttmath +{ + +template<uint value_size, uint dec_digits> +class Dec +{ +public: + + UInt<value_size> value; + unsigned char info; + + + /*! + Sign + the mask of a bit from 'info' which means that there is a sign + (when the bit is set) + */ + #define TTMATH_DEC_SIGN 128 + + + /*! + Not a number + if this bit is set that there is not a valid number + */ + #define TTMATH_DEC_NAN 64 + + + + + Dec() + { + info = TTMATH_DEC_NAN; + } + + + Dec(const char * s) + { + info = TTMATH_DEC_NAN; + FromString(s); + } + + + Dec<value_size, dec_digits> & operator=(const char * s) + { + FromString(s); + + return *this; + } + + + uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0) + { + return FromStringBase(s, after_source, value_read); + } + + + void ToString(std::string & result) const + { + ToStringBase(result); + } + + + /*! + this method clears a specific bit in the 'info' variable + + bit is one of: + */ + void ClearInfoBit(unsigned char bit) + { + info = info & (~bit); + } + + + /*! + this method sets a specific bit in the 'info' variable + + bit is one of: + + */ + void SetInfoBit(unsigned char bit) + { + info = info | bit; + } + + + /*! + this method returns true if a specific bit in the 'info' variable is set + + bit is one of: + */ + bool IsInfoBit(unsigned char bit) const + { + return (info & bit) != 0; + } + + + bool IsNan() const + { + return IsInfoBit(TTMATH_DEC_NAN); + } + + + bool IsSign() const + { + return IsInfoBit(TTMATH_DEC_SIGN); + } + + + /*! + this method sets the sign + + e.g. + -1 -> -1 + 2 -> -2 + + we do not check whether there is a zero or not, if you're using this method + you must be sure that the value is (or will be afterwards) different from zero + */ + void SetSign() + { + SetInfoBit(TTMATH_DEC_SIGN); + } + + + void SetNaN() + { + SetInfoBit(TTMATH_DEC_NAN); + } + + + void Abs() + { + ClearInfoBit(TTMATH_DEC_SIGN); + } + + + + uint Add(const Dec<value_size, dec_digits> & arg) + { + uint c = 0; + + if( IsSign() == arg.IsSign() ) + { + c += value.Add(arg.value); + } + else + { + bool is_sign; + + if( value > arg.value ) + { + is_sign = IsSign(); + value.Sub(arg.value); + } + else + { + is_sign = arg.IsSign(); + UInt<value_size> temp(this->value); + value = arg.value; + value.Sub(temp); + } + + is_sign ? SetSign() : Abs(); + } + + if( c ) + SetNaN(); + + return (c==0)? 0 : 1; + } + +/* + uint Sub(const Dec<value_size, dec_digits> & arg) + { + } +*/ + +private: + + + + + + +#ifndef TTMATH_MULTITHREADS + + /*! + */ + void SetMultipler(UInt<value_size> & result) + { + // this guardian is initialized before the program runs (static POD type) + static int guardian = 0; + static UInt<value_size> multipler; + + if( guardian == 0 ) + { + multipler = 10; + multipler.Pow(dec_digits); + guardian = 1; + } + + result = multipler; + } + +#else + + /*! + */ + void SetMultipler(UInt<value_size> & result) + { + // this guardian is initialized before the program runs (static POD type) + volatile static sig_atomic_t guardian = 0; + static UInt<value_size> * pmultipler; + + // double-checked locking + if( guardian == 0 ) + { + ThreadLock thread_lock; + + // locking + if( thread_lock.Lock() ) + { + static UInt<value_size> multipler; + + if( guardian == 0 ) + { + pmultipler = &multipler; + multipler = 10; + multipler.Pow(dec_digits); + guardian = 1; + } + } + else + { + // there was a problem with locking, we store the result directly in 'result' object + result = 10; + result.Pow(dec_digits); + + return; + } + + // automatically unlocking + } + + result = *pmultipler; + } + +#endif + + + + /*! + an auxiliary method for converting from a string + */ + template<class char_type> + uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) + { + UInt<value_size> multipler; + const char_type * after; + uint c = 0; + info = 0; + + Misc::SkipWhiteCharacters(s); + + if( *s == '-' ) + { + s += 1; + SetSign(); + } + else + if( *s == '+' ) + { + s += 1; + } + + c += value.FromString(s, 10, &after, value_read); + + if( after_source ) + *after_source = after; + + SetMultipler(multipler); + c += value.Mul(multipler); + + if( *after == '.' ) + c += FromStringBaseAfterComma(after+1, after_source); + + if( c ) + SetInfoBit(TTMATH_DEC_NAN); + + return (c==0)? 0 : 1; + } + + + template<class char_type> + uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) + { + UInt<value_size> temp; + UInt<value_size> multipler; + sint z; + uint c = 0; + size_t i = dec_digits; + + SetMultipler(multipler); + + for( ; i>0 && (z=Misc::CharToDigit(*s, 10)) != -1 ; --i, ++s ) + { + multipler.DivInt(10); + temp.SetZero(); + + if( value_read ) + *value_read = true; + + if( c == 0 ) + { + temp.table[0] = z; + c += temp.Mul(multipler); + c += value.Add(temp); + } + } + + if( i == 0 && (z=Misc::CharToDigit(*s, 10)) != -1 && z >= 5 ) + c += value.AddOne(); + + if( after_source ) + { + while( (z=Misc::CharToDigit(*s, 10)) != -1 ) + s += 1; + + *after_source = s; + } + + return c; + } + + + + template<class string_type> + void ToStringBase(string_type & result) const + { + if( IsNan() ) + { + result = "NaN"; + return; + } + + value.ToStringBase(result, 10, IsSign()); + + if( dec_digits > 0 ) + { + size_t size = result.size(); + + if( IsSign() && size > 0 ) + size -= 1; + + if( dec_digits >= size ) + { + size_t zeroes = dec_digits - size + 1; + size_t start = IsSign() ? 1 : 0; + result.insert(start, zeroes, '0'); + } + + result.insert(result.end() - dec_digits, '.'); + } + } + + + +}; + + +} // namespace + +#endif +