Library for big numbers from http://www.ttmath.org/
Dependents: PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more
ttmathdec.h
00001 /* 00002 * This file is a part of TTMath Bignum Library 00003 * and is distributed under the (new) BSD licence. 00004 * Author: Tomasz Sowa <t.sowa@ttmath.org> 00005 */ 00006 00007 /* 00008 * Copyright (c) 2012, Tomasz Sowa 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 00017 * * Redistributions in binary form must reproduce the above copyright 00018 * notice, this list of conditions and the following disclaimer in the 00019 * documentation and/or other materials provided with the distribution. 00020 * 00021 * * Neither the name Tomasz Sowa nor the names of contributors to this 00022 * project may be used to endorse or promote products derived 00023 * from this software without specific prior written permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00035 * THE POSSIBILITY OF SUCH DAMAGE. 00036 */ 00037 00038 #ifndef headerfilettmathdec 00039 #define headerfilettmathdec 00040 00041 #include "ttmathtypes.h" 00042 #include "ttmaththreads.h" 00043 #include "ttmathuint.h" 00044 00045 00046 00047 namespace ttmath 00048 { 00049 00050 template<uint value_size, uint dec_digits> 00051 class Dec 00052 { 00053 public: 00054 00055 UInt<value_size> value; 00056 unsigned char info; 00057 00058 00059 /*! 00060 Sign 00061 the mask of a bit from 'info' which means that there is a sign 00062 (when the bit is set) 00063 */ 00064 #define TTMATH_DEC_SIGN 128 00065 00066 00067 /*! 00068 Not a number 00069 if this bit is set that there is not a valid number 00070 */ 00071 #define TTMATH_DEC_NAN 64 00072 00073 00074 00075 00076 Dec() 00077 { 00078 info = TTMATH_DEC_NAN; 00079 } 00080 00081 00082 Dec(const char * s) 00083 { 00084 info = TTMATH_DEC_NAN; 00085 FromString(s); 00086 } 00087 00088 00089 Dec<value_size, dec_digits> & operator=(const char * s) 00090 { 00091 FromString(s); 00092 00093 return *this; 00094 } 00095 00096 00097 uint FromString(const char * s, const char ** after_source = 0, bool * value_read = 0) 00098 { 00099 return FromStringBase(s, after_source, value_read); 00100 } 00101 00102 00103 void ToString(std::string & result) const 00104 { 00105 ToStringBase(result); 00106 } 00107 00108 00109 /*! 00110 this method clears a specific bit in the 'info' variable 00111 00112 bit is one of: 00113 */ 00114 void ClearInfoBit(unsigned char bit) 00115 { 00116 info = info & (~bit); 00117 } 00118 00119 00120 /*! 00121 this method sets a specific bit in the 'info' variable 00122 00123 bit is one of: 00124 00125 */ 00126 void SetInfoBit(unsigned char bit) 00127 { 00128 info = info | bit; 00129 } 00130 00131 00132 /*! 00133 this method returns true if a specific bit in the 'info' variable is set 00134 00135 bit is one of: 00136 */ 00137 bool IsInfoBit(unsigned char bit) const 00138 { 00139 return (info & bit) != 0; 00140 } 00141 00142 00143 bool IsNan() const 00144 { 00145 return IsInfoBit(TTMATH_DEC_NAN); 00146 } 00147 00148 00149 bool IsSign() const 00150 { 00151 return IsInfoBit(TTMATH_DEC_SIGN); 00152 } 00153 00154 00155 /*! 00156 this method sets the sign 00157 00158 e.g. 00159 -1 -> -1 00160 2 -> -2 00161 00162 we do not check whether there is a zero or not, if you're using this method 00163 you must be sure that the value is (or will be afterwards) different from zero 00164 */ 00165 void SetSign() 00166 { 00167 SetInfoBit(TTMATH_DEC_SIGN); 00168 } 00169 00170 00171 void SetNaN() 00172 { 00173 SetInfoBit(TTMATH_DEC_NAN); 00174 } 00175 00176 00177 void Abs () 00178 { 00179 ClearInfoBit(TTMATH_DEC_SIGN); 00180 } 00181 00182 00183 00184 uint Add(const Dec<value_size, dec_digits> & arg) 00185 { 00186 uint c = 0; 00187 00188 if( IsSign() == arg.IsSign() ) 00189 { 00190 c += value.Add(arg.value); 00191 } 00192 else 00193 { 00194 bool is_sign; 00195 00196 if( value > arg.value ) 00197 { 00198 is_sign = IsSign(); 00199 value.Sub(arg.value); 00200 } 00201 else 00202 { 00203 is_sign = arg.IsSign(); 00204 UInt<value_size> temp(this->value); 00205 value = arg.value; 00206 value.Sub(temp); 00207 } 00208 00209 is_sign ? SetSign() : Abs (); 00210 } 00211 00212 if( c ) 00213 SetNaN(); 00214 00215 return (c==0)? 0 : 1; 00216 } 00217 00218 /* 00219 uint Sub(const Dec<value_size, dec_digits> & arg) 00220 { 00221 } 00222 */ 00223 00224 private: 00225 00226 00227 00228 00229 00230 00231 #ifndef TTMATH_MULTITHREADS 00232 00233 /*! 00234 */ 00235 void SetMultipler(UInt<value_size> & result) 00236 { 00237 // this guardian is initialized before the program runs (static POD type) 00238 static int guardian = 0; 00239 static UInt<value_size> multipler; 00240 00241 if( guardian == 0 ) 00242 { 00243 multipler = 10; 00244 multipler.Pow(dec_digits); 00245 guardian = 1; 00246 } 00247 00248 result = multipler; 00249 } 00250 00251 #else 00252 00253 /*! 00254 */ 00255 void SetMultipler(UInt<value_size> & result) 00256 { 00257 // this guardian is initialized before the program runs (static POD type) 00258 volatile static sig_atomic_t guardian = 0; 00259 static UInt<value_size> * pmultipler; 00260 00261 // double-checked locking 00262 if( guardian == 0 ) 00263 { 00264 ThreadLock thread_lock; 00265 00266 // locking 00267 if( thread_lock.Lock() ) 00268 { 00269 static UInt<value_size> multipler; 00270 00271 if( guardian == 0 ) 00272 { 00273 pmultipler = &multipler; 00274 multipler = 10; 00275 multipler.Pow(dec_digits); 00276 guardian = 1; 00277 } 00278 } 00279 else 00280 { 00281 // there was a problem with locking, we store the result directly in 'result' object 00282 result = 10; 00283 result.Pow(dec_digits); 00284 00285 return; 00286 } 00287 00288 // automatically unlocking 00289 } 00290 00291 result = *pmultipler; 00292 } 00293 00294 #endif 00295 00296 00297 00298 /*! 00299 an auxiliary method for converting from a string 00300 */ 00301 template<class char_type> 00302 uint FromStringBase(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) 00303 { 00304 UInt<value_size> multipler; 00305 const char_type * after; 00306 uint c = 0; 00307 info = 0; 00308 00309 Misc::SkipWhiteCharacters(s); 00310 00311 if( *s == '-' ) 00312 { 00313 s += 1; 00314 SetSign(); 00315 } 00316 else 00317 if( *s == '+' ) 00318 { 00319 s += 1; 00320 } 00321 00322 c += value.FromString(s, 10, &after, value_read); 00323 00324 if( after_source ) 00325 *after_source = after; 00326 00327 SetMultipler(multipler); 00328 c += value.Mul(multipler); 00329 00330 if( *after == '.' ) 00331 c += FromStringBaseAfterComma(after+1, after_source); 00332 00333 if( c ) 00334 SetInfoBit(TTMATH_DEC_NAN); 00335 00336 return (c==0)? 0 : 1; 00337 } 00338 00339 00340 template<class char_type> 00341 uint FromStringBaseAfterComma(const char_type * s, const char_type ** after_source = 0, bool * value_read = 0) 00342 { 00343 UInt<value_size> temp; 00344 UInt<value_size> multipler; 00345 sint z; 00346 uint c = 0; 00347 size_t i = dec_digits; 00348 00349 SetMultipler(multipler); 00350 00351 for( ; i>0 && (z=Misc::CharToDigit (*s, 10)) != -1 ; --i, ++s ) 00352 { 00353 multipler.DivInt(10); 00354 temp.SetZero(); 00355 00356 if( value_read ) 00357 *value_read = true; 00358 00359 if( c == 0 ) 00360 { 00361 temp.table[0] = z; 00362 c += temp.Mul(multipler); 00363 c += value.Add(temp); 00364 } 00365 } 00366 00367 if( i == 0 && (z=Misc::CharToDigit (*s, 10)) != -1 && z >= 5 ) 00368 c += value.AddOne(); 00369 00370 if( after_source ) 00371 { 00372 while( (z=Misc::CharToDigit (*s, 10)) != -1 ) 00373 s += 1; 00374 00375 *after_source = s; 00376 } 00377 00378 return c; 00379 } 00380 00381 00382 00383 template<class string_type> 00384 void ToStringBase(string_type & result) const 00385 { 00386 if( IsNan() ) 00387 { 00388 result = "NaN"; 00389 return; 00390 } 00391 00392 value.ToStringBase(result, 10, IsSign()); 00393 00394 if( dec_digits > 0 ) 00395 { 00396 size_t size = result.size(); 00397 00398 if( IsSign() && size > 0 ) 00399 size -= 1; 00400 00401 if( dec_digits >= size ) 00402 { 00403 size_t zeroes = dec_digits - size + 1; 00404 size_t start = IsSign() ? 1 : 0; 00405 result.insert(start, zeroes, '0'); 00406 } 00407 00408 result.insert(result.end() - dec_digits, '.'); 00409 } 00410 } 00411 00412 00413 00414 }; 00415 00416 00417 } // namespace 00418 00419 #endif 00420
Generated on Tue Jul 12 2022 14:03:18 by 1.7.2