Library for big numbers from http://www.ttmath.org/
Dependents: PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more
ttmathbig.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) 2006-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 headerfilettmathbig 00039 #define headerfilettmathbig 00040 00041 /*! 00042 \file ttmathbig.h 00043 \brief A Class for representing floating point numbers 00044 */ 00045 00046 #include "ttmathint.h" 00047 #include "ttmaththreads.h" 00048 00049 #include <iostream> 00050 00051 #ifdef TTMATH_MULTITHREADS 00052 #include <signal.h> 00053 #endif 00054 00055 namespace ttmath 00056 { 00057 00058 00059 /*! 00060 \brief Big implements the floating point numbers 00061 */ 00062 template <uint exp, uint man> 00063 class Big 00064 { 00065 00066 /* 00067 value = mantissa * 2^exponent 00068 00069 exponent - an integer value with a sign 00070 mantissa - an integer value without a sing 00071 00072 mantissa must be pushed into the left side that is the highest bit from 00073 mantissa must be one (of course if there's another value than zero) -- this job 00074 (pushing bits into the left side) making Standardizing() method 00075 00076 for example: 00077 if we want to store value one (1) into our Big object we must: 00078 set mantissa to 1 00079 set exponent to 0 00080 set info to 0 00081 and call method Standardizing() 00082 */ 00083 00084 00085 public: 00086 00087 Int<exp> exponent; 00088 UInt<man> mantissa; 00089 unsigned char info; 00090 00091 00092 /*! 00093 Sign 00094 the mask of a bit from 'info' which means that there is a sign 00095 (when the bit is set) 00096 */ 00097 #define TTMATH_BIG_SIGN 128 00098 00099 00100 /*! 00101 Not a number 00102 if this bit is set that there is not a valid number 00103 */ 00104 #define TTMATH_BIG_NAN 64 00105 00106 00107 /*! 00108 Zero 00109 if this bit is set that there is value zero 00110 mantissa should be zero and exponent should be zero too 00111 (the Standardizing() method does this) 00112 */ 00113 #define TTMATH_BIG_ZERO 32 00114 00115 00116 /*! 00117 this method sets NaN if there was a carry (and returns 1 in such a case) 00118 00119 c can be 0, 1 or other value different from zero 00120 */ 00121 uint CheckCarry (uint c) 00122 { 00123 if( c != 0 ) 00124 { 00125 SetNan (); 00126 return 1; 00127 } 00128 00129 return 0; 00130 } 00131 00132 public: 00133 00134 00135 /*! 00136 returning the string represents the currect type of the library 00137 we have following types: 00138 asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) 00139 asm_gcc_32 - with asm code designed for GCC (32 bits) 00140 asm_vc_64 - with asm for VC (64 bit) 00141 asm_gcc_64 - with asm for GCC (64 bit) 00142 no_asm_32 - pure C++ version (32 bit) - without any asm code 00143 no_asm_64 - pure C++ version (64 bit) - without any asm code 00144 */ 00145 static const char * LibTypeStr () 00146 { 00147 return UInt<man>::LibTypeStr (); 00148 } 00149 00150 00151 /*! 00152 returning the currect type of the library 00153 */ 00154 static LibTypeCode LibType () 00155 { 00156 return UInt<man>::LibType (); 00157 } 00158 00159 00160 00161 /*! 00162 this method moves all bits from mantissa into its left side 00163 (suitably changes the exponent) or if the mantissa is zero 00164 it sets the exponent to zero as well 00165 (and clears the sign bit and sets the zero bit) 00166 00167 it can return a carry 00168 the carry will be when we don't have enough space in the exponent 00169 00170 you don't have to use this method if you don't change the mantissa 00171 and exponent directly 00172 */ 00173 uint Standardizing () 00174 { 00175 if( mantissa.IsTheHighestBitSet () ) 00176 { 00177 ClearInfoBit (TTMATH_BIG_ZERO); 00178 return 0; 00179 } 00180 00181 if( CorrectZero() ) 00182 return 0; 00183 00184 uint comp = mantissa.CompensationToLeft (); 00185 00186 return exponent.Sub ( comp ); 00187 } 00188 00189 00190 private: 00191 00192 /*! 00193 if the mantissa is equal zero this method sets exponent to zero and 00194 info without the sign 00195 00196 it returns true if there was the correction 00197 */ 00198 bool CorrectZero() 00199 { 00200 if( mantissa.IsZero () ) 00201 { 00202 SetInfoBit (TTMATH_BIG_ZERO); 00203 ClearInfoBit (TTMATH_BIG_SIGN); 00204 exponent.SetZero (); 00205 00206 return true; 00207 } 00208 else 00209 { 00210 ClearInfoBit (TTMATH_BIG_ZERO); 00211 } 00212 00213 return false; 00214 } 00215 00216 00217 public: 00218 00219 /*! 00220 this method clears a specific bit in the 'info' variable 00221 00222 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. 00223 */ 00224 void ClearInfoBit (unsigned char bit) 00225 { 00226 info = info & (~bit); 00227 } 00228 00229 00230 /*! 00231 this method sets a specific bit in the 'info' variable 00232 00233 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. 00234 00235 */ 00236 void SetInfoBit (unsigned char bit) 00237 { 00238 info = info | bit; 00239 } 00240 00241 00242 /*! 00243 this method returns true if a specific bit in the 'info' variable is set 00244 00245 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. 00246 */ 00247 bool IsInfoBit (unsigned char bit) const 00248 { 00249 return (info & bit) != 0; 00250 } 00251 00252 00253 /*! 00254 this method sets zero 00255 */ 00256 void SetZero () 00257 { 00258 info = TTMATH_BIG_ZERO; 00259 exponent.SetZero (); 00260 mantissa.SetZero (); 00261 00262 /* 00263 we don't have to compensate zero 00264 */ 00265 } 00266 00267 00268 /*! 00269 this method sets one 00270 */ 00271 void SetOne () 00272 { 00273 info = 0; 00274 mantissa.SetZero (); 00275 mantissa.table [man-1] = TTMATH_UINT_HIGHEST_BIT; 00276 exponent = -sint(man * TTMATH_BITS_PER_UINT - 1); 00277 00278 // don't have to Standardize() - the last bit from mantissa is set 00279 } 00280 00281 00282 /*! 00283 this method sets value 0.5 00284 */ 00285 void Set05 () 00286 { 00287 SetOne (); 00288 exponent.SubOne (); 00289 } 00290 00291 00292 /*! 00293 this method sets NaN flag (Not a Number) 00294 when this flag is set that means there is no a valid number 00295 */ 00296 void SetNan () 00297 { 00298 SetInfoBit (TTMATH_BIG_NAN); 00299 } 00300 00301 00302 /*! 00303 this method sets NaN flag (Not a Number) 00304 also clears the mantissa and exponent (similarly as it would be a zero value) 00305 */ 00306 void SetZeroNan () 00307 { 00308 SetZero (); 00309 SetNan (); 00310 } 00311 00312 00313 /*! 00314 this method swappes this for an argument 00315 */ 00316 void Swap (Big<exp, man> & ss2) 00317 { 00318 unsigned char info_temp = info; 00319 info = ss2.info; 00320 ss2.info = info_temp; 00321 00322 exponent.Swap (ss2.exponent); 00323 mantissa.Swap (ss2.mantissa); 00324 } 00325 00326 00327 private: 00328 00329 /*! 00330 this method sets the mantissa of the value of pi 00331 */ 00332 void SetMantissaPi() 00333 { 00334 // this is a static table which represents the value of Pi (mantissa of it) 00335 // (first is the highest word) 00336 // we must define this table as 'unsigned int' because 00337 // both on 32bit and 64bit platforms this table is 32bit 00338 static const unsigned int temp_table[] = { 00339 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22, 00340 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245, 00341 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5, 00342 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a, 00343 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d, 00344 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603, 00345 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5, 00346 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64, 00347 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7, 00348 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64, 00349 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31, 00350 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26, 00351 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9, 00352 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed, 00353 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1, 00354 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de, 00355 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831, 00356 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b, 00357 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03, 00358 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3, 00359 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8, 00360 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0, 00361 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee, 00362 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c, 00363 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466, 00364 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9, 00365 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd, 00366 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d, 00367 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1, 00368 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7, 00369 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df, 00370 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52 00371 //0x86d44014, ... 00372 // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..) 00373 // 256 32bit words for the mantissa -- about 2464 valid decimal digits 00374 }; 00375 // the value of PI is comming from the website http://zenwerx.com/pi.php 00376 // 3101 digits were taken from this website 00377 // (later the digits were compared with: 00378 // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html ) 00379 // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform) 00380 // and then the first 256 words were taken into this table 00381 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, 00382 // and on 64bit platform value 128 (256/2=128)) 00383 00384 mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); 00385 } 00386 00387 public: 00388 00389 00390 /*! 00391 this method sets the value of pi 00392 */ 00393 void SetPi () 00394 { 00395 SetMantissaPi(); 00396 info = 0; 00397 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; 00398 } 00399 00400 00401 /*! 00402 this method sets the value of 0.5 * pi 00403 */ 00404 void Set05Pi () 00405 { 00406 SetMantissaPi(); 00407 info = 0; 00408 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1; 00409 } 00410 00411 00412 /*! 00413 this method sets the value of 2 * pi 00414 */ 00415 void Set2Pi () 00416 { 00417 SetMantissaPi(); 00418 info = 0; 00419 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3; 00420 } 00421 00422 00423 /*! 00424 this method sets the value of e 00425 (the base of the natural logarithm) 00426 */ 00427 void SetE () 00428 { 00429 static const unsigned int temp_table[] = { 00430 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb, 00431 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561, 00432 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77, 00433 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61, 00434 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19, 00435 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff, 00436 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2, 00437 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238, 00438 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270, 00439 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e, 00440 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef, 00441 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6, 00442 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a, 00443 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a, 00444 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b, 00445 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a, 00446 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a, 00447 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910, 00448 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3, 00449 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6, 00450 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e, 00451 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403, 00452 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1, 00453 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64, 00454 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829, 00455 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282, 00456 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74, 00457 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b, 00458 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457, 00459 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e, 00460 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e, 00461 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749 00462 // 0x2fe26dd4, ... 00463 // 256 32bit words for the mantissa -- about 2464 valid decimal digits 00464 }; 00465 00466 // above value was calculated using Big<1,400> type on a 32bit platform 00467 // and then the first 256 words were taken, 00468 // the calculating was made by using ExpSurrounding0(1) method 00469 // which took 1420 iterations 00470 // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil) 00471 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, 00472 // and on 64bit platform value 128 (256/2=128)) 00473 00474 mantissa.SetFromTable (temp_table, sizeof(temp_table) / sizeof(int)); 00475 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; 00476 info = 0; 00477 } 00478 00479 00480 /*! 00481 this method sets the value of ln(2) 00482 the natural logarithm from 2 00483 */ 00484 void SetLn2 () 00485 { 00486 static const unsigned int temp_table[] = { 00487 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b, 00488 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825, 00489 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b, 00490 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6, 00491 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396, 00492 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d, 00493 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c, 00494 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b, 00495 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b, 00496 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982, 00497 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2, 00498 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c, 00499 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a, 00500 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9, 00501 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae, 00502 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8, 00503 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c, 00504 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f, 00505 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00, 00506 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783, 00507 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8, 00508 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a, 00509 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda, 00510 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8, 00511 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527, 00512 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7, 00513 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca, 00514 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb, 00515 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab, 00516 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797, 00517 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6, 00518 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992 00519 //0xcbb9ac40, ... 00520 // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..) 00521 // 256 32bit words for the mantissa -- about 2464 valid decimal digits 00522 }; 00523 00524 // above value was calculated using Big<1,400> type on a 32bit platform 00525 // and then the first 256 words were taken, 00526 // the calculating was made by using LnSurrounding1(2) method 00527 // which took 4035 iterations 00528 // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html) 00529 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, 00530 // and on 64bit platform value 128 (256/2=128)) 00531 00532 mantissa.SetFromTable (temp_table, sizeof(temp_table) / sizeof(int)); 00533 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT); 00534 info = 0; 00535 } 00536 00537 00538 /*! 00539 this method sets the value of ln(10) 00540 the natural logarithm from 10 00541 00542 I introduced this constant especially to make the conversion ToString() 00543 being faster. In fact the method ToString() is keeping values of logarithms 00544 it has calculated but it must calculate the logarithm at least once. 00545 If a program, which uses this library, is running for a long time this 00546 would be ok, but for programs which are running shorter, for example for 00547 CGI applications which only once are printing values, this would be much 00548 inconvenience. Then if we're printing with base (radix) 10 and the mantissa 00549 of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE 00550 we don't calculate the logarithm but take it from this constant. 00551 */ 00552 void SetLn10 () 00553 { 00554 static const unsigned int temp_table[] = { 00555 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72, 00556 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6, 00557 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb, 00558 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981, 00559 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0, 00560 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e, 00561 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5, 00562 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e, 00563 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47, 00564 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834, 00565 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a, 00566 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d, 00567 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a, 00568 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353, 00569 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd, 00570 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8, 00571 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022, 00572 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f, 00573 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31, 00574 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766, 00575 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84, 00576 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8, 00577 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8, 00578 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f, 00579 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6, 00580 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c, 00581 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73, 00582 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7, 00583 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68, 00584 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d, 00585 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687, 00586 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347 00587 // 0xb4a638ef, ... 00588 //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..) 00589 // 256 32bit words for the mantissa -- about 2464 valid digits (decimal) 00590 }; 00591 00592 // above value was calculated using Big<1,400> type on a 32bit platform 00593 // and then the first 256 32bit words were taken, 00594 // the calculating was made by using LnSurrounding1(10) method 00595 // which took 22080 iterations 00596 // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html) 00597 // (the formula used in LnSurrounding1(x) converges badly when 00598 // the x is greater than one but in fact we can use it, only the 00599 // number of iterations will be greater) 00600 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, 00601 // and on 64bit platform value 128 (256/2=128)) 00602 00603 mantissa.SetFromTable (temp_table, sizeof(temp_table) / sizeof(int)); 00604 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; 00605 info = 0; 00606 } 00607 00608 00609 /*! 00610 this method sets the maximum value which can be held in this type 00611 */ 00612 void SetMax () 00613 { 00614 info = 0; 00615 mantissa.SetMax (); 00616 exponent.SetMax (); 00617 00618 // we don't have to use 'Standardizing()' because the last bit from 00619 // the mantissa is set 00620 } 00621 00622 00623 /*! 00624 this method sets the minimum value which can be held in this type 00625 */ 00626 void SetMin () 00627 { 00628 info = 0; 00629 00630 mantissa.SetMax (); 00631 exponent.SetMax (); 00632 SetSign (); 00633 00634 // we don't have to use 'Standardizing()' because the last bit from 00635 // the mantissa is set 00636 } 00637 00638 00639 /*! 00640 testing whether there is a value zero or not 00641 */ 00642 bool IsZero () const 00643 { 00644 return IsInfoBit (TTMATH_BIG_ZERO); 00645 } 00646 00647 00648 /*! 00649 this method returns true when there's the sign set 00650 also we don't check the NaN flag 00651 */ 00652 bool IsSign () const 00653 { 00654 return IsInfoBit (TTMATH_BIG_SIGN); 00655 } 00656 00657 00658 /*! 00659 this method returns true when there is not a valid number 00660 */ 00661 bool IsNan () const 00662 { 00663 return IsInfoBit (TTMATH_BIG_NAN); 00664 } 00665 00666 00667 00668 /*! 00669 this method clears the sign 00670 (there'll be an absolute value) 00671 00672 e.g. 00673 -1 -> 1 00674 2 -> 2 00675 */ 00676 void Abs () 00677 { 00678 ClearInfoBit (TTMATH_BIG_SIGN); 00679 } 00680 00681 00682 /*! 00683 this method remains the 'sign' of the value 00684 e.g. -2 = -1 00685 0 = 0 00686 10 = 1 00687 */ 00688 void Sgn () 00689 { 00690 // we have to check the NaN flag, because the next SetOne() method would clear it 00691 if( IsNan () ) 00692 return; 00693 00694 if( IsSign () ) 00695 { 00696 SetOne (); 00697 SetSign (); 00698 } 00699 else 00700 if( IsZero () ) 00701 SetZero (); // !! is nedeed here? 00702 else 00703 SetOne (); 00704 } 00705 00706 00707 00708 /*! 00709 this method sets the sign 00710 00711 e.g. 00712 -1 -> -1 00713 2 -> -2 00714 00715 we do not check whether there is a zero or not, if you're using this method 00716 you must be sure that the value is (or will be afterwards) different from zero 00717 */ 00718 void SetSign () 00719 { 00720 SetInfoBit (TTMATH_BIG_SIGN); 00721 } 00722 00723 00724 /*! 00725 this method changes the sign 00726 when there is a value of zero then the sign is not changed 00727 00728 e.g. 00729 -1 -> 1 00730 2 -> -2 00731 */ 00732 void ChangeSign () 00733 { 00734 // we don't have to check the NaN flag here 00735 00736 if( IsZero () ) 00737 return; 00738 00739 if( IsSign () ) 00740 ClearInfoBit (TTMATH_BIG_SIGN); 00741 else 00742 SetInfoBit (TTMATH_BIG_SIGN); 00743 } 00744 00745 00746 00747 private: 00748 00749 /*! 00750 this method does the half-to-even rounding (banker's rounding) 00751 00752 if is_half is: 00753 true - that means the rest was equal the half (0.5 decimal) 00754 false - that means the rest was greater than a half (greater than 0.5 decimal) 00755 00756 if the rest was less than a half then don't call this method 00757 (the rounding should does nothing then) 00758 */ 00759 uint RoundHalfToEven(bool is_half, bool rounding_up = true) 00760 { 00761 uint c = 0; 00762 00763 if( !is_half || mantissa.IsTheLowestBitSet () ) 00764 { 00765 if( rounding_up ) 00766 { 00767 if( mantissa.AddOne () ) 00768 { 00769 mantissa.Rcr (1, 1); 00770 c = exponent.AddOne (); 00771 } 00772 } 00773 else 00774 { 00775 #ifdef TTMATH_DEBUG 00776 uint c_from_zero = 00777 #endif 00778 mantissa.SubOne(); 00779 00780 // we're using rounding_up=false in Add() when the mantissas have different signs 00781 // mantissa can be zero only when previous mantissa was equal to ss2.mantissa 00782 // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false 00783 TTMATH_ASSERT( c_from_zero == 0 ) 00784 } 00785 } 00786 00787 return c; 00788 } 00789 00790 00791 00792 00793 00794 /*! 00795 * 00796 * basic mathematic functions 00797 * 00798 */ 00799 00800 00801 /*! 00802 this method adds one to the existing value 00803 */ 00804 uint AddOne() 00805 { 00806 Big<exp, man> one; 00807 00808 one.SetOne(); 00809 00810 return Add (one); 00811 } 00812 00813 00814 /*! 00815 this method subtracts one from the existing value 00816 */ 00817 uint SubOne() 00818 { 00819 Big<exp, man> one; 00820 00821 one.SetOne(); 00822 00823 return Sub (one); 00824 } 00825 00826 00827 private: 00828 00829 00830 /*! 00831 an auxiliary method for adding 00832 */ 00833 void AddCheckExponents( Big<exp, man> & ss2, 00834 Int<exp> & exp_offset, 00835 bool & last_bit_set, 00836 bool & rest_zero, 00837 bool & do_adding, 00838 bool & do_rounding) 00839 { 00840 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); 00841 00842 if( exp_offset == mantissa_size_in_bits ) 00843 { 00844 last_bit_set = ss2.mantissa.IsTheHighestBitSet(); 00845 rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1); 00846 do_rounding = true; // we'are only rounding 00847 } 00848 else 00849 if( exp_offset < mantissa_size_in_bits ) 00850 { 00851 uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa 00852 rest_zero = true; 00853 00854 if( moved > 0 ) 00855 { 00856 last_bit_set = static_cast<bool>( ss2.mantissa.GetBit(moved-1) ); 00857 00858 if( moved > 1 ) 00859 rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1); 00860 00861 // (2) moving 'exp_offset' times 00862 ss2.mantissa.Rcr(moved, 0); 00863 } 00864 00865 do_adding = true; 00866 do_rounding = true; 00867 } 00868 00869 // if exp_offset is greater than mantissa_size_in_bits then we do nothing 00870 // ss2 is too small for taking into consideration in the sum 00871 } 00872 00873 00874 /*! 00875 an auxiliary method for adding 00876 */ 00877 uint AddMantissas( Big<exp, man> & ss2, 00878 bool & last_bit_set, 00879 bool & rest_zero) 00880 { 00881 uint c = 0; 00882 00883 if( IsSign () == ss2.IsSign() ) 00884 { 00885 // values have the same signs 00886 if( mantissa.Add(ss2.mantissa) ) 00887 { 00888 // we have one bit more from addition (carry) 00889 // now rest_zero means the old rest_zero with the old last_bit_set 00890 rest_zero = (!last_bit_set && rest_zero); 00891 last_bit_set = mantissa.Rcr(1,1); 00892 c += exponent.AddOne(); 00893 } 00894 } 00895 else 00896 { 00897 // values have different signs 00898 // there shouldn't be a carry here because 00899 // (1) (2) guarantee that the mantissa of this 00900 // is greater than or equal to the mantissa of the ss2 00901 00902 #ifdef TTMATH_DEBUG 00903 uint c_temp = 00904 #endif 00905 mantissa.Sub(ss2.mantissa); 00906 00907 TTMATH_ASSERT( c_temp == 0 ) 00908 } 00909 00910 return c; 00911 } 00912 00913 00914 public: 00915 00916 00917 /*! 00918 Addition this = this + ss2 00919 00920 it returns carry if the sum is too big 00921 */ 00922 uint Add (Big<exp, man> ss2, bool round = true, bool adding = true) 00923 { 00924 bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up; 00925 Int<exp> exp_offset( exponent ); 00926 uint c = 0; 00927 00928 if( IsNan () || ss2.IsNan () ) 00929 return CheckCarry (1); 00930 00931 if( !adding ) 00932 ss2.ChangeSign (); // subtracting 00933 00934 exp_offset.Sub ( ss2.exponent ); 00935 exp_offset.Abs (); 00936 00937 // (1) abs(this) will be >= abs(ss2) 00938 if( SmallerWithoutSignThan (ss2) ) 00939 Swap (ss2); 00940 00941 if( ss2.IsZero () ) 00942 return 0; 00943 00944 last_bit_set = rest_zero = do_adding = do_rounding = false; 00945 rounding_up = (IsSign () == ss2.IsSign ()); 00946 00947 AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding); 00948 00949 if( do_adding ) 00950 c += AddMantissas(ss2, last_bit_set, rest_zero); 00951 00952 if( !round || !last_bit_set ) 00953 do_rounding = false; 00954 00955 if( do_rounding ) 00956 c += RoundHalfToEven(rest_zero, rounding_up); 00957 00958 if( do_adding || do_rounding ) 00959 c += Standardizing (); 00960 00961 return CheckCarry (c); 00962 } 00963 00964 00965 /*! 00966 Subtraction this = this - ss2 00967 00968 it returns carry if the result is too big 00969 */ 00970 uint Sub (const Big<exp, man> & ss2, bool round = true) 00971 { 00972 return Add (ss2, round, false); 00973 } 00974 00975 00976 /*! 00977 bitwise AND 00978 00979 this and ss2 must be >= 0 00980 return values: 00981 0 - ok 00982 1 - carry 00983 2 - this or ss2 was negative 00984 */ 00985 uint BitAnd (Big<exp, man> ss2) 00986 { 00987 if( IsNan () || ss2.IsNan () ) 00988 return CheckCarry (1); 00989 00990 if( IsSign () || ss2.IsSign () ) 00991 { 00992 SetNan (); 00993 return 2; 00994 } 00995 00996 if( IsZero () ) 00997 return 0; 00998 00999 if( ss2.IsZero () ) 01000 { 01001 SetZero (); 01002 return 0; 01003 } 01004 01005 Int<exp> exp_offset( exponent ); 01006 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); 01007 01008 uint c = 0; 01009 01010 exp_offset.Sub ( ss2.exponent ); 01011 exp_offset.Abs (); 01012 01013 // abs(this) will be >= abs(ss2) 01014 if( SmallerWithoutSignThan (ss2) ) 01015 Swap (ss2); 01016 01017 if( exp_offset >= mantissa_size_in_bits ) 01018 { 01019 // the second value is too small 01020 SetZero (); 01021 return 0; 01022 } 01023 01024 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times 01025 ss2.mantissa.Rcr ( exp_offset.ToInt (), 0 ); 01026 mantissa.BitAnd (ss2.mantissa); 01027 01028 c += Standardizing (); 01029 01030 return CheckCarry (c); 01031 } 01032 01033 01034 /*! 01035 bitwise OR 01036 01037 this and ss2 must be >= 0 01038 return values: 01039 0 - ok 01040 1 - carry 01041 2 - this or ss2 was negative 01042 */ 01043 uint BitOr (Big<exp, man> ss2) 01044 { 01045 if( IsNan () || ss2.IsNan () ) 01046 return CheckCarry (1); 01047 01048 if( IsSign () || ss2.IsSign () ) 01049 { 01050 SetNan (); 01051 return 2; 01052 } 01053 01054 if( IsZero () ) 01055 { 01056 *this = ss2; 01057 return 0; 01058 } 01059 01060 if( ss2.IsZero () ) 01061 return 0; 01062 01063 Int<exp> exp_offset( exponent ); 01064 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); 01065 01066 uint c = 0; 01067 01068 exp_offset.Sub ( ss2.exponent ); 01069 exp_offset.Abs (); 01070 01071 // abs(this) will be >= abs(ss2) 01072 if( SmallerWithoutSignThan (ss2) ) 01073 Swap (ss2); 01074 01075 if( exp_offset >= mantissa_size_in_bits ) 01076 // the second value is too small 01077 return 0; 01078 01079 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times 01080 ss2.mantissa.Rcr ( exp_offset.ToInt (), 0 ); 01081 mantissa.BitOr (ss2.mantissa); 01082 01083 c += Standardizing (); 01084 01085 return CheckCarry (c); 01086 } 01087 01088 01089 /*! 01090 bitwise XOR 01091 01092 this and ss2 must be >= 0 01093 return values: 01094 0 - ok 01095 1 - carry 01096 2 - this or ss2 was negative 01097 */ 01098 uint BitXor (Big<exp, man> ss2) 01099 { 01100 if( IsNan () || ss2.IsNan () ) 01101 return CheckCarry (1); 01102 01103 if( IsSign () || ss2.IsSign () ) 01104 { 01105 SetNan (); 01106 return 2; 01107 } 01108 01109 if( ss2.IsZero () ) 01110 return 0; 01111 01112 if( IsZero () ) 01113 { 01114 *this = ss2; 01115 return 0; 01116 } 01117 01118 Int<exp> exp_offset( exponent ); 01119 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); 01120 01121 uint c = 0; 01122 01123 exp_offset.Sub ( ss2.exponent ); 01124 exp_offset.Abs (); 01125 01126 // abs(this) will be >= abs(ss2) 01127 if( SmallerWithoutSignThan (ss2) ) 01128 Swap (ss2); 01129 01130 if( exp_offset >= mantissa_size_in_bits ) 01131 // the second value is too small 01132 return 0; 01133 01134 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times 01135 ss2.mantissa.Rcr ( exp_offset.ToInt (), 0 ); 01136 mantissa.BitXor (ss2.mantissa); 01137 01138 c += Standardizing (); 01139 01140 return CheckCarry (c); 01141 } 01142 01143 01144 01145 /*! 01146 Multiplication this = this * ss2 (ss2 is uint) 01147 01148 ss2 without a sign 01149 */ 01150 uint MulUInt (uint ss2) 01151 { 01152 UInt<man+1> man_result; 01153 uint i,c = 0; 01154 01155 if( IsNan () ) 01156 return 1; 01157 01158 if( IsZero () ) 01159 return 0; 01160 01161 if( ss2 == 0 ) 01162 { 01163 SetZero (); 01164 return 0; 01165 } 01166 01167 // man_result = mantissa * ss2.mantissa 01168 mantissa.MulInt (ss2, man_result); 01169 01170 sint bit = UInt<man>::FindLeadingBitInWord(man_result.table [man]); // man - last word 01171 01172 if( bit!=-1 && uint (bit) > (TTMATH_BITS_PER_UINT/2) ) 01173 { 01174 // 'i' will be from 0 to TTMATH_BITS_PER_UINT 01175 i = man_result.CompensationToLeft (); 01176 c = exponent.Add ( TTMATH_BITS_PER_UINT - i ); 01177 01178 for(i=0 ; i<man ; ++i) 01179 mantissa.table [i] = man_result.table [i+1]; 01180 } 01181 else 01182 { 01183 if( bit != -1 ) 01184 { 01185 man_result.Rcr (bit+1, 0); 01186 c += exponent.Add (bit+1); 01187 } 01188 01189 for(i=0 ; i<man ; ++i) 01190 mantissa.table [i] = man_result.table [i]; 01191 } 01192 01193 c += Standardizing (); 01194 01195 return CheckCarry (c); 01196 } 01197 01198 01199 /*! 01200 Multiplication this = this * ss2 (ss2 is sint) 01201 01202 ss2 with a sign 01203 */ 01204 uint MulInt (sint ss2) 01205 { 01206 if( IsNan () ) 01207 return 1; 01208 01209 if( ss2 == 0 ) 01210 { 01211 SetZero (); 01212 return 0; 01213 } 01214 01215 if( IsZero () ) 01216 return 0; 01217 01218 if( IsSign () == (ss2<0) ) 01219 { 01220 // the signs are the same (both are either - or +), the result is positive 01221 Abs (); 01222 } 01223 else 01224 { 01225 // the signs are different, the result is negative 01226 SetSign (); 01227 } 01228 01229 if( ss2<0 ) 01230 ss2 = -ss2; 01231 01232 01233 return MulUInt ( uint (ss2) ); 01234 } 01235 01236 01237 private: 01238 01239 01240 /*! 01241 this method checks whether a table pointed by 'tab' and 'len' 01242 has the value 0.5 decimal 01243 (it is treated as the comma operator would be before the highest bit) 01244 call this method only if the highest bit is set - you have to test it beforehand 01245 01246 return: 01247 true - tab was equal the half (0.5 decimal) 01248 false - tab was greater than a half (greater than 0.5 decimal) 01249 01250 */ 01251 bool CheckGreaterOrEqualHalf(uint * tab, uint len) 01252 { 01253 uint i; 01254 01255 TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 ) 01256 01257 for(i=0 ; i<len-1 ; ++i) 01258 if( tab[i] != 0 ) 01259 return false; 01260 01261 if( tab[i] != TTMATH_UINT_HIGHEST_BIT ) 01262 return false; 01263 01264 return true; 01265 } 01266 01267 01268 private: 01269 01270 /*! 01271 multiplication this = this * ss2 01272 this method returns a carry 01273 */ 01274 uint MulRef(const Big<exp, man> & ss2, bool round = true) 01275 { 01276 TTMATH_REFERENCE_ASSERT( ss2 ) 01277 01278 UInt<man*2> man_result; 01279 uint c = 0; 01280 uint i; 01281 01282 if( IsNan () || ss2.IsNan () ) 01283 return CheckCarry (1); 01284 01285 if( IsZero () ) 01286 return 0; 01287 01288 if( ss2.IsZero () ) 01289 { 01290 SetZero (); 01291 return 0; 01292 } 01293 01294 // man_result = mantissa * ss2.mantissa 01295 mantissa.MulBig(ss2.mantissa, man_result); 01296 01297 // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT 01298 // because mantissa and ss2.mantissa are standardized 01299 // (the highest bit in man_result is set to 1 or 01300 // if there is a zero value in man_result the method CompensationToLeft() 01301 // returns 0 but we'll correct this at the end in Standardizing() method) 01302 i = man_result.CompensationToLeft(); 01303 uint exp_add = man * TTMATH_BITS_PER_UINT - i; 01304 01305 if( exp_add ) 01306 c += exponent.Add( exp_add ); 01307 01308 c += exponent.Add( ss2.exponent ); 01309 01310 for(i=0 ; i<man ; ++i) 01311 mantissa.table[i] = man_result.table[i+man]; 01312 01313 if( round && (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 ) 01314 { 01315 bool is_half = CheckGreaterOrEqualHalf(man_result.table, man); 01316 c += RoundHalfToEven(is_half); 01317 } 01318 01319 if( IsSign () == ss2.IsSign() ) 01320 { 01321 // the signs are the same, the result is positive 01322 Abs (); 01323 } 01324 else 01325 { 01326 // the signs are different, the result is negative 01327 // if the value is zero it will be corrected later in Standardizing method 01328 SetSign (); 01329 } 01330 01331 c += Standardizing (); 01332 01333 return CheckCarry (c); 01334 } 01335 01336 01337 public: 01338 01339 01340 /*! 01341 multiplication this = this * ss2 01342 this method returns a carry 01343 */ 01344 uint Mul (const Big<exp, man> & ss2, bool round = true) 01345 { 01346 if( this == &ss2 ) 01347 { 01348 Big<exp, man> copy_ss2(ss2); 01349 return MulRef(copy_ss2, round); 01350 } 01351 else 01352 { 01353 return MulRef(ss2, round); 01354 } 01355 } 01356 01357 01358 private: 01359 01360 /*! 01361 division this = this / ss2 01362 01363 return value: 01364 0 - ok 01365 1 - carry (in a division carry can be as well) 01366 2 - improper argument (ss2 is zero) 01367 */ 01368 uint DivRef(const Big<exp, man> & ss2, bool round = true) 01369 { 01370 TTMATH_REFERENCE_ASSERT( ss2 ) 01371 01372 UInt<man*2> man1; 01373 UInt<man*2> man2; 01374 uint i,c = 0; 01375 01376 if( IsNan () || ss2.IsNan () ) 01377 return CheckCarry (1); 01378 01379 if( ss2.IsZero () ) 01380 { 01381 SetNan (); 01382 return 2; 01383 } 01384 01385 if( IsZero () ) 01386 return 0; 01387 01388 // !! this two loops can be joined together 01389 01390 for(i=0 ; i<man ; ++i) 01391 { 01392 man1.table[i+man] = mantissa.table[i]; 01393 man2.table[i] = ss2.mantissa.table[i]; 01394 } 01395 01396 for(i=0 ; i<man ; ++i) 01397 { 01398 man1.table[i] = 0; 01399 man2.table[i+man] = 0; 01400 } 01401 01402 man1.Div(man2); 01403 01404 i = man1.CompensationToLeft(); 01405 01406 if( i ) 01407 c += exponent.Sub(i); 01408 01409 c += exponent.Sub(ss2.exponent); 01410 01411 for(i=0 ; i<man ; ++i) 01412 mantissa.table[i] = man1.table[i+man]; 01413 01414 if( round && (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 ) 01415 { 01416 bool is_half = CheckGreaterOrEqualHalf(man1.table, man); 01417 c += RoundHalfToEven(is_half); 01418 } 01419 01420 if( IsSign () == ss2.IsSign () ) 01421 Abs (); 01422 else 01423 SetSign (); // if there is a zero it will be corrected in Standardizing() 01424 01425 c += Standardizing (); 01426 01427 return CheckCarry (c); 01428 } 01429 01430 01431 public: 01432 01433 /*! 01434 division this = this / ss2 01435 01436 return value: 01437 0 - ok 01438 1 - carry (in a division carry can be as well) 01439 2 - improper argument (ss2 is zero) 01440 */ 01441 uint Div (const Big<exp, man> & ss2, bool round = true) 01442 { 01443 if( this == &ss2 ) 01444 { 01445 Big<exp, man> copy_ss2(ss2); 01446 return DivRef(copy_ss2, round); 01447 } 01448 else 01449 { 01450 return DivRef(ss2, round); 01451 } 01452 } 01453 01454 01455 private: 01456 01457 /*! 01458 the remainder from a division 01459 */ 01460 uint ModRef(const Big<exp, man> & ss2) 01461 { 01462 TTMATH_REFERENCE_ASSERT( ss2 ) 01463 01464 uint c = 0; 01465 01466 if( IsNan () || ss2.IsNan () ) 01467 return CheckCarry (1); 01468 01469 if( ss2.IsZero () ) 01470 { 01471 SetNan (); 01472 return 2; 01473 } 01474 01475 if( !SmallerWithoutSignThan (ss2) ) 01476 { 01477 Big<exp, man> temp(*this); 01478 01479 c = temp.Div(ss2); 01480 temp.SkipFraction(); 01481 c += temp.Mul(ss2); 01482 c += Sub (temp); 01483 01484 if( !SmallerWithoutSignThan ( ss2 ) ) 01485 c += 1; 01486 } 01487 01488 return CheckCarry (c); 01489 } 01490 01491 01492 public: 01493 01494 /*! 01495 the remainder from a division 01496 01497 e.g. 01498 12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6 01499 -12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6) 01500 12.6 mod -3 = 0.6 01501 -12.6 mod -3 = -0.6 01502 01503 it means: 01504 in other words: this(old) = ss2 * q + this(new) 01505 01506 return value: 01507 0 - ok 01508 1 - carry 01509 2 - improper argument (ss2 is zero) 01510 */ 01511 uint Mod (const Big<exp, man> & ss2) 01512 { 01513 if( this == &ss2 ) 01514 { 01515 Big<exp, man> copy_ss2(ss2); 01516 return ModRef(copy_ss2); 01517 } 01518 else 01519 { 01520 return ModRef(ss2); 01521 } 01522 } 01523 01524 01525 /*! 01526 this method returns: 'this' mod 2 01527 (either zero or one) 01528 01529 this method is much faster than using Mod( object_with_value_two ) 01530 */ 01531 uint Mod2 () const 01532 { 01533 if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) ) 01534 return 0; 01535 01536 sint exp_int = exponent.ToInt (); 01537 // 'exp_int' is negative (or zero), we set it as positive 01538 exp_int = -exp_int; 01539 01540 return mantissa.GetBit (exp_int); 01541 } 01542 01543 01544 /*! 01545 power this = this ^ pow 01546 (pow without a sign) 01547 01548 binary algorithm (r-to-l) 01549 01550 return values: 01551 0 - ok 01552 1 - carry 01553 2 - incorrect arguments (0^0) 01554 */ 01555 template<uint pow_size> 01556 uint Pow (UInt<pow_size> pow) 01557 { 01558 if( IsNan () ) 01559 return 1; 01560 01561 if( IsZero () ) 01562 { 01563 if( pow.IsZero () ) 01564 { 01565 // we don't define zero^zero 01566 SetNan (); 01567 return 2; 01568 } 01569 01570 // 0^(+something) is zero 01571 return 0; 01572 } 01573 01574 Big<exp, man> start(*this); 01575 Big<exp, man> result; 01576 result.SetOne (); 01577 uint c = 0; 01578 01579 while( !c ) 01580 { 01581 if( pow.table [0] & 1 ) 01582 c += result.Mul (start); 01583 01584 pow.Rcr (1); 01585 01586 if( pow.IsZero () ) 01587 break; 01588 01589 c += start.Mul (start); 01590 } 01591 01592 *this = result; 01593 01594 return CheckCarry (c); 01595 } 01596 01597 01598 /*! 01599 power this = this ^ pow 01600 p can be negative 01601 01602 return values: 01603 0 - ok 01604 1 - carry 01605 2 - incorrect arguments 0^0 or 0^(-something) 01606 */ 01607 template<uint pow_size> 01608 uint Pow (Int<pow_size> pow) 01609 { 01610 if( IsNan () ) 01611 return 1; 01612 01613 if( !pow.IsSign () ) 01614 return Pow ( UInt<pow_size>(pow) ); 01615 01616 if( IsZero () ) 01617 { 01618 // if 'p' is negative then 01619 // 'this' must be different from zero 01620 SetNan (); 01621 return 2; 01622 } 01623 01624 uint c = pow.ChangeSign (); 01625 01626 Big<exp, man> t(*this); 01627 c += t.Pow ( UInt<pow_size>(pow) ); // here can only be a carry (return:1) 01628 01629 SetOne (); 01630 c += Div (t); 01631 01632 return CheckCarry (c); 01633 } 01634 01635 01636 /*! 01637 power this = this ^ abs([pow]) 01638 pow is treated as a value without a sign and without a fraction 01639 if pow has a sign then the method pow.Abs() is used 01640 if pow has a fraction the fraction is skipped (not used in calculation) 01641 01642 return values: 01643 0 - ok 01644 1 - carry 01645 2 - incorrect arguments (0^0) 01646 */ 01647 uint PowUInt (Big<exp, man> pow) 01648 { 01649 if( IsNan () || pow.IsNan () ) 01650 return CheckCarry (1); 01651 01652 if( IsZero () ) 01653 { 01654 if( pow.IsZero () ) 01655 { 01656 SetNan (); 01657 return 2; 01658 } 01659 01660 // 0^(+something) is zero 01661 return 0; 01662 } 01663 01664 if( pow.IsSign () ) 01665 pow.Abs (); 01666 01667 Big<exp, man> start(*this); 01668 Big<exp, man> result; 01669 Big<exp, man> one; 01670 uint c = 0; 01671 one.SetOne (); 01672 result = one; 01673 01674 while( !c ) 01675 { 01676 if( pow.Mod2 () ) 01677 c += result.Mul (start); 01678 01679 c += pow.exponent.SubOne (); 01680 01681 if( pow < one ) 01682 break; 01683 01684 c += start.Mul (start); 01685 } 01686 01687 *this = result; 01688 01689 return CheckCarry (c); 01690 } 01691 01692 01693 /*! 01694 power this = this ^ [pow] 01695 pow is treated as a value without a fraction 01696 pow can be negative 01697 01698 return values: 01699 0 - ok 01700 1 - carry 01701 2 - incorrect arguments 0^0 or 0^(-something) 01702 */ 01703 uint PowInt (const Big<exp, man> & pow) 01704 { 01705 if( IsNan () || pow.IsNan () ) 01706 return CheckCarry (1); 01707 01708 if( !pow.IsSign () ) 01709 return PowUInt (pow); 01710 01711 if( IsZero () ) 01712 { 01713 // if 'pow' is negative then 01714 // 'this' must be different from zero 01715 SetNan (); 01716 return 2; 01717 } 01718 01719 Big<exp, man> temp(*this); 01720 uint c = temp.PowUInt (pow); // here can only be a carry (result:1) 01721 01722 SetOne (); 01723 c += Div (temp); 01724 01725 return CheckCarry (c); 01726 } 01727 01728 01729 /*! 01730 power this = this ^ pow 01731 this must be greater than zero (this > 0) 01732 pow can be negative and with fraction 01733 01734 return values: 01735 0 - ok 01736 1 - carry 01737 2 - incorrect argument ('this' <= 0) 01738 */ 01739 uint PowFrac (const Big<exp, man> & pow) 01740 { 01741 if( IsNan () || pow.IsNan () ) 01742 return CheckCarry (1); 01743 01744 Big<exp, man> temp; 01745 uint c = temp.Ln (*this); 01746 01747 if( c != 0 ) // can be 2 from Ln() 01748 { 01749 SetNan (); 01750 return c; 01751 } 01752 01753 c += temp.Mul (pow); 01754 c += Exp (temp); 01755 01756 return CheckCarry (c); 01757 } 01758 01759 01760 /*! 01761 power this = this ^ pow 01762 pow can be negative and with fraction 01763 01764 return values: 01765 0 - ok 01766 1 - carry 01767 2 - incorrect argument ('this' or 'pow') 01768 */ 01769 uint Pow (const Big<exp, man> & pow) 01770 { 01771 if( IsNan () || pow.IsNan () ) 01772 return CheckCarry (1); 01773 01774 if( IsZero () ) 01775 { 01776 // 0^pow will be 0 only for pow>0 01777 if( pow.IsSign () || pow.IsZero () ) 01778 { 01779 SetNan (); 01780 return 2; 01781 } 01782 01783 SetZero (); 01784 01785 return 0; 01786 } 01787 01788 if( pow.exponent>-sint(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 ) 01789 { 01790 if( pow.IsInteger () ) 01791 return PowInt ( pow ); 01792 } 01793 01794 return PowFrac (pow); 01795 } 01796 01797 01798 /*! 01799 this function calculates the square root 01800 e.g. let this=9 then this.Sqrt() gives 3 01801 01802 return: 0 - ok 01803 1 - carry 01804 2 - improper argument (this<0 or NaN) 01805 */ 01806 uint Sqrt () 01807 { 01808 if( IsNan () || IsSign () ) 01809 { 01810 SetNan (); 01811 return 2; 01812 } 01813 01814 if( IsZero () ) 01815 return 0; 01816 01817 Big<exp, man> old(*this); 01818 Big<exp, man> ln; 01819 uint c = 0; 01820 01821 // we're using the formula: sqrt(x) = e ^ (ln(x) / 2) 01822 c += ln.Ln (*this); 01823 c += ln.exponent.SubOne (); // ln = ln / 2 01824 c += Exp (ln); 01825 01826 // above formula doesn't give accurate results for some integers 01827 // e.g. Sqrt(81) would not be 9 but a value very closed to 9 01828 // we're rounding the result, calculating result*result and comparing 01829 // with the old value, if they are equal then the result is an integer too 01830 01831 if( !c && old.IsInteger () && !IsInteger () ) 01832 { 01833 Big<exp, man> temp(*this); 01834 c += temp.Round (); 01835 01836 Big<exp, man> temp2(temp); 01837 c += temp.Mul (temp2); 01838 01839 if( temp == old ) 01840 *this = temp2; 01841 } 01842 01843 return CheckCarry (c); 01844 } 01845 01846 01847 private: 01848 01849 #ifdef TTMATH_CONSTANTSGENERATOR 01850 public: 01851 #endif 01852 01853 /*! 01854 Exponent this = exp(x) = e^x where x is in (-1,1) 01855 01856 we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ... 01857 */ 01858 void ExpSurrounding0 (const Big<exp,man> & x, uint * steps = 0) 01859 { 01860 TTMATH_REFERENCE_ASSERT( x ) 01861 01862 Big<exp,man> denominator, denominator_i; 01863 Big<exp,man> one, old_value, next_part; 01864 Big<exp,man> numerator = x; 01865 01866 SetOne (); 01867 one.SetOne (); 01868 denominator.SetOne (); 01869 denominator_i.SetOne (); 01870 01871 uint i; 01872 old_value = *this; 01873 01874 // we begin from 1 in order to not test at the beginning 01875 #ifdef TTMATH_CONSTANTSGENERATOR 01876 for(i=1 ; true ; ++i) 01877 #else 01878 for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) 01879 #endif 01880 { 01881 bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' 01882 01883 next_part = numerator; 01884 01885 if( next_part.Div ( denominator ) ) 01886 // if there is a carry here we only break the loop 01887 // however the result we return as good 01888 // it means there are too many parts of the formula 01889 break; 01890 01891 // there shouldn't be a carry here 01892 Add ( next_part ); 01893 01894 if( testing ) 01895 { 01896 if( old_value == *this ) 01897 // we've added next few parts of the formula but the result 01898 // is still the same then we break the loop 01899 break; 01900 else 01901 old_value = *this; 01902 } 01903 01904 // we set the denominator and the numerator for a next part of the formula 01905 if( denominator_i.Add (one) ) 01906 // if there is a carry here the result we return as good 01907 break; 01908 01909 if( denominator.Mul (denominator_i) ) 01910 break; 01911 01912 if( numerator.Mul (x) ) 01913 break; 01914 } 01915 01916 if( steps ) 01917 *steps = i; 01918 } 01919 01920 public: 01921 01922 01923 /*! 01924 Exponent this = exp(x) = e^x 01925 01926 we're using the fact that our value is stored in form of: 01927 x = mantissa * 2^exponent 01928 then 01929 e^x = e^(mantissa* 2^exponent) or 01930 e^x = (e^mantissa)^(2^exponent) 01931 01932 'Exp' returns a carry if we can't count the result ('x' is too big) 01933 */ 01934 uint Exp (const Big<exp,man> & x) 01935 { 01936 uint c = 0; 01937 01938 if( x.IsNan () ) 01939 return CheckCarry (1); 01940 01941 if( x.IsZero () ) 01942 { 01943 SetOne (); 01944 return 0; 01945 } 01946 01947 // m will be the value of the mantissa in range (-1,1) 01948 Big<exp,man> m(x); 01949 m.exponent = -sint(man*TTMATH_BITS_PER_UINT); 01950 01951 // 'e_' will be the value of '2^exponent' 01952 // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and 01953 // e_.exponent.Add(1) mean: 01954 // e_.mantissa.table[0] = 1; 01955 // e_.Standardizing(); 01956 // e_.exponent.Add(man*TTMATH_BITS_PER_UINT) 01957 // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa) 01958 Big<exp,man> e_(x); 01959 e_.mantissa.SetZero (); 01960 e_.mantissa.table [man-1] = TTMATH_UINT_HIGHEST_BIT; 01961 c += e_.exponent.Add (1); 01962 e_.Abs (); 01963 01964 /* 01965 now we've got: 01966 m - the value of the mantissa in range (-1,1) 01967 e_ - 2^exponent 01968 01969 e_ can be as: 01970 ...2^-2, 2^-1, 2^0, 2^1, 2^2 ... 01971 ...1/4 , 1/2 , 1 , 2 , 4 ... 01972 01973 above one e_ is integer 01974 01975 if e_ is greater than 1 we calculate the exponent as: 01976 e^(m * e_) = ExpSurrounding0(m) ^ e_ 01977 and if e_ is smaller or equal one we calculate the exponent in this way: 01978 e^(m * e_) = ExpSurrounding0(m* e_) 01979 because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m 01980 */ 01981 01982 if( e_ <= 1 ) 01983 { 01984 m.Mul (e_); 01985 ExpSurrounding0 (m); 01986 } 01987 else 01988 { 01989 ExpSurrounding0 (m); 01990 c += PowUInt (e_); 01991 } 01992 01993 return CheckCarry (c); 01994 } 01995 01996 01997 01998 01999 private: 02000 02001 #ifdef TTMATH_CONSTANTSGENERATOR 02002 public: 02003 #endif 02004 02005 /*! 02006 Natural logarithm this = ln(x) where x in range <1,2) 02007 02008 we're using the formula: 02009 ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ] 02010 */ 02011 void LnSurrounding1 (const Big<exp,man> & x, uint * steps = 0) 02012 { 02013 Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x); 02014 02015 one.SetOne (); 02016 02017 if( x == one ) 02018 { 02019 // LnSurrounding1(1) is 0 02020 SetZero (); 02021 return; 02022 } 02023 02024 two = 2; 02025 02026 x1.Sub (one); 02027 x2.Add (one); 02028 02029 x1.Div(x2); 02030 x2 = x1; 02031 x2.Mul (x1); 02032 02033 denominator.SetOne (); 02034 SetZero (); 02035 02036 old_value = *this; 02037 uint i; 02038 02039 02040 #ifdef TTMATH_CONSTANTSGENERATOR 02041 for(i=1 ; true ; ++i) 02042 #else 02043 // we begin from 1 in order to not test at the beginning 02044 for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) 02045 #endif 02046 { 02047 bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' 02048 02049 next_part = x1; 02050 02051 if( next_part.Div (denominator) ) 02052 // if there is a carry here we only break the loop 02053 // however the result we return as good 02054 // it means there are too many parts of the formula 02055 break; 02056 02057 // there shouldn't be a carry here 02058 Add (next_part); 02059 02060 if( testing ) 02061 { 02062 if( old_value == *this ) 02063 // we've added next (step_test) parts of the formula but the result 02064 // is still the same then we break the loop 02065 break; 02066 else 02067 old_value = *this; 02068 } 02069 02070 if( x1.Mul(x2) ) 02071 // if there is a carry here the result we return as good 02072 break; 02073 02074 if( denominator.Add (two) ) 02075 break; 02076 } 02077 02078 // this = this * 2 02079 // ( there can't be a carry here because we calculate the logarithm between <1,2) ) 02080 exponent.AddOne (); 02081 02082 if( steps ) 02083 *steps = i; 02084 } 02085 02086 02087 02088 02089 public: 02090 02091 02092 /*! 02093 Natural logarithm this = ln(x) 02094 (a logarithm with the base equal 'e') 02095 02096 we're using the fact that our value is stored in form of: 02097 x = mantissa * 2^exponent 02098 then 02099 ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2)) 02100 02101 the mantissa we'll show as a value from range <1,2) because the logarithm 02102 is decreasing too fast when 'x' is going to 0 02103 02104 return values: 02105 0 - ok 02106 1 - overflow (carry) 02107 2 - incorrect argument (x<=0) 02108 */ 02109 uint Ln (const Big<exp,man> & x) 02110 { 02111 if( x.IsNan () ) 02112 return CheckCarry (1); 02113 02114 if( x.IsSign () || x.IsZero () ) 02115 { 02116 SetNan (); 02117 return 2; 02118 } 02119 02120 Big<exp,man> exponent_temp; 02121 exponent_temp.FromInt ( x.exponent ); 02122 02123 // m will be the value of the mantissa in range <1,2) 02124 Big<exp,man> m(x); 02125 m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1); 02126 02127 // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa 02128 uint c = exponent_temp.Add (man*TTMATH_BITS_PER_UINT-1); 02129 02130 LnSurrounding1 (m); 02131 02132 Big<exp,man> ln2; 02133 ln2.SetLn2 (); 02134 c += exponent_temp.Mul (ln2); 02135 c += Add (exponent_temp); 02136 02137 return CheckCarry (c); 02138 } 02139 02140 02141 /*! 02142 Logarithm from 'x' with a 'base' 02143 02144 we're using the formula: 02145 Log(x) with 'base' = ln(x) / ln(base) 02146 02147 return values: 02148 0 - ok 02149 1 - overflow 02150 2 - incorrect argument (x<=0) 02151 3 - incorrect base (a<=0 lub a=1) 02152 */ 02153 uint Log (const Big<exp,man> & x, const Big<exp,man> & base) 02154 { 02155 if( x.IsNan () || base.IsNan () ) 02156 return CheckCarry (1); 02157 02158 if( x.IsSign () || x.IsZero () ) 02159 { 02160 SetNan (); 02161 return 2; 02162 } 02163 02164 Big<exp,man> denominator;; 02165 denominator.SetOne (); 02166 02167 if( base.IsSign () || base.IsZero () || base==denominator ) 02168 { 02169 SetNan (); 02170 return 3; 02171 } 02172 02173 if( x == denominator ) // (this is: if x == 1) 02174 { 02175 // log(1) is 0 02176 SetZero (); 02177 return 0; 02178 } 02179 02180 // another error values we've tested at the beginning 02181 // there can only be a carry 02182 uint c = Ln (x); 02183 02184 c += denominator.Ln (base); 02185 c += Div (denominator); 02186 02187 return CheckCarry (c); 02188 } 02189 02190 02191 02192 02193 /*! 02194 * 02195 * converting methods 02196 * 02197 */ 02198 02199 02200 /*! 02201 converting from another type of a Big object 02202 */ 02203 template<uint another_exp, uint another_man> 02204 uint FromBig (const Big<another_exp, another_man> & another) 02205 { 02206 info = another.info; 02207 02208 if( IsNan () ) 02209 return 1; 02210 02211 if( exponent.FromInt (another.exponent) ) 02212 { 02213 SetNan (); 02214 return 1; 02215 } 02216 02217 uint man_len_min = (man < another_man)? man : another_man; 02218 uint i; 02219 uint c = 0; 02220 02221 for( i = 0 ; i<man_len_min ; ++i ) 02222 mantissa.table [man-1-i] = another.mantissa.table [another_man-1-i]; 02223 02224 for( ; i<man ; ++i ) 02225 mantissa.table [man-1-i] = 0; 02226 02227 02228 // MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'): 02229 // warning C4307: '*' : integral constant overflow 02230 // but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here 02231 #ifdef _MSC_VER 02232 #pragma warning( disable: 4307 ) 02233 #endif 02234 02235 if( man > another_man ) 02236 { 02237 uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT; 02238 c += exponent.SubInt (man_diff, 0); 02239 } 02240 else 02241 if( man < another_man ) 02242 { 02243 uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT; 02244 c += exponent.AddInt (man_diff, 0); 02245 } 02246 02247 #ifdef _MSC_VER 02248 #pragma warning( default: 4307 ) 02249 #endif 02250 02251 // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero) 02252 CorrectZero(); 02253 02254 return CheckCarry (c); 02255 } 02256 02257 02258 private: 02259 02260 /*! 02261 an auxiliary method for converting 'this' into 'result' 02262 if the value is too big this method returns a carry (1) 02263 */ 02264 uint ToUIntOrInt(uint & result) const 02265 { 02266 result = 0; 02267 02268 if( IsZero () ) 02269 return 0; 02270 02271 sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); 02272 02273 if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) ) 02274 // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed 02275 // into the 'sint' type (it's too big) 02276 return 1; 02277 02278 if( exponent <= maxbit ) 02279 // our value is from the range of (-1,1) and we return zero 02280 return 0; 02281 02282 // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) > 02283 // and [maxbit + sint(TTMATH_BITS_PER_UINT] <= 0 02284 sint how_many_bits = exponent.ToInt (); 02285 02286 // how_many_bits is negative, we'll make it positive 02287 how_many_bits = -how_many_bits; 02288 02289 result = (mantissa.table [man-1] >> (how_many_bits % TTMATH_BITS_PER_UINT)); 02290 02291 return 0; 02292 } 02293 02294 02295 public: 02296 02297 /*! 02298 this method converts 'this' into uint 02299 */ 02300 uint ToUInt () const 02301 { 02302 uint result; 02303 02304 ToUInt (result); 02305 02306 return result; 02307 } 02308 02309 02310 /*! 02311 this method converts 'this' into 'result' 02312 02313 if the value is too big this method returns a carry (1) 02314 */ 02315 uint ToUInt (uint & result) const 02316 { 02317 if( ToUIntOrInt(result) ) 02318 return 1; 02319 02320 if( IsSign () ) 02321 return 1; 02322 02323 return 0; 02324 } 02325 02326 02327 /*! 02328 this method converts 'this' into sint 02329 */ 02330 sint ToInt () const 02331 { 02332 sint result; 02333 02334 ToInt (result); 02335 02336 return result; 02337 } 02338 02339 02340 /*! 02341 this method converts 'this' into 'result' 02342 02343 if the value is too big this method returns a carry (1) 02344 */ 02345 uint ToInt (uint & result) const 02346 { 02347 return ToUInt (result); 02348 } 02349 02350 02351 /*! 02352 this method converts 'this' into 'result' 02353 02354 if the value is too big this method returns a carry (1) 02355 */ 02356 uint ToInt (sint & result) const 02357 { 02358 uint result_uint; 02359 02360 uint c = ToUIntOrInt(result_uint); 02361 result = sint(result_uint); 02362 02363 if( c ) 02364 return 1; 02365 02366 uint mask = 0; 02367 02368 if( IsSign () ) 02369 { 02370 mask = TTMATH_UINT_MAX_VALUE; 02371 result = -result; 02372 } 02373 02374 return ((result & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; 02375 } 02376 02377 02378 private: 02379 02380 /*! 02381 an auxiliary method for converting 'this' into 'result' 02382 02383 if the value is too big this method returns a carry (1) 02384 */ 02385 template<uint int_size> 02386 uint ToUIntOrInt(UInt<int_size> & result) const 02387 { 02388 result.SetZero (); 02389 02390 if( IsZero () ) 02391 return 0; 02392 02393 sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); 02394 02395 if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) ) 02396 // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed 02397 // into the 'UInt<int_size>' type (it's too big) 02398 return 1; 02399 02400 if( exponent <= maxbit ) 02401 // our value is from range (-1,1) and we return zero 02402 return 0; 02403 02404 sint how_many_bits = exponent.ToInt (); 02405 02406 if( how_many_bits < 0 ) 02407 { 02408 how_many_bits = -how_many_bits; 02409 uint index = how_many_bits / TTMATH_BITS_PER_UINT; 02410 02411 UInt<man> mantissa_temp(mantissa); 02412 mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); 02413 02414 for(uint i=index, a=0 ; i<man ; ++i,++a) 02415 result.table [a] = mantissa_temp.table[i]; 02416 } 02417 else 02418 { 02419 uint index = how_many_bits / TTMATH_BITS_PER_UINT; 02420 02421 if( index + (man-1) < int_size ) 02422 { 02423 // above 'if' is always true 02424 // this is only to get rid of a warning "warning: array subscript is above array bounds" 02425 // (from gcc) 02426 // we checked the condition there: "if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )" 02427 // but gcc doesn't understand our types - exponent is Int<> 02428 02429 for(uint i=0 ; i<man ; ++i) 02430 result.table [index+i] = mantissa.table[i]; 02431 } 02432 02433 result.Rcl ( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); 02434 } 02435 02436 return 0; 02437 } 02438 02439 02440 public: 02441 02442 /*! 02443 this method converts 'this' into 'result' 02444 02445 if the value is too big this method returns a carry (1) 02446 */ 02447 template<uint int_size> 02448 uint ToUInt (UInt<int_size> & result) const 02449 { 02450 uint c = ToUIntOrInt(result); 02451 02452 if( c ) 02453 return 1; 02454 02455 if( IsSign () ) 02456 return 1; 02457 02458 return 0; 02459 } 02460 02461 02462 /*! 02463 this method converts 'this' into 'result' 02464 02465 if the value is too big this method returns a carry (1) 02466 */ 02467 template<uint int_size> 02468 uint ToInt (UInt<int_size> & result) const 02469 { 02470 return ToUInt (result); 02471 } 02472 02473 02474 /*! 02475 this method converts 'this' into 'result' 02476 02477 if the value is too big this method returns a carry (1) 02478 */ 02479 template<uint int_size> 02480 uint ToInt (Int<int_size> & result) const 02481 { 02482 uint c = ToUIntOrInt(result); 02483 02484 if( c ) 02485 return 1; 02486 02487 uint mask = 0; 02488 02489 if( IsSign () ) 02490 { 02491 result.ChangeSign (); 02492 mask = TTMATH_UINT_MAX_VALUE; 02493 } 02494 02495 return ((result.table [int_size-1] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT))? 0 : 1; 02496 } 02497 02498 02499 /*! 02500 a method for converting 'uint' to this class 02501 */ 02502 uint FromUInt (uint value) 02503 { 02504 if( value == 0 ) 02505 { 02506 SetZero (); 02507 return 0; 02508 } 02509 02510 info = 0; 02511 02512 for(uint i=0 ; i<man-1 ; ++i) 02513 mantissa.table [i] = 0; 02514 02515 mantissa.table [man-1] = value; 02516 exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT); 02517 02518 // there shouldn't be a carry because 'value' has the 'uint' type 02519 Standardizing (); 02520 02521 return 0; 02522 } 02523 02524 02525 /*! 02526 a method for converting 'uint' to this class 02527 */ 02528 uint FromInt (uint value) 02529 { 02530 return FromUInt (value); 02531 } 02532 02533 02534 /*! 02535 a method for converting 'sint' to this class 02536 */ 02537 uint FromInt (sint value) 02538 { 02539 bool is_sign = false; 02540 02541 if( value < 0 ) 02542 { 02543 value = -value; 02544 is_sign = true; 02545 } 02546 02547 FromUInt (uint (value)); 02548 02549 if( is_sign ) 02550 SetSign (); 02551 02552 return 0; 02553 } 02554 02555 02556 02557 /*! 02558 this method converts from standard double into this class 02559 02560 standard double means IEEE-754 floating point value with 64 bits 02561 it is as follows (from http://www.psc.edu/general/software/packages/ieee/ieee.html): 02562 02563 The IEEE double precision floating point standard representation requires 02564 a 64 bit word, which may be represented as numbered from 0 to 63, left to 02565 right. The first bit is the sign bit, S, the next eleven bits are the 02566 exponent bits, 'E', and the final 52 bits are the fraction 'F': 02567 02568 S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 02569 0 1 11 12 63 02570 02571 The value V represented by the word may be determined as follows: 02572 02573 * If E=2047 and F is nonzero, then V=NaN ("Not a number") 02574 * If E=2047 and F is zero and S is 1, then V=-Infinity 02575 * If E=2047 and F is zero and S is 0, then V=Infinity 02576 * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended 02577 to represent the binary number created by prefixing F with an implicit 02578 leading 1 and a binary point. 02579 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are 02580 "unnormalized" values. 02581 * If E=0 and F is zero and S is 1, then V=-0 02582 * If E=0 and F is zero and S is 0, then V=0 02583 */ 02584 02585 #ifdef TTMATH_PLATFORM32 02586 02587 uint FromDouble (double value) 02588 { 02589 // I am not sure what will be on a platform which has 02590 // a different endianness... but we use this library only 02591 // on x86 and amd (intel) 64 bits (as there's a lot of assembler code) 02592 union 02593 { 02594 double d; 02595 uint u[2]; // two 32bit words 02596 } temp; 02597 02598 temp.d = value; 02599 02600 sint e = ( temp.u[1] & 0x7FF00000u) >> 20; 02601 uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21); 02602 uint m2 = temp.u[0] << 11; 02603 02604 if( e == 2047 ) 02605 { 02606 // If E=2047 and F is nonzero, then V=NaN ("Not a number") 02607 // If E=2047 and F is zero and S is 1, then V=-Infinity 02608 // If E=2047 and F is zero and S is 0, then V=Infinity 02609 02610 // we do not support -Infinity and +Infinity 02611 // we assume that there is always NaN 02612 02613 SetNan (); 02614 } 02615 else 02616 if( e > 0 ) 02617 { 02618 // If 0<E<2047 then 02619 // V=(-1)**S * 2 ** (E-1023) * (1.F) 02620 // where "1.F" is intended to represent the binary number 02621 // created by prefixing F with an implicit leading 1 and a binary point. 02622 02623 FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0, 02624 e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u, 02625 m1, m2); 02626 02627 // we do not have to call Standardizing() here 02628 // because the mantissa will have the highest bit set 02629 } 02630 else 02631 { 02632 // e == 0 02633 02634 if( m1 != 0 || m2 != 0 ) 02635 { 02636 // If E=0 and F is nonzero, 02637 // then V=(-1)**S * 2 ** (-1022) * (0.F) 02638 // These are "unnormalized" values. 02639 02640 UInt<2> m; 02641 m.table [1] = m1; 02642 m.table [0] = m2; 02643 uint moved = m.CompensationToLeft (); 02644 02645 FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0, 02646 e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0, 02647 m.table [1], m.table [0]); 02648 } 02649 else 02650 { 02651 // If E=0 and F is zero and S is 1, then V=-0 02652 // If E=0 and F is zero and S is 0, then V=0 02653 02654 // we do not support -0 or 0, only is one 0 02655 SetZero (); 02656 } 02657 } 02658 02659 return 0; // never be a carry 02660 } 02661 02662 02663 private: 02664 02665 void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2) 02666 { 02667 exponent = e; 02668 02669 if( man > 1 ) 02670 { 02671 mantissa.table [man-1] = m1 | mhighest; 02672 mantissa.table [sint(man-2)] = m2; 02673 // although man>1 we're using casting into sint 02674 // to get rid from a warning which generates Microsoft Visual: 02675 // warning C4307: '*' : integral constant overflow 02676 02677 for(uint i=0 ; i<man-2 ; ++i) 02678 mantissa.table [i] = 0; 02679 } 02680 else 02681 { 02682 mantissa.table[0] = m1 | mhighest; 02683 } 02684 02685 info = 0; 02686 02687 // the value should be different from zero 02688 TTMATH_ASSERT( mantissa.IsZero() == false ) 02689 02690 if( is_sign ) 02691 SetSign (); 02692 } 02693 02694 02695 #else 02696 02697 public: 02698 02699 // 64bit platforms 02700 uint FromDouble (double value) 02701 { 02702 // I am not sure what will be on a plaltform which has 02703 // a different endianness... but we use this library only 02704 // on x86 and amd (intel) 64 bits (as there's a lot of assembler code) 02705 union 02706 { 02707 double d; 02708 uint u; // one 64bit word 02709 } temp; 02710 02711 temp.d = value; 02712 02713 sint e = (temp.u & 0x7FF0000000000000ul) >> 52; 02714 uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11; 02715 02716 if( e == 2047 ) 02717 { 02718 // If E=2047 and F is nonzero, then V=NaN ("Not a number") 02719 // If E=2047 and F is zero and S is 1, then V=-Infinity 02720 // If E=2047 and F is zero and S is 0, then V=Infinity 02721 02722 // we do not support -Infinity and +Infinity 02723 // we assume that there is always NaN 02724 02725 SetNan (); 02726 } 02727 else 02728 if( e > 0 ) 02729 { 02730 // If 0<E<2047 then 02731 // V=(-1)**S * 2 ** (E-1023) * (1.F) 02732 // where "1.F" is intended to represent the binary number 02733 // created by prefixing F with an implicit leading 1 and a binary point. 02734 02735 FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0, 02736 e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 02737 0x8000000000000000ul, m); 02738 02739 // we do not have to call Standardizing() here 02740 // because the mantissa will have the highest bit set 02741 } 02742 else 02743 { 02744 // e == 0 02745 02746 if( m != 0 ) 02747 { 02748 // If E=0 and F is nonzero, 02749 // then V=(-1)**S * 2 ** (-1022) * (0.F) 02750 // These are "unnormalized" values. 02751 02752 FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul), 02753 e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m); 02754 Standardizing (); 02755 } 02756 else 02757 { 02758 // If E=0 and F is zero and S is 1, then V=-0 02759 // If E=0 and F is zero and S is 0, then V=0 02760 02761 // we do not support -0 or 0, only is one 0 02762 SetZero (); 02763 } 02764 } 02765 02766 return 0; // never be a carry 02767 } 02768 02769 private: 02770 02771 void FromDouble_SetExpAndMan(bool is_sign, sint e, uint mhighest, uint m) 02772 { 02773 exponent = e; 02774 mantissa.table[man-1] = m | mhighest; 02775 02776 for(uint i=0 ; i<man-1 ; ++i) 02777 mantissa.table[i] = 0; 02778 02779 info = 0; 02780 02781 // the value should be different from zero 02782 TTMATH_ASSERT( mantissa.IsZero() == false ) 02783 02784 if( is_sign ) 02785 SetSign (); 02786 } 02787 02788 #endif 02789 02790 02791 public: 02792 02793 02794 /*! 02795 this method converts from float to this class 02796 */ 02797 uint FromFloat (float value) 02798 { 02799 return FromDouble (double(value)); 02800 } 02801 02802 02803 /*! 02804 this method converts from this class into the 'double' 02805 02806 if the value is too big: 02807 'result' will be +/-infinity (depending on the sign) 02808 if the value is too small: 02809 'result' will be 0 02810 */ 02811 double ToDouble () const 02812 { 02813 double result; 02814 02815 ToDouble (result); 02816 02817 return result; 02818 } 02819 02820 02821 private: 02822 02823 02824 /*! 02825 an auxiliary method to check if the float value is +/-infinity 02826 we provide this method because isinf(float) in only in C99 language 02827 02828 description taken from: http://www.psc.edu/general/software/packages/ieee/ieee.php 02829 02830 The IEEE single precision floating point standard representation requires a 32 bit word, 02831 which may be represented as numbered from 0 to 31, left to right. 02832 The first bit is the sign bit, S, the next eight bits are the exponent bits, 'E', 02833 and the final 23 bits are the fraction 'F': 02834 02835 S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF 02836 0 1 8 9 31 02837 02838 The value V represented by the word may be determined as follows: 02839 02840 * If E=255 and F is nonzero, then V=NaN ("Not a number") 02841 * If E=255 and F is zero and S is 1, then V=-Infinity 02842 * If E=255 and F is zero and S is 0, then V=Infinity 02843 * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent 02844 the binary number created by prefixing F with an implicit leading 1 and a binary point. 02845 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values. 02846 * If E=0 and F is zero and S is 1, then V=-0 02847 * If E=0 and F is zero and S is 0, then V=0 02848 */ 02849 bool IsInf(float value) const 02850 { 02851 // need testing on a 64 bit machine 02852 02853 union 02854 { 02855 float d; 02856 uint u; 02857 } temp; 02858 02859 temp.d = value; 02860 02861 if( ((temp.u >> 23) & 0xff) == 0xff ) 02862 { 02863 if( (temp.u & 0x7FFFFF) == 0 ) 02864 return true; // +/- infinity 02865 } 02866 02867 return false; 02868 } 02869 02870 02871 public: 02872 02873 /*! 02874 this method converts from this class into the 'float' 02875 02876 if the value is too big: 02877 'result' will be +/-infinity (depending on the sign) 02878 if the value is too small: 02879 'result' will be 0 02880 */ 02881 float ToFloat () const 02882 { 02883 float result; 02884 02885 ToFloat (result); 02886 02887 return result; 02888 } 02889 02890 02891 /*! 02892 this method converts from this class into the 'float' 02893 02894 if the value is too big: 02895 'result' will be +/-infinity (depending on the sign) 02896 and the method returns 1 02897 if the value is too small: 02898 'result' will be 0 02899 and the method returns 1 02900 */ 02901 uint ToFloat (float & result) const 02902 { 02903 double result_double; 02904 02905 uint c = ToDouble (result_double); 02906 result = float(result_double); 02907 02908 if( result == -0.0f ) 02909 result = 0.0f; 02910 02911 if( c ) 02912 return 1; 02913 02914 // although the result_double can have a correct value 02915 // but after converting to float there can be infinity 02916 02917 if( IsInf(result) ) 02918 return 1; 02919 02920 if( result == 0.0f && result_double != 0.0 ) 02921 // result_double was too small for float 02922 return 1; 02923 02924 return 0; 02925 } 02926 02927 02928 /*! 02929 this method converts from this class into the 'double' 02930 02931 if the value is too big: 02932 'result' will be +/-infinity (depending on the sign) 02933 and the method returns 1 02934 if the value is too small: 02935 'result' will be 0 02936 and the method returns 1 02937 */ 02938 uint ToDouble (double & result) const 02939 { 02940 if( IsZero () ) 02941 { 02942 result = 0.0; 02943 return 0; 02944 } 02945 02946 if( IsNan () ) 02947 { 02948 result = ToDouble_SetDouble( false, 2047, 0, false, true); 02949 02950 return 0; 02951 } 02952 02953 sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1; 02954 02955 if( exponent >= 1024 - e_correction ) 02956 { 02957 // +/- infinity 02958 result = ToDouble_SetDouble( IsSign (), 2047, 0, true); 02959 02960 return 1; 02961 } 02962 else 02963 if( exponent <= -1023 - 52 - e_correction ) 02964 { 02965 // too small value - we assume that there'll be a zero 02966 result = 0; 02967 02968 // and return a carry 02969 return 1; 02970 } 02971 02972 sint e = exponent.ToInt () + e_correction; 02973 02974 if( e <= -1023 ) 02975 { 02976 // -1023-52 < e <= -1023 (unnormalized value) 02977 result = ToDouble_SetDouble( IsSign (), 0, -(e + 1023)); 02978 } 02979 else 02980 { 02981 // -1023 < e < 1024 02982 result = ToDouble_SetDouble( IsSign (), e + 1023, -1); 02983 } 02984 02985 return 0; 02986 } 02987 02988 private: 02989 02990 #ifdef TTMATH_PLATFORM32 02991 02992 // 32bit platforms 02993 double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const 02994 { 02995 union 02996 { 02997 double d; 02998 uint u[2]; // two 32bit words 02999 } temp; 03000 03001 temp.u[0] = temp.u[1] = 0; 03002 03003 if( is_sign ) 03004 temp.u[1] |= 0x80000000u; 03005 03006 temp.u[1] |= (e << 20) & 0x7FF00000u; 03007 03008 if( nan ) 03009 { 03010 temp.u[0] |= 1; 03011 return temp.d; 03012 } 03013 03014 if( infinity ) 03015 return temp.d; 03016 03017 UInt<2> m; 03018 m.table[1] = mantissa.table[man-1]; 03019 m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0; 03020 // although man>1 we're using casting into sint 03021 // to get rid from a warning which generates Microsoft Visual: 03022 // warning C4307: '*' : integral constant overflow 03023 03024 m.Rcr( 12 + move ); 03025 m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1) 03026 03027 temp.u[1] |= m.table[1]; 03028 temp.u[0] |= m.table[0]; 03029 03030 return temp.d; 03031 } 03032 03033 #else 03034 03035 // 64bit platforms 03036 double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const 03037 { 03038 union 03039 { 03040 double d; 03041 uint u; // 64bit word 03042 } temp; 03043 03044 temp.u = 0; 03045 03046 if( is_sign ) 03047 temp.u |= 0x8000000000000000ul; 03048 03049 temp.u |= (e << 52) & 0x7FF0000000000000ul; 03050 03051 if( nan ) 03052 { 03053 temp.u |= 1; 03054 return temp.d; 03055 } 03056 03057 if( infinity ) 03058 return temp.d; 03059 03060 uint m = mantissa.table[man-1]; 03061 03062 m >>= ( 12 + move ); 03063 m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1) 03064 temp.u |= m; 03065 03066 return temp.d; 03067 } 03068 03069 #endif 03070 03071 03072 public: 03073 03074 03075 /*! 03076 an operator= for converting 'sint' to this class 03077 */ 03078 Big<exp, man> & operator= (sint value) 03079 { 03080 FromInt (value); 03081 03082 return *this; 03083 } 03084 03085 03086 /*! 03087 an operator= for converting 'uint' to this class 03088 */ 03089 Big<exp, man> & operator= (uint value) 03090 { 03091 FromUInt (value); 03092 03093 return *this; 03094 } 03095 03096 03097 /*! 03098 an operator= for converting 'float' to this class 03099 */ 03100 Big<exp, man> & operator= (float value) 03101 { 03102 FromFloat (value); 03103 03104 return *this; 03105 } 03106 03107 03108 /*! 03109 an operator= for converting 'double' to this class 03110 */ 03111 Big<exp, man> & operator= (double value) 03112 { 03113 FromDouble (value); 03114 03115 return *this; 03116 } 03117 03118 03119 /*! 03120 a constructor for converting 'sint' to this class 03121 */ 03122 Big (sint value) 03123 { 03124 FromInt (value); 03125 } 03126 03127 /*! 03128 a constructor for converting 'uint' to this class 03129 */ 03130 Big (uint value) 03131 { 03132 FromUInt (value); 03133 } 03134 03135 03136 /*! 03137 a constructor for converting 'double' to this class 03138 */ 03139 Big (double value) 03140 { 03141 FromDouble (value); 03142 } 03143 03144 03145 /*! 03146 a constructor for converting 'float' to this class 03147 */ 03148 Big (float value) 03149 { 03150 FromFloat (value); 03151 } 03152 03153 03154 #ifdef TTMATH_PLATFORM32 03155 03156 /*! 03157 this method converts 'this' into 'result' (64 bit unsigned integer) 03158 if the value is too big this method returns a carry (1) 03159 */ 03160 uint ToUInt (ulint & result) const 03161 { 03162 UInt<2> temp; // 64 bits container 03163 03164 uint c = ToUInt (temp); 03165 temp.ToUInt (result); 03166 03167 return c; 03168 } 03169 03170 03171 /*! 03172 this method converts 'this' into 'result' (64 bit unsigned integer) 03173 if the value is too big this method returns a carry (1) 03174 */ 03175 uint ToInt (ulint & result) const 03176 { 03177 return ToUInt (result); 03178 } 03179 03180 03181 /*! 03182 this method converts 'this' into 'result' (64 bit unsigned integer) 03183 if the value is too big this method returns a carry (1) 03184 */ 03185 uint ToInt (slint & result) const 03186 { 03187 Int<2> temp; // 64 bits container 03188 03189 uint c = ToInt (temp); 03190 temp.ToInt (result); 03191 03192 return c; 03193 } 03194 03195 03196 /*! 03197 a method for converting 'ulint' (64bit unsigned integer) to this class 03198 */ 03199 uint FromUInt (ulint value) 03200 { 03201 if( value == 0 ) 03202 { 03203 SetZero (); 03204 return 0; 03205 } 03206 03207 info = 0; 03208 03209 if( man == 1 ) 03210 { 03211 sint bit = mantissa.FindLeadingBitInWord (uint (value >> TTMATH_BITS_PER_UINT)); 03212 03213 if( bit != -1 ) 03214 { 03215 // the highest word from value is different from zero 03216 bit += 1; 03217 value >>= bit; 03218 exponent = bit; 03219 } 03220 else 03221 { 03222 exponent.SetZero (); 03223 } 03224 03225 mantissa.table [0] = uint (value); 03226 } 03227 else 03228 { 03229 #ifdef _MSC_VER 03230 //warning C4307: '*' : integral constant overflow 03231 #pragma warning( disable: 4307 ) 03232 #endif 03233 03234 // man >= 2 03235 mantissa.table [man-1] = uint (value >> TTMATH_BITS_PER_UINT); 03236 mantissa.table [man-2] = uint (value); 03237 03238 #ifdef _MSC_VER 03239 //warning C4307: '*' : integral constant overflow 03240 #pragma warning( default: 4307 ) 03241 #endif 03242 03243 exponent = -sint(man-2) * sint(TTMATH_BITS_PER_UINT); 03244 03245 for(uint i=0 ; i<man-2 ; ++i) 03246 mantissa.table [i] = 0; 03247 } 03248 03249 // there shouldn't be a carry because 'value' has the 'ulint' type 03250 // (we have sufficient exponent) 03251 Standardizing (); 03252 03253 return 0; 03254 } 03255 03256 03257 /*! 03258 a method for converting 'ulint' (64bit unsigned integer) to this class 03259 */ 03260 uint FromInt (ulint value) 03261 { 03262 return FromUInt (value); 03263 } 03264 03265 03266 /*! 03267 a method for converting 'slint' (64bit signed integer) to this class 03268 */ 03269 uint FromInt (slint value) 03270 { 03271 bool is_sign = false; 03272 03273 if( value < 0 ) 03274 { 03275 value = -value; 03276 is_sign = true; 03277 } 03278 03279 FromUInt (ulint (value)); 03280 03281 if( is_sign ) 03282 SetSign (); 03283 03284 return 0; 03285 } 03286 03287 03288 /*! 03289 a constructor for converting 'ulint' (64bit unsigned integer) to this class 03290 */ 03291 Big (ulint value) 03292 { 03293 FromUInt (value); 03294 } 03295 03296 03297 /*! 03298 an operator for converting 'ulint' (64bit unsigned integer) to this class 03299 */ 03300 Big<exp, man> & operator= (ulint value) 03301 { 03302 FromUInt (value); 03303 03304 return *this; 03305 } 03306 03307 03308 /*! 03309 a constructor for converting 'slint' (64bit signed integer) to this class 03310 */ 03311 Big (slint value) 03312 { 03313 FromInt (value); 03314 } 03315 03316 03317 /*! 03318 an operator for converting 'slint' (64bit signed integer) to this class 03319 */ 03320 Big<exp, man> & operator= (slint value) 03321 { 03322 FromInt (value); 03323 03324 return *this; 03325 } 03326 03327 #endif 03328 03329 03330 03331 #ifdef TTMATH_PLATFORM64 03332 03333 03334 /*! 03335 this method converts 'this' into 'result' (32 bit unsigned integer) 03336 ***this method is created only on a 64bit platform*** 03337 if the value is too big this method returns a carry (1) 03338 */ 03339 uint ToUInt (unsigned int & result) const 03340 { 03341 uint result_uint; 03342 03343 uint c = ToUInt (result_uint); 03344 result = (unsigned int)result_uint; 03345 03346 if( c || result_uint != uint (result) ) 03347 return 1; 03348 03349 return 0; 03350 } 03351 03352 03353 /*! 03354 this method converts 'this' into 'result' (32 bit unsigned integer) 03355 ***this method is created only on a 64bit platform*** 03356 if the value is too big this method returns a carry (1) 03357 */ 03358 uint ToInt (unsigned int & result) const 03359 { 03360 return ToUInt (result); 03361 } 03362 03363 03364 /*! 03365 this method converts 'this' into 'result' (32 bit signed integer) 03366 ***this method is created only on a 64bit platform*** 03367 if the value is too big this method returns a carry (1) 03368 */ 03369 uint ToInt (signed int & result) const 03370 { 03371 sint result_sint; 03372 03373 uint c = ToInt (result_sint); 03374 result = (signed int)result_sint; 03375 03376 if( c || result_sint != sint(result) ) 03377 return 1; 03378 03379 return 0; 03380 } 03381 03382 03383 /* 03384 this method converts 32 bit unsigned int to this class 03385 ***this method is created only on a 64bit platform*** 03386 */ 03387 uint FromUInt (unsigned int value) 03388 { 03389 return FromUInt (uint (value)); 03390 } 03391 03392 03393 /* 03394 this method converts 32 bit unsigned int to this class 03395 ***this method is created only on a 64bit platform*** 03396 */ 03397 uint FromInt (unsigned int value) 03398 { 03399 return FromUInt (uint (value)); 03400 } 03401 03402 03403 /* 03404 this method converts 32 bit signed int to this class 03405 ***this method is created only on a 64bit platform*** 03406 */ 03407 uint FromInt (signed int value) 03408 { 03409 return FromInt (sint(value)); 03410 } 03411 03412 03413 /*! 03414 an operator= for converting 32 bit unsigned int to this class 03415 ***this operator is created only on a 64bit platform*** 03416 */ 03417 Big<exp, man> & operator= (unsigned int value) 03418 { 03419 FromUInt (value); 03420 03421 return *this; 03422 } 03423 03424 03425 /*! 03426 a constructor for converting 32 bit unsigned int to this class 03427 ***this constructor is created only on a 64bit platform*** 03428 */ 03429 Big (unsigned int value) 03430 { 03431 FromUInt (value); 03432 } 03433 03434 03435 /*! 03436 an operator for converting 32 bit signed int to this class 03437 ***this operator is created only on a 64bit platform*** 03438 */ 03439 Big<exp, man> & operator= (signed int value) 03440 { 03441 FromInt (value); 03442 03443 return *this; 03444 } 03445 03446 03447 /*! 03448 a constructor for converting 32 bit signed int to this class 03449 ***this constructor is created only on a 64bit platform*** 03450 */ 03451 Big (signed int value) 03452 { 03453 FromInt (value); 03454 } 03455 03456 #endif 03457 03458 03459 private: 03460 03461 /*! 03462 an auxiliary method for converting from UInt and Int 03463 03464 we assume that there'll never be a carry here 03465 (we have an exponent and the value in Big can be bigger than 03466 that one from the UInt) 03467 */ 03468 template<uint int_size> 03469 uint FromUIntOrInt(const UInt<int_size> & value, sint compensation) 03470 { 03471 uint minimum_size = (int_size < man)? int_size : man; 03472 exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation; 03473 03474 // copying the highest words 03475 uint i; 03476 for(i=1 ; i<=minimum_size ; ++i) 03477 mantissa.table [man-i] = value.table [int_size-i]; 03478 03479 // setting the rest of mantissa.table into zero (if some has left) 03480 for( ; i<=man ; ++i) 03481 mantissa.table [man-i] = 0; 03482 03483 // the highest bit is either one or zero (when the whole mantissa is zero) 03484 // we can only call CorrectZero() 03485 CorrectZero(); 03486 03487 return 0; 03488 } 03489 03490 03491 public: 03492 03493 /*! 03494 a method for converting from 'UInt<int_size>' to this class 03495 */ 03496 template<uint int_size> 03497 uint FromUInt (UInt<int_size> value) 03498 { 03499 info = 0; 03500 sint compensation = (sint)value.CompensationToLeft (); 03501 03502 return FromUIntOrInt(value, compensation); 03503 } 03504 03505 03506 /*! 03507 a method for converting from 'UInt<int_size>' to this class 03508 */ 03509 template<uint int_size> 03510 uint FromInt (const UInt<int_size> & value) 03511 { 03512 return FromUInt (value); 03513 } 03514 03515 03516 /*! 03517 a method for converting from 'Int<int_size>' to this class 03518 */ 03519 template<uint int_size> 03520 uint FromInt (Int<int_size> value) 03521 { 03522 info = 0; 03523 bool is_sign = false; 03524 03525 if( value.IsSign () ) 03526 { 03527 value.ChangeSign (); 03528 is_sign = true; 03529 } 03530 03531 sint compensation = (sint)value.CompensationToLeft (); 03532 FromUIntOrInt(value, compensation); 03533 03534 if( is_sign ) 03535 SetSign (); 03536 03537 return 0; 03538 } 03539 03540 03541 /*! 03542 an operator= for converting from 'Int<int_size>' to this class 03543 */ 03544 template<uint int_size> 03545 Big<exp,man> & operator= (const Int<int_size> & value) 03546 { 03547 FromInt (value); 03548 03549 return *this; 03550 } 03551 03552 03553 /*! 03554 a constructor for converting from 'Int<int_size>' to this class 03555 */ 03556 template<uint int_size> 03557 Big (const Int<int_size> & value) 03558 { 03559 FromInt (value); 03560 } 03561 03562 03563 /*! 03564 an operator= for converting from 'UInt<int_size>' to this class 03565 */ 03566 template<uint int_size> 03567 Big<exp,man> & operator= (const UInt<int_size> & value) 03568 { 03569 FromUInt (value); 03570 03571 return *this; 03572 } 03573 03574 03575 /*! 03576 a constructor for converting from 'UInt<int_size>' to this class 03577 */ 03578 template<uint int_size> 03579 Big (const UInt<int_size> & value) 03580 { 03581 FromUInt (value); 03582 } 03583 03584 03585 /*! 03586 an operator= for converting from 'Big<another_exp, another_man>' to this class 03587 */ 03588 template<uint another_exp, uint another_man> 03589 Big<exp,man> & operator= (const Big<another_exp, another_man> & value) 03590 { 03591 FromBig (value); 03592 03593 return *this; 03594 } 03595 03596 03597 /*! 03598 a constructor for converting from 'Big<another_exp, another_man>' to this class 03599 */ 03600 template<uint another_exp, uint another_man> 03601 Big (const Big<another_exp, another_man> & value) 03602 { 03603 FromBig (value); 03604 } 03605 03606 03607 /*! 03608 a default constructor 03609 03610 by default we don't set any of the members to zero 03611 only NaN flag is set 03612 03613 if you want the mantissa and exponent to be set to zero 03614 define TTMATH_BIG_DEFAULT_CLEAR macro 03615 (useful for debug purposes) 03616 */ 03617 Big () 03618 { 03619 #ifdef TTMATH_BIG_DEFAULT_CLEAR 03620 03621 SetZeroNan (); 03622 03623 #else 03624 03625 info = TTMATH_BIG_NAN; 03626 // we're directly setting 'info' (instead of calling SetNan()) 03627 // in order to get rid of a warning saying that 'info' is uninitialized 03628 03629 #endif 03630 } 03631 03632 03633 /*! 03634 a destructor 03635 */ 03636 ~Big () 03637 { 03638 } 03639 03640 03641 /*! 03642 the default assignment operator 03643 */ 03644 Big<exp,man> & operator= (const Big<exp,man> & value) 03645 { 03646 info = value.info; 03647 exponent = value.exponent; 03648 mantissa = value.mantissa; 03649 03650 return *this; 03651 } 03652 03653 03654 /*! 03655 a constructor for copying from another object of this class 03656 */ 03657 03658 Big (const Big<exp,man> & value) 03659 { 03660 operator= (value); 03661 } 03662 03663 03664 03665 /*! 03666 a method for converting into a string 03667 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03668 03669 output: 03670 return value: 03671 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value 03672 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there 03673 is somewhere an error in the library) 03674 */ 03675 uint ToString ( std::string & result, 03676 uint base = 10, 03677 bool scient = false, 03678 sint scient_from = 15, 03679 sint round = -1, 03680 bool trim_zeroes = true, 03681 char comma = '.' ) const 03682 { 03683 Conv conv; 03684 03685 conv.base = base; 03686 conv.scient = scient; 03687 conv.scient_from = scient_from; 03688 conv.round = round; 03689 conv.trim_zeroes = trim_zeroes; 03690 conv.comma = static_cast<uint >(comma); 03691 03692 return ToStringBase<std::string, char>(result, conv); 03693 } 03694 03695 03696 /*! 03697 a method for converting into a string 03698 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03699 */ 03700 uint ToString (std::string & result, const Conv & conv) const 03701 { 03702 return ToStringBase<std::string, char>(result, conv); 03703 } 03704 03705 03706 /*! 03707 a method for converting into a string 03708 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03709 */ 03710 std::string ToString (const Conv & conv) const 03711 { 03712 std::string result; 03713 ToStringBase<std::string, char>(result, conv); 03714 03715 return result; 03716 } 03717 03718 03719 /*! 03720 a method for converting into a string 03721 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03722 */ 03723 std::string ToString (uint base = 10) const 03724 { 03725 Conv conv; 03726 conv.base = base; 03727 03728 return ToString (conv); 03729 } 03730 03731 03732 03733 #ifndef TTMATH_DONT_USE_WCHAR 03734 03735 03736 /*! 03737 a method for converting into a string 03738 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03739 */ 03740 uint ToString ( std::wstring & result, 03741 uint base = 10, 03742 bool scient = false, 03743 sint scient_from = 15, 03744 sint round = -1, 03745 bool trim_zeroes = true, 03746 wchar_t comma = '.' ) const 03747 { 03748 Conv conv; 03749 03750 conv.base = base; 03751 conv.scient = scient; 03752 conv.scient_from = scient_from; 03753 conv.round = round; 03754 conv.trim_zeroes = trim_zeroes; 03755 conv.comma = static_cast<uint >(comma); 03756 03757 return ToStringBase<std::wstring, wchar_t>(result, conv); 03758 } 03759 03760 03761 /*! 03762 a method for converting into a string 03763 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03764 */ 03765 uint ToString (std::wstring & result, const Conv & conv) const 03766 { 03767 return ToStringBase<std::wstring, wchar_t>(result, conv); 03768 } 03769 03770 03771 /*! 03772 a method for converting into a string 03773 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03774 */ 03775 std::wstring ToWString (const Conv & conv) const 03776 { 03777 std::wstring result; 03778 ToStringBase<std::wstring, wchar_t>(result, conv); 03779 03780 return result; 03781 } 03782 03783 03784 /*! 03785 a method for converting into a string 03786 struct Conv is defined in ttmathtypes.h, look there for more information about parameters 03787 */ 03788 std::wstring ToWString (uint base = 10) const 03789 { 03790 Conv conv; 03791 conv.base = base; 03792 03793 return ToWString (conv); 03794 } 03795 03796 #endif 03797 03798 03799 03800 private: 03801 03802 03803 /*! 03804 an auxiliary method for converting into the string 03805 */ 03806 template<class string_type, class char_type> 03807 uint ToStringBase(string_type & result, const Conv & conv) const 03808 { 03809 static char error_overflow_msg[] = "overflow"; 03810 static char error_nan_msg[] = "NaN"; 03811 result.erase(); 03812 03813 if( IsNan () ) 03814 { 03815 Misc::AssignString (result, error_nan_msg); 03816 return 0; 03817 } 03818 03819 if( conv.base <2 || conv.base >16 ) 03820 { 03821 Misc::AssignString (result, error_overflow_msg); 03822 return 1; 03823 } 03824 03825 if( IsZero () ) 03826 { 03827 result = '0'; 03828 03829 return 0; 03830 } 03831 03832 /* 03833 since 'base' is greater or equal 2 that 'new_exp' of type 'Int<exp>' should 03834 hold the new value of exponent but we're using 'Int<exp+1>' because 03835 if the value for example would be 'max()' then we couldn't show it 03836 03837 max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set) 03838 if we were using 'Int<exp>' we couldn't show it in this format: 03839 1,1111111 * 2 ^ 11111111111 (bin) 03840 because we have to add something to the mantissa and because 03841 mantissa is full we can't do it and it'll be a carry 03842 (look at ToString_SetCommaAndExponent(...)) 03843 03844 when the base would be greater than two (for example 10) 03845 we could use 'Int<exp>' here 03846 */ 03847 Int<exp+1> new_exp; 03848 03849 if( ToString_CreateNewMantissaAndExponent<string_type, char_type>(result, conv, new_exp) ) 03850 { 03851 Misc::AssignString (result, error_overflow_msg); 03852 return 1; 03853 } 03854 03855 03856 if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) ) 03857 { 03858 Misc::AssignString (result, error_overflow_msg); 03859 return 1; 03860 } 03861 03862 if( IsSign () ) 03863 result.insert(result.begin(), '-'); 03864 03865 03866 // converted successfully 03867 return 0; 03868 } 03869 03870 03871 03872 /*! 03873 in the method 'ToString_CreateNewMantissaAndExponent()' we're using 03874 type 'Big<exp+1,man>' and we should have the ability to use some 03875 necessary methods from that class (methods which are private here) 03876 */ 03877 friend class Big<exp-1,man>; 03878 03879 03880 /*! 03881 an auxiliary method for converting into the string 03882 03883 input: 03884 base - the base in range <2,16> 03885 03886 output: 03887 return values: 03888 0 - ok 03889 1 - if there was a carry 03890 new_man - the new mantissa for 'base' 03891 new_exp - the new exponent for 'base' 03892 03893 mathematic part: 03894 03895 the value is stored as: 03896 value = mantissa * 2^exponent 03897 we want to show 'value' as: 03898 value = new_man * base^new_exp 03899 03900 then 'new_man' we'll print using the standard method from UInt<> type for printing 03901 and 'new_exp' is the offset of the comma operator in a system of a base 'base' 03902 03903 value = mantissa * 2^exponent 03904 value = mantissa * 2^exponent * (base^new_exp / base^new_exp) 03905 value = mantissa * (2^exponent / base^new_exp) * base^new_exp 03906 03907 look at the part (2^exponent / base^new_exp), there'll be good if we take 03908 a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one 03909 03910 on account of the 'base' is not as power of 2 (can be from 2 to 16), 03911 this formula will not be true for integer 'new_exp' then in our case we take 03912 'base^new_exp' _greater_ than '2^exponent' 03913 03914 if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be 03915 greater than the max value of the container UInt<man> 03916 03917 value = mantissa * (2^exponent / base^new_exp) * base^new_exp 03918 let M = mantissa * (2^exponent / base^new_exp) then 03919 value = M * base^new_exp 03920 03921 in our calculation we treat M as floating value showing it as: 03922 M = mm * 2^ee where ee will be <= 0 03923 03924 next we'll move all bits of mm into the right when ee is equal zero 03925 abs(ee) must not be too big that only few bits from mm we can leave 03926 03927 then we'll have: 03928 M = mmm * 2^0 03929 'mmm' is the new_man which we're looking for 03930 03931 03932 new_exp we calculate in this way: 03933 2^exponent <= base^new_exp 03934 new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent) 03935 03936 but we need new_exp as integer then we test: 03937 if new_exp is greater than zero and with fraction we add one to new_exp 03938 new_exp = new_exp + 1 (if new_exp>0 and with fraction) 03939 and at the end we take the integer part: 03940 new_exp = int(new_exp) 03941 */ 03942 template<class string_type, class char_type> 03943 uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv, 03944 Int<exp+1> & new_exp) const 03945 { 03946 uint c = 0; 03947 03948 if( conv.base <2 || conv.base >16 ) 03949 return 1; 03950 03951 // special method for base equal 2 03952 if( conv.base == 2 ) 03953 return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp); 03954 03955 // special method for base equal 4 03956 if( conv.base == 4 ) 03957 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2); 03958 03959 // special method for base equal 8 03960 if( conv.base == 8 ) 03961 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3); 03962 03963 // special method for base equal 16 03964 if( conv.base == 16 ) 03965 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4); 03966 03967 03968 // this = mantissa * 2^exponent 03969 03970 // temp = +1 * 2^exponent 03971 // we're using a bigger type than 'big<exp,man>' (look below) 03972 Big<exp+1,man> temp; 03973 temp.info = 0; 03974 temp.exponent = exponent; 03975 temp.mantissa.SetOne (); 03976 c += temp.Standardizing (); 03977 03978 // new_exp_ = log base (2^exponent) 03979 // if new_exp_ is positive and with fraction then we add one 03980 Big<exp+1,man> new_exp_; 03981 c += new_exp_.ToString_Log(temp, conv.base ); // this logarithm isn't very complicated 03982 03983 // rounding up to the nearest integer 03984 if( !new_exp_.IsInteger () ) 03985 { 03986 if( !new_exp_.IsSign () ) 03987 c += new_exp_.AddOne(); // new_exp_ > 0 and with fraction 03988 03989 new_exp_.SkipFraction (); 03990 } 03991 03992 if( ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp) ) 03993 { 03994 // in very rare cases there can be an overflow from ToString_CreateNewMantissaTryExponent 03995 // it means that new_exp_ was too small (the problem comes from floating point numbers precision) 03996 // so we increse new_exp_ and try again 03997 new_exp_.AddOne(); 03998 c += ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp); 03999 } 04000 04001 return (c==0)? 0 : 1; 04002 } 04003 04004 04005 04006 /*! 04007 an auxiliary method for converting into the string 04008 04009 trying to calculate new_man for given exponent (new_exp_) 04010 if there is a carry it can mean that new_exp_ is too small 04011 */ 04012 template<class string_type, class char_type> 04013 uint ToString_CreateNewMantissaTryExponent( string_type & new_man, const Conv & conv, 04014 const Big<exp+1,man> & new_exp_, Int<exp+1> & new_exp) const 04015 { 04016 uint c = 0; 04017 04018 // because 'base^new_exp' is >= '2^exponent' then 04019 // because base is >= 2 then we've got: 04020 // 'new_exp_' must be smaller or equal 'new_exp' 04021 // and we can pass it into the Int<exp> type 04022 // (in fact we're using a greater type then it'll be ok) 04023 c += new_exp_.ToInt(new_exp); 04024 04025 // base_ = base 04026 Big<exp+1,man> base_(conv.base); 04027 04028 // base_ = base_ ^ new_exp_ 04029 c += base_.Pow( new_exp_ ); // use new_exp_ so Pow(Big<> &) version will be used 04030 // if we hadn't used a bigger type than 'Big<exp,man>' then the result 04031 // of this formula 'Pow(...)' would have been with an overflow 04032 04033 // temp = mantissa * 2^exponent / base_^new_exp_ 04034 Big<exp+1,man> temp; 04035 temp.info = 0; 04036 temp.mantissa = mantissa; 04037 temp.exponent = exponent; 04038 c += temp.Div(base_); 04039 04040 // moving all bits of the mantissa into the right 04041 // (how many times to move depend on the exponent) 04042 c += temp.ToString_MoveMantissaIntoRight(); 04043 04044 // because we took 'new_exp' as small as it was 04045 // possible ([log base (2^exponent)] + 1) that after the division 04046 // (temp.Div( base_ )) the value of exponent should be equal zero or 04047 // minimum smaller than zero then we've got the mantissa which has 04048 // maximum valid bits 04049 temp.mantissa.ToString(new_man, conv.base); 04050 04051 if( IsInteger () ) 04052 { 04053 // making sure the new mantissa will be without fraction (integer) 04054 ToString_CheckMantissaInteger<string_type, char_type>(new_man, new_exp); 04055 } 04056 else 04057 if( conv.base_round ) 04058 { 04059 c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp); 04060 } 04061 04062 return (c==0)? 0 : 1; 04063 } 04064 04065 04066 /*! 04067 this method calculates the logarithm 04068 it is used by ToString_CreateNewMantissaAndExponent() method 04069 04070 it's not too complicated 04071 because x=+1*2^exponent (mantissa is one) then during the calculation 04072 the Ln(x) will not be making the long formula from LnSurrounding1() 04073 and only we have to calculate 'Ln(base)' but it'll be calculated 04074 only once, the next time we will get it from the 'history' 04075 04076 x is greater than 0 04077 base is in <2,16> range 04078 */ 04079 uint ToString_Log(const Big<exp,man> & x, uint base) 04080 { 04081 TTMATH_REFERENCE_ASSERT( x ) 04082 TTMATH_ASSERT( base>=2 && base<=16 ) 04083 04084 Big <exp,man> temp; 04085 temp.SetOne (); 04086 04087 if( x == temp ) 04088 { 04089 // log(1) is 0 04090 SetZero (); 04091 04092 return 0; 04093 } 04094 04095 // there can be only a carry 04096 // because the 'x' is in '1+2*exponent' form then 04097 // the long formula from LnSurrounding1() will not be calculated 04098 // (LnSurrounding1() will return one immediately) 04099 uint c = Ln (x); 04100 04101 if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE ) 04102 { 04103 // for the base equal 10 we're using SetLn10() instead of calculating it 04104 // (only if we have the constant sufficient big) 04105 temp.SetLn10(); 04106 } 04107 else 04108 { 04109 c += ToString_LogBase(base, temp); 04110 } 04111 04112 c += Div ( temp ); 04113 04114 return (c==0)? 0 : 1; 04115 } 04116 04117 04118 #ifndef TTMATH_MULTITHREADS 04119 04120 /*! 04121 this method calculates the logarithm of 'base' 04122 it's used in single thread environment 04123 */ 04124 uint ToString_LogBase(uint base, Big<exp,man> & result) 04125 { 04126 TTMATH_ASSERT( base>=2 && base<=16 ) 04127 04128 // this guardians are initialized before the program runs (static POD types) 04129 static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 04130 static Big<exp,man> log_history[15]; 04131 uint index = base - 2; 04132 uint c = 0; 04133 04134 if( guardians[index] == 0 ) 04135 { 04136 Big<exp,man> base_(base); 04137 c += log_history[index].Ln(base_); 04138 guardians[index] = 1; 04139 } 04140 04141 result = log_history[index]; 04142 04143 return (c==0)? 0 : 1; 04144 } 04145 04146 #else 04147 04148 /*! 04149 this method calculates the logarithm of 'base' 04150 it's used in multi-thread environment 04151 */ 04152 uint ToString_LogBase(uint base, Big<exp,man> & result) 04153 { 04154 TTMATH_ASSERT( base>=2 && base<=16 ) 04155 04156 // this guardians are initialized before the program runs (static POD types) 04157 volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 04158 static Big<exp,man> * plog_history; 04159 uint index = base - 2; 04160 uint c = 0; 04161 04162 // double-checked locking 04163 if( guardians[index] == 0 ) 04164 { 04165 ThreadLock thread_lock; 04166 04167 // locking 04168 if( thread_lock.Lock() ) 04169 { 04170 static Big<exp,man> log_history[15]; 04171 04172 if( guardians[index] == 0 ) 04173 { 04174 plog_history = log_history; 04175 04176 Big<exp,man> base_(base); 04177 c += log_history[index].Ln(base_); 04178 guardians[index] = 1; 04179 } 04180 } 04181 else 04182 { 04183 // there was a problem with locking, we store the result directly in 'result' object 04184 Big<exp,man> base_(base); 04185 c += result.Ln(base_); 04186 04187 return (c==0)? 0 : 1; 04188 } 04189 04190 // automatically unlocking 04191 } 04192 04193 result = plog_history[index]; 04194 04195 return (c==0)? 0 : 1; 04196 } 04197 04198 #endif 04199 04200 /*! 04201 an auxiliary method for converting into the string (private) 04202 04203 this method moving all bits from mantissa into the right side 04204 the exponent tell us how many times moving (the exponent is <=0) 04205 */ 04206 uint ToString_MoveMantissaIntoRight() 04207 { 04208 if( exponent.IsZero() ) 04209 return 0; 04210 04211 // exponent can't be greater than zero 04212 // because we would cat the highest bits of the mantissa 04213 if( !exponent.IsSign() ) 04214 return 1; 04215 04216 04217 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) 04218 // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)' 04219 // it means that we must cut the whole mantissa 04220 // (there'll not be any of the valid bits) 04221 return 1; 04222 04223 // e will be from (-man*TTMATH_BITS_PER_UINT, 0> 04224 sint e = -( exponent.ToInt() ); 04225 mantissa.Rcr(e,0); 04226 04227 return 0; 04228 } 04229 04230 04231 /*! 04232 a special method similar to the 'ToString_CreateNewMantissaAndExponent' 04233 when the 'base' is equal 2 04234 04235 we use it because if base is equal 2 we don't have to make those 04236 complicated calculations and the output is directly from the source 04237 (there will not be any small distortions) 04238 */ 04239 template<class string_type> 04240 uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man, 04241 Int<exp+1> & new_exp ) const 04242 { 04243 for( sint i=man-1 ; i>=0 ; --i ) 04244 { 04245 uint value = mantissa.table[i]; 04246 04247 for( uint bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit ) 04248 { 04249 if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 ) 04250 new_man += '1'; 04251 else 04252 new_man += '0'; 04253 04254 value <<= 1; 04255 } 04256 } 04257 04258 new_exp = exponent; 04259 04260 return 0; 04261 } 04262 04263 04264 /*! 04265 a special method used to calculate the new mantissa and exponent 04266 when the 'base' is equal 4, 8 or 16 04267 04268 when base is 4 then bits is 2 04269 when base is 8 then bits is 3 04270 when base is 16 then bits is 4 04271 (and the algorithm can be used with a base greater than 16) 04272 */ 04273 template<class string_type> 04274 uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man, 04275 Int<exp+1> & new_exp, 04276 uint bits) const 04277 { 04278 sint move; // how many times move the mantissa 04279 UInt<man+1> man_temp(mantissa); // man+1 for moving 04280 new_exp = exponent; 04281 new_exp.DivInt((sint)bits, move); 04282 04283 if( move != 0 ) 04284 { 04285 // we're moving the man_temp to left-hand side 04286 if( move < 0 ) 04287 { 04288 move = sint(bits) + move; 04289 new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too 04290 } 04291 04292 man_temp.Rcl(move); 04293 } 04294 04295 04296 if( bits == 3 ) 04297 { 04298 // base 8 04299 // now 'move' is greater than or equal 0 04300 uint len = man*TTMATH_BITS_PER_UINT + move; 04301 return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits); 04302 } 04303 else 04304 { 04305 // base 4 or 16 04306 return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits); 04307 } 04308 } 04309 04310 04311 /*! 04312 a special method used to calculate the new mantissa 04313 when the 'base' is equal 8 04314 04315 bits is always 3 04316 04317 we can use this algorithm when the base is 4 or 16 too 04318 but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16() 04319 */ 04320 template<class string_type> 04321 uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man, 04322 UInt<man+1> & man_temp, 04323 uint len, 04324 uint bits) const 04325 { 04326 uint shift = TTMATH_BITS_PER_UINT - bits; 04327 uint mask = TTMATH_UINT_MAX_VALUE >> shift; 04328 uint i; 04329 04330 for( i=0 ; i<len ; i+=bits ) 04331 { 04332 uint digit = man_temp.table[0] & mask; 04333 new_man.insert(new_man.begin(), static_cast<char>(Misc::DigitToChar (digit))); 04334 04335 man_temp.Rcr(bits); 04336 } 04337 04338 TTMATH_ASSERT( man_temp.IsZero() ) 04339 04340 return 0; 04341 } 04342 04343 04344 /*! 04345 a special method used to calculate the new mantissa 04346 when the 'base' is equal 4 or 16 04347 04348 when the base is equal 4 or 16 the bits is 2 or 4 04349 and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4) 04350 then we can get digits from the end of our mantissa 04351 */ 04352 template<class string_type> 04353 uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man, 04354 UInt<man+1> & man_temp, 04355 uint bits) const 04356 { 04357 TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 ) 04358 TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 ) 04359 04360 uint shift = TTMATH_BITS_PER_UINT - bits; 04361 uint mask = TTMATH_UINT_MAX_VALUE << shift; 04362 uint digit; 04363 04364 // table[man] - last word - is different from zero if we moved man_temp 04365 digit = man_temp.table[man]; 04366 04367 if( digit != 0 ) 04368 new_man += static_cast<char>(Misc::DigitToChar(digit)); 04369 04370 04371 for( int i=man-1 ; i>=0 ; --i ) 04372 { 04373 uint shift_local = shift; 04374 uint mask_local = mask; 04375 04376 while( mask_local != 0 ) 04377 { 04378 digit = man_temp.table[i] & mask_local; 04379 04380 if( shift_local != 0 ) 04381 digit = digit >> shift_local; 04382 04383 new_man += static_cast<char>(Misc::DigitToChar (digit)); 04384 mask_local = mask_local >> bits; 04385 shift_local = shift_local - bits; 04386 } 04387 } 04388 04389 return 0; 04390 } 04391 04392 04393 /*! 04394 an auxiliary method for converting into the string 04395 */ 04396 template<class string_type, class char_type> 04397 bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const 04398 { 04399 // if new_exp is greater or equal to zero then we have an integer value, 04400 // if new_exp is equal -1 then we have only one digit after the comma 04401 // and after rounding it would be an integer value 04402 if( !new_exp.IsSign() || new_exp == -1 ) 04403 return true; 04404 04405 if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 ) 04406 return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding 04407 04408 uint i = 0; 04409 char_type digit; 04410 04411 if( new_exp >= -sint(new_man.size()) ) 04412 { 04413 uint new_exp_abs = -new_exp.ToInt(); 04414 i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator 04415 } 04416 04417 if( Misc::CharToDigit (new_man[new_man.size()-1]) >= conv.base/2 ) 04418 { 04419 if( new_exp < -sint(new_man.size()) ) 04420 { 04421 // there are some zeroes after the comma operator 04422 // (between the comma and the first digit from the mantissa) 04423 // and the result value will never be an integer 04424 return false; 04425 } 04426 04427 digit = static_cast<char_type>( Misc::DigitToChar (conv.base-1) ); 04428 } 04429 else 04430 { 04431 digit = '0'; 04432 } 04433 04434 for( ; i < new_man.size()-1 ; ++i) 04435 if( new_man[i] != digit ) 04436 return false; // it will not be an integer 04437 04438 return true; // it will be integer after rounding 04439 } 04440 04441 04442 /*! 04443 an auxiliary method for converting into the string 04444 (when this is integer) 04445 04446 after floating point calculating the new mantissa can consist of some fraction 04447 so if our value is integer we should check the new mantissa 04448 (after the decimal point there should be only zeroes) 04449 04450 often this is a last digit different from zero 04451 ToString_BaseRound would not get rid of it because the method make a test against 04452 an integer value (ToString_RoundMantissaWouldBeInteger) and returns immediately 04453 */ 04454 template<class string_type, class char_type> 04455 void ToString_CheckMantissaInteger(string_type & new_man, const Int<exp+1> & new_exp) const 04456 { 04457 if( !new_exp.IsSign() ) 04458 return; // return if new_exp >= 0 04459 04460 uint i = 0; 04461 uint man_size = new_man.size(); 04462 04463 if( man_size >= TTMATH_UINT_HIGHEST_BIT ) 04464 return; // ops, the mantissa is too long 04465 04466 sint sman_size = -sint(man_size); 04467 04468 if( new_exp >= sman_size ) 04469 { 04470 sint e = new_exp.ToInt(); 04471 e = -e; 04472 // now e means how many last digits from the mantissa should be equal zero 04473 04474 i = man_size - uint (e); 04475 } 04476 04477 for( ; i<man_size ; ++i) 04478 new_man[i] = '0'; 04479 } 04480 04481 04482 /*! 04483 an auxiliary method for converting into the string 04484 04485 this method is used for base!=2, base!=4, base!=8 and base!=16 04486 we do the rounding when the value has fraction (is not an integer) 04487 */ 04488 template<class string_type, class char_type> 04489 uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const 04490 { 04491 // we must have minimum two characters 04492 if( new_man.size() < 2 ) 04493 return 0; 04494 04495 // assert that there will not be an integer after rounding 04496 if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) ) 04497 return 0; 04498 04499 typename string_type::size_type i = new_man.length() - 1; 04500 04501 // we're erasing the last character 04502 uint digit = Misc::CharToDigit ( new_man[i] ); 04503 new_man.erase(i, 1); 04504 uint c = new_exp.AddOne(); 04505 04506 // if the last character is greater or equal 'base/2' 04507 // we are adding one into the new mantissa 04508 if( digit >= conv.base / 2 ) 04509 ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv); 04510 04511 return c; 04512 } 04513 04514 04515 /*! 04516 an auxiliary method for converting into the string 04517 04518 this method addes one into the new mantissa 04519 */ 04520 template<class string_type, class char_type> 04521 void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const 04522 { 04523 if( new_man.empty() ) 04524 return; 04525 04526 sint i = sint( new_man.length() ) - 1; 04527 bool was_carry = true; 04528 04529 for( ; i>=0 && was_carry ; --i ) 04530 { 04531 // we can have the comma as well because 04532 // we're using this method later in ToString_CorrectDigitsAfterComma_Round() 04533 // (we're only ignoring it) 04534 if( new_man[i] == static_cast<char_type>(conv.comma) ) 04535 continue; 04536 04537 // we're adding one 04538 uint digit = Misc::CharToDigit ( new_man[i] ) + 1; 04539 04540 if( digit == conv.base ) 04541 digit = 0; 04542 else 04543 was_carry = false; 04544 04545 new_man[i] = static_cast<char_type>( Misc::DigitToChar (digit) ); 04546 } 04547 04548 if( i<0 && was_carry ) 04549 new_man.insert( new_man.begin() , '1' ); 04550 } 04551 04552 04553 04554 /*! 04555 an auxiliary method for converting into the string 04556 04557 this method sets the comma operator and/or puts the exponent 04558 into the string 04559 */ 04560 template<class string_type, class char_type> 04561 uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const 04562 { 04563 uint carry = 0; 04564 04565 if( new_man.empty() ) 04566 return carry; 04567 04568 Int<exp+1> scientific_exp( new_exp ); 04569 04570 // 'new_exp' depends on the 'new_man' which is stored like this e.g: 04571 // 32342343234 (the comma is at the end) 04572 // we'd like to show it in this way: 04573 // 3.2342343234 (the 'scientific_exp' is connected with this example) 04574 04575 sint offset = sint( new_man.length() ) - 1; 04576 carry += scientific_exp.Add( offset ); 04577 // there shouldn't have been a carry because we're using 04578 // a greater type -- 'Int<exp+1>' instead of 'Int<exp>' 04579 04580 bool print_scientific = conv.scient; 04581 04582 if( !print_scientific ) 04583 { 04584 if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) ) 04585 print_scientific = true; 04586 } 04587 04588 if( !print_scientific ) 04589 ToString_SetCommaAndExponent_Normal<string_type, char_type>(new_man, conv, new_exp); 04590 else 04591 // we're passing the 'scientific_exp' instead of 'new_exp' here 04592 ToString_SetCommaAndExponent_Scientific<string_type, char_type>(new_man, conv, scientific_exp); 04593 04594 return (carry==0)? 0 : 1; 04595 } 04596 04597 04598 /*! 04599 an auxiliary method for converting into the string 04600 */ 04601 template<class string_type, class char_type> 04602 void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp ) const 04603 { 04604 if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 ) 04605 ToString_SetCommaAndExponent_Normal_AddingZero<string_type, char_type>(new_man, new_exp); 04606 else 04607 ToString_SetCommaAndExponent_Normal_SetCommaInside<string_type, char_type>(new_man, conv, new_exp); 04608 04609 04610 ToString_Group_man<string_type, char_type>(new_man, conv); 04611 } 04612 04613 04614 /*! 04615 an auxiliary method for converting into the string 04616 */ 04617 template<class string_type, class char_type> 04618 void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man, 04619 Int<exp+1> & new_exp) const 04620 { 04621 // we're adding zero characters at the end 04622 // 'i' will be smaller than 'when_scientific' (or equal) 04623 uint i = new_exp.ToInt(); 04624 04625 if( new_man.length() + i > new_man.capacity() ) 04626 // about 6 characters more (we'll need it for the comma or something) 04627 new_man.reserve( new_man.length() + i + 6 ); 04628 04629 for( ; i>0 ; --i) 04630 new_man += '0'; 04631 } 04632 04633 04634 /*! 04635 an auxiliary method for converting into the string 04636 */ 04637 template<class string_type, class char_type> 04638 void ToString_SetCommaAndExponent_Normal_SetCommaInside( 04639 string_type & new_man, 04640 const Conv & conv, 04641 Int<exp+1> & new_exp ) const 04642 { 04643 // new_exp is < 0 04644 04645 sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign 04646 sint e = -( new_exp.ToInt() ); // 'e' will be positive 04647 04648 if( new_exp > -new_man_len ) 04649 { 04650 // we're setting the comma within the mantissa 04651 04652 sint index = new_man_len - e; 04653 new_man.insert( new_man.begin() + index, static_cast<char_type>(conv.comma)); 04654 } 04655 else 04656 { 04657 // we're adding zero characters before the mantissa 04658 04659 uint how_many = e - new_man_len; 04660 string_type man_temp(how_many+1, '0'); 04661 04662 man_temp.insert( man_temp.begin()+1, static_cast<char_type>(conv.comma)); 04663 new_man.insert(0, man_temp); 04664 } 04665 04666 ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv); 04667 } 04668 04669 04670 /*! 04671 an auxiliary method for converting into the string 04672 */ 04673 template<class string_type, class char_type> 04674 void ToString_SetCommaAndExponent_Scientific( string_type & new_man, 04675 const Conv & conv, 04676 Int<exp+1> & scientific_exp ) const 04677 { 04678 if( new_man.empty() ) 04679 return; 04680 04681 if( new_man.size() > 1 ) 04682 { 04683 new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) ); 04684 ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv); 04685 } 04686 04687 ToString_Group_man<string_type, char_type>(new_man, conv); 04688 04689 if( conv.base == 10 ) 04690 { 04691 new_man += 'e'; 04692 04693 if( !scientific_exp.IsSign() ) 04694 new_man += '+'; 04695 } 04696 else 04697 { 04698 // the 10 here is meant as the base 'base' 04699 // (no matter which 'base' we're using there'll always be 10 here) 04700 Misc::AddString (new_man, "*10^"); 04701 } 04702 04703 string_type temp_exp; 04704 scientific_exp.ToString( temp_exp, conv.base ); 04705 04706 new_man += temp_exp; 04707 } 04708 04709 04710 /*! 04711 an auxiliary method for converting into the string 04712 */ 04713 template<class string_type, class char_type> 04714 void ToString_Group_man(string_type & new_man, const Conv & conv) const 04715 { 04716 typedef typename string_type::size_type StrSize; 04717 04718 if( conv.group == 0 ) 04719 return; 04720 04721 // first we're looking for the comma operator 04722 StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0); 04723 04724 if( index == string_type::npos ) 04725 index = new_man.size(); 04726 04727 ToString_Group_man_before_comma<string_type, char_type>(new_man, conv, index); 04728 ToString_Group_man_after_comma<string_type, char_type>(new_man, conv, index+1); 04729 } 04730 04731 04732 04733 /*! 04734 an auxiliary method for converting into the string 04735 */ 04736 template<class string_type, class char_type> 04737 void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv, 04738 typename string_type::size_type & index) const 04739 { 04740 typedef typename string_type::size_type StrSize; 04741 04742 uint group = 0; 04743 StrSize i = index; 04744 uint group_digits = conv.group_digits; 04745 04746 if( group_digits < 1 ) 04747 group_digits = 1; 04748 04749 // adding group characters before the comma operator 04750 // i>0 because on the first position we don't put any additional grouping characters 04751 for( ; i>0 ; --i, ++group) 04752 { 04753 if( group >= group_digits ) 04754 { 04755 group = 0; 04756 new_man.insert(i, 1, static_cast<char_type>(conv.group)); 04757 ++index; 04758 } 04759 } 04760 } 04761 04762 04763 /*! 04764 an auxiliary method for converting into the string 04765 */ 04766 template<class string_type, class char_type> 04767 void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv, 04768 typename string_type::size_type index) const 04769 { 04770 uint group = 0; 04771 uint group_digits = conv.group_digits; 04772 04773 if( group_digits < 1 ) 04774 group_digits = 1; 04775 04776 for( ; index<new_man.size() ; ++index, ++group) 04777 { 04778 if( group >= group_digits ) 04779 { 04780 group = 0; 04781 new_man.insert(index, 1, static_cast<char_type>(conv.group)); 04782 ++index; 04783 } 04784 } 04785 } 04786 04787 04788 /*! 04789 an auxiliary method for converting into the string 04790 */ 04791 template<class string_type, class char_type> 04792 void ToString_CorrectDigitsAfterComma( string_type & new_man, 04793 const Conv & conv ) const 04794 { 04795 if( conv.round >= 0 ) 04796 ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv); 04797 04798 if( conv.trim_zeroes ) 04799 ToString_CorrectDigitsAfterComma_CutOffZeroCharacters<string_type, char_type>(new_man, conv); 04800 } 04801 04802 04803 /*! 04804 an auxiliary method for converting into the string 04805 */ 04806 template<class string_type, class char_type> 04807 void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( 04808 string_type & new_man, 04809 const Conv & conv) const 04810 { 04811 // minimum two characters 04812 if( new_man.length() < 2 ) 04813 return; 04814 04815 // we're looking for the index of the last character which is not zero 04816 uint i = uint ( new_man.length() ) - 1; 04817 for( ; i>0 && new_man[i]=='0' ; --i ); 04818 04819 // if there is another character than zero at the end 04820 // we're finishing 04821 if( i == new_man.length() - 1 ) 04822 return; 04823 04824 // we must have a comma 04825 // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round 04826 // which is called before) 04827 if( new_man.find_last_of(static_cast<char_type>(conv.comma), i) == string_type::npos ) 04828 return; 04829 04830 // if directly before the first zero is the comma operator 04831 // we're cutting it as well 04832 if( i>0 && new_man[i]==static_cast<char_type>(conv.comma) ) 04833 --i; 04834 04835 new_man.erase(i+1, new_man.length()-i-1); 04836 } 04837 04838 04839 /*! 04840 an auxiliary method for converting into the string 04841 */ 04842 template<class string_type, class char_type> 04843 void ToString_CorrectDigitsAfterComma_Round( 04844 string_type & new_man, 04845 const Conv & conv ) const 04846 { 04847 typedef typename string_type::size_type StrSize; 04848 04849 // first we're looking for the comma operator 04850 StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0); 04851 04852 if( index == string_type::npos ) 04853 // nothing was found (actually there can't be this situation) 04854 return; 04855 04856 // we're calculating how many digits there are at the end (after the comma) 04857 // 'after_comma' will be greater than zero because at the end 04858 // we have at least one digit 04859 StrSize after_comma = new_man.length() - index - 1; 04860 04861 // if 'max_digit_after_comma' is greater than 'after_comma' (or equal) 04862 // we don't have anything for cutting 04863 if( static_cast<StrSize>(conv.round) >= after_comma ) 04864 return; 04865 04866 uint last_digit = Misc::CharToDigit ( new_man[ index + conv.round + 1 ], conv.base ); 04867 04868 // we're cutting the rest of the string 04869 new_man.erase(index + conv.round + 1, after_comma - conv.round); 04870 04871 if( conv.round == 0 ) 04872 { 04873 // we're cutting the comma operator as well 04874 // (it's not needed now because we've cut the whole rest after the comma) 04875 new_man.erase(index, 1); 04876 } 04877 04878 if( last_digit >= conv.base / 2 ) 04879 // we must round here 04880 ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv); 04881 } 04882 04883 04884 04885 public: 04886 04887 /*! 04888 a method for converting a string into its value 04889 04890 it returns 1 if the value is too big -- we cannot pass it into the range 04891 of our class Big<exp,man> (or if the base is incorrect) 04892 04893 that means only digits before the comma operator can make this value too big, 04894 all digits after the comma we can ignore 04895 04896 'source' - pointer to the string for parsing 04897 04898 if 'after_source' is set that when this method finishes 04899 it sets the pointer to the new first character after parsed value 04900 04901 'value_read' - if the pointer is provided that means the value_read will be true 04902 only when a value has been actually read, there can be situation where only such 04903 a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but 04904 no value has been read (there are no digits) 04905 on other words if 'value_read' is true -- there is at least one digit in the string 04906 */ 04907 uint FromString (const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0) 04908 { 04909 Conv conv; 04910 conv.base = base; 04911 04912 return FromStringBase(source, conv, after_source, value_read); 04913 } 04914 04915 04916 /*! 04917 a method for converting a string into its value 04918 */ 04919 uint FromString (const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0) 04920 { 04921 return FromStringBase(source, conv, after_source, value_read); 04922 } 04923 04924 04925 /*! 04926 a method for converting a string into its value 04927 */ 04928 uint FromString (const std::string & string, uint base = 10, const char ** after_source = 0, bool * value_read = 0) 04929 { 04930 return FromString (string.c_str(), base, after_source, value_read); 04931 } 04932 04933 04934 /*! 04935 a method for converting a string into its value 04936 */ 04937 uint FromString (const std::string & string, const Conv & conv, const char ** after_source = 0, bool * value_read = 0) 04938 { 04939 return FromString (string.c_str(), conv, after_source, value_read); 04940 } 04941 04942 04943 #ifndef TTMATH_DONT_USE_WCHAR 04944 04945 /*! 04946 a method for converting a string into its value 04947 */ 04948 uint FromString (const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) 04949 { 04950 Conv conv; 04951 conv.base = base; 04952 04953 return FromStringBase(source, conv, after_source, value_read); 04954 } 04955 04956 04957 /*! 04958 a method for converting a string into its value 04959 */ 04960 uint FromString (const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) 04961 { 04962 return FromStringBase(source, conv, after_source, value_read); 04963 } 04964 04965 04966 /*! 04967 a method for converting a string into its value 04968 */ 04969 uint FromString (const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) 04970 { 04971 return FromString (string.c_str(), base, after_source, value_read); 04972 } 04973 04974 04975 /*! 04976 a method for converting a string into its value 04977 */ 04978 uint FromString (const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) 04979 { 04980 return FromString (string.c_str(), conv, after_source, value_read); 04981 } 04982 04983 #endif 04984 04985 04986 private: 04987 04988 04989 /*! 04990 an auxiliary method for converting from a string 04991 */ 04992 template<class char_type> 04993 uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0) 04994 { 04995 bool is_sign; 04996 bool value_read_temp = false; 04997 04998 if( conv.base <2 || conv.base >16 ) 04999 { 05000 SetNan (); 05001 05002 if( after_source ) 05003 *after_source = source; 05004 05005 if( value_read ) 05006 *value_read = value_read_temp; 05007 05008 return 1; 05009 } 05010 05011 SetZero (); 05012 FromString_TestSign( source, is_sign ); 05013 05014 uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp ); 05015 05016 if( FromString_TestCommaOperator(source, conv) ) 05017 c += FromString_ReadPartAfterComma( source, conv, value_read_temp ); 05018 05019 if( value_read_temp && conv.base == 10 ) 05020 c += FromString_ReadScientificIfExists( source ); 05021 05022 if( is_sign && !IsZero () ) 05023 ChangeSign (); 05024 05025 if( after_source ) 05026 *after_source = source; 05027 05028 if( value_read ) 05029 *value_read = value_read_temp; 05030 05031 return CheckCarry (c); 05032 } 05033 05034 05035 /*! 05036 we're testing whether the value is with the sign 05037 05038 (this method is used from 'FromString_ReadPartScientific' too) 05039 */ 05040 template<class char_type> 05041 void FromString_TestSign( const char_type * & source, bool & is_sign ) 05042 { 05043 Misc::SkipWhiteCharacters(source); 05044 05045 is_sign = false; 05046 05047 if( *source == '-' ) 05048 { 05049 is_sign = true; 05050 ++source; 05051 } 05052 else 05053 if( *source == '+' ) 05054 { 05055 ++source; 05056 } 05057 } 05058 05059 05060 /*! 05061 we're testing whether there's a comma operator 05062 */ 05063 template<class char_type> 05064 bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv) 05065 { 05066 if( (*source == static_cast<char_type>(conv.comma)) || 05067 (*source == static_cast<char_type>(conv.comma2) && conv.comma2 != 0 ) ) 05068 { 05069 ++source; 05070 05071 return true; 05072 } 05073 05074 return false; 05075 } 05076 05077 05078 /*! 05079 this method reads the first part of a string 05080 (before the comma operator) 05081 */ 05082 template<class char_type> 05083 uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read ) 05084 { 05085 sint character; 05086 Big<exp, man> temp; 05087 Big<exp, man> base_( conv.base ); 05088 05089 Misc::SkipWhiteCharacters( source ); 05090 05091 for( ; true ; ++source ) 05092 { 05093 if( conv.group!=0 && *source==static_cast<char>(conv.group) ) 05094 continue; 05095 05096 character = Misc::CharToDigit (*source, conv.base); 05097 05098 if( character == -1 ) 05099 break; 05100 05101 value_read = true; 05102 temp = character; 05103 05104 if( Mul (base_) ) 05105 return 1; 05106 05107 if( Add (temp) ) 05108 return 1; 05109 } 05110 05111 return 0; 05112 } 05113 05114 05115 /*! 05116 this method reads the second part of a string 05117 (after the comma operator) 05118 */ 05119 template<class char_type> 05120 uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read ) 05121 { 05122 sint character; 05123 uint c = 0, power = 0; 05124 UInt<1> power_; 05125 Big<exp, man> sum, base_(conv.base); 05126 05127 // we don't remove any white characters here 05128 sum.SetZero(); 05129 05130 for( ; sum.exponent.IsSign() || sum.exponent.IsZero() ; ++source ) 05131 { 05132 if( conv.group!=0 && *source==static_cast<char>(conv.group) ) 05133 continue; 05134 05135 character = Misc::CharToDigit (*source, conv.base); 05136 05137 if( character == -1 ) 05138 break; 05139 05140 value_read = true; 05141 05142 // there actually shouldn't be a carry here 05143 c += sum.Mul(base_); 05144 c += sum.Add(character); 05145 power += 1; 05146 05147 if( power == 0 ) 05148 c += 1; 05149 } 05150 05151 // we could break the parsing somewhere in the middle of the string, 05152 // but the result (value) still can be good 05153 // we should set a correct value of 'source' now 05154 for( ; Misc::CharToDigit (*source, conv.base) != -1 ; ++source ); 05155 05156 power_ = power; 05157 c += base_.Pow(power_); 05158 c += sum.Div(base_); 05159 c += Add (sum); 05160 05161 return (c==0)? 0 : 1; 05162 } 05163 05164 05165 /*! 05166 this method checks whether there is a scientific part: [e|E][-|+]value 05167 05168 it is called when the base is 10 and some digits were read before 05169 */ 05170 template<class char_type> 05171 uint FromString_ReadScientificIfExists(const char_type * & source) 05172 { 05173 uint c = 0; 05174 05175 bool scientific_read = false; 05176 const char_type * before_scientific = source; 05177 05178 if( FromString_TestScientific(source) ) 05179 c += FromString_ReadPartScientific( source, scientific_read ); 05180 05181 if( !scientific_read ) 05182 source = before_scientific; 05183 05184 return (c==0)? 0 : 1; 05185 } 05186 05187 05188 05189 /*! 05190 we're testing whether is there the character 'e' 05191 05192 this character is only allowed when we're using the base equals 10 05193 */ 05194 template<class char_type> 05195 bool FromString_TestScientific(const char_type * & source) 05196 { 05197 Misc::SkipWhiteCharacters(source); 05198 05199 if( *source=='e' || *source=='E' ) 05200 { 05201 ++source; 05202 05203 return true; 05204 } 05205 05206 return false; 05207 } 05208 05209 05210 /*! 05211 this method reads the exponent (after 'e' character) when there's a scientific 05212 format of value and only when we're using the base equals 10 05213 */ 05214 template<class char_type> 05215 uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read ) 05216 { 05217 uint c = 0; 05218 Big<exp, man> new_exponent, temp; 05219 bool was_sign = false; 05220 05221 FromString_TestSign( source, was_sign ); 05222 c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read ); 05223 05224 if( scientific_read ) 05225 { 05226 if( was_sign ) 05227 new_exponent.ChangeSign(); 05228 05229 temp = 10; 05230 c += temp.Pow( new_exponent ); 05231 c += Mul (temp); 05232 } 05233 05234 return (c==0)? 0 : 1; 05235 } 05236 05237 05238 /*! 05239 this method reads the value of the extra exponent when scientific format is used 05240 (only when base == 10) 05241 */ 05242 template<class char_type> 05243 uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big<exp, man> & new_exponent, bool & scientific_read ) 05244 { 05245 sint character; 05246 Big<exp, man> base, temp; 05247 05248 Misc::SkipWhiteCharacters(source); 05249 05250 new_exponent.SetZero(); 05251 base = 10; 05252 05253 for( ; (character=Misc::CharToDigit (*source, 10)) != -1 ; ++source ) 05254 { 05255 scientific_read = true; 05256 05257 temp = character; 05258 05259 if( new_exponent.Mul(base) ) 05260 return 1; 05261 05262 if( new_exponent.Add(temp) ) 05263 return 1; 05264 } 05265 05266 return 0; 05267 } 05268 05269 05270 public: 05271 05272 05273 /*! 05274 a constructor for converting a string into this class 05275 */ 05276 Big (const char * string) 05277 { 05278 FromString ( string ); 05279 } 05280 05281 05282 /*! 05283 a constructor for converting a string into this class 05284 */ 05285 Big (const std::string & string) 05286 { 05287 FromString ( string.c_str() ); 05288 } 05289 05290 05291 /*! 05292 an operator= for converting a string into its value 05293 */ 05294 Big<exp, man> & operator= (const char * string) 05295 { 05296 FromString ( string ); 05297 05298 return *this; 05299 } 05300 05301 05302 /*! 05303 an operator= for converting a string into its value 05304 */ 05305 Big<exp, man> & operator= (const std::string & string) 05306 { 05307 FromString ( string.c_str() ); 05308 05309 return *this; 05310 } 05311 05312 05313 05314 #ifndef TTMATH_DONT_USE_WCHAR 05315 05316 /*! 05317 a constructor for converting a string into this class 05318 */ 05319 Big (const wchar_t * string) 05320 { 05321 FromString ( string ); 05322 } 05323 05324 05325 /*! 05326 a constructor for converting a string into this class 05327 */ 05328 Big (const std::wstring & string) 05329 { 05330 FromString ( string.c_str() ); 05331 } 05332 05333 05334 /*! 05335 an operator= for converting a string into its value 05336 */ 05337 Big<exp, man> & operator= (const wchar_t * string) 05338 { 05339 FromString ( string ); 05340 05341 return *this; 05342 } 05343 05344 05345 /*! 05346 an operator= for converting a string into its value 05347 */ 05348 Big<exp, man> & operator= (const std::wstring & string) 05349 { 05350 FromString ( string.c_str() ); 05351 05352 return *this; 05353 } 05354 05355 05356 #endif 05357 05358 05359 05360 /*! 05361 * 05362 * methods for comparing 05363 * 05364 */ 05365 05366 05367 /*! 05368 this method performs the formula 'abs(this) < abs(ss2)' 05369 and returns the result 05370 05371 (in other words it treats 'this' and 'ss2' as values without a sign) 05372 we don't check the NaN flag 05373 */ 05374 bool SmallerWithoutSignThan (const Big<exp,man> & ss2) const 05375 { 05376 if( IsZero () ) 05377 { 05378 if( ss2.IsZero () ) 05379 // we've got two zeroes 05380 return false; 05381 else 05382 // this==0 and ss2!=0 05383 return true; 05384 } 05385 05386 if( ss2.IsZero () ) 05387 // this!=0 and ss2==0 05388 return false; 05389 05390 // we're using the fact that all bits in mantissa are pushed 05391 // into the left side -- Standardizing() 05392 if( exponent == ss2.exponent ) 05393 return mantissa < ss2.mantissa; 05394 05395 return exponent < ss2.exponent; 05396 } 05397 05398 05399 /*! 05400 this method performs the formula 'abs(this) > abs(ss2)' 05401 and returns the result 05402 05403 (in other words it treats 'this' and 'ss2' as values without a sign) 05404 we don't check the NaN flag 05405 */ 05406 bool GreaterWithoutSignThan (const Big<exp,man> & ss2) const 05407 { 05408 if( IsZero () ) 05409 { 05410 if( ss2.IsZero () ) 05411 // we've got two zeroes 05412 return false; 05413 else 05414 // this==0 and ss2!=0 05415 return false; 05416 } 05417 05418 if( ss2.IsZero () ) 05419 // this!=0 and ss2==0 05420 return true; 05421 05422 // we're using the fact that all bits in mantissa are pushed 05423 // into the left side -- Standardizing() 05424 if( exponent == ss2.exponent ) 05425 return mantissa > ss2.mantissa; 05426 05427 return exponent > ss2.exponent; 05428 } 05429 05430 05431 /*! 05432 this method performs the formula 'abs(this) == abs(ss2)' 05433 and returns the result 05434 05435 (in other words it treats 'this' and 'ss2' as values without a sign) 05436 we don't check the NaN flag 05437 */ 05438 bool EqualWithoutSign (const Big<exp,man> & ss2) const 05439 { 05440 if( IsZero () ) 05441 { 05442 if( ss2.IsZero () ) 05443 // we've got two zeroes 05444 return true; 05445 else 05446 // this==0 and ss2!=0 05447 return false; 05448 } 05449 05450 if( ss2.IsZero () ) 05451 // this!=0 and ss2==0 05452 return false; 05453 05454 if( exponent==ss2.exponent && mantissa==ss2.mantissa ) 05455 return true; 05456 05457 return false; 05458 } 05459 05460 05461 bool operator<(const Big<exp,man> & ss2) const 05462 { 05463 if( IsSign () && !ss2.IsSign () ) 05464 // this<0 and ss2>=0 05465 return true; 05466 05467 if( !IsSign () && ss2.IsSign () ) 05468 // this>=0 and ss2<0 05469 return false; 05470 05471 // both signs are the same 05472 05473 if( IsSign () ) 05474 return ss2.SmallerWithoutSignThan ( *this ); 05475 05476 return SmallerWithoutSignThan ( ss2 ); 05477 } 05478 05479 05480 bool operator==(const Big<exp,man> & ss2) const 05481 { 05482 if( IsSign () != ss2.IsSign() ) 05483 return false; 05484 05485 return EqualWithoutSign ( ss2 ); 05486 } 05487 05488 05489 bool operator>(const Big<exp,man> & ss2) const 05490 { 05491 if( IsSign () && !ss2.IsSign() ) 05492 // this<0 and ss2>=0 05493 return false; 05494 05495 if( !IsSign () && ss2.IsSign() ) 05496 // this>=0 and ss2<0 05497 return true; 05498 05499 // both signs are the same 05500 05501 if( IsSign () ) 05502 return ss2.GreaterWithoutSignThan( *this ); 05503 05504 return GreaterWithoutSignThan ( ss2 ); 05505 } 05506 05507 05508 bool operator>=(const Big<exp,man> & ss2) const 05509 { 05510 return !operator<( ss2 ); 05511 } 05512 05513 05514 bool operator<=(const Big<exp,man> & ss2) const 05515 { 05516 return !operator>( ss2 ); 05517 } 05518 05519 05520 bool operator!=(const Big<exp,man> & ss2) const 05521 { 05522 return !operator==(ss2); 05523 } 05524 05525 05526 05527 05528 05529 /*! 05530 * 05531 * standard mathematical operators 05532 * 05533 */ 05534 05535 05536 /*! 05537 an operator for changing the sign 05538 05539 this method is not changing 'this' but the changed value is returned 05540 */ 05541 Big<exp,man> operator- () const 05542 { 05543 Big<exp,man> temp(*this); 05544 05545 temp.ChangeSign (); 05546 05547 return temp; 05548 } 05549 05550 05551 Big<exp,man> operator- (const Big<exp,man> & ss2) const 05552 { 05553 Big<exp,man> temp(*this); 05554 05555 temp.Sub(ss2); 05556 05557 return temp; 05558 } 05559 05560 Big<exp,man> & operator-=(const Big<exp,man> & ss2) 05561 { 05562 Sub (ss2); 05563 05564 return *this; 05565 } 05566 05567 05568 Big<exp,man> operator+(const Big<exp,man> & ss2) const 05569 { 05570 Big<exp,man> temp(*this); 05571 05572 temp.Add(ss2); 05573 05574 return temp; 05575 } 05576 05577 05578 Big<exp,man> & operator+=(const Big<exp,man> & ss2) 05579 { 05580 Add (ss2); 05581 05582 return *this; 05583 } 05584 05585 05586 Big<exp,man> operator*(const Big<exp,man> & ss2) const 05587 { 05588 Big<exp,man> temp(*this); 05589 05590 temp.Mul(ss2); 05591 05592 return temp; 05593 } 05594 05595 05596 Big<exp,man> & operator*=(const Big<exp,man> & ss2) 05597 { 05598 Mul (ss2); 05599 05600 return *this; 05601 } 05602 05603 05604 Big<exp,man> operator/(const Big<exp,man> & ss2) const 05605 { 05606 Big<exp,man> temp(*this); 05607 05608 temp.Div(ss2); 05609 05610 return temp; 05611 } 05612 05613 05614 Big<exp,man> & operator/=(const Big<exp,man> & ss2) 05615 { 05616 Div (ss2); 05617 05618 return *this; 05619 } 05620 05621 05622 /*! 05623 Prefix operator e.g ++variable 05624 */ 05625 Big<exp,man> & operator++ () 05626 { 05627 AddOne(); 05628 05629 return *this; 05630 } 05631 05632 05633 /*! 05634 Postfix operator e.g variable++ 05635 */ 05636 Big<exp,man> operator++ (int) 05637 { 05638 Big<exp,man> temp( *this ); 05639 05640 AddOne(); 05641 05642 return temp; 05643 } 05644 05645 05646 Big<exp,man> & operator--() 05647 { 05648 SubOne(); 05649 05650 return *this; 05651 } 05652 05653 05654 Big<exp,man> operator--(int) 05655 { 05656 Big<exp,man> temp( *this ); 05657 05658 SubOne(); 05659 05660 return temp; 05661 } 05662 05663 05664 05665 /*! 05666 * 05667 * bitwise operators 05668 * (we do not define bitwise not) 05669 */ 05670 05671 05672 Big<exp,man> operator& (const Big<exp,man> & p2) const 05673 { 05674 Big<exp,man> temp( *this ); 05675 05676 temp.BitAnd (p2); 05677 05678 return temp; 05679 } 05680 05681 05682 Big<exp,man> & operator&=(const Big<exp,man> & p2) 05683 { 05684 BitAnd (p2); 05685 05686 return *this; 05687 } 05688 05689 05690 Big<exp,man> operator|(const Big<exp,man> & p2) const 05691 { 05692 Big<exp,man> temp( *this ); 05693 05694 temp.BitOr(p2); 05695 05696 return temp; 05697 } 05698 05699 05700 Big<exp,man> & operator|=(const Big<exp,man> & p2) 05701 { 05702 BitOr (p2); 05703 05704 return *this; 05705 } 05706 05707 05708 Big<exp,man> operator^(const Big<exp,man> & p2) const 05709 { 05710 Big<exp,man> temp( *this ); 05711 05712 temp.BitXor(p2); 05713 05714 return temp; 05715 } 05716 05717 05718 Big<exp,man> & operator^=(const Big<exp,man> & p2) 05719 { 05720 BitXor (p2); 05721 05722 return *this; 05723 } 05724 05725 05726 05727 05728 05729 05730 /*! 05731 this method makes an integer value by skipping any fractions 05732 05733 for example: 05734 10.7 will be 10 05735 12.1 -- 12 05736 -20.2 -- 20 05737 -20.9 -- 20 05738 -0.7 -- 0 05739 0.8 -- 0 05740 */ 05741 void SkipFraction () 05742 { 05743 if( IsNan () || IsZero () ) 05744 return; 05745 05746 if( !exponent.IsSign () ) 05747 // exponent >=0 -- the value don't have any fractions 05748 return; 05749 05750 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) 05751 { 05752 // the value is from (-1,1), we return zero 05753 SetZero (); 05754 return; 05755 } 05756 05757 // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) 05758 sint e = exponent.ToInt (); 05759 05760 mantissa.ClearFirstBits ( -e ); 05761 05762 // we don't have to standardize 'Standardizing()' the value because 05763 // there's at least one bit in the mantissa 05764 // (the highest bit which we didn't touch) 05765 } 05766 05767 05768 /*! 05769 this method remains only a fraction from the value 05770 05771 for example: 05772 30.56 will be 0.56 05773 -12.67 -- -0.67 05774 */ 05775 void RemainFraction () 05776 { 05777 if( IsNan () || IsZero () ) 05778 return; 05779 05780 if( !exponent.IsSign () ) 05781 { 05782 // exponent >= 0 -- the value doesn't have any fractions 05783 // we return zero 05784 SetZero (); 05785 return; 05786 } 05787 05788 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) 05789 { 05790 // the value is from (-1,1) 05791 // we don't make anything with the value 05792 return; 05793 } 05794 05795 // e will be from (-man*TTMATH_BITS_PER_UINT, 0) 05796 sint e = exponent.ToInt (); 05797 05798 sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative 05799 mantissa.Rcl ( how_many_bits_leave, 0); 05800 05801 // there'll not be a carry because the exponent is too small 05802 exponent.Sub ( how_many_bits_leave ); 05803 05804 // we must call Standardizing() here 05805 Standardizing (); 05806 } 05807 05808 05809 05810 /*! 05811 this method returns true if the value is integer 05812 (there is no a fraction) 05813 05814 (we don't check nan) 05815 */ 05816 bool IsInteger () const 05817 { 05818 if( IsZero () ) 05819 return true; 05820 05821 if( !exponent.IsSign () ) 05822 // exponent >=0 -- the value don't have any fractions 05823 return true; 05824 05825 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) 05826 // the value is from (-1,1) 05827 return false; 05828 05829 // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) 05830 sint e = exponent.ToInt (); 05831 e = -e; // e means how many bits we must check 05832 05833 uint len = e / TTMATH_BITS_PER_UINT; 05834 uint rest = e % TTMATH_BITS_PER_UINT; 05835 uint i = 0; 05836 05837 for( ; i<len ; ++i ) 05838 if( mantissa.table [i] != 0 ) 05839 return false; 05840 05841 if( rest > 0 ) 05842 { 05843 uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest); 05844 if( (mantissa.table [i] & rest_mask) != 0 ) 05845 return false; 05846 } 05847 05848 return true; 05849 } 05850 05851 05852 /*! 05853 this method rounds to the nearest integer value 05854 (it returns a carry if it was) 05855 05856 for example: 05857 2.3 = 2 05858 2.8 = 3 05859 05860 -2.3 = -2 05861 -2.8 = 3 05862 */ 05863 uint Round () 05864 { 05865 Big<exp,man> half; 05866 uint c; 05867 05868 if( IsNan () ) 05869 return 1; 05870 05871 if( IsZero () ) 05872 return 0; 05873 05874 half.Set05 (); 05875 05876 if( IsSign () ) 05877 { 05878 // 'this' is < 0 05879 c = Sub ( half ); 05880 } 05881 else 05882 { 05883 // 'this' is > 0 05884 c = Add ( half ); 05885 } 05886 05887 SkipFraction (); 05888 05889 return CheckCarry (c); 05890 } 05891 05892 05893 05894 /*! 05895 * 05896 * input/output operators for standard streams 05897 * 05898 */ 05899 05900 private: 05901 05902 /*! 05903 an auxiliary method for outputing to standard streams 05904 */ 05905 template<class ostream_type, class string_type> 05906 static ostream_type & OutputToStream(ostream_type & s, const Big<exp,man> & l) 05907 { 05908 string_type ss; 05909 05910 l.ToString (ss); 05911 s << ss; 05912 05913 return s; 05914 } 05915 05916 05917 public: 05918 05919 05920 /*! 05921 output to standard streams 05922 */ 05923 friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l) 05924 { 05925 return OutputToStream<std::ostream, std::string>(s, l); 05926 } 05927 05928 05929 #ifndef TTMATH_DONT_USE_WCHAR 05930 05931 /*! 05932 output to standard streams 05933 */ 05934 friend std::wostream & operator<<(std::wostream & s, const Big<exp,man> & l) 05935 { 05936 return OutputToStream<std::wostream, std::wstring>(s, l); 05937 } 05938 05939 #endif 05940 05941 05942 05943 private: 05944 05945 /*! 05946 an auxiliary method for converting from a string 05947 */ 05948 template<class istream_type, class string_type, class char_type> 05949 static istream_type & InputFromStream(istream_type & s, Big<exp,man> & l) 05950 { 05951 string_type ss; 05952 05953 // char or wchar_t for operator>> 05954 char_type z, old_z; 05955 bool was_comma = false; 05956 bool was_e = false; 05957 05958 05959 // operator>> omits white characters if they're set for ommiting 05960 s >> z; 05961 05962 if( z=='-' || z=='+' ) 05963 { 05964 ss += z; 05965 s >> z; // we're reading a next character (white characters can be ommited) 05966 } 05967 05968 old_z = 0; 05969 05970 // we're reading only digits (base=10) and only one comma operator 05971 for( ; s.good() ; z=static_cast<char_type>(s.get()) ) 05972 { 05973 if( z=='.' || z==',' ) 05974 { 05975 if( was_comma || was_e ) 05976 // second comma operator or comma operator after 'e' character 05977 break; 05978 05979 was_comma = true; 05980 } 05981 else 05982 if( z == 'e' || z == 'E' ) 05983 { 05984 if( was_e ) 05985 // second 'e' character 05986 break; 05987 05988 was_e = true; 05989 } 05990 else 05991 if( z == '+' || z == '-' ) 05992 { 05993 if( old_z != 'e' && old_z != 'E' ) 05994 // '+' or '-' is allowed only after 'e' character 05995 break; 05996 } 05997 else 05998 if( Misc::CharToDigit (z, 10) < 0 ) 05999 break; 06000 06001 06002 ss += z; 06003 old_z = z; 06004 } 06005 06006 // we're leaving the last read character 06007 // (it's not belonging to the value) 06008 s.unget(); 06009 06010 l.FromString ( ss ); 06011 06012 return s; 06013 } 06014 06015 06016 06017 public: 06018 06019 /*! 06020 input from standard streams 06021 */ 06022 friend std::istream & operator>> (std::istream & s, Big<exp,man> & l) 06023 { 06024 return InputFromStream<std::istream, std::string, char>(s, l); 06025 } 06026 06027 06028 #ifndef TTMATH_DONT_USE_WCHAR 06029 06030 /*! 06031 input from standard streams 06032 */ 06033 friend std::wistream & operator>> (std::wistream & s, Big<exp,man> & l) 06034 { 06035 return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l); 06036 } 06037 06038 #endif 06039 06040 }; 06041 06042 06043 } // namespace 06044 06045 #endif 06046
Generated on Tue Jul 12 2022 14:03:18 by 1.7.2