Library for big numbers from http://www.ttmath.org/

Dependents:   PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more

TTMath is a small library which allows one to perform arithmetic operations with big unsigned integer, big signed integer and big floating point numbers. It provides standard mathematical operations like adding, subtracting, multiplying, dividing.

TTMath is BSD Licensed (new/modified BSD)

For more information about ttmath see http://www.ttmath.org/

Committer:
stevep
Date:
Tue Jul 30 18:43:48 2013 +0000
Revision:
0:04a9f72bbca7
v0.9.3 of ttmath

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stevep 0:04a9f72bbca7 1 /*
stevep 0:04a9f72bbca7 2 * This file is a part of TTMath Bignum Library
stevep 0:04a9f72bbca7 3 * and is distributed under the (new) BSD licence.
stevep 0:04a9f72bbca7 4 * Author: Tomasz Sowa <t.sowa@ttmath.org>
stevep 0:04a9f72bbca7 5 */
stevep 0:04a9f72bbca7 6
stevep 0:04a9f72bbca7 7 /*
stevep 0:04a9f72bbca7 8 * Copyright (c) 2006-2012, Tomasz Sowa
stevep 0:04a9f72bbca7 9 * All rights reserved.
stevep 0:04a9f72bbca7 10 *
stevep 0:04a9f72bbca7 11 * Redistribution and use in source and binary forms, with or without
stevep 0:04a9f72bbca7 12 * modification, are permitted provided that the following conditions are met:
stevep 0:04a9f72bbca7 13 *
stevep 0:04a9f72bbca7 14 * * Redistributions of source code must retain the above copyright notice,
stevep 0:04a9f72bbca7 15 * this list of conditions and the following disclaimer.
stevep 0:04a9f72bbca7 16 *
stevep 0:04a9f72bbca7 17 * * Redistributions in binary form must reproduce the above copyright
stevep 0:04a9f72bbca7 18 * notice, this list of conditions and the following disclaimer in the
stevep 0:04a9f72bbca7 19 * documentation and/or other materials provided with the distribution.
stevep 0:04a9f72bbca7 20 *
stevep 0:04a9f72bbca7 21 * * Neither the name Tomasz Sowa nor the names of contributors to this
stevep 0:04a9f72bbca7 22 * project may be used to endorse or promote products derived
stevep 0:04a9f72bbca7 23 * from this software without specific prior written permission.
stevep 0:04a9f72bbca7 24 *
stevep 0:04a9f72bbca7 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
stevep 0:04a9f72bbca7 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
stevep 0:04a9f72bbca7 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
stevep 0:04a9f72bbca7 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
stevep 0:04a9f72bbca7 29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
stevep 0:04a9f72bbca7 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
stevep 0:04a9f72bbca7 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
stevep 0:04a9f72bbca7 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
stevep 0:04a9f72bbca7 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
stevep 0:04a9f72bbca7 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
stevep 0:04a9f72bbca7 35 * THE POSSIBILITY OF SUCH DAMAGE.
stevep 0:04a9f72bbca7 36 */
stevep 0:04a9f72bbca7 37
stevep 0:04a9f72bbca7 38 #ifndef headerfilettmathbig
stevep 0:04a9f72bbca7 39 #define headerfilettmathbig
stevep 0:04a9f72bbca7 40
stevep 0:04a9f72bbca7 41 /*!
stevep 0:04a9f72bbca7 42 \file ttmathbig.h
stevep 0:04a9f72bbca7 43 \brief A Class for representing floating point numbers
stevep 0:04a9f72bbca7 44 */
stevep 0:04a9f72bbca7 45
stevep 0:04a9f72bbca7 46 #include "ttmathint.h"
stevep 0:04a9f72bbca7 47 #include "ttmaththreads.h"
stevep 0:04a9f72bbca7 48
stevep 0:04a9f72bbca7 49 #include <iostream>
stevep 0:04a9f72bbca7 50
stevep 0:04a9f72bbca7 51 #ifdef TTMATH_MULTITHREADS
stevep 0:04a9f72bbca7 52 #include <signal.h>
stevep 0:04a9f72bbca7 53 #endif
stevep 0:04a9f72bbca7 54
stevep 0:04a9f72bbca7 55 namespace ttmath
stevep 0:04a9f72bbca7 56 {
stevep 0:04a9f72bbca7 57
stevep 0:04a9f72bbca7 58
stevep 0:04a9f72bbca7 59 /*!
stevep 0:04a9f72bbca7 60 \brief Big implements the floating point numbers
stevep 0:04a9f72bbca7 61 */
stevep 0:04a9f72bbca7 62 template <uint exp, uint man>
stevep 0:04a9f72bbca7 63 class Big
stevep 0:04a9f72bbca7 64 {
stevep 0:04a9f72bbca7 65
stevep 0:04a9f72bbca7 66 /*
stevep 0:04a9f72bbca7 67 value = mantissa * 2^exponent
stevep 0:04a9f72bbca7 68
stevep 0:04a9f72bbca7 69 exponent - an integer value with a sign
stevep 0:04a9f72bbca7 70 mantissa - an integer value without a sing
stevep 0:04a9f72bbca7 71
stevep 0:04a9f72bbca7 72 mantissa must be pushed into the left side that is the highest bit from
stevep 0:04a9f72bbca7 73 mantissa must be one (of course if there's another value than zero) -- this job
stevep 0:04a9f72bbca7 74 (pushing bits into the left side) making Standardizing() method
stevep 0:04a9f72bbca7 75
stevep 0:04a9f72bbca7 76 for example:
stevep 0:04a9f72bbca7 77 if we want to store value one (1) into our Big object we must:
stevep 0:04a9f72bbca7 78 set mantissa to 1
stevep 0:04a9f72bbca7 79 set exponent to 0
stevep 0:04a9f72bbca7 80 set info to 0
stevep 0:04a9f72bbca7 81 and call method Standardizing()
stevep 0:04a9f72bbca7 82 */
stevep 0:04a9f72bbca7 83
stevep 0:04a9f72bbca7 84
stevep 0:04a9f72bbca7 85 public:
stevep 0:04a9f72bbca7 86
stevep 0:04a9f72bbca7 87 Int<exp> exponent;
stevep 0:04a9f72bbca7 88 UInt<man> mantissa;
stevep 0:04a9f72bbca7 89 unsigned char info;
stevep 0:04a9f72bbca7 90
stevep 0:04a9f72bbca7 91
stevep 0:04a9f72bbca7 92 /*!
stevep 0:04a9f72bbca7 93 Sign
stevep 0:04a9f72bbca7 94 the mask of a bit from 'info' which means that there is a sign
stevep 0:04a9f72bbca7 95 (when the bit is set)
stevep 0:04a9f72bbca7 96 */
stevep 0:04a9f72bbca7 97 #define TTMATH_BIG_SIGN 128
stevep 0:04a9f72bbca7 98
stevep 0:04a9f72bbca7 99
stevep 0:04a9f72bbca7 100 /*!
stevep 0:04a9f72bbca7 101 Not a number
stevep 0:04a9f72bbca7 102 if this bit is set that there is not a valid number
stevep 0:04a9f72bbca7 103 */
stevep 0:04a9f72bbca7 104 #define TTMATH_BIG_NAN 64
stevep 0:04a9f72bbca7 105
stevep 0:04a9f72bbca7 106
stevep 0:04a9f72bbca7 107 /*!
stevep 0:04a9f72bbca7 108 Zero
stevep 0:04a9f72bbca7 109 if this bit is set that there is value zero
stevep 0:04a9f72bbca7 110 mantissa should be zero and exponent should be zero too
stevep 0:04a9f72bbca7 111 (the Standardizing() method does this)
stevep 0:04a9f72bbca7 112 */
stevep 0:04a9f72bbca7 113 #define TTMATH_BIG_ZERO 32
stevep 0:04a9f72bbca7 114
stevep 0:04a9f72bbca7 115
stevep 0:04a9f72bbca7 116 /*!
stevep 0:04a9f72bbca7 117 this method sets NaN if there was a carry (and returns 1 in such a case)
stevep 0:04a9f72bbca7 118
stevep 0:04a9f72bbca7 119 c can be 0, 1 or other value different from zero
stevep 0:04a9f72bbca7 120 */
stevep 0:04a9f72bbca7 121 uint CheckCarry(uint c)
stevep 0:04a9f72bbca7 122 {
stevep 0:04a9f72bbca7 123 if( c != 0 )
stevep 0:04a9f72bbca7 124 {
stevep 0:04a9f72bbca7 125 SetNan();
stevep 0:04a9f72bbca7 126 return 1;
stevep 0:04a9f72bbca7 127 }
stevep 0:04a9f72bbca7 128
stevep 0:04a9f72bbca7 129 return 0;
stevep 0:04a9f72bbca7 130 }
stevep 0:04a9f72bbca7 131
stevep 0:04a9f72bbca7 132 public:
stevep 0:04a9f72bbca7 133
stevep 0:04a9f72bbca7 134
stevep 0:04a9f72bbca7 135 /*!
stevep 0:04a9f72bbca7 136 returning the string represents the currect type of the library
stevep 0:04a9f72bbca7 137 we have following types:
stevep 0:04a9f72bbca7 138 asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
stevep 0:04a9f72bbca7 139 asm_gcc_32 - with asm code designed for GCC (32 bits)
stevep 0:04a9f72bbca7 140 asm_vc_64 - with asm for VC (64 bit)
stevep 0:04a9f72bbca7 141 asm_gcc_64 - with asm for GCC (64 bit)
stevep 0:04a9f72bbca7 142 no_asm_32 - pure C++ version (32 bit) - without any asm code
stevep 0:04a9f72bbca7 143 no_asm_64 - pure C++ version (64 bit) - without any asm code
stevep 0:04a9f72bbca7 144 */
stevep 0:04a9f72bbca7 145 static const char * LibTypeStr()
stevep 0:04a9f72bbca7 146 {
stevep 0:04a9f72bbca7 147 return UInt<man>::LibTypeStr();
stevep 0:04a9f72bbca7 148 }
stevep 0:04a9f72bbca7 149
stevep 0:04a9f72bbca7 150
stevep 0:04a9f72bbca7 151 /*!
stevep 0:04a9f72bbca7 152 returning the currect type of the library
stevep 0:04a9f72bbca7 153 */
stevep 0:04a9f72bbca7 154 static LibTypeCode LibType()
stevep 0:04a9f72bbca7 155 {
stevep 0:04a9f72bbca7 156 return UInt<man>::LibType();
stevep 0:04a9f72bbca7 157 }
stevep 0:04a9f72bbca7 158
stevep 0:04a9f72bbca7 159
stevep 0:04a9f72bbca7 160
stevep 0:04a9f72bbca7 161 /*!
stevep 0:04a9f72bbca7 162 this method moves all bits from mantissa into its left side
stevep 0:04a9f72bbca7 163 (suitably changes the exponent) or if the mantissa is zero
stevep 0:04a9f72bbca7 164 it sets the exponent to zero as well
stevep 0:04a9f72bbca7 165 (and clears the sign bit and sets the zero bit)
stevep 0:04a9f72bbca7 166
stevep 0:04a9f72bbca7 167 it can return a carry
stevep 0:04a9f72bbca7 168 the carry will be when we don't have enough space in the exponent
stevep 0:04a9f72bbca7 169
stevep 0:04a9f72bbca7 170 you don't have to use this method if you don't change the mantissa
stevep 0:04a9f72bbca7 171 and exponent directly
stevep 0:04a9f72bbca7 172 */
stevep 0:04a9f72bbca7 173 uint Standardizing()
stevep 0:04a9f72bbca7 174 {
stevep 0:04a9f72bbca7 175 if( mantissa.IsTheHighestBitSet() )
stevep 0:04a9f72bbca7 176 {
stevep 0:04a9f72bbca7 177 ClearInfoBit(TTMATH_BIG_ZERO);
stevep 0:04a9f72bbca7 178 return 0;
stevep 0:04a9f72bbca7 179 }
stevep 0:04a9f72bbca7 180
stevep 0:04a9f72bbca7 181 if( CorrectZero() )
stevep 0:04a9f72bbca7 182 return 0;
stevep 0:04a9f72bbca7 183
stevep 0:04a9f72bbca7 184 uint comp = mantissa.CompensationToLeft();
stevep 0:04a9f72bbca7 185
stevep 0:04a9f72bbca7 186 return exponent.Sub( comp );
stevep 0:04a9f72bbca7 187 }
stevep 0:04a9f72bbca7 188
stevep 0:04a9f72bbca7 189
stevep 0:04a9f72bbca7 190 private:
stevep 0:04a9f72bbca7 191
stevep 0:04a9f72bbca7 192 /*!
stevep 0:04a9f72bbca7 193 if the mantissa is equal zero this method sets exponent to zero and
stevep 0:04a9f72bbca7 194 info without the sign
stevep 0:04a9f72bbca7 195
stevep 0:04a9f72bbca7 196 it returns true if there was the correction
stevep 0:04a9f72bbca7 197 */
stevep 0:04a9f72bbca7 198 bool CorrectZero()
stevep 0:04a9f72bbca7 199 {
stevep 0:04a9f72bbca7 200 if( mantissa.IsZero() )
stevep 0:04a9f72bbca7 201 {
stevep 0:04a9f72bbca7 202 SetInfoBit(TTMATH_BIG_ZERO);
stevep 0:04a9f72bbca7 203 ClearInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 204 exponent.SetZero();
stevep 0:04a9f72bbca7 205
stevep 0:04a9f72bbca7 206 return true;
stevep 0:04a9f72bbca7 207 }
stevep 0:04a9f72bbca7 208 else
stevep 0:04a9f72bbca7 209 {
stevep 0:04a9f72bbca7 210 ClearInfoBit(TTMATH_BIG_ZERO);
stevep 0:04a9f72bbca7 211 }
stevep 0:04a9f72bbca7 212
stevep 0:04a9f72bbca7 213 return false;
stevep 0:04a9f72bbca7 214 }
stevep 0:04a9f72bbca7 215
stevep 0:04a9f72bbca7 216
stevep 0:04a9f72bbca7 217 public:
stevep 0:04a9f72bbca7 218
stevep 0:04a9f72bbca7 219 /*!
stevep 0:04a9f72bbca7 220 this method clears a specific bit in the 'info' variable
stevep 0:04a9f72bbca7 221
stevep 0:04a9f72bbca7 222 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
stevep 0:04a9f72bbca7 223 */
stevep 0:04a9f72bbca7 224 void ClearInfoBit(unsigned char bit)
stevep 0:04a9f72bbca7 225 {
stevep 0:04a9f72bbca7 226 info = info & (~bit);
stevep 0:04a9f72bbca7 227 }
stevep 0:04a9f72bbca7 228
stevep 0:04a9f72bbca7 229
stevep 0:04a9f72bbca7 230 /*!
stevep 0:04a9f72bbca7 231 this method sets a specific bit in the 'info' variable
stevep 0:04a9f72bbca7 232
stevep 0:04a9f72bbca7 233 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
stevep 0:04a9f72bbca7 234
stevep 0:04a9f72bbca7 235 */
stevep 0:04a9f72bbca7 236 void SetInfoBit(unsigned char bit)
stevep 0:04a9f72bbca7 237 {
stevep 0:04a9f72bbca7 238 info = info | bit;
stevep 0:04a9f72bbca7 239 }
stevep 0:04a9f72bbca7 240
stevep 0:04a9f72bbca7 241
stevep 0:04a9f72bbca7 242 /*!
stevep 0:04a9f72bbca7 243 this method returns true if a specific bit in the 'info' variable is set
stevep 0:04a9f72bbca7 244
stevep 0:04a9f72bbca7 245 bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc.
stevep 0:04a9f72bbca7 246 */
stevep 0:04a9f72bbca7 247 bool IsInfoBit(unsigned char bit) const
stevep 0:04a9f72bbca7 248 {
stevep 0:04a9f72bbca7 249 return (info & bit) != 0;
stevep 0:04a9f72bbca7 250 }
stevep 0:04a9f72bbca7 251
stevep 0:04a9f72bbca7 252
stevep 0:04a9f72bbca7 253 /*!
stevep 0:04a9f72bbca7 254 this method sets zero
stevep 0:04a9f72bbca7 255 */
stevep 0:04a9f72bbca7 256 void SetZero()
stevep 0:04a9f72bbca7 257 {
stevep 0:04a9f72bbca7 258 info = TTMATH_BIG_ZERO;
stevep 0:04a9f72bbca7 259 exponent.SetZero();
stevep 0:04a9f72bbca7 260 mantissa.SetZero();
stevep 0:04a9f72bbca7 261
stevep 0:04a9f72bbca7 262 /*
stevep 0:04a9f72bbca7 263 we don't have to compensate zero
stevep 0:04a9f72bbca7 264 */
stevep 0:04a9f72bbca7 265 }
stevep 0:04a9f72bbca7 266
stevep 0:04a9f72bbca7 267
stevep 0:04a9f72bbca7 268 /*!
stevep 0:04a9f72bbca7 269 this method sets one
stevep 0:04a9f72bbca7 270 */
stevep 0:04a9f72bbca7 271 void SetOne()
stevep 0:04a9f72bbca7 272 {
stevep 0:04a9f72bbca7 273 info = 0;
stevep 0:04a9f72bbca7 274 mantissa.SetZero();
stevep 0:04a9f72bbca7 275 mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
stevep 0:04a9f72bbca7 276 exponent = -sint(man * TTMATH_BITS_PER_UINT - 1);
stevep 0:04a9f72bbca7 277
stevep 0:04a9f72bbca7 278 // don't have to Standardize() - the last bit from mantissa is set
stevep 0:04a9f72bbca7 279 }
stevep 0:04a9f72bbca7 280
stevep 0:04a9f72bbca7 281
stevep 0:04a9f72bbca7 282 /*!
stevep 0:04a9f72bbca7 283 this method sets value 0.5
stevep 0:04a9f72bbca7 284 */
stevep 0:04a9f72bbca7 285 void Set05()
stevep 0:04a9f72bbca7 286 {
stevep 0:04a9f72bbca7 287 SetOne();
stevep 0:04a9f72bbca7 288 exponent.SubOne();
stevep 0:04a9f72bbca7 289 }
stevep 0:04a9f72bbca7 290
stevep 0:04a9f72bbca7 291
stevep 0:04a9f72bbca7 292 /*!
stevep 0:04a9f72bbca7 293 this method sets NaN flag (Not a Number)
stevep 0:04a9f72bbca7 294 when this flag is set that means there is no a valid number
stevep 0:04a9f72bbca7 295 */
stevep 0:04a9f72bbca7 296 void SetNan()
stevep 0:04a9f72bbca7 297 {
stevep 0:04a9f72bbca7 298 SetInfoBit(TTMATH_BIG_NAN);
stevep 0:04a9f72bbca7 299 }
stevep 0:04a9f72bbca7 300
stevep 0:04a9f72bbca7 301
stevep 0:04a9f72bbca7 302 /*!
stevep 0:04a9f72bbca7 303 this method sets NaN flag (Not a Number)
stevep 0:04a9f72bbca7 304 also clears the mantissa and exponent (similarly as it would be a zero value)
stevep 0:04a9f72bbca7 305 */
stevep 0:04a9f72bbca7 306 void SetZeroNan()
stevep 0:04a9f72bbca7 307 {
stevep 0:04a9f72bbca7 308 SetZero();
stevep 0:04a9f72bbca7 309 SetNan();
stevep 0:04a9f72bbca7 310 }
stevep 0:04a9f72bbca7 311
stevep 0:04a9f72bbca7 312
stevep 0:04a9f72bbca7 313 /*!
stevep 0:04a9f72bbca7 314 this method swappes this for an argument
stevep 0:04a9f72bbca7 315 */
stevep 0:04a9f72bbca7 316 void Swap(Big<exp, man> & ss2)
stevep 0:04a9f72bbca7 317 {
stevep 0:04a9f72bbca7 318 unsigned char info_temp = info;
stevep 0:04a9f72bbca7 319 info = ss2.info;
stevep 0:04a9f72bbca7 320 ss2.info = info_temp;
stevep 0:04a9f72bbca7 321
stevep 0:04a9f72bbca7 322 exponent.Swap(ss2.exponent);
stevep 0:04a9f72bbca7 323 mantissa.Swap(ss2.mantissa);
stevep 0:04a9f72bbca7 324 }
stevep 0:04a9f72bbca7 325
stevep 0:04a9f72bbca7 326
stevep 0:04a9f72bbca7 327 private:
stevep 0:04a9f72bbca7 328
stevep 0:04a9f72bbca7 329 /*!
stevep 0:04a9f72bbca7 330 this method sets the mantissa of the value of pi
stevep 0:04a9f72bbca7 331 */
stevep 0:04a9f72bbca7 332 void SetMantissaPi()
stevep 0:04a9f72bbca7 333 {
stevep 0:04a9f72bbca7 334 // this is a static table which represents the value of Pi (mantissa of it)
stevep 0:04a9f72bbca7 335 // (first is the highest word)
stevep 0:04a9f72bbca7 336 // we must define this table as 'unsigned int' because
stevep 0:04a9f72bbca7 337 // both on 32bit and 64bit platforms this table is 32bit
stevep 0:04a9f72bbca7 338 static const unsigned int temp_table[] = {
stevep 0:04a9f72bbca7 339 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22,
stevep 0:04a9f72bbca7 340 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245,
stevep 0:04a9f72bbca7 341 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5,
stevep 0:04a9f72bbca7 342 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a,
stevep 0:04a9f72bbca7 343 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d,
stevep 0:04a9f72bbca7 344 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603,
stevep 0:04a9f72bbca7 345 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5,
stevep 0:04a9f72bbca7 346 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64,
stevep 0:04a9f72bbca7 347 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7,
stevep 0:04a9f72bbca7 348 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64,
stevep 0:04a9f72bbca7 349 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31,
stevep 0:04a9f72bbca7 350 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26,
stevep 0:04a9f72bbca7 351 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9,
stevep 0:04a9f72bbca7 352 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed,
stevep 0:04a9f72bbca7 353 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1,
stevep 0:04a9f72bbca7 354 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de,
stevep 0:04a9f72bbca7 355 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831,
stevep 0:04a9f72bbca7 356 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b,
stevep 0:04a9f72bbca7 357 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03,
stevep 0:04a9f72bbca7 358 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3,
stevep 0:04a9f72bbca7 359 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8,
stevep 0:04a9f72bbca7 360 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0,
stevep 0:04a9f72bbca7 361 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee,
stevep 0:04a9f72bbca7 362 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c,
stevep 0:04a9f72bbca7 363 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466,
stevep 0:04a9f72bbca7 364 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9,
stevep 0:04a9f72bbca7 365 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd,
stevep 0:04a9f72bbca7 366 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d,
stevep 0:04a9f72bbca7 367 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1,
stevep 0:04a9f72bbca7 368 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7,
stevep 0:04a9f72bbca7 369 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df,
stevep 0:04a9f72bbca7 370 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52
stevep 0:04a9f72bbca7 371 //0x86d44014, ...
stevep 0:04a9f72bbca7 372 // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..)
stevep 0:04a9f72bbca7 373 // 256 32bit words for the mantissa -- about 2464 valid decimal digits
stevep 0:04a9f72bbca7 374 };
stevep 0:04a9f72bbca7 375 // the value of PI is comming from the website http://zenwerx.com/pi.php
stevep 0:04a9f72bbca7 376 // 3101 digits were taken from this website
stevep 0:04a9f72bbca7 377 // (later the digits were compared with:
stevep 0:04a9f72bbca7 378 // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html )
stevep 0:04a9f72bbca7 379 // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform)
stevep 0:04a9f72bbca7 380 // and then the first 256 words were taken into this table
stevep 0:04a9f72bbca7 381 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
stevep 0:04a9f72bbca7 382 // and on 64bit platform value 128 (256/2=128))
stevep 0:04a9f72bbca7 383
stevep 0:04a9f72bbca7 384 mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
stevep 0:04a9f72bbca7 385 }
stevep 0:04a9f72bbca7 386
stevep 0:04a9f72bbca7 387 public:
stevep 0:04a9f72bbca7 388
stevep 0:04a9f72bbca7 389
stevep 0:04a9f72bbca7 390 /*!
stevep 0:04a9f72bbca7 391 this method sets the value of pi
stevep 0:04a9f72bbca7 392 */
stevep 0:04a9f72bbca7 393 void SetPi()
stevep 0:04a9f72bbca7 394 {
stevep 0:04a9f72bbca7 395 SetMantissaPi();
stevep 0:04a9f72bbca7 396 info = 0;
stevep 0:04a9f72bbca7 397 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
stevep 0:04a9f72bbca7 398 }
stevep 0:04a9f72bbca7 399
stevep 0:04a9f72bbca7 400
stevep 0:04a9f72bbca7 401 /*!
stevep 0:04a9f72bbca7 402 this method sets the value of 0.5 * pi
stevep 0:04a9f72bbca7 403 */
stevep 0:04a9f72bbca7 404 void Set05Pi()
stevep 0:04a9f72bbca7 405 {
stevep 0:04a9f72bbca7 406 SetMantissaPi();
stevep 0:04a9f72bbca7 407 info = 0;
stevep 0:04a9f72bbca7 408 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
stevep 0:04a9f72bbca7 409 }
stevep 0:04a9f72bbca7 410
stevep 0:04a9f72bbca7 411
stevep 0:04a9f72bbca7 412 /*!
stevep 0:04a9f72bbca7 413 this method sets the value of 2 * pi
stevep 0:04a9f72bbca7 414 */
stevep 0:04a9f72bbca7 415 void Set2Pi()
stevep 0:04a9f72bbca7 416 {
stevep 0:04a9f72bbca7 417 SetMantissaPi();
stevep 0:04a9f72bbca7 418 info = 0;
stevep 0:04a9f72bbca7 419 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
stevep 0:04a9f72bbca7 420 }
stevep 0:04a9f72bbca7 421
stevep 0:04a9f72bbca7 422
stevep 0:04a9f72bbca7 423 /*!
stevep 0:04a9f72bbca7 424 this method sets the value of e
stevep 0:04a9f72bbca7 425 (the base of the natural logarithm)
stevep 0:04a9f72bbca7 426 */
stevep 0:04a9f72bbca7 427 void SetE()
stevep 0:04a9f72bbca7 428 {
stevep 0:04a9f72bbca7 429 static const unsigned int temp_table[] = {
stevep 0:04a9f72bbca7 430 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb,
stevep 0:04a9f72bbca7 431 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561,
stevep 0:04a9f72bbca7 432 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77,
stevep 0:04a9f72bbca7 433 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61,
stevep 0:04a9f72bbca7 434 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19,
stevep 0:04a9f72bbca7 435 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff,
stevep 0:04a9f72bbca7 436 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2,
stevep 0:04a9f72bbca7 437 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238,
stevep 0:04a9f72bbca7 438 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270,
stevep 0:04a9f72bbca7 439 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e,
stevep 0:04a9f72bbca7 440 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef,
stevep 0:04a9f72bbca7 441 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6,
stevep 0:04a9f72bbca7 442 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a,
stevep 0:04a9f72bbca7 443 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a,
stevep 0:04a9f72bbca7 444 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b,
stevep 0:04a9f72bbca7 445 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a,
stevep 0:04a9f72bbca7 446 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a,
stevep 0:04a9f72bbca7 447 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910,
stevep 0:04a9f72bbca7 448 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3,
stevep 0:04a9f72bbca7 449 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6,
stevep 0:04a9f72bbca7 450 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e,
stevep 0:04a9f72bbca7 451 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403,
stevep 0:04a9f72bbca7 452 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1,
stevep 0:04a9f72bbca7 453 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64,
stevep 0:04a9f72bbca7 454 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829,
stevep 0:04a9f72bbca7 455 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282,
stevep 0:04a9f72bbca7 456 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74,
stevep 0:04a9f72bbca7 457 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b,
stevep 0:04a9f72bbca7 458 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457,
stevep 0:04a9f72bbca7 459 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e,
stevep 0:04a9f72bbca7 460 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e,
stevep 0:04a9f72bbca7 461 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749
stevep 0:04a9f72bbca7 462 // 0x2fe26dd4, ...
stevep 0:04a9f72bbca7 463 // 256 32bit words for the mantissa -- about 2464 valid decimal digits
stevep 0:04a9f72bbca7 464 };
stevep 0:04a9f72bbca7 465
stevep 0:04a9f72bbca7 466 // above value was calculated using Big<1,400> type on a 32bit platform
stevep 0:04a9f72bbca7 467 // and then the first 256 words were taken,
stevep 0:04a9f72bbca7 468 // the calculating was made by using ExpSurrounding0(1) method
stevep 0:04a9f72bbca7 469 // which took 1420 iterations
stevep 0:04a9f72bbca7 470 // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil)
stevep 0:04a9f72bbca7 471 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
stevep 0:04a9f72bbca7 472 // and on 64bit platform value 128 (256/2=128))
stevep 0:04a9f72bbca7 473
stevep 0:04a9f72bbca7 474 mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
stevep 0:04a9f72bbca7 475 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
stevep 0:04a9f72bbca7 476 info = 0;
stevep 0:04a9f72bbca7 477 }
stevep 0:04a9f72bbca7 478
stevep 0:04a9f72bbca7 479
stevep 0:04a9f72bbca7 480 /*!
stevep 0:04a9f72bbca7 481 this method sets the value of ln(2)
stevep 0:04a9f72bbca7 482 the natural logarithm from 2
stevep 0:04a9f72bbca7 483 */
stevep 0:04a9f72bbca7 484 void SetLn2()
stevep 0:04a9f72bbca7 485 {
stevep 0:04a9f72bbca7 486 static const unsigned int temp_table[] = {
stevep 0:04a9f72bbca7 487 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b,
stevep 0:04a9f72bbca7 488 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825,
stevep 0:04a9f72bbca7 489 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b,
stevep 0:04a9f72bbca7 490 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6,
stevep 0:04a9f72bbca7 491 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396,
stevep 0:04a9f72bbca7 492 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d,
stevep 0:04a9f72bbca7 493 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c,
stevep 0:04a9f72bbca7 494 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b,
stevep 0:04a9f72bbca7 495 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b,
stevep 0:04a9f72bbca7 496 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982,
stevep 0:04a9f72bbca7 497 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2,
stevep 0:04a9f72bbca7 498 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c,
stevep 0:04a9f72bbca7 499 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a,
stevep 0:04a9f72bbca7 500 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9,
stevep 0:04a9f72bbca7 501 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae,
stevep 0:04a9f72bbca7 502 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8,
stevep 0:04a9f72bbca7 503 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c,
stevep 0:04a9f72bbca7 504 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f,
stevep 0:04a9f72bbca7 505 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00,
stevep 0:04a9f72bbca7 506 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783,
stevep 0:04a9f72bbca7 507 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8,
stevep 0:04a9f72bbca7 508 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a,
stevep 0:04a9f72bbca7 509 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda,
stevep 0:04a9f72bbca7 510 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8,
stevep 0:04a9f72bbca7 511 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527,
stevep 0:04a9f72bbca7 512 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7,
stevep 0:04a9f72bbca7 513 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca,
stevep 0:04a9f72bbca7 514 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb,
stevep 0:04a9f72bbca7 515 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab,
stevep 0:04a9f72bbca7 516 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797,
stevep 0:04a9f72bbca7 517 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6,
stevep 0:04a9f72bbca7 518 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992
stevep 0:04a9f72bbca7 519 //0xcbb9ac40, ...
stevep 0:04a9f72bbca7 520 // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..)
stevep 0:04a9f72bbca7 521 // 256 32bit words for the mantissa -- about 2464 valid decimal digits
stevep 0:04a9f72bbca7 522 };
stevep 0:04a9f72bbca7 523
stevep 0:04a9f72bbca7 524 // above value was calculated using Big<1,400> type on a 32bit platform
stevep 0:04a9f72bbca7 525 // and then the first 256 words were taken,
stevep 0:04a9f72bbca7 526 // the calculating was made by using LnSurrounding1(2) method
stevep 0:04a9f72bbca7 527 // which took 4035 iterations
stevep 0:04a9f72bbca7 528 // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html)
stevep 0:04a9f72bbca7 529 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
stevep 0:04a9f72bbca7 530 // and on 64bit platform value 128 (256/2=128))
stevep 0:04a9f72bbca7 531
stevep 0:04a9f72bbca7 532 mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
stevep 0:04a9f72bbca7 533 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 534 info = 0;
stevep 0:04a9f72bbca7 535 }
stevep 0:04a9f72bbca7 536
stevep 0:04a9f72bbca7 537
stevep 0:04a9f72bbca7 538 /*!
stevep 0:04a9f72bbca7 539 this method sets the value of ln(10)
stevep 0:04a9f72bbca7 540 the natural logarithm from 10
stevep 0:04a9f72bbca7 541
stevep 0:04a9f72bbca7 542 I introduced this constant especially to make the conversion ToString()
stevep 0:04a9f72bbca7 543 being faster. In fact the method ToString() is keeping values of logarithms
stevep 0:04a9f72bbca7 544 it has calculated but it must calculate the logarithm at least once.
stevep 0:04a9f72bbca7 545 If a program, which uses this library, is running for a long time this
stevep 0:04a9f72bbca7 546 would be ok, but for programs which are running shorter, for example for
stevep 0:04a9f72bbca7 547 CGI applications which only once are printing values, this would be much
stevep 0:04a9f72bbca7 548 inconvenience. Then if we're printing with base (radix) 10 and the mantissa
stevep 0:04a9f72bbca7 549 of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE
stevep 0:04a9f72bbca7 550 we don't calculate the logarithm but take it from this constant.
stevep 0:04a9f72bbca7 551 */
stevep 0:04a9f72bbca7 552 void SetLn10()
stevep 0:04a9f72bbca7 553 {
stevep 0:04a9f72bbca7 554 static const unsigned int temp_table[] = {
stevep 0:04a9f72bbca7 555 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72,
stevep 0:04a9f72bbca7 556 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6,
stevep 0:04a9f72bbca7 557 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb,
stevep 0:04a9f72bbca7 558 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981,
stevep 0:04a9f72bbca7 559 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0,
stevep 0:04a9f72bbca7 560 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e,
stevep 0:04a9f72bbca7 561 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5,
stevep 0:04a9f72bbca7 562 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e,
stevep 0:04a9f72bbca7 563 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47,
stevep 0:04a9f72bbca7 564 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834,
stevep 0:04a9f72bbca7 565 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a,
stevep 0:04a9f72bbca7 566 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d,
stevep 0:04a9f72bbca7 567 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a,
stevep 0:04a9f72bbca7 568 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353,
stevep 0:04a9f72bbca7 569 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd,
stevep 0:04a9f72bbca7 570 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8,
stevep 0:04a9f72bbca7 571 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022,
stevep 0:04a9f72bbca7 572 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f,
stevep 0:04a9f72bbca7 573 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31,
stevep 0:04a9f72bbca7 574 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766,
stevep 0:04a9f72bbca7 575 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84,
stevep 0:04a9f72bbca7 576 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8,
stevep 0:04a9f72bbca7 577 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8,
stevep 0:04a9f72bbca7 578 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f,
stevep 0:04a9f72bbca7 579 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6,
stevep 0:04a9f72bbca7 580 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c,
stevep 0:04a9f72bbca7 581 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73,
stevep 0:04a9f72bbca7 582 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7,
stevep 0:04a9f72bbca7 583 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68,
stevep 0:04a9f72bbca7 584 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d,
stevep 0:04a9f72bbca7 585 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687,
stevep 0:04a9f72bbca7 586 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347
stevep 0:04a9f72bbca7 587 // 0xb4a638ef, ...
stevep 0:04a9f72bbca7 588 //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..)
stevep 0:04a9f72bbca7 589 // 256 32bit words for the mantissa -- about 2464 valid digits (decimal)
stevep 0:04a9f72bbca7 590 };
stevep 0:04a9f72bbca7 591
stevep 0:04a9f72bbca7 592 // above value was calculated using Big<1,400> type on a 32bit platform
stevep 0:04a9f72bbca7 593 // and then the first 256 32bit words were taken,
stevep 0:04a9f72bbca7 594 // the calculating was made by using LnSurrounding1(10) method
stevep 0:04a9f72bbca7 595 // which took 22080 iterations
stevep 0:04a9f72bbca7 596 // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html)
stevep 0:04a9f72bbca7 597 // (the formula used in LnSurrounding1(x) converges badly when
stevep 0:04a9f72bbca7 598 // the x is greater than one but in fact we can use it, only the
stevep 0:04a9f72bbca7 599 // number of iterations will be greater)
stevep 0:04a9f72bbca7 600 // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256,
stevep 0:04a9f72bbca7 601 // and on 64bit platform value 128 (256/2=128))
stevep 0:04a9f72bbca7 602
stevep 0:04a9f72bbca7 603 mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int));
stevep 0:04a9f72bbca7 604 exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
stevep 0:04a9f72bbca7 605 info = 0;
stevep 0:04a9f72bbca7 606 }
stevep 0:04a9f72bbca7 607
stevep 0:04a9f72bbca7 608
stevep 0:04a9f72bbca7 609 /*!
stevep 0:04a9f72bbca7 610 this method sets the maximum value which can be held in this type
stevep 0:04a9f72bbca7 611 */
stevep 0:04a9f72bbca7 612 void SetMax()
stevep 0:04a9f72bbca7 613 {
stevep 0:04a9f72bbca7 614 info = 0;
stevep 0:04a9f72bbca7 615 mantissa.SetMax();
stevep 0:04a9f72bbca7 616 exponent.SetMax();
stevep 0:04a9f72bbca7 617
stevep 0:04a9f72bbca7 618 // we don't have to use 'Standardizing()' because the last bit from
stevep 0:04a9f72bbca7 619 // the mantissa is set
stevep 0:04a9f72bbca7 620 }
stevep 0:04a9f72bbca7 621
stevep 0:04a9f72bbca7 622
stevep 0:04a9f72bbca7 623 /*!
stevep 0:04a9f72bbca7 624 this method sets the minimum value which can be held in this type
stevep 0:04a9f72bbca7 625 */
stevep 0:04a9f72bbca7 626 void SetMin()
stevep 0:04a9f72bbca7 627 {
stevep 0:04a9f72bbca7 628 info = 0;
stevep 0:04a9f72bbca7 629
stevep 0:04a9f72bbca7 630 mantissa.SetMax();
stevep 0:04a9f72bbca7 631 exponent.SetMax();
stevep 0:04a9f72bbca7 632 SetSign();
stevep 0:04a9f72bbca7 633
stevep 0:04a9f72bbca7 634 // we don't have to use 'Standardizing()' because the last bit from
stevep 0:04a9f72bbca7 635 // the mantissa is set
stevep 0:04a9f72bbca7 636 }
stevep 0:04a9f72bbca7 637
stevep 0:04a9f72bbca7 638
stevep 0:04a9f72bbca7 639 /*!
stevep 0:04a9f72bbca7 640 testing whether there is a value zero or not
stevep 0:04a9f72bbca7 641 */
stevep 0:04a9f72bbca7 642 bool IsZero() const
stevep 0:04a9f72bbca7 643 {
stevep 0:04a9f72bbca7 644 return IsInfoBit(TTMATH_BIG_ZERO);
stevep 0:04a9f72bbca7 645 }
stevep 0:04a9f72bbca7 646
stevep 0:04a9f72bbca7 647
stevep 0:04a9f72bbca7 648 /*!
stevep 0:04a9f72bbca7 649 this method returns true when there's the sign set
stevep 0:04a9f72bbca7 650 also we don't check the NaN flag
stevep 0:04a9f72bbca7 651 */
stevep 0:04a9f72bbca7 652 bool IsSign() const
stevep 0:04a9f72bbca7 653 {
stevep 0:04a9f72bbca7 654 return IsInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 655 }
stevep 0:04a9f72bbca7 656
stevep 0:04a9f72bbca7 657
stevep 0:04a9f72bbca7 658 /*!
stevep 0:04a9f72bbca7 659 this method returns true when there is not a valid number
stevep 0:04a9f72bbca7 660 */
stevep 0:04a9f72bbca7 661 bool IsNan() const
stevep 0:04a9f72bbca7 662 {
stevep 0:04a9f72bbca7 663 return IsInfoBit(TTMATH_BIG_NAN);
stevep 0:04a9f72bbca7 664 }
stevep 0:04a9f72bbca7 665
stevep 0:04a9f72bbca7 666
stevep 0:04a9f72bbca7 667
stevep 0:04a9f72bbca7 668 /*!
stevep 0:04a9f72bbca7 669 this method clears the sign
stevep 0:04a9f72bbca7 670 (there'll be an absolute value)
stevep 0:04a9f72bbca7 671
stevep 0:04a9f72bbca7 672 e.g.
stevep 0:04a9f72bbca7 673 -1 -> 1
stevep 0:04a9f72bbca7 674 2 -> 2
stevep 0:04a9f72bbca7 675 */
stevep 0:04a9f72bbca7 676 void Abs()
stevep 0:04a9f72bbca7 677 {
stevep 0:04a9f72bbca7 678 ClearInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 679 }
stevep 0:04a9f72bbca7 680
stevep 0:04a9f72bbca7 681
stevep 0:04a9f72bbca7 682 /*!
stevep 0:04a9f72bbca7 683 this method remains the 'sign' of the value
stevep 0:04a9f72bbca7 684 e.g. -2 = -1
stevep 0:04a9f72bbca7 685 0 = 0
stevep 0:04a9f72bbca7 686 10 = 1
stevep 0:04a9f72bbca7 687 */
stevep 0:04a9f72bbca7 688 void Sgn()
stevep 0:04a9f72bbca7 689 {
stevep 0:04a9f72bbca7 690 // we have to check the NaN flag, because the next SetOne() method would clear it
stevep 0:04a9f72bbca7 691 if( IsNan() )
stevep 0:04a9f72bbca7 692 return;
stevep 0:04a9f72bbca7 693
stevep 0:04a9f72bbca7 694 if( IsSign() )
stevep 0:04a9f72bbca7 695 {
stevep 0:04a9f72bbca7 696 SetOne();
stevep 0:04a9f72bbca7 697 SetSign();
stevep 0:04a9f72bbca7 698 }
stevep 0:04a9f72bbca7 699 else
stevep 0:04a9f72bbca7 700 if( IsZero() )
stevep 0:04a9f72bbca7 701 SetZero(); // !! is nedeed here?
stevep 0:04a9f72bbca7 702 else
stevep 0:04a9f72bbca7 703 SetOne();
stevep 0:04a9f72bbca7 704 }
stevep 0:04a9f72bbca7 705
stevep 0:04a9f72bbca7 706
stevep 0:04a9f72bbca7 707
stevep 0:04a9f72bbca7 708 /*!
stevep 0:04a9f72bbca7 709 this method sets the sign
stevep 0:04a9f72bbca7 710
stevep 0:04a9f72bbca7 711 e.g.
stevep 0:04a9f72bbca7 712 -1 -> -1
stevep 0:04a9f72bbca7 713 2 -> -2
stevep 0:04a9f72bbca7 714
stevep 0:04a9f72bbca7 715 we do not check whether there is a zero or not, if you're using this method
stevep 0:04a9f72bbca7 716 you must be sure that the value is (or will be afterwards) different from zero
stevep 0:04a9f72bbca7 717 */
stevep 0:04a9f72bbca7 718 void SetSign()
stevep 0:04a9f72bbca7 719 {
stevep 0:04a9f72bbca7 720 SetInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 721 }
stevep 0:04a9f72bbca7 722
stevep 0:04a9f72bbca7 723
stevep 0:04a9f72bbca7 724 /*!
stevep 0:04a9f72bbca7 725 this method changes the sign
stevep 0:04a9f72bbca7 726 when there is a value of zero then the sign is not changed
stevep 0:04a9f72bbca7 727
stevep 0:04a9f72bbca7 728 e.g.
stevep 0:04a9f72bbca7 729 -1 -> 1
stevep 0:04a9f72bbca7 730 2 -> -2
stevep 0:04a9f72bbca7 731 */
stevep 0:04a9f72bbca7 732 void ChangeSign()
stevep 0:04a9f72bbca7 733 {
stevep 0:04a9f72bbca7 734 // we don't have to check the NaN flag here
stevep 0:04a9f72bbca7 735
stevep 0:04a9f72bbca7 736 if( IsZero() )
stevep 0:04a9f72bbca7 737 return;
stevep 0:04a9f72bbca7 738
stevep 0:04a9f72bbca7 739 if( IsSign() )
stevep 0:04a9f72bbca7 740 ClearInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 741 else
stevep 0:04a9f72bbca7 742 SetInfoBit(TTMATH_BIG_SIGN);
stevep 0:04a9f72bbca7 743 }
stevep 0:04a9f72bbca7 744
stevep 0:04a9f72bbca7 745
stevep 0:04a9f72bbca7 746
stevep 0:04a9f72bbca7 747 private:
stevep 0:04a9f72bbca7 748
stevep 0:04a9f72bbca7 749 /*!
stevep 0:04a9f72bbca7 750 this method does the half-to-even rounding (banker's rounding)
stevep 0:04a9f72bbca7 751
stevep 0:04a9f72bbca7 752 if is_half is:
stevep 0:04a9f72bbca7 753 true - that means the rest was equal the half (0.5 decimal)
stevep 0:04a9f72bbca7 754 false - that means the rest was greater than a half (greater than 0.5 decimal)
stevep 0:04a9f72bbca7 755
stevep 0:04a9f72bbca7 756 if the rest was less than a half then don't call this method
stevep 0:04a9f72bbca7 757 (the rounding should does nothing then)
stevep 0:04a9f72bbca7 758 */
stevep 0:04a9f72bbca7 759 uint RoundHalfToEven(bool is_half, bool rounding_up = true)
stevep 0:04a9f72bbca7 760 {
stevep 0:04a9f72bbca7 761 uint c = 0;
stevep 0:04a9f72bbca7 762
stevep 0:04a9f72bbca7 763 if( !is_half || mantissa.IsTheLowestBitSet() )
stevep 0:04a9f72bbca7 764 {
stevep 0:04a9f72bbca7 765 if( rounding_up )
stevep 0:04a9f72bbca7 766 {
stevep 0:04a9f72bbca7 767 if( mantissa.AddOne() )
stevep 0:04a9f72bbca7 768 {
stevep 0:04a9f72bbca7 769 mantissa.Rcr(1, 1);
stevep 0:04a9f72bbca7 770 c = exponent.AddOne();
stevep 0:04a9f72bbca7 771 }
stevep 0:04a9f72bbca7 772 }
stevep 0:04a9f72bbca7 773 else
stevep 0:04a9f72bbca7 774 {
stevep 0:04a9f72bbca7 775 #ifdef TTMATH_DEBUG
stevep 0:04a9f72bbca7 776 uint c_from_zero =
stevep 0:04a9f72bbca7 777 #endif
stevep 0:04a9f72bbca7 778 mantissa.SubOne();
stevep 0:04a9f72bbca7 779
stevep 0:04a9f72bbca7 780 // we're using rounding_up=false in Add() when the mantissas have different signs
stevep 0:04a9f72bbca7 781 // mantissa can be zero only when previous mantissa was equal to ss2.mantissa
stevep 0:04a9f72bbca7 782 // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false
stevep 0:04a9f72bbca7 783 TTMATH_ASSERT( c_from_zero == 0 )
stevep 0:04a9f72bbca7 784 }
stevep 0:04a9f72bbca7 785 }
stevep 0:04a9f72bbca7 786
stevep 0:04a9f72bbca7 787 return c;
stevep 0:04a9f72bbca7 788 }
stevep 0:04a9f72bbca7 789
stevep 0:04a9f72bbca7 790
stevep 0:04a9f72bbca7 791
stevep 0:04a9f72bbca7 792
stevep 0:04a9f72bbca7 793
stevep 0:04a9f72bbca7 794 /*!
stevep 0:04a9f72bbca7 795 *
stevep 0:04a9f72bbca7 796 * basic mathematic functions
stevep 0:04a9f72bbca7 797 *
stevep 0:04a9f72bbca7 798 */
stevep 0:04a9f72bbca7 799
stevep 0:04a9f72bbca7 800
stevep 0:04a9f72bbca7 801 /*!
stevep 0:04a9f72bbca7 802 this method adds one to the existing value
stevep 0:04a9f72bbca7 803 */
stevep 0:04a9f72bbca7 804 uint AddOne()
stevep 0:04a9f72bbca7 805 {
stevep 0:04a9f72bbca7 806 Big<exp, man> one;
stevep 0:04a9f72bbca7 807
stevep 0:04a9f72bbca7 808 one.SetOne();
stevep 0:04a9f72bbca7 809
stevep 0:04a9f72bbca7 810 return Add(one);
stevep 0:04a9f72bbca7 811 }
stevep 0:04a9f72bbca7 812
stevep 0:04a9f72bbca7 813
stevep 0:04a9f72bbca7 814 /*!
stevep 0:04a9f72bbca7 815 this method subtracts one from the existing value
stevep 0:04a9f72bbca7 816 */
stevep 0:04a9f72bbca7 817 uint SubOne()
stevep 0:04a9f72bbca7 818 {
stevep 0:04a9f72bbca7 819 Big<exp, man> one;
stevep 0:04a9f72bbca7 820
stevep 0:04a9f72bbca7 821 one.SetOne();
stevep 0:04a9f72bbca7 822
stevep 0:04a9f72bbca7 823 return Sub(one);
stevep 0:04a9f72bbca7 824 }
stevep 0:04a9f72bbca7 825
stevep 0:04a9f72bbca7 826
stevep 0:04a9f72bbca7 827 private:
stevep 0:04a9f72bbca7 828
stevep 0:04a9f72bbca7 829
stevep 0:04a9f72bbca7 830 /*!
stevep 0:04a9f72bbca7 831 an auxiliary method for adding
stevep 0:04a9f72bbca7 832 */
stevep 0:04a9f72bbca7 833 void AddCheckExponents( Big<exp, man> & ss2,
stevep 0:04a9f72bbca7 834 Int<exp> & exp_offset,
stevep 0:04a9f72bbca7 835 bool & last_bit_set,
stevep 0:04a9f72bbca7 836 bool & rest_zero,
stevep 0:04a9f72bbca7 837 bool & do_adding,
stevep 0:04a9f72bbca7 838 bool & do_rounding)
stevep 0:04a9f72bbca7 839 {
stevep 0:04a9f72bbca7 840 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
stevep 0:04a9f72bbca7 841
stevep 0:04a9f72bbca7 842 if( exp_offset == mantissa_size_in_bits )
stevep 0:04a9f72bbca7 843 {
stevep 0:04a9f72bbca7 844 last_bit_set = ss2.mantissa.IsTheHighestBitSet();
stevep 0:04a9f72bbca7 845 rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1);
stevep 0:04a9f72bbca7 846 do_rounding = true; // we'are only rounding
stevep 0:04a9f72bbca7 847 }
stevep 0:04a9f72bbca7 848 else
stevep 0:04a9f72bbca7 849 if( exp_offset < mantissa_size_in_bits )
stevep 0:04a9f72bbca7 850 {
stevep 0:04a9f72bbca7 851 uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa
stevep 0:04a9f72bbca7 852 rest_zero = true;
stevep 0:04a9f72bbca7 853
stevep 0:04a9f72bbca7 854 if( moved > 0 )
stevep 0:04a9f72bbca7 855 {
stevep 0:04a9f72bbca7 856 last_bit_set = static_cast<bool>( ss2.mantissa.GetBit(moved-1) );
stevep 0:04a9f72bbca7 857
stevep 0:04a9f72bbca7 858 if( moved > 1 )
stevep 0:04a9f72bbca7 859 rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1);
stevep 0:04a9f72bbca7 860
stevep 0:04a9f72bbca7 861 // (2) moving 'exp_offset' times
stevep 0:04a9f72bbca7 862 ss2.mantissa.Rcr(moved, 0);
stevep 0:04a9f72bbca7 863 }
stevep 0:04a9f72bbca7 864
stevep 0:04a9f72bbca7 865 do_adding = true;
stevep 0:04a9f72bbca7 866 do_rounding = true;
stevep 0:04a9f72bbca7 867 }
stevep 0:04a9f72bbca7 868
stevep 0:04a9f72bbca7 869 // if exp_offset is greater than mantissa_size_in_bits then we do nothing
stevep 0:04a9f72bbca7 870 // ss2 is too small for taking into consideration in the sum
stevep 0:04a9f72bbca7 871 }
stevep 0:04a9f72bbca7 872
stevep 0:04a9f72bbca7 873
stevep 0:04a9f72bbca7 874 /*!
stevep 0:04a9f72bbca7 875 an auxiliary method for adding
stevep 0:04a9f72bbca7 876 */
stevep 0:04a9f72bbca7 877 uint AddMantissas( Big<exp, man> & ss2,
stevep 0:04a9f72bbca7 878 bool & last_bit_set,
stevep 0:04a9f72bbca7 879 bool & rest_zero)
stevep 0:04a9f72bbca7 880 {
stevep 0:04a9f72bbca7 881 uint c = 0;
stevep 0:04a9f72bbca7 882
stevep 0:04a9f72bbca7 883 if( IsSign() == ss2.IsSign() )
stevep 0:04a9f72bbca7 884 {
stevep 0:04a9f72bbca7 885 // values have the same signs
stevep 0:04a9f72bbca7 886 if( mantissa.Add(ss2.mantissa) )
stevep 0:04a9f72bbca7 887 {
stevep 0:04a9f72bbca7 888 // we have one bit more from addition (carry)
stevep 0:04a9f72bbca7 889 // now rest_zero means the old rest_zero with the old last_bit_set
stevep 0:04a9f72bbca7 890 rest_zero = (!last_bit_set && rest_zero);
stevep 0:04a9f72bbca7 891 last_bit_set = mantissa.Rcr(1,1);
stevep 0:04a9f72bbca7 892 c += exponent.AddOne();
stevep 0:04a9f72bbca7 893 }
stevep 0:04a9f72bbca7 894 }
stevep 0:04a9f72bbca7 895 else
stevep 0:04a9f72bbca7 896 {
stevep 0:04a9f72bbca7 897 // values have different signs
stevep 0:04a9f72bbca7 898 // there shouldn't be a carry here because
stevep 0:04a9f72bbca7 899 // (1) (2) guarantee that the mantissa of this
stevep 0:04a9f72bbca7 900 // is greater than or equal to the mantissa of the ss2
stevep 0:04a9f72bbca7 901
stevep 0:04a9f72bbca7 902 #ifdef TTMATH_DEBUG
stevep 0:04a9f72bbca7 903 uint c_temp =
stevep 0:04a9f72bbca7 904 #endif
stevep 0:04a9f72bbca7 905 mantissa.Sub(ss2.mantissa);
stevep 0:04a9f72bbca7 906
stevep 0:04a9f72bbca7 907 TTMATH_ASSERT( c_temp == 0 )
stevep 0:04a9f72bbca7 908 }
stevep 0:04a9f72bbca7 909
stevep 0:04a9f72bbca7 910 return c;
stevep 0:04a9f72bbca7 911 }
stevep 0:04a9f72bbca7 912
stevep 0:04a9f72bbca7 913
stevep 0:04a9f72bbca7 914 public:
stevep 0:04a9f72bbca7 915
stevep 0:04a9f72bbca7 916
stevep 0:04a9f72bbca7 917 /*!
stevep 0:04a9f72bbca7 918 Addition this = this + ss2
stevep 0:04a9f72bbca7 919
stevep 0:04a9f72bbca7 920 it returns carry if the sum is too big
stevep 0:04a9f72bbca7 921 */
stevep 0:04a9f72bbca7 922 uint Add(Big<exp, man> ss2, bool round = true, bool adding = true)
stevep 0:04a9f72bbca7 923 {
stevep 0:04a9f72bbca7 924 bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up;
stevep 0:04a9f72bbca7 925 Int<exp> exp_offset( exponent );
stevep 0:04a9f72bbca7 926 uint c = 0;
stevep 0:04a9f72bbca7 927
stevep 0:04a9f72bbca7 928 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 929 return CheckCarry(1);
stevep 0:04a9f72bbca7 930
stevep 0:04a9f72bbca7 931 if( !adding )
stevep 0:04a9f72bbca7 932 ss2.ChangeSign(); // subtracting
stevep 0:04a9f72bbca7 933
stevep 0:04a9f72bbca7 934 exp_offset.Sub( ss2.exponent );
stevep 0:04a9f72bbca7 935 exp_offset.Abs();
stevep 0:04a9f72bbca7 936
stevep 0:04a9f72bbca7 937 // (1) abs(this) will be >= abs(ss2)
stevep 0:04a9f72bbca7 938 if( SmallerWithoutSignThan(ss2) )
stevep 0:04a9f72bbca7 939 Swap(ss2);
stevep 0:04a9f72bbca7 940
stevep 0:04a9f72bbca7 941 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 942 return 0;
stevep 0:04a9f72bbca7 943
stevep 0:04a9f72bbca7 944 last_bit_set = rest_zero = do_adding = do_rounding = false;
stevep 0:04a9f72bbca7 945 rounding_up = (IsSign() == ss2.IsSign());
stevep 0:04a9f72bbca7 946
stevep 0:04a9f72bbca7 947 AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding);
stevep 0:04a9f72bbca7 948
stevep 0:04a9f72bbca7 949 if( do_adding )
stevep 0:04a9f72bbca7 950 c += AddMantissas(ss2, last_bit_set, rest_zero);
stevep 0:04a9f72bbca7 951
stevep 0:04a9f72bbca7 952 if( !round || !last_bit_set )
stevep 0:04a9f72bbca7 953 do_rounding = false;
stevep 0:04a9f72bbca7 954
stevep 0:04a9f72bbca7 955 if( do_rounding )
stevep 0:04a9f72bbca7 956 c += RoundHalfToEven(rest_zero, rounding_up);
stevep 0:04a9f72bbca7 957
stevep 0:04a9f72bbca7 958 if( do_adding || do_rounding )
stevep 0:04a9f72bbca7 959 c += Standardizing();
stevep 0:04a9f72bbca7 960
stevep 0:04a9f72bbca7 961 return CheckCarry(c);
stevep 0:04a9f72bbca7 962 }
stevep 0:04a9f72bbca7 963
stevep 0:04a9f72bbca7 964
stevep 0:04a9f72bbca7 965 /*!
stevep 0:04a9f72bbca7 966 Subtraction this = this - ss2
stevep 0:04a9f72bbca7 967
stevep 0:04a9f72bbca7 968 it returns carry if the result is too big
stevep 0:04a9f72bbca7 969 */
stevep 0:04a9f72bbca7 970 uint Sub(const Big<exp, man> & ss2, bool round = true)
stevep 0:04a9f72bbca7 971 {
stevep 0:04a9f72bbca7 972 return Add(ss2, round, false);
stevep 0:04a9f72bbca7 973 }
stevep 0:04a9f72bbca7 974
stevep 0:04a9f72bbca7 975
stevep 0:04a9f72bbca7 976 /*!
stevep 0:04a9f72bbca7 977 bitwise AND
stevep 0:04a9f72bbca7 978
stevep 0:04a9f72bbca7 979 this and ss2 must be >= 0
stevep 0:04a9f72bbca7 980 return values:
stevep 0:04a9f72bbca7 981 0 - ok
stevep 0:04a9f72bbca7 982 1 - carry
stevep 0:04a9f72bbca7 983 2 - this or ss2 was negative
stevep 0:04a9f72bbca7 984 */
stevep 0:04a9f72bbca7 985 uint BitAnd(Big<exp, man> ss2)
stevep 0:04a9f72bbca7 986 {
stevep 0:04a9f72bbca7 987 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 988 return CheckCarry(1);
stevep 0:04a9f72bbca7 989
stevep 0:04a9f72bbca7 990 if( IsSign() || ss2.IsSign() )
stevep 0:04a9f72bbca7 991 {
stevep 0:04a9f72bbca7 992 SetNan();
stevep 0:04a9f72bbca7 993 return 2;
stevep 0:04a9f72bbca7 994 }
stevep 0:04a9f72bbca7 995
stevep 0:04a9f72bbca7 996 if( IsZero() )
stevep 0:04a9f72bbca7 997 return 0;
stevep 0:04a9f72bbca7 998
stevep 0:04a9f72bbca7 999 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1000 {
stevep 0:04a9f72bbca7 1001 SetZero();
stevep 0:04a9f72bbca7 1002 return 0;
stevep 0:04a9f72bbca7 1003 }
stevep 0:04a9f72bbca7 1004
stevep 0:04a9f72bbca7 1005 Int<exp> exp_offset( exponent );
stevep 0:04a9f72bbca7 1006 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
stevep 0:04a9f72bbca7 1007
stevep 0:04a9f72bbca7 1008 uint c = 0;
stevep 0:04a9f72bbca7 1009
stevep 0:04a9f72bbca7 1010 exp_offset.Sub( ss2.exponent );
stevep 0:04a9f72bbca7 1011 exp_offset.Abs();
stevep 0:04a9f72bbca7 1012
stevep 0:04a9f72bbca7 1013 // abs(this) will be >= abs(ss2)
stevep 0:04a9f72bbca7 1014 if( SmallerWithoutSignThan(ss2) )
stevep 0:04a9f72bbca7 1015 Swap(ss2);
stevep 0:04a9f72bbca7 1016
stevep 0:04a9f72bbca7 1017 if( exp_offset >= mantissa_size_in_bits )
stevep 0:04a9f72bbca7 1018 {
stevep 0:04a9f72bbca7 1019 // the second value is too small
stevep 0:04a9f72bbca7 1020 SetZero();
stevep 0:04a9f72bbca7 1021 return 0;
stevep 0:04a9f72bbca7 1022 }
stevep 0:04a9f72bbca7 1023
stevep 0:04a9f72bbca7 1024 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
stevep 0:04a9f72bbca7 1025 ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
stevep 0:04a9f72bbca7 1026 mantissa.BitAnd(ss2.mantissa);
stevep 0:04a9f72bbca7 1027
stevep 0:04a9f72bbca7 1028 c += Standardizing();
stevep 0:04a9f72bbca7 1029
stevep 0:04a9f72bbca7 1030 return CheckCarry(c);
stevep 0:04a9f72bbca7 1031 }
stevep 0:04a9f72bbca7 1032
stevep 0:04a9f72bbca7 1033
stevep 0:04a9f72bbca7 1034 /*!
stevep 0:04a9f72bbca7 1035 bitwise OR
stevep 0:04a9f72bbca7 1036
stevep 0:04a9f72bbca7 1037 this and ss2 must be >= 0
stevep 0:04a9f72bbca7 1038 return values:
stevep 0:04a9f72bbca7 1039 0 - ok
stevep 0:04a9f72bbca7 1040 1 - carry
stevep 0:04a9f72bbca7 1041 2 - this or ss2 was negative
stevep 0:04a9f72bbca7 1042 */
stevep 0:04a9f72bbca7 1043 uint BitOr(Big<exp, man> ss2)
stevep 0:04a9f72bbca7 1044 {
stevep 0:04a9f72bbca7 1045 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 1046 return CheckCarry(1);
stevep 0:04a9f72bbca7 1047
stevep 0:04a9f72bbca7 1048 if( IsSign() || ss2.IsSign() )
stevep 0:04a9f72bbca7 1049 {
stevep 0:04a9f72bbca7 1050 SetNan();
stevep 0:04a9f72bbca7 1051 return 2;
stevep 0:04a9f72bbca7 1052 }
stevep 0:04a9f72bbca7 1053
stevep 0:04a9f72bbca7 1054 if( IsZero() )
stevep 0:04a9f72bbca7 1055 {
stevep 0:04a9f72bbca7 1056 *this = ss2;
stevep 0:04a9f72bbca7 1057 return 0;
stevep 0:04a9f72bbca7 1058 }
stevep 0:04a9f72bbca7 1059
stevep 0:04a9f72bbca7 1060 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1061 return 0;
stevep 0:04a9f72bbca7 1062
stevep 0:04a9f72bbca7 1063 Int<exp> exp_offset( exponent );
stevep 0:04a9f72bbca7 1064 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
stevep 0:04a9f72bbca7 1065
stevep 0:04a9f72bbca7 1066 uint c = 0;
stevep 0:04a9f72bbca7 1067
stevep 0:04a9f72bbca7 1068 exp_offset.Sub( ss2.exponent );
stevep 0:04a9f72bbca7 1069 exp_offset.Abs();
stevep 0:04a9f72bbca7 1070
stevep 0:04a9f72bbca7 1071 // abs(this) will be >= abs(ss2)
stevep 0:04a9f72bbca7 1072 if( SmallerWithoutSignThan(ss2) )
stevep 0:04a9f72bbca7 1073 Swap(ss2);
stevep 0:04a9f72bbca7 1074
stevep 0:04a9f72bbca7 1075 if( exp_offset >= mantissa_size_in_bits )
stevep 0:04a9f72bbca7 1076 // the second value is too small
stevep 0:04a9f72bbca7 1077 return 0;
stevep 0:04a9f72bbca7 1078
stevep 0:04a9f72bbca7 1079 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
stevep 0:04a9f72bbca7 1080 ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
stevep 0:04a9f72bbca7 1081 mantissa.BitOr(ss2.mantissa);
stevep 0:04a9f72bbca7 1082
stevep 0:04a9f72bbca7 1083 c += Standardizing();
stevep 0:04a9f72bbca7 1084
stevep 0:04a9f72bbca7 1085 return CheckCarry(c);
stevep 0:04a9f72bbca7 1086 }
stevep 0:04a9f72bbca7 1087
stevep 0:04a9f72bbca7 1088
stevep 0:04a9f72bbca7 1089 /*!
stevep 0:04a9f72bbca7 1090 bitwise XOR
stevep 0:04a9f72bbca7 1091
stevep 0:04a9f72bbca7 1092 this and ss2 must be >= 0
stevep 0:04a9f72bbca7 1093 return values:
stevep 0:04a9f72bbca7 1094 0 - ok
stevep 0:04a9f72bbca7 1095 1 - carry
stevep 0:04a9f72bbca7 1096 2 - this or ss2 was negative
stevep 0:04a9f72bbca7 1097 */
stevep 0:04a9f72bbca7 1098 uint BitXor(Big<exp, man> ss2)
stevep 0:04a9f72bbca7 1099 {
stevep 0:04a9f72bbca7 1100 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 1101 return CheckCarry(1);
stevep 0:04a9f72bbca7 1102
stevep 0:04a9f72bbca7 1103 if( IsSign() || ss2.IsSign() )
stevep 0:04a9f72bbca7 1104 {
stevep 0:04a9f72bbca7 1105 SetNan();
stevep 0:04a9f72bbca7 1106 return 2;
stevep 0:04a9f72bbca7 1107 }
stevep 0:04a9f72bbca7 1108
stevep 0:04a9f72bbca7 1109 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1110 return 0;
stevep 0:04a9f72bbca7 1111
stevep 0:04a9f72bbca7 1112 if( IsZero() )
stevep 0:04a9f72bbca7 1113 {
stevep 0:04a9f72bbca7 1114 *this = ss2;
stevep 0:04a9f72bbca7 1115 return 0;
stevep 0:04a9f72bbca7 1116 }
stevep 0:04a9f72bbca7 1117
stevep 0:04a9f72bbca7 1118 Int<exp> exp_offset( exponent );
stevep 0:04a9f72bbca7 1119 Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
stevep 0:04a9f72bbca7 1120
stevep 0:04a9f72bbca7 1121 uint c = 0;
stevep 0:04a9f72bbca7 1122
stevep 0:04a9f72bbca7 1123 exp_offset.Sub( ss2.exponent );
stevep 0:04a9f72bbca7 1124 exp_offset.Abs();
stevep 0:04a9f72bbca7 1125
stevep 0:04a9f72bbca7 1126 // abs(this) will be >= abs(ss2)
stevep 0:04a9f72bbca7 1127 if( SmallerWithoutSignThan(ss2) )
stevep 0:04a9f72bbca7 1128 Swap(ss2);
stevep 0:04a9f72bbca7 1129
stevep 0:04a9f72bbca7 1130 if( exp_offset >= mantissa_size_in_bits )
stevep 0:04a9f72bbca7 1131 // the second value is too small
stevep 0:04a9f72bbca7 1132 return 0;
stevep 0:04a9f72bbca7 1133
stevep 0:04a9f72bbca7 1134 // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times
stevep 0:04a9f72bbca7 1135 ss2.mantissa.Rcr( exp_offset.ToInt(), 0 );
stevep 0:04a9f72bbca7 1136 mantissa.BitXor(ss2.mantissa);
stevep 0:04a9f72bbca7 1137
stevep 0:04a9f72bbca7 1138 c += Standardizing();
stevep 0:04a9f72bbca7 1139
stevep 0:04a9f72bbca7 1140 return CheckCarry(c);
stevep 0:04a9f72bbca7 1141 }
stevep 0:04a9f72bbca7 1142
stevep 0:04a9f72bbca7 1143
stevep 0:04a9f72bbca7 1144
stevep 0:04a9f72bbca7 1145 /*!
stevep 0:04a9f72bbca7 1146 Multiplication this = this * ss2 (ss2 is uint)
stevep 0:04a9f72bbca7 1147
stevep 0:04a9f72bbca7 1148 ss2 without a sign
stevep 0:04a9f72bbca7 1149 */
stevep 0:04a9f72bbca7 1150 uint MulUInt(uint ss2)
stevep 0:04a9f72bbca7 1151 {
stevep 0:04a9f72bbca7 1152 UInt<man+1> man_result;
stevep 0:04a9f72bbca7 1153 uint i,c = 0;
stevep 0:04a9f72bbca7 1154
stevep 0:04a9f72bbca7 1155 if( IsNan() )
stevep 0:04a9f72bbca7 1156 return 1;
stevep 0:04a9f72bbca7 1157
stevep 0:04a9f72bbca7 1158 if( IsZero() )
stevep 0:04a9f72bbca7 1159 return 0;
stevep 0:04a9f72bbca7 1160
stevep 0:04a9f72bbca7 1161 if( ss2 == 0 )
stevep 0:04a9f72bbca7 1162 {
stevep 0:04a9f72bbca7 1163 SetZero();
stevep 0:04a9f72bbca7 1164 return 0;
stevep 0:04a9f72bbca7 1165 }
stevep 0:04a9f72bbca7 1166
stevep 0:04a9f72bbca7 1167 // man_result = mantissa * ss2.mantissa
stevep 0:04a9f72bbca7 1168 mantissa.MulInt(ss2, man_result);
stevep 0:04a9f72bbca7 1169
stevep 0:04a9f72bbca7 1170 sint bit = UInt<man>::FindLeadingBitInWord(man_result.table[man]); // man - last word
stevep 0:04a9f72bbca7 1171
stevep 0:04a9f72bbca7 1172 if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) )
stevep 0:04a9f72bbca7 1173 {
stevep 0:04a9f72bbca7 1174 // 'i' will be from 0 to TTMATH_BITS_PER_UINT
stevep 0:04a9f72bbca7 1175 i = man_result.CompensationToLeft();
stevep 0:04a9f72bbca7 1176 c = exponent.Add( TTMATH_BITS_PER_UINT - i );
stevep 0:04a9f72bbca7 1177
stevep 0:04a9f72bbca7 1178 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1179 mantissa.table[i] = man_result.table[i+1];
stevep 0:04a9f72bbca7 1180 }
stevep 0:04a9f72bbca7 1181 else
stevep 0:04a9f72bbca7 1182 {
stevep 0:04a9f72bbca7 1183 if( bit != -1 )
stevep 0:04a9f72bbca7 1184 {
stevep 0:04a9f72bbca7 1185 man_result.Rcr(bit+1, 0);
stevep 0:04a9f72bbca7 1186 c += exponent.Add(bit+1);
stevep 0:04a9f72bbca7 1187 }
stevep 0:04a9f72bbca7 1188
stevep 0:04a9f72bbca7 1189 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1190 mantissa.table[i] = man_result.table[i];
stevep 0:04a9f72bbca7 1191 }
stevep 0:04a9f72bbca7 1192
stevep 0:04a9f72bbca7 1193 c += Standardizing();
stevep 0:04a9f72bbca7 1194
stevep 0:04a9f72bbca7 1195 return CheckCarry(c);
stevep 0:04a9f72bbca7 1196 }
stevep 0:04a9f72bbca7 1197
stevep 0:04a9f72bbca7 1198
stevep 0:04a9f72bbca7 1199 /*!
stevep 0:04a9f72bbca7 1200 Multiplication this = this * ss2 (ss2 is sint)
stevep 0:04a9f72bbca7 1201
stevep 0:04a9f72bbca7 1202 ss2 with a sign
stevep 0:04a9f72bbca7 1203 */
stevep 0:04a9f72bbca7 1204 uint MulInt(sint ss2)
stevep 0:04a9f72bbca7 1205 {
stevep 0:04a9f72bbca7 1206 if( IsNan() )
stevep 0:04a9f72bbca7 1207 return 1;
stevep 0:04a9f72bbca7 1208
stevep 0:04a9f72bbca7 1209 if( ss2 == 0 )
stevep 0:04a9f72bbca7 1210 {
stevep 0:04a9f72bbca7 1211 SetZero();
stevep 0:04a9f72bbca7 1212 return 0;
stevep 0:04a9f72bbca7 1213 }
stevep 0:04a9f72bbca7 1214
stevep 0:04a9f72bbca7 1215 if( IsZero() )
stevep 0:04a9f72bbca7 1216 return 0;
stevep 0:04a9f72bbca7 1217
stevep 0:04a9f72bbca7 1218 if( IsSign() == (ss2<0) )
stevep 0:04a9f72bbca7 1219 {
stevep 0:04a9f72bbca7 1220 // the signs are the same (both are either - or +), the result is positive
stevep 0:04a9f72bbca7 1221 Abs();
stevep 0:04a9f72bbca7 1222 }
stevep 0:04a9f72bbca7 1223 else
stevep 0:04a9f72bbca7 1224 {
stevep 0:04a9f72bbca7 1225 // the signs are different, the result is negative
stevep 0:04a9f72bbca7 1226 SetSign();
stevep 0:04a9f72bbca7 1227 }
stevep 0:04a9f72bbca7 1228
stevep 0:04a9f72bbca7 1229 if( ss2<0 )
stevep 0:04a9f72bbca7 1230 ss2 = -ss2;
stevep 0:04a9f72bbca7 1231
stevep 0:04a9f72bbca7 1232
stevep 0:04a9f72bbca7 1233 return MulUInt( uint(ss2) );
stevep 0:04a9f72bbca7 1234 }
stevep 0:04a9f72bbca7 1235
stevep 0:04a9f72bbca7 1236
stevep 0:04a9f72bbca7 1237 private:
stevep 0:04a9f72bbca7 1238
stevep 0:04a9f72bbca7 1239
stevep 0:04a9f72bbca7 1240 /*!
stevep 0:04a9f72bbca7 1241 this method checks whether a table pointed by 'tab' and 'len'
stevep 0:04a9f72bbca7 1242 has the value 0.5 decimal
stevep 0:04a9f72bbca7 1243 (it is treated as the comma operator would be before the highest bit)
stevep 0:04a9f72bbca7 1244 call this method only if the highest bit is set - you have to test it beforehand
stevep 0:04a9f72bbca7 1245
stevep 0:04a9f72bbca7 1246 return:
stevep 0:04a9f72bbca7 1247 true - tab was equal the half (0.5 decimal)
stevep 0:04a9f72bbca7 1248 false - tab was greater than a half (greater than 0.5 decimal)
stevep 0:04a9f72bbca7 1249
stevep 0:04a9f72bbca7 1250 */
stevep 0:04a9f72bbca7 1251 bool CheckGreaterOrEqualHalf(uint * tab, uint len)
stevep 0:04a9f72bbca7 1252 {
stevep 0:04a9f72bbca7 1253 uint i;
stevep 0:04a9f72bbca7 1254
stevep 0:04a9f72bbca7 1255 TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 )
stevep 0:04a9f72bbca7 1256
stevep 0:04a9f72bbca7 1257 for(i=0 ; i<len-1 ; ++i)
stevep 0:04a9f72bbca7 1258 if( tab[i] != 0 )
stevep 0:04a9f72bbca7 1259 return false;
stevep 0:04a9f72bbca7 1260
stevep 0:04a9f72bbca7 1261 if( tab[i] != TTMATH_UINT_HIGHEST_BIT )
stevep 0:04a9f72bbca7 1262 return false;
stevep 0:04a9f72bbca7 1263
stevep 0:04a9f72bbca7 1264 return true;
stevep 0:04a9f72bbca7 1265 }
stevep 0:04a9f72bbca7 1266
stevep 0:04a9f72bbca7 1267
stevep 0:04a9f72bbca7 1268 private:
stevep 0:04a9f72bbca7 1269
stevep 0:04a9f72bbca7 1270 /*!
stevep 0:04a9f72bbca7 1271 multiplication this = this * ss2
stevep 0:04a9f72bbca7 1272 this method returns a carry
stevep 0:04a9f72bbca7 1273 */
stevep 0:04a9f72bbca7 1274 uint MulRef(const Big<exp, man> & ss2, bool round = true)
stevep 0:04a9f72bbca7 1275 {
stevep 0:04a9f72bbca7 1276 TTMATH_REFERENCE_ASSERT( ss2 )
stevep 0:04a9f72bbca7 1277
stevep 0:04a9f72bbca7 1278 UInt<man*2> man_result;
stevep 0:04a9f72bbca7 1279 uint c = 0;
stevep 0:04a9f72bbca7 1280 uint i;
stevep 0:04a9f72bbca7 1281
stevep 0:04a9f72bbca7 1282 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 1283 return CheckCarry(1);
stevep 0:04a9f72bbca7 1284
stevep 0:04a9f72bbca7 1285 if( IsZero() )
stevep 0:04a9f72bbca7 1286 return 0;
stevep 0:04a9f72bbca7 1287
stevep 0:04a9f72bbca7 1288 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1289 {
stevep 0:04a9f72bbca7 1290 SetZero();
stevep 0:04a9f72bbca7 1291 return 0;
stevep 0:04a9f72bbca7 1292 }
stevep 0:04a9f72bbca7 1293
stevep 0:04a9f72bbca7 1294 // man_result = mantissa * ss2.mantissa
stevep 0:04a9f72bbca7 1295 mantissa.MulBig(ss2.mantissa, man_result);
stevep 0:04a9f72bbca7 1296
stevep 0:04a9f72bbca7 1297 // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT
stevep 0:04a9f72bbca7 1298 // because mantissa and ss2.mantissa are standardized
stevep 0:04a9f72bbca7 1299 // (the highest bit in man_result is set to 1 or
stevep 0:04a9f72bbca7 1300 // if there is a zero value in man_result the method CompensationToLeft()
stevep 0:04a9f72bbca7 1301 // returns 0 but we'll correct this at the end in Standardizing() method)
stevep 0:04a9f72bbca7 1302 i = man_result.CompensationToLeft();
stevep 0:04a9f72bbca7 1303 uint exp_add = man * TTMATH_BITS_PER_UINT - i;
stevep 0:04a9f72bbca7 1304
stevep 0:04a9f72bbca7 1305 if( exp_add )
stevep 0:04a9f72bbca7 1306 c += exponent.Add( exp_add );
stevep 0:04a9f72bbca7 1307
stevep 0:04a9f72bbca7 1308 c += exponent.Add( ss2.exponent );
stevep 0:04a9f72bbca7 1309
stevep 0:04a9f72bbca7 1310 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1311 mantissa.table[i] = man_result.table[i+man];
stevep 0:04a9f72bbca7 1312
stevep 0:04a9f72bbca7 1313 if( round && (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
stevep 0:04a9f72bbca7 1314 {
stevep 0:04a9f72bbca7 1315 bool is_half = CheckGreaterOrEqualHalf(man_result.table, man);
stevep 0:04a9f72bbca7 1316 c += RoundHalfToEven(is_half);
stevep 0:04a9f72bbca7 1317 }
stevep 0:04a9f72bbca7 1318
stevep 0:04a9f72bbca7 1319 if( IsSign() == ss2.IsSign() )
stevep 0:04a9f72bbca7 1320 {
stevep 0:04a9f72bbca7 1321 // the signs are the same, the result is positive
stevep 0:04a9f72bbca7 1322 Abs();
stevep 0:04a9f72bbca7 1323 }
stevep 0:04a9f72bbca7 1324 else
stevep 0:04a9f72bbca7 1325 {
stevep 0:04a9f72bbca7 1326 // the signs are different, the result is negative
stevep 0:04a9f72bbca7 1327 // if the value is zero it will be corrected later in Standardizing method
stevep 0:04a9f72bbca7 1328 SetSign();
stevep 0:04a9f72bbca7 1329 }
stevep 0:04a9f72bbca7 1330
stevep 0:04a9f72bbca7 1331 c += Standardizing();
stevep 0:04a9f72bbca7 1332
stevep 0:04a9f72bbca7 1333 return CheckCarry(c);
stevep 0:04a9f72bbca7 1334 }
stevep 0:04a9f72bbca7 1335
stevep 0:04a9f72bbca7 1336
stevep 0:04a9f72bbca7 1337 public:
stevep 0:04a9f72bbca7 1338
stevep 0:04a9f72bbca7 1339
stevep 0:04a9f72bbca7 1340 /*!
stevep 0:04a9f72bbca7 1341 multiplication this = this * ss2
stevep 0:04a9f72bbca7 1342 this method returns a carry
stevep 0:04a9f72bbca7 1343 */
stevep 0:04a9f72bbca7 1344 uint Mul(const Big<exp, man> & ss2, bool round = true)
stevep 0:04a9f72bbca7 1345 {
stevep 0:04a9f72bbca7 1346 if( this == &ss2 )
stevep 0:04a9f72bbca7 1347 {
stevep 0:04a9f72bbca7 1348 Big<exp, man> copy_ss2(ss2);
stevep 0:04a9f72bbca7 1349 return MulRef(copy_ss2, round);
stevep 0:04a9f72bbca7 1350 }
stevep 0:04a9f72bbca7 1351 else
stevep 0:04a9f72bbca7 1352 {
stevep 0:04a9f72bbca7 1353 return MulRef(ss2, round);
stevep 0:04a9f72bbca7 1354 }
stevep 0:04a9f72bbca7 1355 }
stevep 0:04a9f72bbca7 1356
stevep 0:04a9f72bbca7 1357
stevep 0:04a9f72bbca7 1358 private:
stevep 0:04a9f72bbca7 1359
stevep 0:04a9f72bbca7 1360 /*!
stevep 0:04a9f72bbca7 1361 division this = this / ss2
stevep 0:04a9f72bbca7 1362
stevep 0:04a9f72bbca7 1363 return value:
stevep 0:04a9f72bbca7 1364 0 - ok
stevep 0:04a9f72bbca7 1365 1 - carry (in a division carry can be as well)
stevep 0:04a9f72bbca7 1366 2 - improper argument (ss2 is zero)
stevep 0:04a9f72bbca7 1367 */
stevep 0:04a9f72bbca7 1368 uint DivRef(const Big<exp, man> & ss2, bool round = true)
stevep 0:04a9f72bbca7 1369 {
stevep 0:04a9f72bbca7 1370 TTMATH_REFERENCE_ASSERT( ss2 )
stevep 0:04a9f72bbca7 1371
stevep 0:04a9f72bbca7 1372 UInt<man*2> man1;
stevep 0:04a9f72bbca7 1373 UInt<man*2> man2;
stevep 0:04a9f72bbca7 1374 uint i,c = 0;
stevep 0:04a9f72bbca7 1375
stevep 0:04a9f72bbca7 1376 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 1377 return CheckCarry(1);
stevep 0:04a9f72bbca7 1378
stevep 0:04a9f72bbca7 1379 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1380 {
stevep 0:04a9f72bbca7 1381 SetNan();
stevep 0:04a9f72bbca7 1382 return 2;
stevep 0:04a9f72bbca7 1383 }
stevep 0:04a9f72bbca7 1384
stevep 0:04a9f72bbca7 1385 if( IsZero() )
stevep 0:04a9f72bbca7 1386 return 0;
stevep 0:04a9f72bbca7 1387
stevep 0:04a9f72bbca7 1388 // !! this two loops can be joined together
stevep 0:04a9f72bbca7 1389
stevep 0:04a9f72bbca7 1390 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1391 {
stevep 0:04a9f72bbca7 1392 man1.table[i+man] = mantissa.table[i];
stevep 0:04a9f72bbca7 1393 man2.table[i] = ss2.mantissa.table[i];
stevep 0:04a9f72bbca7 1394 }
stevep 0:04a9f72bbca7 1395
stevep 0:04a9f72bbca7 1396 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1397 {
stevep 0:04a9f72bbca7 1398 man1.table[i] = 0;
stevep 0:04a9f72bbca7 1399 man2.table[i+man] = 0;
stevep 0:04a9f72bbca7 1400 }
stevep 0:04a9f72bbca7 1401
stevep 0:04a9f72bbca7 1402 man1.Div(man2);
stevep 0:04a9f72bbca7 1403
stevep 0:04a9f72bbca7 1404 i = man1.CompensationToLeft();
stevep 0:04a9f72bbca7 1405
stevep 0:04a9f72bbca7 1406 if( i )
stevep 0:04a9f72bbca7 1407 c += exponent.Sub(i);
stevep 0:04a9f72bbca7 1408
stevep 0:04a9f72bbca7 1409 c += exponent.Sub(ss2.exponent);
stevep 0:04a9f72bbca7 1410
stevep 0:04a9f72bbca7 1411 for(i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 1412 mantissa.table[i] = man1.table[i+man];
stevep 0:04a9f72bbca7 1413
stevep 0:04a9f72bbca7 1414 if( round && (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
stevep 0:04a9f72bbca7 1415 {
stevep 0:04a9f72bbca7 1416 bool is_half = CheckGreaterOrEqualHalf(man1.table, man);
stevep 0:04a9f72bbca7 1417 c += RoundHalfToEven(is_half);
stevep 0:04a9f72bbca7 1418 }
stevep 0:04a9f72bbca7 1419
stevep 0:04a9f72bbca7 1420 if( IsSign() == ss2.IsSign() )
stevep 0:04a9f72bbca7 1421 Abs();
stevep 0:04a9f72bbca7 1422 else
stevep 0:04a9f72bbca7 1423 SetSign(); // if there is a zero it will be corrected in Standardizing()
stevep 0:04a9f72bbca7 1424
stevep 0:04a9f72bbca7 1425 c += Standardizing();
stevep 0:04a9f72bbca7 1426
stevep 0:04a9f72bbca7 1427 return CheckCarry(c);
stevep 0:04a9f72bbca7 1428 }
stevep 0:04a9f72bbca7 1429
stevep 0:04a9f72bbca7 1430
stevep 0:04a9f72bbca7 1431 public:
stevep 0:04a9f72bbca7 1432
stevep 0:04a9f72bbca7 1433 /*!
stevep 0:04a9f72bbca7 1434 division this = this / ss2
stevep 0:04a9f72bbca7 1435
stevep 0:04a9f72bbca7 1436 return value:
stevep 0:04a9f72bbca7 1437 0 - ok
stevep 0:04a9f72bbca7 1438 1 - carry (in a division carry can be as well)
stevep 0:04a9f72bbca7 1439 2 - improper argument (ss2 is zero)
stevep 0:04a9f72bbca7 1440 */
stevep 0:04a9f72bbca7 1441 uint Div(const Big<exp, man> & ss2, bool round = true)
stevep 0:04a9f72bbca7 1442 {
stevep 0:04a9f72bbca7 1443 if( this == &ss2 )
stevep 0:04a9f72bbca7 1444 {
stevep 0:04a9f72bbca7 1445 Big<exp, man> copy_ss2(ss2);
stevep 0:04a9f72bbca7 1446 return DivRef(copy_ss2, round);
stevep 0:04a9f72bbca7 1447 }
stevep 0:04a9f72bbca7 1448 else
stevep 0:04a9f72bbca7 1449 {
stevep 0:04a9f72bbca7 1450 return DivRef(ss2, round);
stevep 0:04a9f72bbca7 1451 }
stevep 0:04a9f72bbca7 1452 }
stevep 0:04a9f72bbca7 1453
stevep 0:04a9f72bbca7 1454
stevep 0:04a9f72bbca7 1455 private:
stevep 0:04a9f72bbca7 1456
stevep 0:04a9f72bbca7 1457 /*!
stevep 0:04a9f72bbca7 1458 the remainder from a division
stevep 0:04a9f72bbca7 1459 */
stevep 0:04a9f72bbca7 1460 uint ModRef(const Big<exp, man> & ss2)
stevep 0:04a9f72bbca7 1461 {
stevep 0:04a9f72bbca7 1462 TTMATH_REFERENCE_ASSERT( ss2 )
stevep 0:04a9f72bbca7 1463
stevep 0:04a9f72bbca7 1464 uint c = 0;
stevep 0:04a9f72bbca7 1465
stevep 0:04a9f72bbca7 1466 if( IsNan() || ss2.IsNan() )
stevep 0:04a9f72bbca7 1467 return CheckCarry(1);
stevep 0:04a9f72bbca7 1468
stevep 0:04a9f72bbca7 1469 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 1470 {
stevep 0:04a9f72bbca7 1471 SetNan();
stevep 0:04a9f72bbca7 1472 return 2;
stevep 0:04a9f72bbca7 1473 }
stevep 0:04a9f72bbca7 1474
stevep 0:04a9f72bbca7 1475 if( !SmallerWithoutSignThan(ss2) )
stevep 0:04a9f72bbca7 1476 {
stevep 0:04a9f72bbca7 1477 Big<exp, man> temp(*this);
stevep 0:04a9f72bbca7 1478
stevep 0:04a9f72bbca7 1479 c = temp.Div(ss2);
stevep 0:04a9f72bbca7 1480 temp.SkipFraction();
stevep 0:04a9f72bbca7 1481 c += temp.Mul(ss2);
stevep 0:04a9f72bbca7 1482 c += Sub(temp);
stevep 0:04a9f72bbca7 1483
stevep 0:04a9f72bbca7 1484 if( !SmallerWithoutSignThan( ss2 ) )
stevep 0:04a9f72bbca7 1485 c += 1;
stevep 0:04a9f72bbca7 1486 }
stevep 0:04a9f72bbca7 1487
stevep 0:04a9f72bbca7 1488 return CheckCarry(c);
stevep 0:04a9f72bbca7 1489 }
stevep 0:04a9f72bbca7 1490
stevep 0:04a9f72bbca7 1491
stevep 0:04a9f72bbca7 1492 public:
stevep 0:04a9f72bbca7 1493
stevep 0:04a9f72bbca7 1494 /*!
stevep 0:04a9f72bbca7 1495 the remainder from a division
stevep 0:04a9f72bbca7 1496
stevep 0:04a9f72bbca7 1497 e.g.
stevep 0:04a9f72bbca7 1498 12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
stevep 0:04a9f72bbca7 1499 -12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
stevep 0:04a9f72bbca7 1500 12.6 mod -3 = 0.6
stevep 0:04a9f72bbca7 1501 -12.6 mod -3 = -0.6
stevep 0:04a9f72bbca7 1502
stevep 0:04a9f72bbca7 1503 it means:
stevep 0:04a9f72bbca7 1504 in other words: this(old) = ss2 * q + this(new)
stevep 0:04a9f72bbca7 1505
stevep 0:04a9f72bbca7 1506 return value:
stevep 0:04a9f72bbca7 1507 0 - ok
stevep 0:04a9f72bbca7 1508 1 - carry
stevep 0:04a9f72bbca7 1509 2 - improper argument (ss2 is zero)
stevep 0:04a9f72bbca7 1510 */
stevep 0:04a9f72bbca7 1511 uint Mod(const Big<exp, man> & ss2)
stevep 0:04a9f72bbca7 1512 {
stevep 0:04a9f72bbca7 1513 if( this == &ss2 )
stevep 0:04a9f72bbca7 1514 {
stevep 0:04a9f72bbca7 1515 Big<exp, man> copy_ss2(ss2);
stevep 0:04a9f72bbca7 1516 return ModRef(copy_ss2);
stevep 0:04a9f72bbca7 1517 }
stevep 0:04a9f72bbca7 1518 else
stevep 0:04a9f72bbca7 1519 {
stevep 0:04a9f72bbca7 1520 return ModRef(ss2);
stevep 0:04a9f72bbca7 1521 }
stevep 0:04a9f72bbca7 1522 }
stevep 0:04a9f72bbca7 1523
stevep 0:04a9f72bbca7 1524
stevep 0:04a9f72bbca7 1525 /*!
stevep 0:04a9f72bbca7 1526 this method returns: 'this' mod 2
stevep 0:04a9f72bbca7 1527 (either zero or one)
stevep 0:04a9f72bbca7 1528
stevep 0:04a9f72bbca7 1529 this method is much faster than using Mod( object_with_value_two )
stevep 0:04a9f72bbca7 1530 */
stevep 0:04a9f72bbca7 1531 uint Mod2() const
stevep 0:04a9f72bbca7 1532 {
stevep 0:04a9f72bbca7 1533 if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 1534 return 0;
stevep 0:04a9f72bbca7 1535
stevep 0:04a9f72bbca7 1536 sint exp_int = exponent.ToInt();
stevep 0:04a9f72bbca7 1537 // 'exp_int' is negative (or zero), we set it as positive
stevep 0:04a9f72bbca7 1538 exp_int = -exp_int;
stevep 0:04a9f72bbca7 1539
stevep 0:04a9f72bbca7 1540 return mantissa.GetBit(exp_int);
stevep 0:04a9f72bbca7 1541 }
stevep 0:04a9f72bbca7 1542
stevep 0:04a9f72bbca7 1543
stevep 0:04a9f72bbca7 1544 /*!
stevep 0:04a9f72bbca7 1545 power this = this ^ pow
stevep 0:04a9f72bbca7 1546 (pow without a sign)
stevep 0:04a9f72bbca7 1547
stevep 0:04a9f72bbca7 1548 binary algorithm (r-to-l)
stevep 0:04a9f72bbca7 1549
stevep 0:04a9f72bbca7 1550 return values:
stevep 0:04a9f72bbca7 1551 0 - ok
stevep 0:04a9f72bbca7 1552 1 - carry
stevep 0:04a9f72bbca7 1553 2 - incorrect arguments (0^0)
stevep 0:04a9f72bbca7 1554 */
stevep 0:04a9f72bbca7 1555 template<uint pow_size>
stevep 0:04a9f72bbca7 1556 uint Pow(UInt<pow_size> pow)
stevep 0:04a9f72bbca7 1557 {
stevep 0:04a9f72bbca7 1558 if( IsNan() )
stevep 0:04a9f72bbca7 1559 return 1;
stevep 0:04a9f72bbca7 1560
stevep 0:04a9f72bbca7 1561 if( IsZero() )
stevep 0:04a9f72bbca7 1562 {
stevep 0:04a9f72bbca7 1563 if( pow.IsZero() )
stevep 0:04a9f72bbca7 1564 {
stevep 0:04a9f72bbca7 1565 // we don't define zero^zero
stevep 0:04a9f72bbca7 1566 SetNan();
stevep 0:04a9f72bbca7 1567 return 2;
stevep 0:04a9f72bbca7 1568 }
stevep 0:04a9f72bbca7 1569
stevep 0:04a9f72bbca7 1570 // 0^(+something) is zero
stevep 0:04a9f72bbca7 1571 return 0;
stevep 0:04a9f72bbca7 1572 }
stevep 0:04a9f72bbca7 1573
stevep 0:04a9f72bbca7 1574 Big<exp, man> start(*this);
stevep 0:04a9f72bbca7 1575 Big<exp, man> result;
stevep 0:04a9f72bbca7 1576 result.SetOne();
stevep 0:04a9f72bbca7 1577 uint c = 0;
stevep 0:04a9f72bbca7 1578
stevep 0:04a9f72bbca7 1579 while( !c )
stevep 0:04a9f72bbca7 1580 {
stevep 0:04a9f72bbca7 1581 if( pow.table[0] & 1 )
stevep 0:04a9f72bbca7 1582 c += result.Mul(start);
stevep 0:04a9f72bbca7 1583
stevep 0:04a9f72bbca7 1584 pow.Rcr(1);
stevep 0:04a9f72bbca7 1585
stevep 0:04a9f72bbca7 1586 if( pow.IsZero() )
stevep 0:04a9f72bbca7 1587 break;
stevep 0:04a9f72bbca7 1588
stevep 0:04a9f72bbca7 1589 c += start.Mul(start);
stevep 0:04a9f72bbca7 1590 }
stevep 0:04a9f72bbca7 1591
stevep 0:04a9f72bbca7 1592 *this = result;
stevep 0:04a9f72bbca7 1593
stevep 0:04a9f72bbca7 1594 return CheckCarry(c);
stevep 0:04a9f72bbca7 1595 }
stevep 0:04a9f72bbca7 1596
stevep 0:04a9f72bbca7 1597
stevep 0:04a9f72bbca7 1598 /*!
stevep 0:04a9f72bbca7 1599 power this = this ^ pow
stevep 0:04a9f72bbca7 1600 p can be negative
stevep 0:04a9f72bbca7 1601
stevep 0:04a9f72bbca7 1602 return values:
stevep 0:04a9f72bbca7 1603 0 - ok
stevep 0:04a9f72bbca7 1604 1 - carry
stevep 0:04a9f72bbca7 1605 2 - incorrect arguments 0^0 or 0^(-something)
stevep 0:04a9f72bbca7 1606 */
stevep 0:04a9f72bbca7 1607 template<uint pow_size>
stevep 0:04a9f72bbca7 1608 uint Pow(Int<pow_size> pow)
stevep 0:04a9f72bbca7 1609 {
stevep 0:04a9f72bbca7 1610 if( IsNan() )
stevep 0:04a9f72bbca7 1611 return 1;
stevep 0:04a9f72bbca7 1612
stevep 0:04a9f72bbca7 1613 if( !pow.IsSign() )
stevep 0:04a9f72bbca7 1614 return Pow( UInt<pow_size>(pow) );
stevep 0:04a9f72bbca7 1615
stevep 0:04a9f72bbca7 1616 if( IsZero() )
stevep 0:04a9f72bbca7 1617 {
stevep 0:04a9f72bbca7 1618 // if 'p' is negative then
stevep 0:04a9f72bbca7 1619 // 'this' must be different from zero
stevep 0:04a9f72bbca7 1620 SetNan();
stevep 0:04a9f72bbca7 1621 return 2;
stevep 0:04a9f72bbca7 1622 }
stevep 0:04a9f72bbca7 1623
stevep 0:04a9f72bbca7 1624 uint c = pow.ChangeSign();
stevep 0:04a9f72bbca7 1625
stevep 0:04a9f72bbca7 1626 Big<exp, man> t(*this);
stevep 0:04a9f72bbca7 1627 c += t.Pow( UInt<pow_size>(pow) ); // here can only be a carry (return:1)
stevep 0:04a9f72bbca7 1628
stevep 0:04a9f72bbca7 1629 SetOne();
stevep 0:04a9f72bbca7 1630 c += Div(t);
stevep 0:04a9f72bbca7 1631
stevep 0:04a9f72bbca7 1632 return CheckCarry(c);
stevep 0:04a9f72bbca7 1633 }
stevep 0:04a9f72bbca7 1634
stevep 0:04a9f72bbca7 1635
stevep 0:04a9f72bbca7 1636 /*!
stevep 0:04a9f72bbca7 1637 power this = this ^ abs([pow])
stevep 0:04a9f72bbca7 1638 pow is treated as a value without a sign and without a fraction
stevep 0:04a9f72bbca7 1639 if pow has a sign then the method pow.Abs() is used
stevep 0:04a9f72bbca7 1640 if pow has a fraction the fraction is skipped (not used in calculation)
stevep 0:04a9f72bbca7 1641
stevep 0:04a9f72bbca7 1642 return values:
stevep 0:04a9f72bbca7 1643 0 - ok
stevep 0:04a9f72bbca7 1644 1 - carry
stevep 0:04a9f72bbca7 1645 2 - incorrect arguments (0^0)
stevep 0:04a9f72bbca7 1646 */
stevep 0:04a9f72bbca7 1647 uint PowUInt(Big<exp, man> pow)
stevep 0:04a9f72bbca7 1648 {
stevep 0:04a9f72bbca7 1649 if( IsNan() || pow.IsNan() )
stevep 0:04a9f72bbca7 1650 return CheckCarry(1);
stevep 0:04a9f72bbca7 1651
stevep 0:04a9f72bbca7 1652 if( IsZero() )
stevep 0:04a9f72bbca7 1653 {
stevep 0:04a9f72bbca7 1654 if( pow.IsZero() )
stevep 0:04a9f72bbca7 1655 {
stevep 0:04a9f72bbca7 1656 SetNan();
stevep 0:04a9f72bbca7 1657 return 2;
stevep 0:04a9f72bbca7 1658 }
stevep 0:04a9f72bbca7 1659
stevep 0:04a9f72bbca7 1660 // 0^(+something) is zero
stevep 0:04a9f72bbca7 1661 return 0;
stevep 0:04a9f72bbca7 1662 }
stevep 0:04a9f72bbca7 1663
stevep 0:04a9f72bbca7 1664 if( pow.IsSign() )
stevep 0:04a9f72bbca7 1665 pow.Abs();
stevep 0:04a9f72bbca7 1666
stevep 0:04a9f72bbca7 1667 Big<exp, man> start(*this);
stevep 0:04a9f72bbca7 1668 Big<exp, man> result;
stevep 0:04a9f72bbca7 1669 Big<exp, man> one;
stevep 0:04a9f72bbca7 1670 uint c = 0;
stevep 0:04a9f72bbca7 1671 one.SetOne();
stevep 0:04a9f72bbca7 1672 result = one;
stevep 0:04a9f72bbca7 1673
stevep 0:04a9f72bbca7 1674 while( !c )
stevep 0:04a9f72bbca7 1675 {
stevep 0:04a9f72bbca7 1676 if( pow.Mod2() )
stevep 0:04a9f72bbca7 1677 c += result.Mul(start);
stevep 0:04a9f72bbca7 1678
stevep 0:04a9f72bbca7 1679 c += pow.exponent.SubOne();
stevep 0:04a9f72bbca7 1680
stevep 0:04a9f72bbca7 1681 if( pow < one )
stevep 0:04a9f72bbca7 1682 break;
stevep 0:04a9f72bbca7 1683
stevep 0:04a9f72bbca7 1684 c += start.Mul(start);
stevep 0:04a9f72bbca7 1685 }
stevep 0:04a9f72bbca7 1686
stevep 0:04a9f72bbca7 1687 *this = result;
stevep 0:04a9f72bbca7 1688
stevep 0:04a9f72bbca7 1689 return CheckCarry(c);
stevep 0:04a9f72bbca7 1690 }
stevep 0:04a9f72bbca7 1691
stevep 0:04a9f72bbca7 1692
stevep 0:04a9f72bbca7 1693 /*!
stevep 0:04a9f72bbca7 1694 power this = this ^ [pow]
stevep 0:04a9f72bbca7 1695 pow is treated as a value without a fraction
stevep 0:04a9f72bbca7 1696 pow can be negative
stevep 0:04a9f72bbca7 1697
stevep 0:04a9f72bbca7 1698 return values:
stevep 0:04a9f72bbca7 1699 0 - ok
stevep 0:04a9f72bbca7 1700 1 - carry
stevep 0:04a9f72bbca7 1701 2 - incorrect arguments 0^0 or 0^(-something)
stevep 0:04a9f72bbca7 1702 */
stevep 0:04a9f72bbca7 1703 uint PowInt(const Big<exp, man> & pow)
stevep 0:04a9f72bbca7 1704 {
stevep 0:04a9f72bbca7 1705 if( IsNan() || pow.IsNan() )
stevep 0:04a9f72bbca7 1706 return CheckCarry(1);
stevep 0:04a9f72bbca7 1707
stevep 0:04a9f72bbca7 1708 if( !pow.IsSign() )
stevep 0:04a9f72bbca7 1709 return PowUInt(pow);
stevep 0:04a9f72bbca7 1710
stevep 0:04a9f72bbca7 1711 if( IsZero() )
stevep 0:04a9f72bbca7 1712 {
stevep 0:04a9f72bbca7 1713 // if 'pow' is negative then
stevep 0:04a9f72bbca7 1714 // 'this' must be different from zero
stevep 0:04a9f72bbca7 1715 SetNan();
stevep 0:04a9f72bbca7 1716 return 2;
stevep 0:04a9f72bbca7 1717 }
stevep 0:04a9f72bbca7 1718
stevep 0:04a9f72bbca7 1719 Big<exp, man> temp(*this);
stevep 0:04a9f72bbca7 1720 uint c = temp.PowUInt(pow); // here can only be a carry (result:1)
stevep 0:04a9f72bbca7 1721
stevep 0:04a9f72bbca7 1722 SetOne();
stevep 0:04a9f72bbca7 1723 c += Div(temp);
stevep 0:04a9f72bbca7 1724
stevep 0:04a9f72bbca7 1725 return CheckCarry(c);
stevep 0:04a9f72bbca7 1726 }
stevep 0:04a9f72bbca7 1727
stevep 0:04a9f72bbca7 1728
stevep 0:04a9f72bbca7 1729 /*!
stevep 0:04a9f72bbca7 1730 power this = this ^ pow
stevep 0:04a9f72bbca7 1731 this must be greater than zero (this > 0)
stevep 0:04a9f72bbca7 1732 pow can be negative and with fraction
stevep 0:04a9f72bbca7 1733
stevep 0:04a9f72bbca7 1734 return values:
stevep 0:04a9f72bbca7 1735 0 - ok
stevep 0:04a9f72bbca7 1736 1 - carry
stevep 0:04a9f72bbca7 1737 2 - incorrect argument ('this' <= 0)
stevep 0:04a9f72bbca7 1738 */
stevep 0:04a9f72bbca7 1739 uint PowFrac(const Big<exp, man> & pow)
stevep 0:04a9f72bbca7 1740 {
stevep 0:04a9f72bbca7 1741 if( IsNan() || pow.IsNan() )
stevep 0:04a9f72bbca7 1742 return CheckCarry(1);
stevep 0:04a9f72bbca7 1743
stevep 0:04a9f72bbca7 1744 Big<exp, man> temp;
stevep 0:04a9f72bbca7 1745 uint c = temp.Ln(*this);
stevep 0:04a9f72bbca7 1746
stevep 0:04a9f72bbca7 1747 if( c != 0 ) // can be 2 from Ln()
stevep 0:04a9f72bbca7 1748 {
stevep 0:04a9f72bbca7 1749 SetNan();
stevep 0:04a9f72bbca7 1750 return c;
stevep 0:04a9f72bbca7 1751 }
stevep 0:04a9f72bbca7 1752
stevep 0:04a9f72bbca7 1753 c += temp.Mul(pow);
stevep 0:04a9f72bbca7 1754 c += Exp(temp);
stevep 0:04a9f72bbca7 1755
stevep 0:04a9f72bbca7 1756 return CheckCarry(c);
stevep 0:04a9f72bbca7 1757 }
stevep 0:04a9f72bbca7 1758
stevep 0:04a9f72bbca7 1759
stevep 0:04a9f72bbca7 1760 /*!
stevep 0:04a9f72bbca7 1761 power this = this ^ pow
stevep 0:04a9f72bbca7 1762 pow can be negative and with fraction
stevep 0:04a9f72bbca7 1763
stevep 0:04a9f72bbca7 1764 return values:
stevep 0:04a9f72bbca7 1765 0 - ok
stevep 0:04a9f72bbca7 1766 1 - carry
stevep 0:04a9f72bbca7 1767 2 - incorrect argument ('this' or 'pow')
stevep 0:04a9f72bbca7 1768 */
stevep 0:04a9f72bbca7 1769 uint Pow(const Big<exp, man> & pow)
stevep 0:04a9f72bbca7 1770 {
stevep 0:04a9f72bbca7 1771 if( IsNan() || pow.IsNan() )
stevep 0:04a9f72bbca7 1772 return CheckCarry(1);
stevep 0:04a9f72bbca7 1773
stevep 0:04a9f72bbca7 1774 if( IsZero() )
stevep 0:04a9f72bbca7 1775 {
stevep 0:04a9f72bbca7 1776 // 0^pow will be 0 only for pow>0
stevep 0:04a9f72bbca7 1777 if( pow.IsSign() || pow.IsZero() )
stevep 0:04a9f72bbca7 1778 {
stevep 0:04a9f72bbca7 1779 SetNan();
stevep 0:04a9f72bbca7 1780 return 2;
stevep 0:04a9f72bbca7 1781 }
stevep 0:04a9f72bbca7 1782
stevep 0:04a9f72bbca7 1783 SetZero();
stevep 0:04a9f72bbca7 1784
stevep 0:04a9f72bbca7 1785 return 0;
stevep 0:04a9f72bbca7 1786 }
stevep 0:04a9f72bbca7 1787
stevep 0:04a9f72bbca7 1788 if( pow.exponent>-sint(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 )
stevep 0:04a9f72bbca7 1789 {
stevep 0:04a9f72bbca7 1790 if( pow.IsInteger() )
stevep 0:04a9f72bbca7 1791 return PowInt( pow );
stevep 0:04a9f72bbca7 1792 }
stevep 0:04a9f72bbca7 1793
stevep 0:04a9f72bbca7 1794 return PowFrac(pow);
stevep 0:04a9f72bbca7 1795 }
stevep 0:04a9f72bbca7 1796
stevep 0:04a9f72bbca7 1797
stevep 0:04a9f72bbca7 1798 /*!
stevep 0:04a9f72bbca7 1799 this function calculates the square root
stevep 0:04a9f72bbca7 1800 e.g. let this=9 then this.Sqrt() gives 3
stevep 0:04a9f72bbca7 1801
stevep 0:04a9f72bbca7 1802 return: 0 - ok
stevep 0:04a9f72bbca7 1803 1 - carry
stevep 0:04a9f72bbca7 1804 2 - improper argument (this<0 or NaN)
stevep 0:04a9f72bbca7 1805 */
stevep 0:04a9f72bbca7 1806 uint Sqrt()
stevep 0:04a9f72bbca7 1807 {
stevep 0:04a9f72bbca7 1808 if( IsNan() || IsSign() )
stevep 0:04a9f72bbca7 1809 {
stevep 0:04a9f72bbca7 1810 SetNan();
stevep 0:04a9f72bbca7 1811 return 2;
stevep 0:04a9f72bbca7 1812 }
stevep 0:04a9f72bbca7 1813
stevep 0:04a9f72bbca7 1814 if( IsZero() )
stevep 0:04a9f72bbca7 1815 return 0;
stevep 0:04a9f72bbca7 1816
stevep 0:04a9f72bbca7 1817 Big<exp, man> old(*this);
stevep 0:04a9f72bbca7 1818 Big<exp, man> ln;
stevep 0:04a9f72bbca7 1819 uint c = 0;
stevep 0:04a9f72bbca7 1820
stevep 0:04a9f72bbca7 1821 // we're using the formula: sqrt(x) = e ^ (ln(x) / 2)
stevep 0:04a9f72bbca7 1822 c += ln.Ln(*this);
stevep 0:04a9f72bbca7 1823 c += ln.exponent.SubOne(); // ln = ln / 2
stevep 0:04a9f72bbca7 1824 c += Exp(ln);
stevep 0:04a9f72bbca7 1825
stevep 0:04a9f72bbca7 1826 // above formula doesn't give accurate results for some integers
stevep 0:04a9f72bbca7 1827 // e.g. Sqrt(81) would not be 9 but a value very closed to 9
stevep 0:04a9f72bbca7 1828 // we're rounding the result, calculating result*result and comparing
stevep 0:04a9f72bbca7 1829 // with the old value, if they are equal then the result is an integer too
stevep 0:04a9f72bbca7 1830
stevep 0:04a9f72bbca7 1831 if( !c && old.IsInteger() && !IsInteger() )
stevep 0:04a9f72bbca7 1832 {
stevep 0:04a9f72bbca7 1833 Big<exp, man> temp(*this);
stevep 0:04a9f72bbca7 1834 c += temp.Round();
stevep 0:04a9f72bbca7 1835
stevep 0:04a9f72bbca7 1836 Big<exp, man> temp2(temp);
stevep 0:04a9f72bbca7 1837 c += temp.Mul(temp2);
stevep 0:04a9f72bbca7 1838
stevep 0:04a9f72bbca7 1839 if( temp == old )
stevep 0:04a9f72bbca7 1840 *this = temp2;
stevep 0:04a9f72bbca7 1841 }
stevep 0:04a9f72bbca7 1842
stevep 0:04a9f72bbca7 1843 return CheckCarry(c);
stevep 0:04a9f72bbca7 1844 }
stevep 0:04a9f72bbca7 1845
stevep 0:04a9f72bbca7 1846
stevep 0:04a9f72bbca7 1847 private:
stevep 0:04a9f72bbca7 1848
stevep 0:04a9f72bbca7 1849 #ifdef TTMATH_CONSTANTSGENERATOR
stevep 0:04a9f72bbca7 1850 public:
stevep 0:04a9f72bbca7 1851 #endif
stevep 0:04a9f72bbca7 1852
stevep 0:04a9f72bbca7 1853 /*!
stevep 0:04a9f72bbca7 1854 Exponent this = exp(x) = e^x where x is in (-1,1)
stevep 0:04a9f72bbca7 1855
stevep 0:04a9f72bbca7 1856 we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ...
stevep 0:04a9f72bbca7 1857 */
stevep 0:04a9f72bbca7 1858 void ExpSurrounding0(const Big<exp,man> & x, uint * steps = 0)
stevep 0:04a9f72bbca7 1859 {
stevep 0:04a9f72bbca7 1860 TTMATH_REFERENCE_ASSERT( x )
stevep 0:04a9f72bbca7 1861
stevep 0:04a9f72bbca7 1862 Big<exp,man> denominator, denominator_i;
stevep 0:04a9f72bbca7 1863 Big<exp,man> one, old_value, next_part;
stevep 0:04a9f72bbca7 1864 Big<exp,man> numerator = x;
stevep 0:04a9f72bbca7 1865
stevep 0:04a9f72bbca7 1866 SetOne();
stevep 0:04a9f72bbca7 1867 one.SetOne();
stevep 0:04a9f72bbca7 1868 denominator.SetOne();
stevep 0:04a9f72bbca7 1869 denominator_i.SetOne();
stevep 0:04a9f72bbca7 1870
stevep 0:04a9f72bbca7 1871 uint i;
stevep 0:04a9f72bbca7 1872 old_value = *this;
stevep 0:04a9f72bbca7 1873
stevep 0:04a9f72bbca7 1874 // we begin from 1 in order to not test at the beginning
stevep 0:04a9f72bbca7 1875 #ifdef TTMATH_CONSTANTSGENERATOR
stevep 0:04a9f72bbca7 1876 for(i=1 ; true ; ++i)
stevep 0:04a9f72bbca7 1877 #else
stevep 0:04a9f72bbca7 1878 for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
stevep 0:04a9f72bbca7 1879 #endif
stevep 0:04a9f72bbca7 1880 {
stevep 0:04a9f72bbca7 1881 bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
stevep 0:04a9f72bbca7 1882
stevep 0:04a9f72bbca7 1883 next_part = numerator;
stevep 0:04a9f72bbca7 1884
stevep 0:04a9f72bbca7 1885 if( next_part.Div( denominator ) )
stevep 0:04a9f72bbca7 1886 // if there is a carry here we only break the loop
stevep 0:04a9f72bbca7 1887 // however the result we return as good
stevep 0:04a9f72bbca7 1888 // it means there are too many parts of the formula
stevep 0:04a9f72bbca7 1889 break;
stevep 0:04a9f72bbca7 1890
stevep 0:04a9f72bbca7 1891 // there shouldn't be a carry here
stevep 0:04a9f72bbca7 1892 Add( next_part );
stevep 0:04a9f72bbca7 1893
stevep 0:04a9f72bbca7 1894 if( testing )
stevep 0:04a9f72bbca7 1895 {
stevep 0:04a9f72bbca7 1896 if( old_value == *this )
stevep 0:04a9f72bbca7 1897 // we've added next few parts of the formula but the result
stevep 0:04a9f72bbca7 1898 // is still the same then we break the loop
stevep 0:04a9f72bbca7 1899 break;
stevep 0:04a9f72bbca7 1900 else
stevep 0:04a9f72bbca7 1901 old_value = *this;
stevep 0:04a9f72bbca7 1902 }
stevep 0:04a9f72bbca7 1903
stevep 0:04a9f72bbca7 1904 // we set the denominator and the numerator for a next part of the formula
stevep 0:04a9f72bbca7 1905 if( denominator_i.Add(one) )
stevep 0:04a9f72bbca7 1906 // if there is a carry here the result we return as good
stevep 0:04a9f72bbca7 1907 break;
stevep 0:04a9f72bbca7 1908
stevep 0:04a9f72bbca7 1909 if( denominator.Mul(denominator_i) )
stevep 0:04a9f72bbca7 1910 break;
stevep 0:04a9f72bbca7 1911
stevep 0:04a9f72bbca7 1912 if( numerator.Mul(x) )
stevep 0:04a9f72bbca7 1913 break;
stevep 0:04a9f72bbca7 1914 }
stevep 0:04a9f72bbca7 1915
stevep 0:04a9f72bbca7 1916 if( steps )
stevep 0:04a9f72bbca7 1917 *steps = i;
stevep 0:04a9f72bbca7 1918 }
stevep 0:04a9f72bbca7 1919
stevep 0:04a9f72bbca7 1920 public:
stevep 0:04a9f72bbca7 1921
stevep 0:04a9f72bbca7 1922
stevep 0:04a9f72bbca7 1923 /*!
stevep 0:04a9f72bbca7 1924 Exponent this = exp(x) = e^x
stevep 0:04a9f72bbca7 1925
stevep 0:04a9f72bbca7 1926 we're using the fact that our value is stored in form of:
stevep 0:04a9f72bbca7 1927 x = mantissa * 2^exponent
stevep 0:04a9f72bbca7 1928 then
stevep 0:04a9f72bbca7 1929 e^x = e^(mantissa* 2^exponent) or
stevep 0:04a9f72bbca7 1930 e^x = (e^mantissa)^(2^exponent)
stevep 0:04a9f72bbca7 1931
stevep 0:04a9f72bbca7 1932 'Exp' returns a carry if we can't count the result ('x' is too big)
stevep 0:04a9f72bbca7 1933 */
stevep 0:04a9f72bbca7 1934 uint Exp(const Big<exp,man> & x)
stevep 0:04a9f72bbca7 1935 {
stevep 0:04a9f72bbca7 1936 uint c = 0;
stevep 0:04a9f72bbca7 1937
stevep 0:04a9f72bbca7 1938 if( x.IsNan() )
stevep 0:04a9f72bbca7 1939 return CheckCarry(1);
stevep 0:04a9f72bbca7 1940
stevep 0:04a9f72bbca7 1941 if( x.IsZero() )
stevep 0:04a9f72bbca7 1942 {
stevep 0:04a9f72bbca7 1943 SetOne();
stevep 0:04a9f72bbca7 1944 return 0;
stevep 0:04a9f72bbca7 1945 }
stevep 0:04a9f72bbca7 1946
stevep 0:04a9f72bbca7 1947 // m will be the value of the mantissa in range (-1,1)
stevep 0:04a9f72bbca7 1948 Big<exp,man> m(x);
stevep 0:04a9f72bbca7 1949 m.exponent = -sint(man*TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 1950
stevep 0:04a9f72bbca7 1951 // 'e_' will be the value of '2^exponent'
stevep 0:04a9f72bbca7 1952 // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
stevep 0:04a9f72bbca7 1953 // e_.exponent.Add(1) mean:
stevep 0:04a9f72bbca7 1954 // e_.mantissa.table[0] = 1;
stevep 0:04a9f72bbca7 1955 // e_.Standardizing();
stevep 0:04a9f72bbca7 1956 // e_.exponent.Add(man*TTMATH_BITS_PER_UINT)
stevep 0:04a9f72bbca7 1957 // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa)
stevep 0:04a9f72bbca7 1958 Big<exp,man> e_(x);
stevep 0:04a9f72bbca7 1959 e_.mantissa.SetZero();
stevep 0:04a9f72bbca7 1960 e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
stevep 0:04a9f72bbca7 1961 c += e_.exponent.Add(1);
stevep 0:04a9f72bbca7 1962 e_.Abs();
stevep 0:04a9f72bbca7 1963
stevep 0:04a9f72bbca7 1964 /*
stevep 0:04a9f72bbca7 1965 now we've got:
stevep 0:04a9f72bbca7 1966 m - the value of the mantissa in range (-1,1)
stevep 0:04a9f72bbca7 1967 e_ - 2^exponent
stevep 0:04a9f72bbca7 1968
stevep 0:04a9f72bbca7 1969 e_ can be as:
stevep 0:04a9f72bbca7 1970 ...2^-2, 2^-1, 2^0, 2^1, 2^2 ...
stevep 0:04a9f72bbca7 1971 ...1/4 , 1/2 , 1 , 2 , 4 ...
stevep 0:04a9f72bbca7 1972
stevep 0:04a9f72bbca7 1973 above one e_ is integer
stevep 0:04a9f72bbca7 1974
stevep 0:04a9f72bbca7 1975 if e_ is greater than 1 we calculate the exponent as:
stevep 0:04a9f72bbca7 1976 e^(m * e_) = ExpSurrounding0(m) ^ e_
stevep 0:04a9f72bbca7 1977 and if e_ is smaller or equal one we calculate the exponent in this way:
stevep 0:04a9f72bbca7 1978 e^(m * e_) = ExpSurrounding0(m* e_)
stevep 0:04a9f72bbca7 1979 because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m
stevep 0:04a9f72bbca7 1980 */
stevep 0:04a9f72bbca7 1981
stevep 0:04a9f72bbca7 1982 if( e_ <= 1 )
stevep 0:04a9f72bbca7 1983 {
stevep 0:04a9f72bbca7 1984 m.Mul(e_);
stevep 0:04a9f72bbca7 1985 ExpSurrounding0(m);
stevep 0:04a9f72bbca7 1986 }
stevep 0:04a9f72bbca7 1987 else
stevep 0:04a9f72bbca7 1988 {
stevep 0:04a9f72bbca7 1989 ExpSurrounding0(m);
stevep 0:04a9f72bbca7 1990 c += PowUInt(e_);
stevep 0:04a9f72bbca7 1991 }
stevep 0:04a9f72bbca7 1992
stevep 0:04a9f72bbca7 1993 return CheckCarry(c);
stevep 0:04a9f72bbca7 1994 }
stevep 0:04a9f72bbca7 1995
stevep 0:04a9f72bbca7 1996
stevep 0:04a9f72bbca7 1997
stevep 0:04a9f72bbca7 1998
stevep 0:04a9f72bbca7 1999 private:
stevep 0:04a9f72bbca7 2000
stevep 0:04a9f72bbca7 2001 #ifdef TTMATH_CONSTANTSGENERATOR
stevep 0:04a9f72bbca7 2002 public:
stevep 0:04a9f72bbca7 2003 #endif
stevep 0:04a9f72bbca7 2004
stevep 0:04a9f72bbca7 2005 /*!
stevep 0:04a9f72bbca7 2006 Natural logarithm this = ln(x) where x in range <1,2)
stevep 0:04a9f72bbca7 2007
stevep 0:04a9f72bbca7 2008 we're using the formula:
stevep 0:04a9f72bbca7 2009 ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ]
stevep 0:04a9f72bbca7 2010 */
stevep 0:04a9f72bbca7 2011 void LnSurrounding1(const Big<exp,man> & x, uint * steps = 0)
stevep 0:04a9f72bbca7 2012 {
stevep 0:04a9f72bbca7 2013 Big<exp,man> old_value, next_part, denominator, one, two, x1(x), x2(x);
stevep 0:04a9f72bbca7 2014
stevep 0:04a9f72bbca7 2015 one.SetOne();
stevep 0:04a9f72bbca7 2016
stevep 0:04a9f72bbca7 2017 if( x == one )
stevep 0:04a9f72bbca7 2018 {
stevep 0:04a9f72bbca7 2019 // LnSurrounding1(1) is 0
stevep 0:04a9f72bbca7 2020 SetZero();
stevep 0:04a9f72bbca7 2021 return;
stevep 0:04a9f72bbca7 2022 }
stevep 0:04a9f72bbca7 2023
stevep 0:04a9f72bbca7 2024 two = 2;
stevep 0:04a9f72bbca7 2025
stevep 0:04a9f72bbca7 2026 x1.Sub(one);
stevep 0:04a9f72bbca7 2027 x2.Add(one);
stevep 0:04a9f72bbca7 2028
stevep 0:04a9f72bbca7 2029 x1.Div(x2);
stevep 0:04a9f72bbca7 2030 x2 = x1;
stevep 0:04a9f72bbca7 2031 x2.Mul(x1);
stevep 0:04a9f72bbca7 2032
stevep 0:04a9f72bbca7 2033 denominator.SetOne();
stevep 0:04a9f72bbca7 2034 SetZero();
stevep 0:04a9f72bbca7 2035
stevep 0:04a9f72bbca7 2036 old_value = *this;
stevep 0:04a9f72bbca7 2037 uint i;
stevep 0:04a9f72bbca7 2038
stevep 0:04a9f72bbca7 2039
stevep 0:04a9f72bbca7 2040 #ifdef TTMATH_CONSTANTSGENERATOR
stevep 0:04a9f72bbca7 2041 for(i=1 ; true ; ++i)
stevep 0:04a9f72bbca7 2042 #else
stevep 0:04a9f72bbca7 2043 // we begin from 1 in order to not test at the beginning
stevep 0:04a9f72bbca7 2044 for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
stevep 0:04a9f72bbca7 2045 #endif
stevep 0:04a9f72bbca7 2046 {
stevep 0:04a9f72bbca7 2047 bool testing = ((i & 3) == 0); // it means '(i % 4) == 0'
stevep 0:04a9f72bbca7 2048
stevep 0:04a9f72bbca7 2049 next_part = x1;
stevep 0:04a9f72bbca7 2050
stevep 0:04a9f72bbca7 2051 if( next_part.Div(denominator) )
stevep 0:04a9f72bbca7 2052 // if there is a carry here we only break the loop
stevep 0:04a9f72bbca7 2053 // however the result we return as good
stevep 0:04a9f72bbca7 2054 // it means there are too many parts of the formula
stevep 0:04a9f72bbca7 2055 break;
stevep 0:04a9f72bbca7 2056
stevep 0:04a9f72bbca7 2057 // there shouldn't be a carry here
stevep 0:04a9f72bbca7 2058 Add(next_part);
stevep 0:04a9f72bbca7 2059
stevep 0:04a9f72bbca7 2060 if( testing )
stevep 0:04a9f72bbca7 2061 {
stevep 0:04a9f72bbca7 2062 if( old_value == *this )
stevep 0:04a9f72bbca7 2063 // we've added next (step_test) parts of the formula but the result
stevep 0:04a9f72bbca7 2064 // is still the same then we break the loop
stevep 0:04a9f72bbca7 2065 break;
stevep 0:04a9f72bbca7 2066 else
stevep 0:04a9f72bbca7 2067 old_value = *this;
stevep 0:04a9f72bbca7 2068 }
stevep 0:04a9f72bbca7 2069
stevep 0:04a9f72bbca7 2070 if( x1.Mul(x2) )
stevep 0:04a9f72bbca7 2071 // if there is a carry here the result we return as good
stevep 0:04a9f72bbca7 2072 break;
stevep 0:04a9f72bbca7 2073
stevep 0:04a9f72bbca7 2074 if( denominator.Add(two) )
stevep 0:04a9f72bbca7 2075 break;
stevep 0:04a9f72bbca7 2076 }
stevep 0:04a9f72bbca7 2077
stevep 0:04a9f72bbca7 2078 // this = this * 2
stevep 0:04a9f72bbca7 2079 // ( there can't be a carry here because we calculate the logarithm between <1,2) )
stevep 0:04a9f72bbca7 2080 exponent.AddOne();
stevep 0:04a9f72bbca7 2081
stevep 0:04a9f72bbca7 2082 if( steps )
stevep 0:04a9f72bbca7 2083 *steps = i;
stevep 0:04a9f72bbca7 2084 }
stevep 0:04a9f72bbca7 2085
stevep 0:04a9f72bbca7 2086
stevep 0:04a9f72bbca7 2087
stevep 0:04a9f72bbca7 2088
stevep 0:04a9f72bbca7 2089 public:
stevep 0:04a9f72bbca7 2090
stevep 0:04a9f72bbca7 2091
stevep 0:04a9f72bbca7 2092 /*!
stevep 0:04a9f72bbca7 2093 Natural logarithm this = ln(x)
stevep 0:04a9f72bbca7 2094 (a logarithm with the base equal 'e')
stevep 0:04a9f72bbca7 2095
stevep 0:04a9f72bbca7 2096 we're using the fact that our value is stored in form of:
stevep 0:04a9f72bbca7 2097 x = mantissa * 2^exponent
stevep 0:04a9f72bbca7 2098 then
stevep 0:04a9f72bbca7 2099 ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2))
stevep 0:04a9f72bbca7 2100
stevep 0:04a9f72bbca7 2101 the mantissa we'll show as a value from range <1,2) because the logarithm
stevep 0:04a9f72bbca7 2102 is decreasing too fast when 'x' is going to 0
stevep 0:04a9f72bbca7 2103
stevep 0:04a9f72bbca7 2104 return values:
stevep 0:04a9f72bbca7 2105 0 - ok
stevep 0:04a9f72bbca7 2106 1 - overflow (carry)
stevep 0:04a9f72bbca7 2107 2 - incorrect argument (x<=0)
stevep 0:04a9f72bbca7 2108 */
stevep 0:04a9f72bbca7 2109 uint Ln(const Big<exp,man> & x)
stevep 0:04a9f72bbca7 2110 {
stevep 0:04a9f72bbca7 2111 if( x.IsNan() )
stevep 0:04a9f72bbca7 2112 return CheckCarry(1);
stevep 0:04a9f72bbca7 2113
stevep 0:04a9f72bbca7 2114 if( x.IsSign() || x.IsZero() )
stevep 0:04a9f72bbca7 2115 {
stevep 0:04a9f72bbca7 2116 SetNan();
stevep 0:04a9f72bbca7 2117 return 2;
stevep 0:04a9f72bbca7 2118 }
stevep 0:04a9f72bbca7 2119
stevep 0:04a9f72bbca7 2120 Big<exp,man> exponent_temp;
stevep 0:04a9f72bbca7 2121 exponent_temp.FromInt( x.exponent );
stevep 0:04a9f72bbca7 2122
stevep 0:04a9f72bbca7 2123 // m will be the value of the mantissa in range <1,2)
stevep 0:04a9f72bbca7 2124 Big<exp,man> m(x);
stevep 0:04a9f72bbca7 2125 m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1);
stevep 0:04a9f72bbca7 2126
stevep 0:04a9f72bbca7 2127 // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa
stevep 0:04a9f72bbca7 2128 uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1);
stevep 0:04a9f72bbca7 2129
stevep 0:04a9f72bbca7 2130 LnSurrounding1(m);
stevep 0:04a9f72bbca7 2131
stevep 0:04a9f72bbca7 2132 Big<exp,man> ln2;
stevep 0:04a9f72bbca7 2133 ln2.SetLn2();
stevep 0:04a9f72bbca7 2134 c += exponent_temp.Mul(ln2);
stevep 0:04a9f72bbca7 2135 c += Add(exponent_temp);
stevep 0:04a9f72bbca7 2136
stevep 0:04a9f72bbca7 2137 return CheckCarry(c);
stevep 0:04a9f72bbca7 2138 }
stevep 0:04a9f72bbca7 2139
stevep 0:04a9f72bbca7 2140
stevep 0:04a9f72bbca7 2141 /*!
stevep 0:04a9f72bbca7 2142 Logarithm from 'x' with a 'base'
stevep 0:04a9f72bbca7 2143
stevep 0:04a9f72bbca7 2144 we're using the formula:
stevep 0:04a9f72bbca7 2145 Log(x) with 'base' = ln(x) / ln(base)
stevep 0:04a9f72bbca7 2146
stevep 0:04a9f72bbca7 2147 return values:
stevep 0:04a9f72bbca7 2148 0 - ok
stevep 0:04a9f72bbca7 2149 1 - overflow
stevep 0:04a9f72bbca7 2150 2 - incorrect argument (x<=0)
stevep 0:04a9f72bbca7 2151 3 - incorrect base (a<=0 lub a=1)
stevep 0:04a9f72bbca7 2152 */
stevep 0:04a9f72bbca7 2153 uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
stevep 0:04a9f72bbca7 2154 {
stevep 0:04a9f72bbca7 2155 if( x.IsNan() || base.IsNan() )
stevep 0:04a9f72bbca7 2156 return CheckCarry(1);
stevep 0:04a9f72bbca7 2157
stevep 0:04a9f72bbca7 2158 if( x.IsSign() || x.IsZero() )
stevep 0:04a9f72bbca7 2159 {
stevep 0:04a9f72bbca7 2160 SetNan();
stevep 0:04a9f72bbca7 2161 return 2;
stevep 0:04a9f72bbca7 2162 }
stevep 0:04a9f72bbca7 2163
stevep 0:04a9f72bbca7 2164 Big<exp,man> denominator;;
stevep 0:04a9f72bbca7 2165 denominator.SetOne();
stevep 0:04a9f72bbca7 2166
stevep 0:04a9f72bbca7 2167 if( base.IsSign() || base.IsZero() || base==denominator )
stevep 0:04a9f72bbca7 2168 {
stevep 0:04a9f72bbca7 2169 SetNan();
stevep 0:04a9f72bbca7 2170 return 3;
stevep 0:04a9f72bbca7 2171 }
stevep 0:04a9f72bbca7 2172
stevep 0:04a9f72bbca7 2173 if( x == denominator ) // (this is: if x == 1)
stevep 0:04a9f72bbca7 2174 {
stevep 0:04a9f72bbca7 2175 // log(1) is 0
stevep 0:04a9f72bbca7 2176 SetZero();
stevep 0:04a9f72bbca7 2177 return 0;
stevep 0:04a9f72bbca7 2178 }
stevep 0:04a9f72bbca7 2179
stevep 0:04a9f72bbca7 2180 // another error values we've tested at the beginning
stevep 0:04a9f72bbca7 2181 // there can only be a carry
stevep 0:04a9f72bbca7 2182 uint c = Ln(x);
stevep 0:04a9f72bbca7 2183
stevep 0:04a9f72bbca7 2184 c += denominator.Ln(base);
stevep 0:04a9f72bbca7 2185 c += Div(denominator);
stevep 0:04a9f72bbca7 2186
stevep 0:04a9f72bbca7 2187 return CheckCarry(c);
stevep 0:04a9f72bbca7 2188 }
stevep 0:04a9f72bbca7 2189
stevep 0:04a9f72bbca7 2190
stevep 0:04a9f72bbca7 2191
stevep 0:04a9f72bbca7 2192
stevep 0:04a9f72bbca7 2193 /*!
stevep 0:04a9f72bbca7 2194 *
stevep 0:04a9f72bbca7 2195 * converting methods
stevep 0:04a9f72bbca7 2196 *
stevep 0:04a9f72bbca7 2197 */
stevep 0:04a9f72bbca7 2198
stevep 0:04a9f72bbca7 2199
stevep 0:04a9f72bbca7 2200 /*!
stevep 0:04a9f72bbca7 2201 converting from another type of a Big object
stevep 0:04a9f72bbca7 2202 */
stevep 0:04a9f72bbca7 2203 template<uint another_exp, uint another_man>
stevep 0:04a9f72bbca7 2204 uint FromBig(const Big<another_exp, another_man> & another)
stevep 0:04a9f72bbca7 2205 {
stevep 0:04a9f72bbca7 2206 info = another.info;
stevep 0:04a9f72bbca7 2207
stevep 0:04a9f72bbca7 2208 if( IsNan() )
stevep 0:04a9f72bbca7 2209 return 1;
stevep 0:04a9f72bbca7 2210
stevep 0:04a9f72bbca7 2211 if( exponent.FromInt(another.exponent) )
stevep 0:04a9f72bbca7 2212 {
stevep 0:04a9f72bbca7 2213 SetNan();
stevep 0:04a9f72bbca7 2214 return 1;
stevep 0:04a9f72bbca7 2215 }
stevep 0:04a9f72bbca7 2216
stevep 0:04a9f72bbca7 2217 uint man_len_min = (man < another_man)? man : another_man;
stevep 0:04a9f72bbca7 2218 uint i;
stevep 0:04a9f72bbca7 2219 uint c = 0;
stevep 0:04a9f72bbca7 2220
stevep 0:04a9f72bbca7 2221 for( i = 0 ; i<man_len_min ; ++i )
stevep 0:04a9f72bbca7 2222 mantissa.table[man-1-i] = another.mantissa.table[another_man-1-i];
stevep 0:04a9f72bbca7 2223
stevep 0:04a9f72bbca7 2224 for( ; i<man ; ++i )
stevep 0:04a9f72bbca7 2225 mantissa.table[man-1-i] = 0;
stevep 0:04a9f72bbca7 2226
stevep 0:04a9f72bbca7 2227
stevep 0:04a9f72bbca7 2228 // MS Visual Express 2005 reports a warning (in the lines with 'uint man_diff = ...'):
stevep 0:04a9f72bbca7 2229 // warning C4307: '*' : integral constant overflow
stevep 0:04a9f72bbca7 2230 // but we're using 'if( man > another_man )' and 'if( man < another_man )' and there'll be no such situation here
stevep 0:04a9f72bbca7 2231 #ifdef _MSC_VER
stevep 0:04a9f72bbca7 2232 #pragma warning( disable: 4307 )
stevep 0:04a9f72bbca7 2233 #endif
stevep 0:04a9f72bbca7 2234
stevep 0:04a9f72bbca7 2235 if( man > another_man )
stevep 0:04a9f72bbca7 2236 {
stevep 0:04a9f72bbca7 2237 uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 2238 c += exponent.SubInt(man_diff, 0);
stevep 0:04a9f72bbca7 2239 }
stevep 0:04a9f72bbca7 2240 else
stevep 0:04a9f72bbca7 2241 if( man < another_man )
stevep 0:04a9f72bbca7 2242 {
stevep 0:04a9f72bbca7 2243 uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 2244 c += exponent.AddInt(man_diff, 0);
stevep 0:04a9f72bbca7 2245 }
stevep 0:04a9f72bbca7 2246
stevep 0:04a9f72bbca7 2247 #ifdef _MSC_VER
stevep 0:04a9f72bbca7 2248 #pragma warning( default: 4307 )
stevep 0:04a9f72bbca7 2249 #endif
stevep 0:04a9f72bbca7 2250
stevep 0:04a9f72bbca7 2251 // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero)
stevep 0:04a9f72bbca7 2252 CorrectZero();
stevep 0:04a9f72bbca7 2253
stevep 0:04a9f72bbca7 2254 return CheckCarry(c);
stevep 0:04a9f72bbca7 2255 }
stevep 0:04a9f72bbca7 2256
stevep 0:04a9f72bbca7 2257
stevep 0:04a9f72bbca7 2258 private:
stevep 0:04a9f72bbca7 2259
stevep 0:04a9f72bbca7 2260 /*!
stevep 0:04a9f72bbca7 2261 an auxiliary method for converting 'this' into 'result'
stevep 0:04a9f72bbca7 2262 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2263 */
stevep 0:04a9f72bbca7 2264 uint ToUIntOrInt(uint & result) const
stevep 0:04a9f72bbca7 2265 {
stevep 0:04a9f72bbca7 2266 result = 0;
stevep 0:04a9f72bbca7 2267
stevep 0:04a9f72bbca7 2268 if( IsZero() )
stevep 0:04a9f72bbca7 2269 return 0;
stevep 0:04a9f72bbca7 2270
stevep 0:04a9f72bbca7 2271 sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 2272
stevep 0:04a9f72bbca7 2273 if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 2274 // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
stevep 0:04a9f72bbca7 2275 // into the 'sint' type (it's too big)
stevep 0:04a9f72bbca7 2276 return 1;
stevep 0:04a9f72bbca7 2277
stevep 0:04a9f72bbca7 2278 if( exponent <= maxbit )
stevep 0:04a9f72bbca7 2279 // our value is from the range of (-1,1) and we return zero
stevep 0:04a9f72bbca7 2280 return 0;
stevep 0:04a9f72bbca7 2281
stevep 0:04a9f72bbca7 2282 // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
stevep 0:04a9f72bbca7 2283 // and [maxbit + sint(TTMATH_BITS_PER_UINT] <= 0
stevep 0:04a9f72bbca7 2284 sint how_many_bits = exponent.ToInt();
stevep 0:04a9f72bbca7 2285
stevep 0:04a9f72bbca7 2286 // how_many_bits is negative, we'll make it positive
stevep 0:04a9f72bbca7 2287 how_many_bits = -how_many_bits;
stevep 0:04a9f72bbca7 2288
stevep 0:04a9f72bbca7 2289 result = (mantissa.table[man-1] >> (how_many_bits % TTMATH_BITS_PER_UINT));
stevep 0:04a9f72bbca7 2290
stevep 0:04a9f72bbca7 2291 return 0;
stevep 0:04a9f72bbca7 2292 }
stevep 0:04a9f72bbca7 2293
stevep 0:04a9f72bbca7 2294
stevep 0:04a9f72bbca7 2295 public:
stevep 0:04a9f72bbca7 2296
stevep 0:04a9f72bbca7 2297 /*!
stevep 0:04a9f72bbca7 2298 this method converts 'this' into uint
stevep 0:04a9f72bbca7 2299 */
stevep 0:04a9f72bbca7 2300 uint ToUInt() const
stevep 0:04a9f72bbca7 2301 {
stevep 0:04a9f72bbca7 2302 uint result;
stevep 0:04a9f72bbca7 2303
stevep 0:04a9f72bbca7 2304 ToUInt(result);
stevep 0:04a9f72bbca7 2305
stevep 0:04a9f72bbca7 2306 return result;
stevep 0:04a9f72bbca7 2307 }
stevep 0:04a9f72bbca7 2308
stevep 0:04a9f72bbca7 2309
stevep 0:04a9f72bbca7 2310 /*!
stevep 0:04a9f72bbca7 2311 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2312
stevep 0:04a9f72bbca7 2313 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2314 */
stevep 0:04a9f72bbca7 2315 uint ToUInt(uint & result) const
stevep 0:04a9f72bbca7 2316 {
stevep 0:04a9f72bbca7 2317 if( ToUIntOrInt(result) )
stevep 0:04a9f72bbca7 2318 return 1;
stevep 0:04a9f72bbca7 2319
stevep 0:04a9f72bbca7 2320 if( IsSign() )
stevep 0:04a9f72bbca7 2321 return 1;
stevep 0:04a9f72bbca7 2322
stevep 0:04a9f72bbca7 2323 return 0;
stevep 0:04a9f72bbca7 2324 }
stevep 0:04a9f72bbca7 2325
stevep 0:04a9f72bbca7 2326
stevep 0:04a9f72bbca7 2327 /*!
stevep 0:04a9f72bbca7 2328 this method converts 'this' into sint
stevep 0:04a9f72bbca7 2329 */
stevep 0:04a9f72bbca7 2330 sint ToInt() const
stevep 0:04a9f72bbca7 2331 {
stevep 0:04a9f72bbca7 2332 sint result;
stevep 0:04a9f72bbca7 2333
stevep 0:04a9f72bbca7 2334 ToInt(result);
stevep 0:04a9f72bbca7 2335
stevep 0:04a9f72bbca7 2336 return result;
stevep 0:04a9f72bbca7 2337 }
stevep 0:04a9f72bbca7 2338
stevep 0:04a9f72bbca7 2339
stevep 0:04a9f72bbca7 2340 /*!
stevep 0:04a9f72bbca7 2341 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2342
stevep 0:04a9f72bbca7 2343 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2344 */
stevep 0:04a9f72bbca7 2345 uint ToInt(uint & result) const
stevep 0:04a9f72bbca7 2346 {
stevep 0:04a9f72bbca7 2347 return ToUInt(result);
stevep 0:04a9f72bbca7 2348 }
stevep 0:04a9f72bbca7 2349
stevep 0:04a9f72bbca7 2350
stevep 0:04a9f72bbca7 2351 /*!
stevep 0:04a9f72bbca7 2352 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2353
stevep 0:04a9f72bbca7 2354 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2355 */
stevep 0:04a9f72bbca7 2356 uint ToInt(sint & result) const
stevep 0:04a9f72bbca7 2357 {
stevep 0:04a9f72bbca7 2358 uint result_uint;
stevep 0:04a9f72bbca7 2359
stevep 0:04a9f72bbca7 2360 uint c = ToUIntOrInt(result_uint);
stevep 0:04a9f72bbca7 2361 result = sint(result_uint);
stevep 0:04a9f72bbca7 2362
stevep 0:04a9f72bbca7 2363 if( c )
stevep 0:04a9f72bbca7 2364 return 1;
stevep 0:04a9f72bbca7 2365
stevep 0:04a9f72bbca7 2366 uint mask = 0;
stevep 0:04a9f72bbca7 2367
stevep 0:04a9f72bbca7 2368 if( IsSign() )
stevep 0:04a9f72bbca7 2369 {
stevep 0:04a9f72bbca7 2370 mask = TTMATH_UINT_MAX_VALUE;
stevep 0:04a9f72bbca7 2371 result = -result;
stevep 0:04a9f72bbca7 2372 }
stevep 0:04a9f72bbca7 2373
stevep 0:04a9f72bbca7 2374 return ((result & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1;
stevep 0:04a9f72bbca7 2375 }
stevep 0:04a9f72bbca7 2376
stevep 0:04a9f72bbca7 2377
stevep 0:04a9f72bbca7 2378 private:
stevep 0:04a9f72bbca7 2379
stevep 0:04a9f72bbca7 2380 /*!
stevep 0:04a9f72bbca7 2381 an auxiliary method for converting 'this' into 'result'
stevep 0:04a9f72bbca7 2382
stevep 0:04a9f72bbca7 2383 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2384 */
stevep 0:04a9f72bbca7 2385 template<uint int_size>
stevep 0:04a9f72bbca7 2386 uint ToUIntOrInt(UInt<int_size> & result) const
stevep 0:04a9f72bbca7 2387 {
stevep 0:04a9f72bbca7 2388 result.SetZero();
stevep 0:04a9f72bbca7 2389
stevep 0:04a9f72bbca7 2390 if( IsZero() )
stevep 0:04a9f72bbca7 2391 return 0;
stevep 0:04a9f72bbca7 2392
stevep 0:04a9f72bbca7 2393 sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 2394
stevep 0:04a9f72bbca7 2395 if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 2396 // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
stevep 0:04a9f72bbca7 2397 // into the 'UInt<int_size>' type (it's too big)
stevep 0:04a9f72bbca7 2398 return 1;
stevep 0:04a9f72bbca7 2399
stevep 0:04a9f72bbca7 2400 if( exponent <= maxbit )
stevep 0:04a9f72bbca7 2401 // our value is from range (-1,1) and we return zero
stevep 0:04a9f72bbca7 2402 return 0;
stevep 0:04a9f72bbca7 2403
stevep 0:04a9f72bbca7 2404 sint how_many_bits = exponent.ToInt();
stevep 0:04a9f72bbca7 2405
stevep 0:04a9f72bbca7 2406 if( how_many_bits < 0 )
stevep 0:04a9f72bbca7 2407 {
stevep 0:04a9f72bbca7 2408 how_many_bits = -how_many_bits;
stevep 0:04a9f72bbca7 2409 uint index = how_many_bits / TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 2410
stevep 0:04a9f72bbca7 2411 UInt<man> mantissa_temp(mantissa);
stevep 0:04a9f72bbca7 2412 mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
stevep 0:04a9f72bbca7 2413
stevep 0:04a9f72bbca7 2414 for(uint i=index, a=0 ; i<man ; ++i,++a)
stevep 0:04a9f72bbca7 2415 result.table[a] = mantissa_temp.table[i];
stevep 0:04a9f72bbca7 2416 }
stevep 0:04a9f72bbca7 2417 else
stevep 0:04a9f72bbca7 2418 {
stevep 0:04a9f72bbca7 2419 uint index = how_many_bits / TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 2420
stevep 0:04a9f72bbca7 2421 if( index + (man-1) < int_size )
stevep 0:04a9f72bbca7 2422 {
stevep 0:04a9f72bbca7 2423 // above 'if' is always true
stevep 0:04a9f72bbca7 2424 // this is only to get rid of a warning "warning: array subscript is above array bounds"
stevep 0:04a9f72bbca7 2425 // (from gcc)
stevep 0:04a9f72bbca7 2426 // we checked the condition there: "if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )"
stevep 0:04a9f72bbca7 2427 // but gcc doesn't understand our types - exponent is Int<>
stevep 0:04a9f72bbca7 2428
stevep 0:04a9f72bbca7 2429 for(uint i=0 ; i<man ; ++i)
stevep 0:04a9f72bbca7 2430 result.table[index+i] = mantissa.table[i];
stevep 0:04a9f72bbca7 2431 }
stevep 0:04a9f72bbca7 2432
stevep 0:04a9f72bbca7 2433 result.Rcl( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
stevep 0:04a9f72bbca7 2434 }
stevep 0:04a9f72bbca7 2435
stevep 0:04a9f72bbca7 2436 return 0;
stevep 0:04a9f72bbca7 2437 }
stevep 0:04a9f72bbca7 2438
stevep 0:04a9f72bbca7 2439
stevep 0:04a9f72bbca7 2440 public:
stevep 0:04a9f72bbca7 2441
stevep 0:04a9f72bbca7 2442 /*!
stevep 0:04a9f72bbca7 2443 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2444
stevep 0:04a9f72bbca7 2445 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2446 */
stevep 0:04a9f72bbca7 2447 template<uint int_size>
stevep 0:04a9f72bbca7 2448 uint ToUInt(UInt<int_size> & result) const
stevep 0:04a9f72bbca7 2449 {
stevep 0:04a9f72bbca7 2450 uint c = ToUIntOrInt(result);
stevep 0:04a9f72bbca7 2451
stevep 0:04a9f72bbca7 2452 if( c )
stevep 0:04a9f72bbca7 2453 return 1;
stevep 0:04a9f72bbca7 2454
stevep 0:04a9f72bbca7 2455 if( IsSign() )
stevep 0:04a9f72bbca7 2456 return 1;
stevep 0:04a9f72bbca7 2457
stevep 0:04a9f72bbca7 2458 return 0;
stevep 0:04a9f72bbca7 2459 }
stevep 0:04a9f72bbca7 2460
stevep 0:04a9f72bbca7 2461
stevep 0:04a9f72bbca7 2462 /*!
stevep 0:04a9f72bbca7 2463 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2464
stevep 0:04a9f72bbca7 2465 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2466 */
stevep 0:04a9f72bbca7 2467 template<uint int_size>
stevep 0:04a9f72bbca7 2468 uint ToInt(UInt<int_size> & result) const
stevep 0:04a9f72bbca7 2469 {
stevep 0:04a9f72bbca7 2470 return ToUInt(result);
stevep 0:04a9f72bbca7 2471 }
stevep 0:04a9f72bbca7 2472
stevep 0:04a9f72bbca7 2473
stevep 0:04a9f72bbca7 2474 /*!
stevep 0:04a9f72bbca7 2475 this method converts 'this' into 'result'
stevep 0:04a9f72bbca7 2476
stevep 0:04a9f72bbca7 2477 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 2478 */
stevep 0:04a9f72bbca7 2479 template<uint int_size>
stevep 0:04a9f72bbca7 2480 uint ToInt(Int<int_size> & result) const
stevep 0:04a9f72bbca7 2481 {
stevep 0:04a9f72bbca7 2482 uint c = ToUIntOrInt(result);
stevep 0:04a9f72bbca7 2483
stevep 0:04a9f72bbca7 2484 if( c )
stevep 0:04a9f72bbca7 2485 return 1;
stevep 0:04a9f72bbca7 2486
stevep 0:04a9f72bbca7 2487 uint mask = 0;
stevep 0:04a9f72bbca7 2488
stevep 0:04a9f72bbca7 2489 if( IsSign() )
stevep 0:04a9f72bbca7 2490 {
stevep 0:04a9f72bbca7 2491 result.ChangeSign();
stevep 0:04a9f72bbca7 2492 mask = TTMATH_UINT_MAX_VALUE;
stevep 0:04a9f72bbca7 2493 }
stevep 0:04a9f72bbca7 2494
stevep 0:04a9f72bbca7 2495 return ((result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT))? 0 : 1;
stevep 0:04a9f72bbca7 2496 }
stevep 0:04a9f72bbca7 2497
stevep 0:04a9f72bbca7 2498
stevep 0:04a9f72bbca7 2499 /*!
stevep 0:04a9f72bbca7 2500 a method for converting 'uint' to this class
stevep 0:04a9f72bbca7 2501 */
stevep 0:04a9f72bbca7 2502 uint FromUInt(uint value)
stevep 0:04a9f72bbca7 2503 {
stevep 0:04a9f72bbca7 2504 if( value == 0 )
stevep 0:04a9f72bbca7 2505 {
stevep 0:04a9f72bbca7 2506 SetZero();
stevep 0:04a9f72bbca7 2507 return 0;
stevep 0:04a9f72bbca7 2508 }
stevep 0:04a9f72bbca7 2509
stevep 0:04a9f72bbca7 2510 info = 0;
stevep 0:04a9f72bbca7 2511
stevep 0:04a9f72bbca7 2512 for(uint i=0 ; i<man-1 ; ++i)
stevep 0:04a9f72bbca7 2513 mantissa.table[i] = 0;
stevep 0:04a9f72bbca7 2514
stevep 0:04a9f72bbca7 2515 mantissa.table[man-1] = value;
stevep 0:04a9f72bbca7 2516 exponent = -sint(man-1) * sint(TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 2517
stevep 0:04a9f72bbca7 2518 // there shouldn't be a carry because 'value' has the 'uint' type
stevep 0:04a9f72bbca7 2519 Standardizing();
stevep 0:04a9f72bbca7 2520
stevep 0:04a9f72bbca7 2521 return 0;
stevep 0:04a9f72bbca7 2522 }
stevep 0:04a9f72bbca7 2523
stevep 0:04a9f72bbca7 2524
stevep 0:04a9f72bbca7 2525 /*!
stevep 0:04a9f72bbca7 2526 a method for converting 'uint' to this class
stevep 0:04a9f72bbca7 2527 */
stevep 0:04a9f72bbca7 2528 uint FromInt(uint value)
stevep 0:04a9f72bbca7 2529 {
stevep 0:04a9f72bbca7 2530 return FromUInt(value);
stevep 0:04a9f72bbca7 2531 }
stevep 0:04a9f72bbca7 2532
stevep 0:04a9f72bbca7 2533
stevep 0:04a9f72bbca7 2534 /*!
stevep 0:04a9f72bbca7 2535 a method for converting 'sint' to this class
stevep 0:04a9f72bbca7 2536 */
stevep 0:04a9f72bbca7 2537 uint FromInt(sint value)
stevep 0:04a9f72bbca7 2538 {
stevep 0:04a9f72bbca7 2539 bool is_sign = false;
stevep 0:04a9f72bbca7 2540
stevep 0:04a9f72bbca7 2541 if( value < 0 )
stevep 0:04a9f72bbca7 2542 {
stevep 0:04a9f72bbca7 2543 value = -value;
stevep 0:04a9f72bbca7 2544 is_sign = true;
stevep 0:04a9f72bbca7 2545 }
stevep 0:04a9f72bbca7 2546
stevep 0:04a9f72bbca7 2547 FromUInt(uint(value));
stevep 0:04a9f72bbca7 2548
stevep 0:04a9f72bbca7 2549 if( is_sign )
stevep 0:04a9f72bbca7 2550 SetSign();
stevep 0:04a9f72bbca7 2551
stevep 0:04a9f72bbca7 2552 return 0;
stevep 0:04a9f72bbca7 2553 }
stevep 0:04a9f72bbca7 2554
stevep 0:04a9f72bbca7 2555
stevep 0:04a9f72bbca7 2556
stevep 0:04a9f72bbca7 2557 /*!
stevep 0:04a9f72bbca7 2558 this method converts from standard double into this class
stevep 0:04a9f72bbca7 2559
stevep 0:04a9f72bbca7 2560 standard double means IEEE-754 floating point value with 64 bits
stevep 0:04a9f72bbca7 2561 it is as follows (from http://www.psc.edu/general/software/packages/ieee/ieee.html):
stevep 0:04a9f72bbca7 2562
stevep 0:04a9f72bbca7 2563 The IEEE double precision floating point standard representation requires
stevep 0:04a9f72bbca7 2564 a 64 bit word, which may be represented as numbered from 0 to 63, left to
stevep 0:04a9f72bbca7 2565 right. The first bit is the sign bit, S, the next eleven bits are the
stevep 0:04a9f72bbca7 2566 exponent bits, 'E', and the final 52 bits are the fraction 'F':
stevep 0:04a9f72bbca7 2567
stevep 0:04a9f72bbca7 2568 S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
stevep 0:04a9f72bbca7 2569 0 1 11 12 63
stevep 0:04a9f72bbca7 2570
stevep 0:04a9f72bbca7 2571 The value V represented by the word may be determined as follows:
stevep 0:04a9f72bbca7 2572
stevep 0:04a9f72bbca7 2573 * If E=2047 and F is nonzero, then V=NaN ("Not a number")
stevep 0:04a9f72bbca7 2574 * If E=2047 and F is zero and S is 1, then V=-Infinity
stevep 0:04a9f72bbca7 2575 * If E=2047 and F is zero and S is 0, then V=Infinity
stevep 0:04a9f72bbca7 2576 * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended
stevep 0:04a9f72bbca7 2577 to represent the binary number created by prefixing F with an implicit
stevep 0:04a9f72bbca7 2578 leading 1 and a binary point.
stevep 0:04a9f72bbca7 2579 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are
stevep 0:04a9f72bbca7 2580 "unnormalized" values.
stevep 0:04a9f72bbca7 2581 * If E=0 and F is zero and S is 1, then V=-0
stevep 0:04a9f72bbca7 2582 * If E=0 and F is zero and S is 0, then V=0
stevep 0:04a9f72bbca7 2583 */
stevep 0:04a9f72bbca7 2584
stevep 0:04a9f72bbca7 2585 #ifdef TTMATH_PLATFORM32
stevep 0:04a9f72bbca7 2586
stevep 0:04a9f72bbca7 2587 uint FromDouble(double value)
stevep 0:04a9f72bbca7 2588 {
stevep 0:04a9f72bbca7 2589 // I am not sure what will be on a platform which has
stevep 0:04a9f72bbca7 2590 // a different endianness... but we use this library only
stevep 0:04a9f72bbca7 2591 // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
stevep 0:04a9f72bbca7 2592 union
stevep 0:04a9f72bbca7 2593 {
stevep 0:04a9f72bbca7 2594 double d;
stevep 0:04a9f72bbca7 2595 uint u[2]; // two 32bit words
stevep 0:04a9f72bbca7 2596 } temp;
stevep 0:04a9f72bbca7 2597
stevep 0:04a9f72bbca7 2598 temp.d = value;
stevep 0:04a9f72bbca7 2599
stevep 0:04a9f72bbca7 2600 sint e = ( temp.u[1] & 0x7FF00000u) >> 20;
stevep 0:04a9f72bbca7 2601 uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21);
stevep 0:04a9f72bbca7 2602 uint m2 = temp.u[0] << 11;
stevep 0:04a9f72bbca7 2603
stevep 0:04a9f72bbca7 2604 if( e == 2047 )
stevep 0:04a9f72bbca7 2605 {
stevep 0:04a9f72bbca7 2606 // If E=2047 and F is nonzero, then V=NaN ("Not a number")
stevep 0:04a9f72bbca7 2607 // If E=2047 and F is zero and S is 1, then V=-Infinity
stevep 0:04a9f72bbca7 2608 // If E=2047 and F is zero and S is 0, then V=Infinity
stevep 0:04a9f72bbca7 2609
stevep 0:04a9f72bbca7 2610 // we do not support -Infinity and +Infinity
stevep 0:04a9f72bbca7 2611 // we assume that there is always NaN
stevep 0:04a9f72bbca7 2612
stevep 0:04a9f72bbca7 2613 SetNan();
stevep 0:04a9f72bbca7 2614 }
stevep 0:04a9f72bbca7 2615 else
stevep 0:04a9f72bbca7 2616 if( e > 0 )
stevep 0:04a9f72bbca7 2617 {
stevep 0:04a9f72bbca7 2618 // If 0<E<2047 then
stevep 0:04a9f72bbca7 2619 // V=(-1)**S * 2 ** (E-1023) * (1.F)
stevep 0:04a9f72bbca7 2620 // where "1.F" is intended to represent the binary number
stevep 0:04a9f72bbca7 2621 // created by prefixing F with an implicit leading 1 and a binary point.
stevep 0:04a9f72bbca7 2622
stevep 0:04a9f72bbca7 2623 FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
stevep 0:04a9f72bbca7 2624 e - 1023 - man*TTMATH_BITS_PER_UINT + 1, 0x80000000u,
stevep 0:04a9f72bbca7 2625 m1, m2);
stevep 0:04a9f72bbca7 2626
stevep 0:04a9f72bbca7 2627 // we do not have to call Standardizing() here
stevep 0:04a9f72bbca7 2628 // because the mantissa will have the highest bit set
stevep 0:04a9f72bbca7 2629 }
stevep 0:04a9f72bbca7 2630 else
stevep 0:04a9f72bbca7 2631 {
stevep 0:04a9f72bbca7 2632 // e == 0
stevep 0:04a9f72bbca7 2633
stevep 0:04a9f72bbca7 2634 if( m1 != 0 || m2 != 0 )
stevep 0:04a9f72bbca7 2635 {
stevep 0:04a9f72bbca7 2636 // If E=0 and F is nonzero,
stevep 0:04a9f72bbca7 2637 // then V=(-1)**S * 2 ** (-1022) * (0.F)
stevep 0:04a9f72bbca7 2638 // These are "unnormalized" values.
stevep 0:04a9f72bbca7 2639
stevep 0:04a9f72bbca7 2640 UInt<2> m;
stevep 0:04a9f72bbca7 2641 m.table[1] = m1;
stevep 0:04a9f72bbca7 2642 m.table[0] = m2;
stevep 0:04a9f72bbca7 2643 uint moved = m.CompensationToLeft();
stevep 0:04a9f72bbca7 2644
stevep 0:04a9f72bbca7 2645 FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0,
stevep 0:04a9f72bbca7 2646 e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0,
stevep 0:04a9f72bbca7 2647 m.table[1], m.table[0]);
stevep 0:04a9f72bbca7 2648 }
stevep 0:04a9f72bbca7 2649 else
stevep 0:04a9f72bbca7 2650 {
stevep 0:04a9f72bbca7 2651 // If E=0 and F is zero and S is 1, then V=-0
stevep 0:04a9f72bbca7 2652 // If E=0 and F is zero and S is 0, then V=0
stevep 0:04a9f72bbca7 2653
stevep 0:04a9f72bbca7 2654 // we do not support -0 or 0, only is one 0
stevep 0:04a9f72bbca7 2655 SetZero();
stevep 0:04a9f72bbca7 2656 }
stevep 0:04a9f72bbca7 2657 }
stevep 0:04a9f72bbca7 2658
stevep 0:04a9f72bbca7 2659 return 0; // never be a carry
stevep 0:04a9f72bbca7 2660 }
stevep 0:04a9f72bbca7 2661
stevep 0:04a9f72bbca7 2662
stevep 0:04a9f72bbca7 2663 private:
stevep 0:04a9f72bbca7 2664
stevep 0:04a9f72bbca7 2665 void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2)
stevep 0:04a9f72bbca7 2666 {
stevep 0:04a9f72bbca7 2667 exponent = e;
stevep 0:04a9f72bbca7 2668
stevep 0:04a9f72bbca7 2669 if( man > 1 )
stevep 0:04a9f72bbca7 2670 {
stevep 0:04a9f72bbca7 2671 mantissa.table[man-1] = m1 | mhighest;
stevep 0:04a9f72bbca7 2672 mantissa.table[sint(man-2)] = m2;
stevep 0:04a9f72bbca7 2673 // although man>1 we're using casting into sint
stevep 0:04a9f72bbca7 2674 // to get rid from a warning which generates Microsoft Visual:
stevep 0:04a9f72bbca7 2675 // warning C4307: '*' : integral constant overflow
stevep 0:04a9f72bbca7 2676
stevep 0:04a9f72bbca7 2677 for(uint i=0 ; i<man-2 ; ++i)
stevep 0:04a9f72bbca7 2678 mantissa.table[i] = 0;
stevep 0:04a9f72bbca7 2679 }
stevep 0:04a9f72bbca7 2680 else
stevep 0:04a9f72bbca7 2681 {
stevep 0:04a9f72bbca7 2682 mantissa.table[0] = m1 | mhighest;
stevep 0:04a9f72bbca7 2683 }
stevep 0:04a9f72bbca7 2684
stevep 0:04a9f72bbca7 2685 info = 0;
stevep 0:04a9f72bbca7 2686
stevep 0:04a9f72bbca7 2687 // the value should be different from zero
stevep 0:04a9f72bbca7 2688 TTMATH_ASSERT( mantissa.IsZero() == false )
stevep 0:04a9f72bbca7 2689
stevep 0:04a9f72bbca7 2690 if( is_sign )
stevep 0:04a9f72bbca7 2691 SetSign();
stevep 0:04a9f72bbca7 2692 }
stevep 0:04a9f72bbca7 2693
stevep 0:04a9f72bbca7 2694
stevep 0:04a9f72bbca7 2695 #else
stevep 0:04a9f72bbca7 2696
stevep 0:04a9f72bbca7 2697 public:
stevep 0:04a9f72bbca7 2698
stevep 0:04a9f72bbca7 2699 // 64bit platforms
stevep 0:04a9f72bbca7 2700 uint FromDouble(double value)
stevep 0:04a9f72bbca7 2701 {
stevep 0:04a9f72bbca7 2702 // I am not sure what will be on a plaltform which has
stevep 0:04a9f72bbca7 2703 // a different endianness... but we use this library only
stevep 0:04a9f72bbca7 2704 // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
stevep 0:04a9f72bbca7 2705 union
stevep 0:04a9f72bbca7 2706 {
stevep 0:04a9f72bbca7 2707 double d;
stevep 0:04a9f72bbca7 2708 uint u; // one 64bit word
stevep 0:04a9f72bbca7 2709 } temp;
stevep 0:04a9f72bbca7 2710
stevep 0:04a9f72bbca7 2711 temp.d = value;
stevep 0:04a9f72bbca7 2712
stevep 0:04a9f72bbca7 2713 sint e = (temp.u & 0x7FF0000000000000ul) >> 52;
stevep 0:04a9f72bbca7 2714 uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11;
stevep 0:04a9f72bbca7 2715
stevep 0:04a9f72bbca7 2716 if( e == 2047 )
stevep 0:04a9f72bbca7 2717 {
stevep 0:04a9f72bbca7 2718 // If E=2047 and F is nonzero, then V=NaN ("Not a number")
stevep 0:04a9f72bbca7 2719 // If E=2047 and F is zero and S is 1, then V=-Infinity
stevep 0:04a9f72bbca7 2720 // If E=2047 and F is zero and S is 0, then V=Infinity
stevep 0:04a9f72bbca7 2721
stevep 0:04a9f72bbca7 2722 // we do not support -Infinity and +Infinity
stevep 0:04a9f72bbca7 2723 // we assume that there is always NaN
stevep 0:04a9f72bbca7 2724
stevep 0:04a9f72bbca7 2725 SetNan();
stevep 0:04a9f72bbca7 2726 }
stevep 0:04a9f72bbca7 2727 else
stevep 0:04a9f72bbca7 2728 if( e > 0 )
stevep 0:04a9f72bbca7 2729 {
stevep 0:04a9f72bbca7 2730 // If 0<E<2047 then
stevep 0:04a9f72bbca7 2731 // V=(-1)**S * 2 ** (E-1023) * (1.F)
stevep 0:04a9f72bbca7 2732 // where "1.F" is intended to represent the binary number
stevep 0:04a9f72bbca7 2733 // created by prefixing F with an implicit leading 1 and a binary point.
stevep 0:04a9f72bbca7 2734
stevep 0:04a9f72bbca7 2735 FromDouble_SetExpAndMan((temp.u & 0x8000000000000000ul) != 0,
stevep 0:04a9f72bbca7 2736 e - 1023 - man*TTMATH_BITS_PER_UINT + 1,
stevep 0:04a9f72bbca7 2737 0x8000000000000000ul, m);
stevep 0:04a9f72bbca7 2738
stevep 0:04a9f72bbca7 2739 // we do not have to call Standardizing() here
stevep 0:04a9f72bbca7 2740 // because the mantissa will have the highest bit set
stevep 0:04a9f72bbca7 2741 }
stevep 0:04a9f72bbca7 2742 else
stevep 0:04a9f72bbca7 2743 {
stevep 0:04a9f72bbca7 2744 // e == 0
stevep 0:04a9f72bbca7 2745
stevep 0:04a9f72bbca7 2746 if( m != 0 )
stevep 0:04a9f72bbca7 2747 {
stevep 0:04a9f72bbca7 2748 // If E=0 and F is nonzero,
stevep 0:04a9f72bbca7 2749 // then V=(-1)**S * 2 ** (-1022) * (0.F)
stevep 0:04a9f72bbca7 2750 // These are "unnormalized" values.
stevep 0:04a9f72bbca7 2751
stevep 0:04a9f72bbca7 2752 FromDouble_SetExpAndMan(bool(temp.u & 0x8000000000000000ul),
stevep 0:04a9f72bbca7 2753 e - 1022 - man*TTMATH_BITS_PER_UINT + 1, 0, m);
stevep 0:04a9f72bbca7 2754 Standardizing();
stevep 0:04a9f72bbca7 2755 }
stevep 0:04a9f72bbca7 2756 else
stevep 0:04a9f72bbca7 2757 {
stevep 0:04a9f72bbca7 2758 // If E=0 and F is zero and S is 1, then V=-0
stevep 0:04a9f72bbca7 2759 // If E=0 and F is zero and S is 0, then V=0
stevep 0:04a9f72bbca7 2760
stevep 0:04a9f72bbca7 2761 // we do not support -0 or 0, only is one 0
stevep 0:04a9f72bbca7 2762 SetZero();
stevep 0:04a9f72bbca7 2763 }
stevep 0:04a9f72bbca7 2764 }
stevep 0:04a9f72bbca7 2765
stevep 0:04a9f72bbca7 2766 return 0; // never be a carry
stevep 0:04a9f72bbca7 2767 }
stevep 0:04a9f72bbca7 2768
stevep 0:04a9f72bbca7 2769 private:
stevep 0:04a9f72bbca7 2770
stevep 0:04a9f72bbca7 2771 void FromDouble_SetExpAndMan(bool is_sign, sint e, uint mhighest, uint m)
stevep 0:04a9f72bbca7 2772 {
stevep 0:04a9f72bbca7 2773 exponent = e;
stevep 0:04a9f72bbca7 2774 mantissa.table[man-1] = m | mhighest;
stevep 0:04a9f72bbca7 2775
stevep 0:04a9f72bbca7 2776 for(uint i=0 ; i<man-1 ; ++i)
stevep 0:04a9f72bbca7 2777 mantissa.table[i] = 0;
stevep 0:04a9f72bbca7 2778
stevep 0:04a9f72bbca7 2779 info = 0;
stevep 0:04a9f72bbca7 2780
stevep 0:04a9f72bbca7 2781 // the value should be different from zero
stevep 0:04a9f72bbca7 2782 TTMATH_ASSERT( mantissa.IsZero() == false )
stevep 0:04a9f72bbca7 2783
stevep 0:04a9f72bbca7 2784 if( is_sign )
stevep 0:04a9f72bbca7 2785 SetSign();
stevep 0:04a9f72bbca7 2786 }
stevep 0:04a9f72bbca7 2787
stevep 0:04a9f72bbca7 2788 #endif
stevep 0:04a9f72bbca7 2789
stevep 0:04a9f72bbca7 2790
stevep 0:04a9f72bbca7 2791 public:
stevep 0:04a9f72bbca7 2792
stevep 0:04a9f72bbca7 2793
stevep 0:04a9f72bbca7 2794 /*!
stevep 0:04a9f72bbca7 2795 this method converts from float to this class
stevep 0:04a9f72bbca7 2796 */
stevep 0:04a9f72bbca7 2797 uint FromFloat(float value)
stevep 0:04a9f72bbca7 2798 {
stevep 0:04a9f72bbca7 2799 return FromDouble(double(value));
stevep 0:04a9f72bbca7 2800 }
stevep 0:04a9f72bbca7 2801
stevep 0:04a9f72bbca7 2802
stevep 0:04a9f72bbca7 2803 /*!
stevep 0:04a9f72bbca7 2804 this method converts from this class into the 'double'
stevep 0:04a9f72bbca7 2805
stevep 0:04a9f72bbca7 2806 if the value is too big:
stevep 0:04a9f72bbca7 2807 'result' will be +/-infinity (depending on the sign)
stevep 0:04a9f72bbca7 2808 if the value is too small:
stevep 0:04a9f72bbca7 2809 'result' will be 0
stevep 0:04a9f72bbca7 2810 */
stevep 0:04a9f72bbca7 2811 double ToDouble() const
stevep 0:04a9f72bbca7 2812 {
stevep 0:04a9f72bbca7 2813 double result;
stevep 0:04a9f72bbca7 2814
stevep 0:04a9f72bbca7 2815 ToDouble(result);
stevep 0:04a9f72bbca7 2816
stevep 0:04a9f72bbca7 2817 return result;
stevep 0:04a9f72bbca7 2818 }
stevep 0:04a9f72bbca7 2819
stevep 0:04a9f72bbca7 2820
stevep 0:04a9f72bbca7 2821 private:
stevep 0:04a9f72bbca7 2822
stevep 0:04a9f72bbca7 2823
stevep 0:04a9f72bbca7 2824 /*!
stevep 0:04a9f72bbca7 2825 an auxiliary method to check if the float value is +/-infinity
stevep 0:04a9f72bbca7 2826 we provide this method because isinf(float) in only in C99 language
stevep 0:04a9f72bbca7 2827
stevep 0:04a9f72bbca7 2828 description taken from: http://www.psc.edu/general/software/packages/ieee/ieee.php
stevep 0:04a9f72bbca7 2829
stevep 0:04a9f72bbca7 2830 The IEEE single precision floating point standard representation requires a 32 bit word,
stevep 0:04a9f72bbca7 2831 which may be represented as numbered from 0 to 31, left to right.
stevep 0:04a9f72bbca7 2832 The first bit is the sign bit, S, the next eight bits are the exponent bits, 'E',
stevep 0:04a9f72bbca7 2833 and the final 23 bits are the fraction 'F':
stevep 0:04a9f72bbca7 2834
stevep 0:04a9f72bbca7 2835 S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
stevep 0:04a9f72bbca7 2836 0 1 8 9 31
stevep 0:04a9f72bbca7 2837
stevep 0:04a9f72bbca7 2838 The value V represented by the word may be determined as follows:
stevep 0:04a9f72bbca7 2839
stevep 0:04a9f72bbca7 2840 * If E=255 and F is nonzero, then V=NaN ("Not a number")
stevep 0:04a9f72bbca7 2841 * If E=255 and F is zero and S is 1, then V=-Infinity
stevep 0:04a9f72bbca7 2842 * If E=255 and F is zero and S is 0, then V=Infinity
stevep 0:04a9f72bbca7 2843 * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent
stevep 0:04a9f72bbca7 2844 the binary number created by prefixing F with an implicit leading 1 and a binary point.
stevep 0:04a9f72bbca7 2845 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
stevep 0:04a9f72bbca7 2846 * If E=0 and F is zero and S is 1, then V=-0
stevep 0:04a9f72bbca7 2847 * If E=0 and F is zero and S is 0, then V=0
stevep 0:04a9f72bbca7 2848 */
stevep 0:04a9f72bbca7 2849 bool IsInf(float value) const
stevep 0:04a9f72bbca7 2850 {
stevep 0:04a9f72bbca7 2851 // need testing on a 64 bit machine
stevep 0:04a9f72bbca7 2852
stevep 0:04a9f72bbca7 2853 union
stevep 0:04a9f72bbca7 2854 {
stevep 0:04a9f72bbca7 2855 float d;
stevep 0:04a9f72bbca7 2856 uint u;
stevep 0:04a9f72bbca7 2857 } temp;
stevep 0:04a9f72bbca7 2858
stevep 0:04a9f72bbca7 2859 temp.d = value;
stevep 0:04a9f72bbca7 2860
stevep 0:04a9f72bbca7 2861 if( ((temp.u >> 23) & 0xff) == 0xff )
stevep 0:04a9f72bbca7 2862 {
stevep 0:04a9f72bbca7 2863 if( (temp.u & 0x7FFFFF) == 0 )
stevep 0:04a9f72bbca7 2864 return true; // +/- infinity
stevep 0:04a9f72bbca7 2865 }
stevep 0:04a9f72bbca7 2866
stevep 0:04a9f72bbca7 2867 return false;
stevep 0:04a9f72bbca7 2868 }
stevep 0:04a9f72bbca7 2869
stevep 0:04a9f72bbca7 2870
stevep 0:04a9f72bbca7 2871 public:
stevep 0:04a9f72bbca7 2872
stevep 0:04a9f72bbca7 2873 /*!
stevep 0:04a9f72bbca7 2874 this method converts from this class into the 'float'
stevep 0:04a9f72bbca7 2875
stevep 0:04a9f72bbca7 2876 if the value is too big:
stevep 0:04a9f72bbca7 2877 'result' will be +/-infinity (depending on the sign)
stevep 0:04a9f72bbca7 2878 if the value is too small:
stevep 0:04a9f72bbca7 2879 'result' will be 0
stevep 0:04a9f72bbca7 2880 */
stevep 0:04a9f72bbca7 2881 float ToFloat() const
stevep 0:04a9f72bbca7 2882 {
stevep 0:04a9f72bbca7 2883 float result;
stevep 0:04a9f72bbca7 2884
stevep 0:04a9f72bbca7 2885 ToFloat(result);
stevep 0:04a9f72bbca7 2886
stevep 0:04a9f72bbca7 2887 return result;
stevep 0:04a9f72bbca7 2888 }
stevep 0:04a9f72bbca7 2889
stevep 0:04a9f72bbca7 2890
stevep 0:04a9f72bbca7 2891 /*!
stevep 0:04a9f72bbca7 2892 this method converts from this class into the 'float'
stevep 0:04a9f72bbca7 2893
stevep 0:04a9f72bbca7 2894 if the value is too big:
stevep 0:04a9f72bbca7 2895 'result' will be +/-infinity (depending on the sign)
stevep 0:04a9f72bbca7 2896 and the method returns 1
stevep 0:04a9f72bbca7 2897 if the value is too small:
stevep 0:04a9f72bbca7 2898 'result' will be 0
stevep 0:04a9f72bbca7 2899 and the method returns 1
stevep 0:04a9f72bbca7 2900 */
stevep 0:04a9f72bbca7 2901 uint ToFloat(float & result) const
stevep 0:04a9f72bbca7 2902 {
stevep 0:04a9f72bbca7 2903 double result_double;
stevep 0:04a9f72bbca7 2904
stevep 0:04a9f72bbca7 2905 uint c = ToDouble(result_double);
stevep 0:04a9f72bbca7 2906 result = float(result_double);
stevep 0:04a9f72bbca7 2907
stevep 0:04a9f72bbca7 2908 if( result == -0.0f )
stevep 0:04a9f72bbca7 2909 result = 0.0f;
stevep 0:04a9f72bbca7 2910
stevep 0:04a9f72bbca7 2911 if( c )
stevep 0:04a9f72bbca7 2912 return 1;
stevep 0:04a9f72bbca7 2913
stevep 0:04a9f72bbca7 2914 // although the result_double can have a correct value
stevep 0:04a9f72bbca7 2915 // but after converting to float there can be infinity
stevep 0:04a9f72bbca7 2916
stevep 0:04a9f72bbca7 2917 if( IsInf(result) )
stevep 0:04a9f72bbca7 2918 return 1;
stevep 0:04a9f72bbca7 2919
stevep 0:04a9f72bbca7 2920 if( result == 0.0f && result_double != 0.0 )
stevep 0:04a9f72bbca7 2921 // result_double was too small for float
stevep 0:04a9f72bbca7 2922 return 1;
stevep 0:04a9f72bbca7 2923
stevep 0:04a9f72bbca7 2924 return 0;
stevep 0:04a9f72bbca7 2925 }
stevep 0:04a9f72bbca7 2926
stevep 0:04a9f72bbca7 2927
stevep 0:04a9f72bbca7 2928 /*!
stevep 0:04a9f72bbca7 2929 this method converts from this class into the 'double'
stevep 0:04a9f72bbca7 2930
stevep 0:04a9f72bbca7 2931 if the value is too big:
stevep 0:04a9f72bbca7 2932 'result' will be +/-infinity (depending on the sign)
stevep 0:04a9f72bbca7 2933 and the method returns 1
stevep 0:04a9f72bbca7 2934 if the value is too small:
stevep 0:04a9f72bbca7 2935 'result' will be 0
stevep 0:04a9f72bbca7 2936 and the method returns 1
stevep 0:04a9f72bbca7 2937 */
stevep 0:04a9f72bbca7 2938 uint ToDouble(double & result) const
stevep 0:04a9f72bbca7 2939 {
stevep 0:04a9f72bbca7 2940 if( IsZero() )
stevep 0:04a9f72bbca7 2941 {
stevep 0:04a9f72bbca7 2942 result = 0.0;
stevep 0:04a9f72bbca7 2943 return 0;
stevep 0:04a9f72bbca7 2944 }
stevep 0:04a9f72bbca7 2945
stevep 0:04a9f72bbca7 2946 if( IsNan() )
stevep 0:04a9f72bbca7 2947 {
stevep 0:04a9f72bbca7 2948 result = ToDouble_SetDouble( false, 2047, 0, false, true);
stevep 0:04a9f72bbca7 2949
stevep 0:04a9f72bbca7 2950 return 0;
stevep 0:04a9f72bbca7 2951 }
stevep 0:04a9f72bbca7 2952
stevep 0:04a9f72bbca7 2953 sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1;
stevep 0:04a9f72bbca7 2954
stevep 0:04a9f72bbca7 2955 if( exponent >= 1024 - e_correction )
stevep 0:04a9f72bbca7 2956 {
stevep 0:04a9f72bbca7 2957 // +/- infinity
stevep 0:04a9f72bbca7 2958 result = ToDouble_SetDouble( IsSign(), 2047, 0, true);
stevep 0:04a9f72bbca7 2959
stevep 0:04a9f72bbca7 2960 return 1;
stevep 0:04a9f72bbca7 2961 }
stevep 0:04a9f72bbca7 2962 else
stevep 0:04a9f72bbca7 2963 if( exponent <= -1023 - 52 - e_correction )
stevep 0:04a9f72bbca7 2964 {
stevep 0:04a9f72bbca7 2965 // too small value - we assume that there'll be a zero
stevep 0:04a9f72bbca7 2966 result = 0;
stevep 0:04a9f72bbca7 2967
stevep 0:04a9f72bbca7 2968 // and return a carry
stevep 0:04a9f72bbca7 2969 return 1;
stevep 0:04a9f72bbca7 2970 }
stevep 0:04a9f72bbca7 2971
stevep 0:04a9f72bbca7 2972 sint e = exponent.ToInt() + e_correction;
stevep 0:04a9f72bbca7 2973
stevep 0:04a9f72bbca7 2974 if( e <= -1023 )
stevep 0:04a9f72bbca7 2975 {
stevep 0:04a9f72bbca7 2976 // -1023-52 < e <= -1023 (unnormalized value)
stevep 0:04a9f72bbca7 2977 result = ToDouble_SetDouble( IsSign(), 0, -(e + 1023));
stevep 0:04a9f72bbca7 2978 }
stevep 0:04a9f72bbca7 2979 else
stevep 0:04a9f72bbca7 2980 {
stevep 0:04a9f72bbca7 2981 // -1023 < e < 1024
stevep 0:04a9f72bbca7 2982 result = ToDouble_SetDouble( IsSign(), e + 1023, -1);
stevep 0:04a9f72bbca7 2983 }
stevep 0:04a9f72bbca7 2984
stevep 0:04a9f72bbca7 2985 return 0;
stevep 0:04a9f72bbca7 2986 }
stevep 0:04a9f72bbca7 2987
stevep 0:04a9f72bbca7 2988 private:
stevep 0:04a9f72bbca7 2989
stevep 0:04a9f72bbca7 2990 #ifdef TTMATH_PLATFORM32
stevep 0:04a9f72bbca7 2991
stevep 0:04a9f72bbca7 2992 // 32bit platforms
stevep 0:04a9f72bbca7 2993 double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
stevep 0:04a9f72bbca7 2994 {
stevep 0:04a9f72bbca7 2995 union
stevep 0:04a9f72bbca7 2996 {
stevep 0:04a9f72bbca7 2997 double d;
stevep 0:04a9f72bbca7 2998 uint u[2]; // two 32bit words
stevep 0:04a9f72bbca7 2999 } temp;
stevep 0:04a9f72bbca7 3000
stevep 0:04a9f72bbca7 3001 temp.u[0] = temp.u[1] = 0;
stevep 0:04a9f72bbca7 3002
stevep 0:04a9f72bbca7 3003 if( is_sign )
stevep 0:04a9f72bbca7 3004 temp.u[1] |= 0x80000000u;
stevep 0:04a9f72bbca7 3005
stevep 0:04a9f72bbca7 3006 temp.u[1] |= (e << 20) & 0x7FF00000u;
stevep 0:04a9f72bbca7 3007
stevep 0:04a9f72bbca7 3008 if( nan )
stevep 0:04a9f72bbca7 3009 {
stevep 0:04a9f72bbca7 3010 temp.u[0] |= 1;
stevep 0:04a9f72bbca7 3011 return temp.d;
stevep 0:04a9f72bbca7 3012 }
stevep 0:04a9f72bbca7 3013
stevep 0:04a9f72bbca7 3014 if( infinity )
stevep 0:04a9f72bbca7 3015 return temp.d;
stevep 0:04a9f72bbca7 3016
stevep 0:04a9f72bbca7 3017 UInt<2> m;
stevep 0:04a9f72bbca7 3018 m.table[1] = mantissa.table[man-1];
stevep 0:04a9f72bbca7 3019 m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0;
stevep 0:04a9f72bbca7 3020 // although man>1 we're using casting into sint
stevep 0:04a9f72bbca7 3021 // to get rid from a warning which generates Microsoft Visual:
stevep 0:04a9f72bbca7 3022 // warning C4307: '*' : integral constant overflow
stevep 0:04a9f72bbca7 3023
stevep 0:04a9f72bbca7 3024 m.Rcr( 12 + move );
stevep 0:04a9f72bbca7 3025 m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1)
stevep 0:04a9f72bbca7 3026
stevep 0:04a9f72bbca7 3027 temp.u[1] |= m.table[1];
stevep 0:04a9f72bbca7 3028 temp.u[0] |= m.table[0];
stevep 0:04a9f72bbca7 3029
stevep 0:04a9f72bbca7 3030 return temp.d;
stevep 0:04a9f72bbca7 3031 }
stevep 0:04a9f72bbca7 3032
stevep 0:04a9f72bbca7 3033 #else
stevep 0:04a9f72bbca7 3034
stevep 0:04a9f72bbca7 3035 // 64bit platforms
stevep 0:04a9f72bbca7 3036 double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const
stevep 0:04a9f72bbca7 3037 {
stevep 0:04a9f72bbca7 3038 union
stevep 0:04a9f72bbca7 3039 {
stevep 0:04a9f72bbca7 3040 double d;
stevep 0:04a9f72bbca7 3041 uint u; // 64bit word
stevep 0:04a9f72bbca7 3042 } temp;
stevep 0:04a9f72bbca7 3043
stevep 0:04a9f72bbca7 3044 temp.u = 0;
stevep 0:04a9f72bbca7 3045
stevep 0:04a9f72bbca7 3046 if( is_sign )
stevep 0:04a9f72bbca7 3047 temp.u |= 0x8000000000000000ul;
stevep 0:04a9f72bbca7 3048
stevep 0:04a9f72bbca7 3049 temp.u |= (e << 52) & 0x7FF0000000000000ul;
stevep 0:04a9f72bbca7 3050
stevep 0:04a9f72bbca7 3051 if( nan )
stevep 0:04a9f72bbca7 3052 {
stevep 0:04a9f72bbca7 3053 temp.u |= 1;
stevep 0:04a9f72bbca7 3054 return temp.d;
stevep 0:04a9f72bbca7 3055 }
stevep 0:04a9f72bbca7 3056
stevep 0:04a9f72bbca7 3057 if( infinity )
stevep 0:04a9f72bbca7 3058 return temp.d;
stevep 0:04a9f72bbca7 3059
stevep 0:04a9f72bbca7 3060 uint m = mantissa.table[man-1];
stevep 0:04a9f72bbca7 3061
stevep 0:04a9f72bbca7 3062 m >>= ( 12 + move );
stevep 0:04a9f72bbca7 3063 m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1)
stevep 0:04a9f72bbca7 3064 temp.u |= m;
stevep 0:04a9f72bbca7 3065
stevep 0:04a9f72bbca7 3066 return temp.d;
stevep 0:04a9f72bbca7 3067 }
stevep 0:04a9f72bbca7 3068
stevep 0:04a9f72bbca7 3069 #endif
stevep 0:04a9f72bbca7 3070
stevep 0:04a9f72bbca7 3071
stevep 0:04a9f72bbca7 3072 public:
stevep 0:04a9f72bbca7 3073
stevep 0:04a9f72bbca7 3074
stevep 0:04a9f72bbca7 3075 /*!
stevep 0:04a9f72bbca7 3076 an operator= for converting 'sint' to this class
stevep 0:04a9f72bbca7 3077 */
stevep 0:04a9f72bbca7 3078 Big<exp, man> & operator=(sint value)
stevep 0:04a9f72bbca7 3079 {
stevep 0:04a9f72bbca7 3080 FromInt(value);
stevep 0:04a9f72bbca7 3081
stevep 0:04a9f72bbca7 3082 return *this;
stevep 0:04a9f72bbca7 3083 }
stevep 0:04a9f72bbca7 3084
stevep 0:04a9f72bbca7 3085
stevep 0:04a9f72bbca7 3086 /*!
stevep 0:04a9f72bbca7 3087 an operator= for converting 'uint' to this class
stevep 0:04a9f72bbca7 3088 */
stevep 0:04a9f72bbca7 3089 Big<exp, man> & operator=(uint value)
stevep 0:04a9f72bbca7 3090 {
stevep 0:04a9f72bbca7 3091 FromUInt(value);
stevep 0:04a9f72bbca7 3092
stevep 0:04a9f72bbca7 3093 return *this;
stevep 0:04a9f72bbca7 3094 }
stevep 0:04a9f72bbca7 3095
stevep 0:04a9f72bbca7 3096
stevep 0:04a9f72bbca7 3097 /*!
stevep 0:04a9f72bbca7 3098 an operator= for converting 'float' to this class
stevep 0:04a9f72bbca7 3099 */
stevep 0:04a9f72bbca7 3100 Big<exp, man> & operator=(float value)
stevep 0:04a9f72bbca7 3101 {
stevep 0:04a9f72bbca7 3102 FromFloat(value);
stevep 0:04a9f72bbca7 3103
stevep 0:04a9f72bbca7 3104 return *this;
stevep 0:04a9f72bbca7 3105 }
stevep 0:04a9f72bbca7 3106
stevep 0:04a9f72bbca7 3107
stevep 0:04a9f72bbca7 3108 /*!
stevep 0:04a9f72bbca7 3109 an operator= for converting 'double' to this class
stevep 0:04a9f72bbca7 3110 */
stevep 0:04a9f72bbca7 3111 Big<exp, man> & operator=(double value)
stevep 0:04a9f72bbca7 3112 {
stevep 0:04a9f72bbca7 3113 FromDouble(value);
stevep 0:04a9f72bbca7 3114
stevep 0:04a9f72bbca7 3115 return *this;
stevep 0:04a9f72bbca7 3116 }
stevep 0:04a9f72bbca7 3117
stevep 0:04a9f72bbca7 3118
stevep 0:04a9f72bbca7 3119 /*!
stevep 0:04a9f72bbca7 3120 a constructor for converting 'sint' to this class
stevep 0:04a9f72bbca7 3121 */
stevep 0:04a9f72bbca7 3122 Big(sint value)
stevep 0:04a9f72bbca7 3123 {
stevep 0:04a9f72bbca7 3124 FromInt(value);
stevep 0:04a9f72bbca7 3125 }
stevep 0:04a9f72bbca7 3126
stevep 0:04a9f72bbca7 3127 /*!
stevep 0:04a9f72bbca7 3128 a constructor for converting 'uint' to this class
stevep 0:04a9f72bbca7 3129 */
stevep 0:04a9f72bbca7 3130 Big(uint value)
stevep 0:04a9f72bbca7 3131 {
stevep 0:04a9f72bbca7 3132 FromUInt(value);
stevep 0:04a9f72bbca7 3133 }
stevep 0:04a9f72bbca7 3134
stevep 0:04a9f72bbca7 3135
stevep 0:04a9f72bbca7 3136 /*!
stevep 0:04a9f72bbca7 3137 a constructor for converting 'double' to this class
stevep 0:04a9f72bbca7 3138 */
stevep 0:04a9f72bbca7 3139 Big(double value)
stevep 0:04a9f72bbca7 3140 {
stevep 0:04a9f72bbca7 3141 FromDouble(value);
stevep 0:04a9f72bbca7 3142 }
stevep 0:04a9f72bbca7 3143
stevep 0:04a9f72bbca7 3144
stevep 0:04a9f72bbca7 3145 /*!
stevep 0:04a9f72bbca7 3146 a constructor for converting 'float' to this class
stevep 0:04a9f72bbca7 3147 */
stevep 0:04a9f72bbca7 3148 Big(float value)
stevep 0:04a9f72bbca7 3149 {
stevep 0:04a9f72bbca7 3150 FromFloat(value);
stevep 0:04a9f72bbca7 3151 }
stevep 0:04a9f72bbca7 3152
stevep 0:04a9f72bbca7 3153
stevep 0:04a9f72bbca7 3154 #ifdef TTMATH_PLATFORM32
stevep 0:04a9f72bbca7 3155
stevep 0:04a9f72bbca7 3156 /*!
stevep 0:04a9f72bbca7 3157 this method converts 'this' into 'result' (64 bit unsigned integer)
stevep 0:04a9f72bbca7 3158 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3159 */
stevep 0:04a9f72bbca7 3160 uint ToUInt(ulint & result) const
stevep 0:04a9f72bbca7 3161 {
stevep 0:04a9f72bbca7 3162 UInt<2> temp; // 64 bits container
stevep 0:04a9f72bbca7 3163
stevep 0:04a9f72bbca7 3164 uint c = ToUInt(temp);
stevep 0:04a9f72bbca7 3165 temp.ToUInt(result);
stevep 0:04a9f72bbca7 3166
stevep 0:04a9f72bbca7 3167 return c;
stevep 0:04a9f72bbca7 3168 }
stevep 0:04a9f72bbca7 3169
stevep 0:04a9f72bbca7 3170
stevep 0:04a9f72bbca7 3171 /*!
stevep 0:04a9f72bbca7 3172 this method converts 'this' into 'result' (64 bit unsigned integer)
stevep 0:04a9f72bbca7 3173 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3174 */
stevep 0:04a9f72bbca7 3175 uint ToInt(ulint & result) const
stevep 0:04a9f72bbca7 3176 {
stevep 0:04a9f72bbca7 3177 return ToUInt(result);
stevep 0:04a9f72bbca7 3178 }
stevep 0:04a9f72bbca7 3179
stevep 0:04a9f72bbca7 3180
stevep 0:04a9f72bbca7 3181 /*!
stevep 0:04a9f72bbca7 3182 this method converts 'this' into 'result' (64 bit unsigned integer)
stevep 0:04a9f72bbca7 3183 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3184 */
stevep 0:04a9f72bbca7 3185 uint ToInt(slint & result) const
stevep 0:04a9f72bbca7 3186 {
stevep 0:04a9f72bbca7 3187 Int<2> temp; // 64 bits container
stevep 0:04a9f72bbca7 3188
stevep 0:04a9f72bbca7 3189 uint c = ToInt(temp);
stevep 0:04a9f72bbca7 3190 temp.ToInt(result);
stevep 0:04a9f72bbca7 3191
stevep 0:04a9f72bbca7 3192 return c;
stevep 0:04a9f72bbca7 3193 }
stevep 0:04a9f72bbca7 3194
stevep 0:04a9f72bbca7 3195
stevep 0:04a9f72bbca7 3196 /*!
stevep 0:04a9f72bbca7 3197 a method for converting 'ulint' (64bit unsigned integer) to this class
stevep 0:04a9f72bbca7 3198 */
stevep 0:04a9f72bbca7 3199 uint FromUInt(ulint value)
stevep 0:04a9f72bbca7 3200 {
stevep 0:04a9f72bbca7 3201 if( value == 0 )
stevep 0:04a9f72bbca7 3202 {
stevep 0:04a9f72bbca7 3203 SetZero();
stevep 0:04a9f72bbca7 3204 return 0;
stevep 0:04a9f72bbca7 3205 }
stevep 0:04a9f72bbca7 3206
stevep 0:04a9f72bbca7 3207 info = 0;
stevep 0:04a9f72bbca7 3208
stevep 0:04a9f72bbca7 3209 if( man == 1 )
stevep 0:04a9f72bbca7 3210 {
stevep 0:04a9f72bbca7 3211 sint bit = mantissa.FindLeadingBitInWord(uint(value >> TTMATH_BITS_PER_UINT));
stevep 0:04a9f72bbca7 3212
stevep 0:04a9f72bbca7 3213 if( bit != -1 )
stevep 0:04a9f72bbca7 3214 {
stevep 0:04a9f72bbca7 3215 // the highest word from value is different from zero
stevep 0:04a9f72bbca7 3216 bit += 1;
stevep 0:04a9f72bbca7 3217 value >>= bit;
stevep 0:04a9f72bbca7 3218 exponent = bit;
stevep 0:04a9f72bbca7 3219 }
stevep 0:04a9f72bbca7 3220 else
stevep 0:04a9f72bbca7 3221 {
stevep 0:04a9f72bbca7 3222 exponent.SetZero();
stevep 0:04a9f72bbca7 3223 }
stevep 0:04a9f72bbca7 3224
stevep 0:04a9f72bbca7 3225 mantissa.table[0] = uint(value);
stevep 0:04a9f72bbca7 3226 }
stevep 0:04a9f72bbca7 3227 else
stevep 0:04a9f72bbca7 3228 {
stevep 0:04a9f72bbca7 3229 #ifdef _MSC_VER
stevep 0:04a9f72bbca7 3230 //warning C4307: '*' : integral constant overflow
stevep 0:04a9f72bbca7 3231 #pragma warning( disable: 4307 )
stevep 0:04a9f72bbca7 3232 #endif
stevep 0:04a9f72bbca7 3233
stevep 0:04a9f72bbca7 3234 // man >= 2
stevep 0:04a9f72bbca7 3235 mantissa.table[man-1] = uint(value >> TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 3236 mantissa.table[man-2] = uint(value);
stevep 0:04a9f72bbca7 3237
stevep 0:04a9f72bbca7 3238 #ifdef _MSC_VER
stevep 0:04a9f72bbca7 3239 //warning C4307: '*' : integral constant overflow
stevep 0:04a9f72bbca7 3240 #pragma warning( default: 4307 )
stevep 0:04a9f72bbca7 3241 #endif
stevep 0:04a9f72bbca7 3242
stevep 0:04a9f72bbca7 3243 exponent = -sint(man-2) * sint(TTMATH_BITS_PER_UINT);
stevep 0:04a9f72bbca7 3244
stevep 0:04a9f72bbca7 3245 for(uint i=0 ; i<man-2 ; ++i)
stevep 0:04a9f72bbca7 3246 mantissa.table[i] = 0;
stevep 0:04a9f72bbca7 3247 }
stevep 0:04a9f72bbca7 3248
stevep 0:04a9f72bbca7 3249 // there shouldn't be a carry because 'value' has the 'ulint' type
stevep 0:04a9f72bbca7 3250 // (we have sufficient exponent)
stevep 0:04a9f72bbca7 3251 Standardizing();
stevep 0:04a9f72bbca7 3252
stevep 0:04a9f72bbca7 3253 return 0;
stevep 0:04a9f72bbca7 3254 }
stevep 0:04a9f72bbca7 3255
stevep 0:04a9f72bbca7 3256
stevep 0:04a9f72bbca7 3257 /*!
stevep 0:04a9f72bbca7 3258 a method for converting 'ulint' (64bit unsigned integer) to this class
stevep 0:04a9f72bbca7 3259 */
stevep 0:04a9f72bbca7 3260 uint FromInt(ulint value)
stevep 0:04a9f72bbca7 3261 {
stevep 0:04a9f72bbca7 3262 return FromUInt(value);
stevep 0:04a9f72bbca7 3263 }
stevep 0:04a9f72bbca7 3264
stevep 0:04a9f72bbca7 3265
stevep 0:04a9f72bbca7 3266 /*!
stevep 0:04a9f72bbca7 3267 a method for converting 'slint' (64bit signed integer) to this class
stevep 0:04a9f72bbca7 3268 */
stevep 0:04a9f72bbca7 3269 uint FromInt(slint value)
stevep 0:04a9f72bbca7 3270 {
stevep 0:04a9f72bbca7 3271 bool is_sign = false;
stevep 0:04a9f72bbca7 3272
stevep 0:04a9f72bbca7 3273 if( value < 0 )
stevep 0:04a9f72bbca7 3274 {
stevep 0:04a9f72bbca7 3275 value = -value;
stevep 0:04a9f72bbca7 3276 is_sign = true;
stevep 0:04a9f72bbca7 3277 }
stevep 0:04a9f72bbca7 3278
stevep 0:04a9f72bbca7 3279 FromUInt(ulint(value));
stevep 0:04a9f72bbca7 3280
stevep 0:04a9f72bbca7 3281 if( is_sign )
stevep 0:04a9f72bbca7 3282 SetSign();
stevep 0:04a9f72bbca7 3283
stevep 0:04a9f72bbca7 3284 return 0;
stevep 0:04a9f72bbca7 3285 }
stevep 0:04a9f72bbca7 3286
stevep 0:04a9f72bbca7 3287
stevep 0:04a9f72bbca7 3288 /*!
stevep 0:04a9f72bbca7 3289 a constructor for converting 'ulint' (64bit unsigned integer) to this class
stevep 0:04a9f72bbca7 3290 */
stevep 0:04a9f72bbca7 3291 Big(ulint value)
stevep 0:04a9f72bbca7 3292 {
stevep 0:04a9f72bbca7 3293 FromUInt(value);
stevep 0:04a9f72bbca7 3294 }
stevep 0:04a9f72bbca7 3295
stevep 0:04a9f72bbca7 3296
stevep 0:04a9f72bbca7 3297 /*!
stevep 0:04a9f72bbca7 3298 an operator for converting 'ulint' (64bit unsigned integer) to this class
stevep 0:04a9f72bbca7 3299 */
stevep 0:04a9f72bbca7 3300 Big<exp, man> & operator=(ulint value)
stevep 0:04a9f72bbca7 3301 {
stevep 0:04a9f72bbca7 3302 FromUInt(value);
stevep 0:04a9f72bbca7 3303
stevep 0:04a9f72bbca7 3304 return *this;
stevep 0:04a9f72bbca7 3305 }
stevep 0:04a9f72bbca7 3306
stevep 0:04a9f72bbca7 3307
stevep 0:04a9f72bbca7 3308 /*!
stevep 0:04a9f72bbca7 3309 a constructor for converting 'slint' (64bit signed integer) to this class
stevep 0:04a9f72bbca7 3310 */
stevep 0:04a9f72bbca7 3311 Big(slint value)
stevep 0:04a9f72bbca7 3312 {
stevep 0:04a9f72bbca7 3313 FromInt(value);
stevep 0:04a9f72bbca7 3314 }
stevep 0:04a9f72bbca7 3315
stevep 0:04a9f72bbca7 3316
stevep 0:04a9f72bbca7 3317 /*!
stevep 0:04a9f72bbca7 3318 an operator for converting 'slint' (64bit signed integer) to this class
stevep 0:04a9f72bbca7 3319 */
stevep 0:04a9f72bbca7 3320 Big<exp, man> & operator=(slint value)
stevep 0:04a9f72bbca7 3321 {
stevep 0:04a9f72bbca7 3322 FromInt(value);
stevep 0:04a9f72bbca7 3323
stevep 0:04a9f72bbca7 3324 return *this;
stevep 0:04a9f72bbca7 3325 }
stevep 0:04a9f72bbca7 3326
stevep 0:04a9f72bbca7 3327 #endif
stevep 0:04a9f72bbca7 3328
stevep 0:04a9f72bbca7 3329
stevep 0:04a9f72bbca7 3330
stevep 0:04a9f72bbca7 3331 #ifdef TTMATH_PLATFORM64
stevep 0:04a9f72bbca7 3332
stevep 0:04a9f72bbca7 3333
stevep 0:04a9f72bbca7 3334 /*!
stevep 0:04a9f72bbca7 3335 this method converts 'this' into 'result' (32 bit unsigned integer)
stevep 0:04a9f72bbca7 3336 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3337 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3338 */
stevep 0:04a9f72bbca7 3339 uint ToUInt(unsigned int & result) const
stevep 0:04a9f72bbca7 3340 {
stevep 0:04a9f72bbca7 3341 uint result_uint;
stevep 0:04a9f72bbca7 3342
stevep 0:04a9f72bbca7 3343 uint c = ToUInt(result_uint);
stevep 0:04a9f72bbca7 3344 result = (unsigned int)result_uint;
stevep 0:04a9f72bbca7 3345
stevep 0:04a9f72bbca7 3346 if( c || result_uint != uint(result) )
stevep 0:04a9f72bbca7 3347 return 1;
stevep 0:04a9f72bbca7 3348
stevep 0:04a9f72bbca7 3349 return 0;
stevep 0:04a9f72bbca7 3350 }
stevep 0:04a9f72bbca7 3351
stevep 0:04a9f72bbca7 3352
stevep 0:04a9f72bbca7 3353 /*!
stevep 0:04a9f72bbca7 3354 this method converts 'this' into 'result' (32 bit unsigned integer)
stevep 0:04a9f72bbca7 3355 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3356 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3357 */
stevep 0:04a9f72bbca7 3358 uint ToInt(unsigned int & result) const
stevep 0:04a9f72bbca7 3359 {
stevep 0:04a9f72bbca7 3360 return ToUInt(result);
stevep 0:04a9f72bbca7 3361 }
stevep 0:04a9f72bbca7 3362
stevep 0:04a9f72bbca7 3363
stevep 0:04a9f72bbca7 3364 /*!
stevep 0:04a9f72bbca7 3365 this method converts 'this' into 'result' (32 bit signed integer)
stevep 0:04a9f72bbca7 3366 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3367 if the value is too big this method returns a carry (1)
stevep 0:04a9f72bbca7 3368 */
stevep 0:04a9f72bbca7 3369 uint ToInt(signed int & result) const
stevep 0:04a9f72bbca7 3370 {
stevep 0:04a9f72bbca7 3371 sint result_sint;
stevep 0:04a9f72bbca7 3372
stevep 0:04a9f72bbca7 3373 uint c = ToInt(result_sint);
stevep 0:04a9f72bbca7 3374 result = (signed int)result_sint;
stevep 0:04a9f72bbca7 3375
stevep 0:04a9f72bbca7 3376 if( c || result_sint != sint(result) )
stevep 0:04a9f72bbca7 3377 return 1;
stevep 0:04a9f72bbca7 3378
stevep 0:04a9f72bbca7 3379 return 0;
stevep 0:04a9f72bbca7 3380 }
stevep 0:04a9f72bbca7 3381
stevep 0:04a9f72bbca7 3382
stevep 0:04a9f72bbca7 3383 /*
stevep 0:04a9f72bbca7 3384 this method converts 32 bit unsigned int to this class
stevep 0:04a9f72bbca7 3385 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3386 */
stevep 0:04a9f72bbca7 3387 uint FromUInt(unsigned int value)
stevep 0:04a9f72bbca7 3388 {
stevep 0:04a9f72bbca7 3389 return FromUInt(uint(value));
stevep 0:04a9f72bbca7 3390 }
stevep 0:04a9f72bbca7 3391
stevep 0:04a9f72bbca7 3392
stevep 0:04a9f72bbca7 3393 /*
stevep 0:04a9f72bbca7 3394 this method converts 32 bit unsigned int to this class
stevep 0:04a9f72bbca7 3395 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3396 */
stevep 0:04a9f72bbca7 3397 uint FromInt(unsigned int value)
stevep 0:04a9f72bbca7 3398 {
stevep 0:04a9f72bbca7 3399 return FromUInt(uint(value));
stevep 0:04a9f72bbca7 3400 }
stevep 0:04a9f72bbca7 3401
stevep 0:04a9f72bbca7 3402
stevep 0:04a9f72bbca7 3403 /*
stevep 0:04a9f72bbca7 3404 this method converts 32 bit signed int to this class
stevep 0:04a9f72bbca7 3405 ***this method is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3406 */
stevep 0:04a9f72bbca7 3407 uint FromInt(signed int value)
stevep 0:04a9f72bbca7 3408 {
stevep 0:04a9f72bbca7 3409 return FromInt(sint(value));
stevep 0:04a9f72bbca7 3410 }
stevep 0:04a9f72bbca7 3411
stevep 0:04a9f72bbca7 3412
stevep 0:04a9f72bbca7 3413 /*!
stevep 0:04a9f72bbca7 3414 an operator= for converting 32 bit unsigned int to this class
stevep 0:04a9f72bbca7 3415 ***this operator is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3416 */
stevep 0:04a9f72bbca7 3417 Big<exp, man> & operator=(unsigned int value)
stevep 0:04a9f72bbca7 3418 {
stevep 0:04a9f72bbca7 3419 FromUInt(value);
stevep 0:04a9f72bbca7 3420
stevep 0:04a9f72bbca7 3421 return *this;
stevep 0:04a9f72bbca7 3422 }
stevep 0:04a9f72bbca7 3423
stevep 0:04a9f72bbca7 3424
stevep 0:04a9f72bbca7 3425 /*!
stevep 0:04a9f72bbca7 3426 a constructor for converting 32 bit unsigned int to this class
stevep 0:04a9f72bbca7 3427 ***this constructor is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3428 */
stevep 0:04a9f72bbca7 3429 Big(unsigned int value)
stevep 0:04a9f72bbca7 3430 {
stevep 0:04a9f72bbca7 3431 FromUInt(value);
stevep 0:04a9f72bbca7 3432 }
stevep 0:04a9f72bbca7 3433
stevep 0:04a9f72bbca7 3434
stevep 0:04a9f72bbca7 3435 /*!
stevep 0:04a9f72bbca7 3436 an operator for converting 32 bit signed int to this class
stevep 0:04a9f72bbca7 3437 ***this operator is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3438 */
stevep 0:04a9f72bbca7 3439 Big<exp, man> & operator=(signed int value)
stevep 0:04a9f72bbca7 3440 {
stevep 0:04a9f72bbca7 3441 FromInt(value);
stevep 0:04a9f72bbca7 3442
stevep 0:04a9f72bbca7 3443 return *this;
stevep 0:04a9f72bbca7 3444 }
stevep 0:04a9f72bbca7 3445
stevep 0:04a9f72bbca7 3446
stevep 0:04a9f72bbca7 3447 /*!
stevep 0:04a9f72bbca7 3448 a constructor for converting 32 bit signed int to this class
stevep 0:04a9f72bbca7 3449 ***this constructor is created only on a 64bit platform***
stevep 0:04a9f72bbca7 3450 */
stevep 0:04a9f72bbca7 3451 Big(signed int value)
stevep 0:04a9f72bbca7 3452 {
stevep 0:04a9f72bbca7 3453 FromInt(value);
stevep 0:04a9f72bbca7 3454 }
stevep 0:04a9f72bbca7 3455
stevep 0:04a9f72bbca7 3456 #endif
stevep 0:04a9f72bbca7 3457
stevep 0:04a9f72bbca7 3458
stevep 0:04a9f72bbca7 3459 private:
stevep 0:04a9f72bbca7 3460
stevep 0:04a9f72bbca7 3461 /*!
stevep 0:04a9f72bbca7 3462 an auxiliary method for converting from UInt and Int
stevep 0:04a9f72bbca7 3463
stevep 0:04a9f72bbca7 3464 we assume that there'll never be a carry here
stevep 0:04a9f72bbca7 3465 (we have an exponent and the value in Big can be bigger than
stevep 0:04a9f72bbca7 3466 that one from the UInt)
stevep 0:04a9f72bbca7 3467 */
stevep 0:04a9f72bbca7 3468 template<uint int_size>
stevep 0:04a9f72bbca7 3469 uint FromUIntOrInt(const UInt<int_size> & value, sint compensation)
stevep 0:04a9f72bbca7 3470 {
stevep 0:04a9f72bbca7 3471 uint minimum_size = (int_size < man)? int_size : man;
stevep 0:04a9f72bbca7 3472 exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation;
stevep 0:04a9f72bbca7 3473
stevep 0:04a9f72bbca7 3474 // copying the highest words
stevep 0:04a9f72bbca7 3475 uint i;
stevep 0:04a9f72bbca7 3476 for(i=1 ; i<=minimum_size ; ++i)
stevep 0:04a9f72bbca7 3477 mantissa.table[man-i] = value.table[int_size-i];
stevep 0:04a9f72bbca7 3478
stevep 0:04a9f72bbca7 3479 // setting the rest of mantissa.table into zero (if some has left)
stevep 0:04a9f72bbca7 3480 for( ; i<=man ; ++i)
stevep 0:04a9f72bbca7 3481 mantissa.table[man-i] = 0;
stevep 0:04a9f72bbca7 3482
stevep 0:04a9f72bbca7 3483 // the highest bit is either one or zero (when the whole mantissa is zero)
stevep 0:04a9f72bbca7 3484 // we can only call CorrectZero()
stevep 0:04a9f72bbca7 3485 CorrectZero();
stevep 0:04a9f72bbca7 3486
stevep 0:04a9f72bbca7 3487 return 0;
stevep 0:04a9f72bbca7 3488 }
stevep 0:04a9f72bbca7 3489
stevep 0:04a9f72bbca7 3490
stevep 0:04a9f72bbca7 3491 public:
stevep 0:04a9f72bbca7 3492
stevep 0:04a9f72bbca7 3493 /*!
stevep 0:04a9f72bbca7 3494 a method for converting from 'UInt<int_size>' to this class
stevep 0:04a9f72bbca7 3495 */
stevep 0:04a9f72bbca7 3496 template<uint int_size>
stevep 0:04a9f72bbca7 3497 uint FromUInt(UInt<int_size> value)
stevep 0:04a9f72bbca7 3498 {
stevep 0:04a9f72bbca7 3499 info = 0;
stevep 0:04a9f72bbca7 3500 sint compensation = (sint)value.CompensationToLeft();
stevep 0:04a9f72bbca7 3501
stevep 0:04a9f72bbca7 3502 return FromUIntOrInt(value, compensation);
stevep 0:04a9f72bbca7 3503 }
stevep 0:04a9f72bbca7 3504
stevep 0:04a9f72bbca7 3505
stevep 0:04a9f72bbca7 3506 /*!
stevep 0:04a9f72bbca7 3507 a method for converting from 'UInt<int_size>' to this class
stevep 0:04a9f72bbca7 3508 */
stevep 0:04a9f72bbca7 3509 template<uint int_size>
stevep 0:04a9f72bbca7 3510 uint FromInt(const UInt<int_size> & value)
stevep 0:04a9f72bbca7 3511 {
stevep 0:04a9f72bbca7 3512 return FromUInt(value);
stevep 0:04a9f72bbca7 3513 }
stevep 0:04a9f72bbca7 3514
stevep 0:04a9f72bbca7 3515
stevep 0:04a9f72bbca7 3516 /*!
stevep 0:04a9f72bbca7 3517 a method for converting from 'Int<int_size>' to this class
stevep 0:04a9f72bbca7 3518 */
stevep 0:04a9f72bbca7 3519 template<uint int_size>
stevep 0:04a9f72bbca7 3520 uint FromInt(Int<int_size> value)
stevep 0:04a9f72bbca7 3521 {
stevep 0:04a9f72bbca7 3522 info = 0;
stevep 0:04a9f72bbca7 3523 bool is_sign = false;
stevep 0:04a9f72bbca7 3524
stevep 0:04a9f72bbca7 3525 if( value.IsSign() )
stevep 0:04a9f72bbca7 3526 {
stevep 0:04a9f72bbca7 3527 value.ChangeSign();
stevep 0:04a9f72bbca7 3528 is_sign = true;
stevep 0:04a9f72bbca7 3529 }
stevep 0:04a9f72bbca7 3530
stevep 0:04a9f72bbca7 3531 sint compensation = (sint)value.CompensationToLeft();
stevep 0:04a9f72bbca7 3532 FromUIntOrInt(value, compensation);
stevep 0:04a9f72bbca7 3533
stevep 0:04a9f72bbca7 3534 if( is_sign )
stevep 0:04a9f72bbca7 3535 SetSign();
stevep 0:04a9f72bbca7 3536
stevep 0:04a9f72bbca7 3537 return 0;
stevep 0:04a9f72bbca7 3538 }
stevep 0:04a9f72bbca7 3539
stevep 0:04a9f72bbca7 3540
stevep 0:04a9f72bbca7 3541 /*!
stevep 0:04a9f72bbca7 3542 an operator= for converting from 'Int<int_size>' to this class
stevep 0:04a9f72bbca7 3543 */
stevep 0:04a9f72bbca7 3544 template<uint int_size>
stevep 0:04a9f72bbca7 3545 Big<exp,man> & operator=(const Int<int_size> & value)
stevep 0:04a9f72bbca7 3546 {
stevep 0:04a9f72bbca7 3547 FromInt(value);
stevep 0:04a9f72bbca7 3548
stevep 0:04a9f72bbca7 3549 return *this;
stevep 0:04a9f72bbca7 3550 }
stevep 0:04a9f72bbca7 3551
stevep 0:04a9f72bbca7 3552
stevep 0:04a9f72bbca7 3553 /*!
stevep 0:04a9f72bbca7 3554 a constructor for converting from 'Int<int_size>' to this class
stevep 0:04a9f72bbca7 3555 */
stevep 0:04a9f72bbca7 3556 template<uint int_size>
stevep 0:04a9f72bbca7 3557 Big(const Int<int_size> & value)
stevep 0:04a9f72bbca7 3558 {
stevep 0:04a9f72bbca7 3559 FromInt(value);
stevep 0:04a9f72bbca7 3560 }
stevep 0:04a9f72bbca7 3561
stevep 0:04a9f72bbca7 3562
stevep 0:04a9f72bbca7 3563 /*!
stevep 0:04a9f72bbca7 3564 an operator= for converting from 'UInt<int_size>' to this class
stevep 0:04a9f72bbca7 3565 */
stevep 0:04a9f72bbca7 3566 template<uint int_size>
stevep 0:04a9f72bbca7 3567 Big<exp,man> & operator=(const UInt<int_size> & value)
stevep 0:04a9f72bbca7 3568 {
stevep 0:04a9f72bbca7 3569 FromUInt(value);
stevep 0:04a9f72bbca7 3570
stevep 0:04a9f72bbca7 3571 return *this;
stevep 0:04a9f72bbca7 3572 }
stevep 0:04a9f72bbca7 3573
stevep 0:04a9f72bbca7 3574
stevep 0:04a9f72bbca7 3575 /*!
stevep 0:04a9f72bbca7 3576 a constructor for converting from 'UInt<int_size>' to this class
stevep 0:04a9f72bbca7 3577 */
stevep 0:04a9f72bbca7 3578 template<uint int_size>
stevep 0:04a9f72bbca7 3579 Big(const UInt<int_size> & value)
stevep 0:04a9f72bbca7 3580 {
stevep 0:04a9f72bbca7 3581 FromUInt(value);
stevep 0:04a9f72bbca7 3582 }
stevep 0:04a9f72bbca7 3583
stevep 0:04a9f72bbca7 3584
stevep 0:04a9f72bbca7 3585 /*!
stevep 0:04a9f72bbca7 3586 an operator= for converting from 'Big<another_exp, another_man>' to this class
stevep 0:04a9f72bbca7 3587 */
stevep 0:04a9f72bbca7 3588 template<uint another_exp, uint another_man>
stevep 0:04a9f72bbca7 3589 Big<exp,man> & operator=(const Big<another_exp, another_man> & value)
stevep 0:04a9f72bbca7 3590 {
stevep 0:04a9f72bbca7 3591 FromBig(value);
stevep 0:04a9f72bbca7 3592
stevep 0:04a9f72bbca7 3593 return *this;
stevep 0:04a9f72bbca7 3594 }
stevep 0:04a9f72bbca7 3595
stevep 0:04a9f72bbca7 3596
stevep 0:04a9f72bbca7 3597 /*!
stevep 0:04a9f72bbca7 3598 a constructor for converting from 'Big<another_exp, another_man>' to this class
stevep 0:04a9f72bbca7 3599 */
stevep 0:04a9f72bbca7 3600 template<uint another_exp, uint another_man>
stevep 0:04a9f72bbca7 3601 Big(const Big<another_exp, another_man> & value)
stevep 0:04a9f72bbca7 3602 {
stevep 0:04a9f72bbca7 3603 FromBig(value);
stevep 0:04a9f72bbca7 3604 }
stevep 0:04a9f72bbca7 3605
stevep 0:04a9f72bbca7 3606
stevep 0:04a9f72bbca7 3607 /*!
stevep 0:04a9f72bbca7 3608 a default constructor
stevep 0:04a9f72bbca7 3609
stevep 0:04a9f72bbca7 3610 by default we don't set any of the members to zero
stevep 0:04a9f72bbca7 3611 only NaN flag is set
stevep 0:04a9f72bbca7 3612
stevep 0:04a9f72bbca7 3613 if you want the mantissa and exponent to be set to zero
stevep 0:04a9f72bbca7 3614 define TTMATH_BIG_DEFAULT_CLEAR macro
stevep 0:04a9f72bbca7 3615 (useful for debug purposes)
stevep 0:04a9f72bbca7 3616 */
stevep 0:04a9f72bbca7 3617 Big()
stevep 0:04a9f72bbca7 3618 {
stevep 0:04a9f72bbca7 3619 #ifdef TTMATH_BIG_DEFAULT_CLEAR
stevep 0:04a9f72bbca7 3620
stevep 0:04a9f72bbca7 3621 SetZeroNan();
stevep 0:04a9f72bbca7 3622
stevep 0:04a9f72bbca7 3623 #else
stevep 0:04a9f72bbca7 3624
stevep 0:04a9f72bbca7 3625 info = TTMATH_BIG_NAN;
stevep 0:04a9f72bbca7 3626 // we're directly setting 'info' (instead of calling SetNan())
stevep 0:04a9f72bbca7 3627 // in order to get rid of a warning saying that 'info' is uninitialized
stevep 0:04a9f72bbca7 3628
stevep 0:04a9f72bbca7 3629 #endif
stevep 0:04a9f72bbca7 3630 }
stevep 0:04a9f72bbca7 3631
stevep 0:04a9f72bbca7 3632
stevep 0:04a9f72bbca7 3633 /*!
stevep 0:04a9f72bbca7 3634 a destructor
stevep 0:04a9f72bbca7 3635 */
stevep 0:04a9f72bbca7 3636 ~Big()
stevep 0:04a9f72bbca7 3637 {
stevep 0:04a9f72bbca7 3638 }
stevep 0:04a9f72bbca7 3639
stevep 0:04a9f72bbca7 3640
stevep 0:04a9f72bbca7 3641 /*!
stevep 0:04a9f72bbca7 3642 the default assignment operator
stevep 0:04a9f72bbca7 3643 */
stevep 0:04a9f72bbca7 3644 Big<exp,man> & operator=(const Big<exp,man> & value)
stevep 0:04a9f72bbca7 3645 {
stevep 0:04a9f72bbca7 3646 info = value.info;
stevep 0:04a9f72bbca7 3647 exponent = value.exponent;
stevep 0:04a9f72bbca7 3648 mantissa = value.mantissa;
stevep 0:04a9f72bbca7 3649
stevep 0:04a9f72bbca7 3650 return *this;
stevep 0:04a9f72bbca7 3651 }
stevep 0:04a9f72bbca7 3652
stevep 0:04a9f72bbca7 3653
stevep 0:04a9f72bbca7 3654 /*!
stevep 0:04a9f72bbca7 3655 a constructor for copying from another object of this class
stevep 0:04a9f72bbca7 3656 */
stevep 0:04a9f72bbca7 3657
stevep 0:04a9f72bbca7 3658 Big(const Big<exp,man> & value)
stevep 0:04a9f72bbca7 3659 {
stevep 0:04a9f72bbca7 3660 operator=(value);
stevep 0:04a9f72bbca7 3661 }
stevep 0:04a9f72bbca7 3662
stevep 0:04a9f72bbca7 3663
stevep 0:04a9f72bbca7 3664
stevep 0:04a9f72bbca7 3665 /*!
stevep 0:04a9f72bbca7 3666 a method for converting into a string
stevep 0:04a9f72bbca7 3667 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3668
stevep 0:04a9f72bbca7 3669 output:
stevep 0:04a9f72bbca7 3670 return value:
stevep 0:04a9f72bbca7 3671 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value
stevep 0:04a9f72bbca7 3672 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there
stevep 0:04a9f72bbca7 3673 is somewhere an error in the library)
stevep 0:04a9f72bbca7 3674 */
stevep 0:04a9f72bbca7 3675 uint ToString( std::string & result,
stevep 0:04a9f72bbca7 3676 uint base = 10,
stevep 0:04a9f72bbca7 3677 bool scient = false,
stevep 0:04a9f72bbca7 3678 sint scient_from = 15,
stevep 0:04a9f72bbca7 3679 sint round = -1,
stevep 0:04a9f72bbca7 3680 bool trim_zeroes = true,
stevep 0:04a9f72bbca7 3681 char comma = '.' ) const
stevep 0:04a9f72bbca7 3682 {
stevep 0:04a9f72bbca7 3683 Conv conv;
stevep 0:04a9f72bbca7 3684
stevep 0:04a9f72bbca7 3685 conv.base = base;
stevep 0:04a9f72bbca7 3686 conv.scient = scient;
stevep 0:04a9f72bbca7 3687 conv.scient_from = scient_from;
stevep 0:04a9f72bbca7 3688 conv.round = round;
stevep 0:04a9f72bbca7 3689 conv.trim_zeroes = trim_zeroes;
stevep 0:04a9f72bbca7 3690 conv.comma = static_cast<uint>(comma);
stevep 0:04a9f72bbca7 3691
stevep 0:04a9f72bbca7 3692 return ToStringBase<std::string, char>(result, conv);
stevep 0:04a9f72bbca7 3693 }
stevep 0:04a9f72bbca7 3694
stevep 0:04a9f72bbca7 3695
stevep 0:04a9f72bbca7 3696 /*!
stevep 0:04a9f72bbca7 3697 a method for converting into a string
stevep 0:04a9f72bbca7 3698 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3699 */
stevep 0:04a9f72bbca7 3700 uint ToString(std::string & result, const Conv & conv) const
stevep 0:04a9f72bbca7 3701 {
stevep 0:04a9f72bbca7 3702 return ToStringBase<std::string, char>(result, conv);
stevep 0:04a9f72bbca7 3703 }
stevep 0:04a9f72bbca7 3704
stevep 0:04a9f72bbca7 3705
stevep 0:04a9f72bbca7 3706 /*!
stevep 0:04a9f72bbca7 3707 a method for converting into a string
stevep 0:04a9f72bbca7 3708 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3709 */
stevep 0:04a9f72bbca7 3710 std::string ToString(const Conv & conv) const
stevep 0:04a9f72bbca7 3711 {
stevep 0:04a9f72bbca7 3712 std::string result;
stevep 0:04a9f72bbca7 3713 ToStringBase<std::string, char>(result, conv);
stevep 0:04a9f72bbca7 3714
stevep 0:04a9f72bbca7 3715 return result;
stevep 0:04a9f72bbca7 3716 }
stevep 0:04a9f72bbca7 3717
stevep 0:04a9f72bbca7 3718
stevep 0:04a9f72bbca7 3719 /*!
stevep 0:04a9f72bbca7 3720 a method for converting into a string
stevep 0:04a9f72bbca7 3721 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3722 */
stevep 0:04a9f72bbca7 3723 std::string ToString(uint base = 10) const
stevep 0:04a9f72bbca7 3724 {
stevep 0:04a9f72bbca7 3725 Conv conv;
stevep 0:04a9f72bbca7 3726 conv.base = base;
stevep 0:04a9f72bbca7 3727
stevep 0:04a9f72bbca7 3728 return ToString(conv);
stevep 0:04a9f72bbca7 3729 }
stevep 0:04a9f72bbca7 3730
stevep 0:04a9f72bbca7 3731
stevep 0:04a9f72bbca7 3732
stevep 0:04a9f72bbca7 3733 #ifndef TTMATH_DONT_USE_WCHAR
stevep 0:04a9f72bbca7 3734
stevep 0:04a9f72bbca7 3735
stevep 0:04a9f72bbca7 3736 /*!
stevep 0:04a9f72bbca7 3737 a method for converting into a string
stevep 0:04a9f72bbca7 3738 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3739 */
stevep 0:04a9f72bbca7 3740 uint ToString( std::wstring & result,
stevep 0:04a9f72bbca7 3741 uint base = 10,
stevep 0:04a9f72bbca7 3742 bool scient = false,
stevep 0:04a9f72bbca7 3743 sint scient_from = 15,
stevep 0:04a9f72bbca7 3744 sint round = -1,
stevep 0:04a9f72bbca7 3745 bool trim_zeroes = true,
stevep 0:04a9f72bbca7 3746 wchar_t comma = '.' ) const
stevep 0:04a9f72bbca7 3747 {
stevep 0:04a9f72bbca7 3748 Conv conv;
stevep 0:04a9f72bbca7 3749
stevep 0:04a9f72bbca7 3750 conv.base = base;
stevep 0:04a9f72bbca7 3751 conv.scient = scient;
stevep 0:04a9f72bbca7 3752 conv.scient_from = scient_from;
stevep 0:04a9f72bbca7 3753 conv.round = round;
stevep 0:04a9f72bbca7 3754 conv.trim_zeroes = trim_zeroes;
stevep 0:04a9f72bbca7 3755 conv.comma = static_cast<uint>(comma);
stevep 0:04a9f72bbca7 3756
stevep 0:04a9f72bbca7 3757 return ToStringBase<std::wstring, wchar_t>(result, conv);
stevep 0:04a9f72bbca7 3758 }
stevep 0:04a9f72bbca7 3759
stevep 0:04a9f72bbca7 3760
stevep 0:04a9f72bbca7 3761 /*!
stevep 0:04a9f72bbca7 3762 a method for converting into a string
stevep 0:04a9f72bbca7 3763 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3764 */
stevep 0:04a9f72bbca7 3765 uint ToString(std::wstring & result, const Conv & conv) const
stevep 0:04a9f72bbca7 3766 {
stevep 0:04a9f72bbca7 3767 return ToStringBase<std::wstring, wchar_t>(result, conv);
stevep 0:04a9f72bbca7 3768 }
stevep 0:04a9f72bbca7 3769
stevep 0:04a9f72bbca7 3770
stevep 0:04a9f72bbca7 3771 /*!
stevep 0:04a9f72bbca7 3772 a method for converting into a string
stevep 0:04a9f72bbca7 3773 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3774 */
stevep 0:04a9f72bbca7 3775 std::wstring ToWString(const Conv & conv) const
stevep 0:04a9f72bbca7 3776 {
stevep 0:04a9f72bbca7 3777 std::wstring result;
stevep 0:04a9f72bbca7 3778 ToStringBase<std::wstring, wchar_t>(result, conv);
stevep 0:04a9f72bbca7 3779
stevep 0:04a9f72bbca7 3780 return result;
stevep 0:04a9f72bbca7 3781 }
stevep 0:04a9f72bbca7 3782
stevep 0:04a9f72bbca7 3783
stevep 0:04a9f72bbca7 3784 /*!
stevep 0:04a9f72bbca7 3785 a method for converting into a string
stevep 0:04a9f72bbca7 3786 struct Conv is defined in ttmathtypes.h, look there for more information about parameters
stevep 0:04a9f72bbca7 3787 */
stevep 0:04a9f72bbca7 3788 std::wstring ToWString(uint base = 10) const
stevep 0:04a9f72bbca7 3789 {
stevep 0:04a9f72bbca7 3790 Conv conv;
stevep 0:04a9f72bbca7 3791 conv.base = base;
stevep 0:04a9f72bbca7 3792
stevep 0:04a9f72bbca7 3793 return ToWString(conv);
stevep 0:04a9f72bbca7 3794 }
stevep 0:04a9f72bbca7 3795
stevep 0:04a9f72bbca7 3796 #endif
stevep 0:04a9f72bbca7 3797
stevep 0:04a9f72bbca7 3798
stevep 0:04a9f72bbca7 3799
stevep 0:04a9f72bbca7 3800 private:
stevep 0:04a9f72bbca7 3801
stevep 0:04a9f72bbca7 3802
stevep 0:04a9f72bbca7 3803 /*!
stevep 0:04a9f72bbca7 3804 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 3805 */
stevep 0:04a9f72bbca7 3806 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 3807 uint ToStringBase(string_type & result, const Conv & conv) const
stevep 0:04a9f72bbca7 3808 {
stevep 0:04a9f72bbca7 3809 static char error_overflow_msg[] = "overflow";
stevep 0:04a9f72bbca7 3810 static char error_nan_msg[] = "NaN";
stevep 0:04a9f72bbca7 3811 result.erase();
stevep 0:04a9f72bbca7 3812
stevep 0:04a9f72bbca7 3813 if( IsNan() )
stevep 0:04a9f72bbca7 3814 {
stevep 0:04a9f72bbca7 3815 Misc::AssignString(result, error_nan_msg);
stevep 0:04a9f72bbca7 3816 return 0;
stevep 0:04a9f72bbca7 3817 }
stevep 0:04a9f72bbca7 3818
stevep 0:04a9f72bbca7 3819 if( conv.base<2 || conv.base>16 )
stevep 0:04a9f72bbca7 3820 {
stevep 0:04a9f72bbca7 3821 Misc::AssignString(result, error_overflow_msg);
stevep 0:04a9f72bbca7 3822 return 1;
stevep 0:04a9f72bbca7 3823 }
stevep 0:04a9f72bbca7 3824
stevep 0:04a9f72bbca7 3825 if( IsZero() )
stevep 0:04a9f72bbca7 3826 {
stevep 0:04a9f72bbca7 3827 result = '0';
stevep 0:04a9f72bbca7 3828
stevep 0:04a9f72bbca7 3829 return 0;
stevep 0:04a9f72bbca7 3830 }
stevep 0:04a9f72bbca7 3831
stevep 0:04a9f72bbca7 3832 /*
stevep 0:04a9f72bbca7 3833 since 'base' is greater or equal 2 that 'new_exp' of type 'Int<exp>' should
stevep 0:04a9f72bbca7 3834 hold the new value of exponent but we're using 'Int<exp+1>' because
stevep 0:04a9f72bbca7 3835 if the value for example would be 'max()' then we couldn't show it
stevep 0:04a9f72bbca7 3836
stevep 0:04a9f72bbca7 3837 max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set)
stevep 0:04a9f72bbca7 3838 if we were using 'Int<exp>' we couldn't show it in this format:
stevep 0:04a9f72bbca7 3839 1,1111111 * 2 ^ 11111111111 (bin)
stevep 0:04a9f72bbca7 3840 because we have to add something to the mantissa and because
stevep 0:04a9f72bbca7 3841 mantissa is full we can't do it and it'll be a carry
stevep 0:04a9f72bbca7 3842 (look at ToString_SetCommaAndExponent(...))
stevep 0:04a9f72bbca7 3843
stevep 0:04a9f72bbca7 3844 when the base would be greater than two (for example 10)
stevep 0:04a9f72bbca7 3845 we could use 'Int<exp>' here
stevep 0:04a9f72bbca7 3846 */
stevep 0:04a9f72bbca7 3847 Int<exp+1> new_exp;
stevep 0:04a9f72bbca7 3848
stevep 0:04a9f72bbca7 3849 if( ToString_CreateNewMantissaAndExponent<string_type, char_type>(result, conv, new_exp) )
stevep 0:04a9f72bbca7 3850 {
stevep 0:04a9f72bbca7 3851 Misc::AssignString(result, error_overflow_msg);
stevep 0:04a9f72bbca7 3852 return 1;
stevep 0:04a9f72bbca7 3853 }
stevep 0:04a9f72bbca7 3854
stevep 0:04a9f72bbca7 3855
stevep 0:04a9f72bbca7 3856 if( ToString_SetCommaAndExponent<string_type, char_type>(result, conv, new_exp) )
stevep 0:04a9f72bbca7 3857 {
stevep 0:04a9f72bbca7 3858 Misc::AssignString(result, error_overflow_msg);
stevep 0:04a9f72bbca7 3859 return 1;
stevep 0:04a9f72bbca7 3860 }
stevep 0:04a9f72bbca7 3861
stevep 0:04a9f72bbca7 3862 if( IsSign() )
stevep 0:04a9f72bbca7 3863 result.insert(result.begin(), '-');
stevep 0:04a9f72bbca7 3864
stevep 0:04a9f72bbca7 3865
stevep 0:04a9f72bbca7 3866 // converted successfully
stevep 0:04a9f72bbca7 3867 return 0;
stevep 0:04a9f72bbca7 3868 }
stevep 0:04a9f72bbca7 3869
stevep 0:04a9f72bbca7 3870
stevep 0:04a9f72bbca7 3871
stevep 0:04a9f72bbca7 3872 /*!
stevep 0:04a9f72bbca7 3873 in the method 'ToString_CreateNewMantissaAndExponent()' we're using
stevep 0:04a9f72bbca7 3874 type 'Big<exp+1,man>' and we should have the ability to use some
stevep 0:04a9f72bbca7 3875 necessary methods from that class (methods which are private here)
stevep 0:04a9f72bbca7 3876 */
stevep 0:04a9f72bbca7 3877 friend class Big<exp-1,man>;
stevep 0:04a9f72bbca7 3878
stevep 0:04a9f72bbca7 3879
stevep 0:04a9f72bbca7 3880 /*!
stevep 0:04a9f72bbca7 3881 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 3882
stevep 0:04a9f72bbca7 3883 input:
stevep 0:04a9f72bbca7 3884 base - the base in range <2,16>
stevep 0:04a9f72bbca7 3885
stevep 0:04a9f72bbca7 3886 output:
stevep 0:04a9f72bbca7 3887 return values:
stevep 0:04a9f72bbca7 3888 0 - ok
stevep 0:04a9f72bbca7 3889 1 - if there was a carry
stevep 0:04a9f72bbca7 3890 new_man - the new mantissa for 'base'
stevep 0:04a9f72bbca7 3891 new_exp - the new exponent for 'base'
stevep 0:04a9f72bbca7 3892
stevep 0:04a9f72bbca7 3893 mathematic part:
stevep 0:04a9f72bbca7 3894
stevep 0:04a9f72bbca7 3895 the value is stored as:
stevep 0:04a9f72bbca7 3896 value = mantissa * 2^exponent
stevep 0:04a9f72bbca7 3897 we want to show 'value' as:
stevep 0:04a9f72bbca7 3898 value = new_man * base^new_exp
stevep 0:04a9f72bbca7 3899
stevep 0:04a9f72bbca7 3900 then 'new_man' we'll print using the standard method from UInt<> type for printing
stevep 0:04a9f72bbca7 3901 and 'new_exp' is the offset of the comma operator in a system of a base 'base'
stevep 0:04a9f72bbca7 3902
stevep 0:04a9f72bbca7 3903 value = mantissa * 2^exponent
stevep 0:04a9f72bbca7 3904 value = mantissa * 2^exponent * (base^new_exp / base^new_exp)
stevep 0:04a9f72bbca7 3905 value = mantissa * (2^exponent / base^new_exp) * base^new_exp
stevep 0:04a9f72bbca7 3906
stevep 0:04a9f72bbca7 3907 look at the part (2^exponent / base^new_exp), there'll be good if we take
stevep 0:04a9f72bbca7 3908 a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one
stevep 0:04a9f72bbca7 3909
stevep 0:04a9f72bbca7 3910 on account of the 'base' is not as power of 2 (can be from 2 to 16),
stevep 0:04a9f72bbca7 3911 this formula will not be true for integer 'new_exp' then in our case we take
stevep 0:04a9f72bbca7 3912 'base^new_exp' _greater_ than '2^exponent'
stevep 0:04a9f72bbca7 3913
stevep 0:04a9f72bbca7 3914 if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be
stevep 0:04a9f72bbca7 3915 greater than the max value of the container UInt<man>
stevep 0:04a9f72bbca7 3916
stevep 0:04a9f72bbca7 3917 value = mantissa * (2^exponent / base^new_exp) * base^new_exp
stevep 0:04a9f72bbca7 3918 let M = mantissa * (2^exponent / base^new_exp) then
stevep 0:04a9f72bbca7 3919 value = M * base^new_exp
stevep 0:04a9f72bbca7 3920
stevep 0:04a9f72bbca7 3921 in our calculation we treat M as floating value showing it as:
stevep 0:04a9f72bbca7 3922 M = mm * 2^ee where ee will be <= 0
stevep 0:04a9f72bbca7 3923
stevep 0:04a9f72bbca7 3924 next we'll move all bits of mm into the right when ee is equal zero
stevep 0:04a9f72bbca7 3925 abs(ee) must not be too big that only few bits from mm we can leave
stevep 0:04a9f72bbca7 3926
stevep 0:04a9f72bbca7 3927 then we'll have:
stevep 0:04a9f72bbca7 3928 M = mmm * 2^0
stevep 0:04a9f72bbca7 3929 'mmm' is the new_man which we're looking for
stevep 0:04a9f72bbca7 3930
stevep 0:04a9f72bbca7 3931
stevep 0:04a9f72bbca7 3932 new_exp we calculate in this way:
stevep 0:04a9f72bbca7 3933 2^exponent <= base^new_exp
stevep 0:04a9f72bbca7 3934 new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent)
stevep 0:04a9f72bbca7 3935
stevep 0:04a9f72bbca7 3936 but we need new_exp as integer then we test:
stevep 0:04a9f72bbca7 3937 if new_exp is greater than zero and with fraction we add one to new_exp
stevep 0:04a9f72bbca7 3938 new_exp = new_exp + 1 (if new_exp>0 and with fraction)
stevep 0:04a9f72bbca7 3939 and at the end we take the integer part:
stevep 0:04a9f72bbca7 3940 new_exp = int(new_exp)
stevep 0:04a9f72bbca7 3941 */
stevep 0:04a9f72bbca7 3942 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 3943 uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv,
stevep 0:04a9f72bbca7 3944 Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 3945 {
stevep 0:04a9f72bbca7 3946 uint c = 0;
stevep 0:04a9f72bbca7 3947
stevep 0:04a9f72bbca7 3948 if( conv.base<2 || conv.base>16 )
stevep 0:04a9f72bbca7 3949 return 1;
stevep 0:04a9f72bbca7 3950
stevep 0:04a9f72bbca7 3951 // special method for base equal 2
stevep 0:04a9f72bbca7 3952 if( conv.base == 2 )
stevep 0:04a9f72bbca7 3953 return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
stevep 0:04a9f72bbca7 3954
stevep 0:04a9f72bbca7 3955 // special method for base equal 4
stevep 0:04a9f72bbca7 3956 if( conv.base == 4 )
stevep 0:04a9f72bbca7 3957 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2);
stevep 0:04a9f72bbca7 3958
stevep 0:04a9f72bbca7 3959 // special method for base equal 8
stevep 0:04a9f72bbca7 3960 if( conv.base == 8 )
stevep 0:04a9f72bbca7 3961 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3);
stevep 0:04a9f72bbca7 3962
stevep 0:04a9f72bbca7 3963 // special method for base equal 16
stevep 0:04a9f72bbca7 3964 if( conv.base == 16 )
stevep 0:04a9f72bbca7 3965 return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4);
stevep 0:04a9f72bbca7 3966
stevep 0:04a9f72bbca7 3967
stevep 0:04a9f72bbca7 3968 // this = mantissa * 2^exponent
stevep 0:04a9f72bbca7 3969
stevep 0:04a9f72bbca7 3970 // temp = +1 * 2^exponent
stevep 0:04a9f72bbca7 3971 // we're using a bigger type than 'big<exp,man>' (look below)
stevep 0:04a9f72bbca7 3972 Big<exp+1,man> temp;
stevep 0:04a9f72bbca7 3973 temp.info = 0;
stevep 0:04a9f72bbca7 3974 temp.exponent = exponent;
stevep 0:04a9f72bbca7 3975 temp.mantissa.SetOne();
stevep 0:04a9f72bbca7 3976 c += temp.Standardizing();
stevep 0:04a9f72bbca7 3977
stevep 0:04a9f72bbca7 3978 // new_exp_ = log base (2^exponent)
stevep 0:04a9f72bbca7 3979 // if new_exp_ is positive and with fraction then we add one
stevep 0:04a9f72bbca7 3980 Big<exp+1,man> new_exp_;
stevep 0:04a9f72bbca7 3981 c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated
stevep 0:04a9f72bbca7 3982
stevep 0:04a9f72bbca7 3983 // rounding up to the nearest integer
stevep 0:04a9f72bbca7 3984 if( !new_exp_.IsInteger() )
stevep 0:04a9f72bbca7 3985 {
stevep 0:04a9f72bbca7 3986 if( !new_exp_.IsSign() )
stevep 0:04a9f72bbca7 3987 c += new_exp_.AddOne(); // new_exp_ > 0 and with fraction
stevep 0:04a9f72bbca7 3988
stevep 0:04a9f72bbca7 3989 new_exp_.SkipFraction();
stevep 0:04a9f72bbca7 3990 }
stevep 0:04a9f72bbca7 3991
stevep 0:04a9f72bbca7 3992 if( ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp) )
stevep 0:04a9f72bbca7 3993 {
stevep 0:04a9f72bbca7 3994 // in very rare cases there can be an overflow from ToString_CreateNewMantissaTryExponent
stevep 0:04a9f72bbca7 3995 // it means that new_exp_ was too small (the problem comes from floating point numbers precision)
stevep 0:04a9f72bbca7 3996 // so we increse new_exp_ and try again
stevep 0:04a9f72bbca7 3997 new_exp_.AddOne();
stevep 0:04a9f72bbca7 3998 c += ToString_CreateNewMantissaTryExponent<string_type, char_type>(new_man, conv, new_exp_, new_exp);
stevep 0:04a9f72bbca7 3999 }
stevep 0:04a9f72bbca7 4000
stevep 0:04a9f72bbca7 4001 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4002 }
stevep 0:04a9f72bbca7 4003
stevep 0:04a9f72bbca7 4004
stevep 0:04a9f72bbca7 4005
stevep 0:04a9f72bbca7 4006 /*!
stevep 0:04a9f72bbca7 4007 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4008
stevep 0:04a9f72bbca7 4009 trying to calculate new_man for given exponent (new_exp_)
stevep 0:04a9f72bbca7 4010 if there is a carry it can mean that new_exp_ is too small
stevep 0:04a9f72bbca7 4011 */
stevep 0:04a9f72bbca7 4012 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4013 uint ToString_CreateNewMantissaTryExponent( string_type & new_man, const Conv & conv,
stevep 0:04a9f72bbca7 4014 const Big<exp+1,man> & new_exp_, Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4015 {
stevep 0:04a9f72bbca7 4016 uint c = 0;
stevep 0:04a9f72bbca7 4017
stevep 0:04a9f72bbca7 4018 // because 'base^new_exp' is >= '2^exponent' then
stevep 0:04a9f72bbca7 4019 // because base is >= 2 then we've got:
stevep 0:04a9f72bbca7 4020 // 'new_exp_' must be smaller or equal 'new_exp'
stevep 0:04a9f72bbca7 4021 // and we can pass it into the Int<exp> type
stevep 0:04a9f72bbca7 4022 // (in fact we're using a greater type then it'll be ok)
stevep 0:04a9f72bbca7 4023 c += new_exp_.ToInt(new_exp);
stevep 0:04a9f72bbca7 4024
stevep 0:04a9f72bbca7 4025 // base_ = base
stevep 0:04a9f72bbca7 4026 Big<exp+1,man> base_(conv.base);
stevep 0:04a9f72bbca7 4027
stevep 0:04a9f72bbca7 4028 // base_ = base_ ^ new_exp_
stevep 0:04a9f72bbca7 4029 c += base_.Pow( new_exp_ ); // use new_exp_ so Pow(Big<> &) version will be used
stevep 0:04a9f72bbca7 4030 // if we hadn't used a bigger type than 'Big<exp,man>' then the result
stevep 0:04a9f72bbca7 4031 // of this formula 'Pow(...)' would have been with an overflow
stevep 0:04a9f72bbca7 4032
stevep 0:04a9f72bbca7 4033 // temp = mantissa * 2^exponent / base_^new_exp_
stevep 0:04a9f72bbca7 4034 Big<exp+1,man> temp;
stevep 0:04a9f72bbca7 4035 temp.info = 0;
stevep 0:04a9f72bbca7 4036 temp.mantissa = mantissa;
stevep 0:04a9f72bbca7 4037 temp.exponent = exponent;
stevep 0:04a9f72bbca7 4038 c += temp.Div(base_);
stevep 0:04a9f72bbca7 4039
stevep 0:04a9f72bbca7 4040 // moving all bits of the mantissa into the right
stevep 0:04a9f72bbca7 4041 // (how many times to move depend on the exponent)
stevep 0:04a9f72bbca7 4042 c += temp.ToString_MoveMantissaIntoRight();
stevep 0:04a9f72bbca7 4043
stevep 0:04a9f72bbca7 4044 // because we took 'new_exp' as small as it was
stevep 0:04a9f72bbca7 4045 // possible ([log base (2^exponent)] + 1) that after the division
stevep 0:04a9f72bbca7 4046 // (temp.Div( base_ )) the value of exponent should be equal zero or
stevep 0:04a9f72bbca7 4047 // minimum smaller than zero then we've got the mantissa which has
stevep 0:04a9f72bbca7 4048 // maximum valid bits
stevep 0:04a9f72bbca7 4049 temp.mantissa.ToString(new_man, conv.base);
stevep 0:04a9f72bbca7 4050
stevep 0:04a9f72bbca7 4051 if( IsInteger() )
stevep 0:04a9f72bbca7 4052 {
stevep 0:04a9f72bbca7 4053 // making sure the new mantissa will be without fraction (integer)
stevep 0:04a9f72bbca7 4054 ToString_CheckMantissaInteger<string_type, char_type>(new_man, new_exp);
stevep 0:04a9f72bbca7 4055 }
stevep 0:04a9f72bbca7 4056 else
stevep 0:04a9f72bbca7 4057 if( conv.base_round )
stevep 0:04a9f72bbca7 4058 {
stevep 0:04a9f72bbca7 4059 c += ToString_BaseRound<string_type, char_type>(new_man, conv, new_exp);
stevep 0:04a9f72bbca7 4060 }
stevep 0:04a9f72bbca7 4061
stevep 0:04a9f72bbca7 4062 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4063 }
stevep 0:04a9f72bbca7 4064
stevep 0:04a9f72bbca7 4065
stevep 0:04a9f72bbca7 4066 /*!
stevep 0:04a9f72bbca7 4067 this method calculates the logarithm
stevep 0:04a9f72bbca7 4068 it is used by ToString_CreateNewMantissaAndExponent() method
stevep 0:04a9f72bbca7 4069
stevep 0:04a9f72bbca7 4070 it's not too complicated
stevep 0:04a9f72bbca7 4071 because x=+1*2^exponent (mantissa is one) then during the calculation
stevep 0:04a9f72bbca7 4072 the Ln(x) will not be making the long formula from LnSurrounding1()
stevep 0:04a9f72bbca7 4073 and only we have to calculate 'Ln(base)' but it'll be calculated
stevep 0:04a9f72bbca7 4074 only once, the next time we will get it from the 'history'
stevep 0:04a9f72bbca7 4075
stevep 0:04a9f72bbca7 4076 x is greater than 0
stevep 0:04a9f72bbca7 4077 base is in <2,16> range
stevep 0:04a9f72bbca7 4078 */
stevep 0:04a9f72bbca7 4079 uint ToString_Log(const Big<exp,man> & x, uint base)
stevep 0:04a9f72bbca7 4080 {
stevep 0:04a9f72bbca7 4081 TTMATH_REFERENCE_ASSERT( x )
stevep 0:04a9f72bbca7 4082 TTMATH_ASSERT( base>=2 && base<=16 )
stevep 0:04a9f72bbca7 4083
stevep 0:04a9f72bbca7 4084 Big<exp,man> temp;
stevep 0:04a9f72bbca7 4085 temp.SetOne();
stevep 0:04a9f72bbca7 4086
stevep 0:04a9f72bbca7 4087 if( x == temp )
stevep 0:04a9f72bbca7 4088 {
stevep 0:04a9f72bbca7 4089 // log(1) is 0
stevep 0:04a9f72bbca7 4090 SetZero();
stevep 0:04a9f72bbca7 4091
stevep 0:04a9f72bbca7 4092 return 0;
stevep 0:04a9f72bbca7 4093 }
stevep 0:04a9f72bbca7 4094
stevep 0:04a9f72bbca7 4095 // there can be only a carry
stevep 0:04a9f72bbca7 4096 // because the 'x' is in '1+2*exponent' form then
stevep 0:04a9f72bbca7 4097 // the long formula from LnSurrounding1() will not be calculated
stevep 0:04a9f72bbca7 4098 // (LnSurrounding1() will return one immediately)
stevep 0:04a9f72bbca7 4099 uint c = Ln(x);
stevep 0:04a9f72bbca7 4100
stevep 0:04a9f72bbca7 4101 if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE )
stevep 0:04a9f72bbca7 4102 {
stevep 0:04a9f72bbca7 4103 // for the base equal 10 we're using SetLn10() instead of calculating it
stevep 0:04a9f72bbca7 4104 // (only if we have the constant sufficient big)
stevep 0:04a9f72bbca7 4105 temp.SetLn10();
stevep 0:04a9f72bbca7 4106 }
stevep 0:04a9f72bbca7 4107 else
stevep 0:04a9f72bbca7 4108 {
stevep 0:04a9f72bbca7 4109 c += ToString_LogBase(base, temp);
stevep 0:04a9f72bbca7 4110 }
stevep 0:04a9f72bbca7 4111
stevep 0:04a9f72bbca7 4112 c += Div( temp );
stevep 0:04a9f72bbca7 4113
stevep 0:04a9f72bbca7 4114 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4115 }
stevep 0:04a9f72bbca7 4116
stevep 0:04a9f72bbca7 4117
stevep 0:04a9f72bbca7 4118 #ifndef TTMATH_MULTITHREADS
stevep 0:04a9f72bbca7 4119
stevep 0:04a9f72bbca7 4120 /*!
stevep 0:04a9f72bbca7 4121 this method calculates the logarithm of 'base'
stevep 0:04a9f72bbca7 4122 it's used in single thread environment
stevep 0:04a9f72bbca7 4123 */
stevep 0:04a9f72bbca7 4124 uint ToString_LogBase(uint base, Big<exp,man> & result)
stevep 0:04a9f72bbca7 4125 {
stevep 0:04a9f72bbca7 4126 TTMATH_ASSERT( base>=2 && base<=16 )
stevep 0:04a9f72bbca7 4127
stevep 0:04a9f72bbca7 4128 // this guardians are initialized before the program runs (static POD types)
stevep 0:04a9f72bbca7 4129 static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
stevep 0:04a9f72bbca7 4130 static Big<exp,man> log_history[15];
stevep 0:04a9f72bbca7 4131 uint index = base - 2;
stevep 0:04a9f72bbca7 4132 uint c = 0;
stevep 0:04a9f72bbca7 4133
stevep 0:04a9f72bbca7 4134 if( guardians[index] == 0 )
stevep 0:04a9f72bbca7 4135 {
stevep 0:04a9f72bbca7 4136 Big<exp,man> base_(base);
stevep 0:04a9f72bbca7 4137 c += log_history[index].Ln(base_);
stevep 0:04a9f72bbca7 4138 guardians[index] = 1;
stevep 0:04a9f72bbca7 4139 }
stevep 0:04a9f72bbca7 4140
stevep 0:04a9f72bbca7 4141 result = log_history[index];
stevep 0:04a9f72bbca7 4142
stevep 0:04a9f72bbca7 4143 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4144 }
stevep 0:04a9f72bbca7 4145
stevep 0:04a9f72bbca7 4146 #else
stevep 0:04a9f72bbca7 4147
stevep 0:04a9f72bbca7 4148 /*!
stevep 0:04a9f72bbca7 4149 this method calculates the logarithm of 'base'
stevep 0:04a9f72bbca7 4150 it's used in multi-thread environment
stevep 0:04a9f72bbca7 4151 */
stevep 0:04a9f72bbca7 4152 uint ToString_LogBase(uint base, Big<exp,man> & result)
stevep 0:04a9f72bbca7 4153 {
stevep 0:04a9f72bbca7 4154 TTMATH_ASSERT( base>=2 && base<=16 )
stevep 0:04a9f72bbca7 4155
stevep 0:04a9f72bbca7 4156 // this guardians are initialized before the program runs (static POD types)
stevep 0:04a9f72bbca7 4157 volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
stevep 0:04a9f72bbca7 4158 static Big<exp,man> * plog_history;
stevep 0:04a9f72bbca7 4159 uint index = base - 2;
stevep 0:04a9f72bbca7 4160 uint c = 0;
stevep 0:04a9f72bbca7 4161
stevep 0:04a9f72bbca7 4162 // double-checked locking
stevep 0:04a9f72bbca7 4163 if( guardians[index] == 0 )
stevep 0:04a9f72bbca7 4164 {
stevep 0:04a9f72bbca7 4165 ThreadLock thread_lock;
stevep 0:04a9f72bbca7 4166
stevep 0:04a9f72bbca7 4167 // locking
stevep 0:04a9f72bbca7 4168 if( thread_lock.Lock() )
stevep 0:04a9f72bbca7 4169 {
stevep 0:04a9f72bbca7 4170 static Big<exp,man> log_history[15];
stevep 0:04a9f72bbca7 4171
stevep 0:04a9f72bbca7 4172 if( guardians[index] == 0 )
stevep 0:04a9f72bbca7 4173 {
stevep 0:04a9f72bbca7 4174 plog_history = log_history;
stevep 0:04a9f72bbca7 4175
stevep 0:04a9f72bbca7 4176 Big<exp,man> base_(base);
stevep 0:04a9f72bbca7 4177 c += log_history[index].Ln(base_);
stevep 0:04a9f72bbca7 4178 guardians[index] = 1;
stevep 0:04a9f72bbca7 4179 }
stevep 0:04a9f72bbca7 4180 }
stevep 0:04a9f72bbca7 4181 else
stevep 0:04a9f72bbca7 4182 {
stevep 0:04a9f72bbca7 4183 // there was a problem with locking, we store the result directly in 'result' object
stevep 0:04a9f72bbca7 4184 Big<exp,man> base_(base);
stevep 0:04a9f72bbca7 4185 c += result.Ln(base_);
stevep 0:04a9f72bbca7 4186
stevep 0:04a9f72bbca7 4187 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4188 }
stevep 0:04a9f72bbca7 4189
stevep 0:04a9f72bbca7 4190 // automatically unlocking
stevep 0:04a9f72bbca7 4191 }
stevep 0:04a9f72bbca7 4192
stevep 0:04a9f72bbca7 4193 result = plog_history[index];
stevep 0:04a9f72bbca7 4194
stevep 0:04a9f72bbca7 4195 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 4196 }
stevep 0:04a9f72bbca7 4197
stevep 0:04a9f72bbca7 4198 #endif
stevep 0:04a9f72bbca7 4199
stevep 0:04a9f72bbca7 4200 /*!
stevep 0:04a9f72bbca7 4201 an auxiliary method for converting into the string (private)
stevep 0:04a9f72bbca7 4202
stevep 0:04a9f72bbca7 4203 this method moving all bits from mantissa into the right side
stevep 0:04a9f72bbca7 4204 the exponent tell us how many times moving (the exponent is <=0)
stevep 0:04a9f72bbca7 4205 */
stevep 0:04a9f72bbca7 4206 uint ToString_MoveMantissaIntoRight()
stevep 0:04a9f72bbca7 4207 {
stevep 0:04a9f72bbca7 4208 if( exponent.IsZero() )
stevep 0:04a9f72bbca7 4209 return 0;
stevep 0:04a9f72bbca7 4210
stevep 0:04a9f72bbca7 4211 // exponent can't be greater than zero
stevep 0:04a9f72bbca7 4212 // because we would cat the highest bits of the mantissa
stevep 0:04a9f72bbca7 4213 if( !exponent.IsSign() )
stevep 0:04a9f72bbca7 4214 return 1;
stevep 0:04a9f72bbca7 4215
stevep 0:04a9f72bbca7 4216
stevep 0:04a9f72bbca7 4217 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 4218 // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)'
stevep 0:04a9f72bbca7 4219 // it means that we must cut the whole mantissa
stevep 0:04a9f72bbca7 4220 // (there'll not be any of the valid bits)
stevep 0:04a9f72bbca7 4221 return 1;
stevep 0:04a9f72bbca7 4222
stevep 0:04a9f72bbca7 4223 // e will be from (-man*TTMATH_BITS_PER_UINT, 0>
stevep 0:04a9f72bbca7 4224 sint e = -( exponent.ToInt() );
stevep 0:04a9f72bbca7 4225 mantissa.Rcr(e,0);
stevep 0:04a9f72bbca7 4226
stevep 0:04a9f72bbca7 4227 return 0;
stevep 0:04a9f72bbca7 4228 }
stevep 0:04a9f72bbca7 4229
stevep 0:04a9f72bbca7 4230
stevep 0:04a9f72bbca7 4231 /*!
stevep 0:04a9f72bbca7 4232 a special method similar to the 'ToString_CreateNewMantissaAndExponent'
stevep 0:04a9f72bbca7 4233 when the 'base' is equal 2
stevep 0:04a9f72bbca7 4234
stevep 0:04a9f72bbca7 4235 we use it because if base is equal 2 we don't have to make those
stevep 0:04a9f72bbca7 4236 complicated calculations and the output is directly from the source
stevep 0:04a9f72bbca7 4237 (there will not be any small distortions)
stevep 0:04a9f72bbca7 4238 */
stevep 0:04a9f72bbca7 4239 template<class string_type>
stevep 0:04a9f72bbca7 4240 uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man,
stevep 0:04a9f72bbca7 4241 Int<exp+1> & new_exp ) const
stevep 0:04a9f72bbca7 4242 {
stevep 0:04a9f72bbca7 4243 for( sint i=man-1 ; i>=0 ; --i )
stevep 0:04a9f72bbca7 4244 {
stevep 0:04a9f72bbca7 4245 uint value = mantissa.table[i];
stevep 0:04a9f72bbca7 4246
stevep 0:04a9f72bbca7 4247 for( uint bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
stevep 0:04a9f72bbca7 4248 {
stevep 0:04a9f72bbca7 4249 if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
stevep 0:04a9f72bbca7 4250 new_man += '1';
stevep 0:04a9f72bbca7 4251 else
stevep 0:04a9f72bbca7 4252 new_man += '0';
stevep 0:04a9f72bbca7 4253
stevep 0:04a9f72bbca7 4254 value <<= 1;
stevep 0:04a9f72bbca7 4255 }
stevep 0:04a9f72bbca7 4256 }
stevep 0:04a9f72bbca7 4257
stevep 0:04a9f72bbca7 4258 new_exp = exponent;
stevep 0:04a9f72bbca7 4259
stevep 0:04a9f72bbca7 4260 return 0;
stevep 0:04a9f72bbca7 4261 }
stevep 0:04a9f72bbca7 4262
stevep 0:04a9f72bbca7 4263
stevep 0:04a9f72bbca7 4264 /*!
stevep 0:04a9f72bbca7 4265 a special method used to calculate the new mantissa and exponent
stevep 0:04a9f72bbca7 4266 when the 'base' is equal 4, 8 or 16
stevep 0:04a9f72bbca7 4267
stevep 0:04a9f72bbca7 4268 when base is 4 then bits is 2
stevep 0:04a9f72bbca7 4269 when base is 8 then bits is 3
stevep 0:04a9f72bbca7 4270 when base is 16 then bits is 4
stevep 0:04a9f72bbca7 4271 (and the algorithm can be used with a base greater than 16)
stevep 0:04a9f72bbca7 4272 */
stevep 0:04a9f72bbca7 4273 template<class string_type>
stevep 0:04a9f72bbca7 4274 uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man,
stevep 0:04a9f72bbca7 4275 Int<exp+1> & new_exp,
stevep 0:04a9f72bbca7 4276 uint bits) const
stevep 0:04a9f72bbca7 4277 {
stevep 0:04a9f72bbca7 4278 sint move; // how many times move the mantissa
stevep 0:04a9f72bbca7 4279 UInt<man+1> man_temp(mantissa); // man+1 for moving
stevep 0:04a9f72bbca7 4280 new_exp = exponent;
stevep 0:04a9f72bbca7 4281 new_exp.DivInt((sint)bits, move);
stevep 0:04a9f72bbca7 4282
stevep 0:04a9f72bbca7 4283 if( move != 0 )
stevep 0:04a9f72bbca7 4284 {
stevep 0:04a9f72bbca7 4285 // we're moving the man_temp to left-hand side
stevep 0:04a9f72bbca7 4286 if( move < 0 )
stevep 0:04a9f72bbca7 4287 {
stevep 0:04a9f72bbca7 4288 move = sint(bits) + move;
stevep 0:04a9f72bbca7 4289 new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too
stevep 0:04a9f72bbca7 4290 }
stevep 0:04a9f72bbca7 4291
stevep 0:04a9f72bbca7 4292 man_temp.Rcl(move);
stevep 0:04a9f72bbca7 4293 }
stevep 0:04a9f72bbca7 4294
stevep 0:04a9f72bbca7 4295
stevep 0:04a9f72bbca7 4296 if( bits == 3 )
stevep 0:04a9f72bbca7 4297 {
stevep 0:04a9f72bbca7 4298 // base 8
stevep 0:04a9f72bbca7 4299 // now 'move' is greater than or equal 0
stevep 0:04a9f72bbca7 4300 uint len = man*TTMATH_BITS_PER_UINT + move;
stevep 0:04a9f72bbca7 4301 return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits);
stevep 0:04a9f72bbca7 4302 }
stevep 0:04a9f72bbca7 4303 else
stevep 0:04a9f72bbca7 4304 {
stevep 0:04a9f72bbca7 4305 // base 4 or 16
stevep 0:04a9f72bbca7 4306 return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits);
stevep 0:04a9f72bbca7 4307 }
stevep 0:04a9f72bbca7 4308 }
stevep 0:04a9f72bbca7 4309
stevep 0:04a9f72bbca7 4310
stevep 0:04a9f72bbca7 4311 /*!
stevep 0:04a9f72bbca7 4312 a special method used to calculate the new mantissa
stevep 0:04a9f72bbca7 4313 when the 'base' is equal 8
stevep 0:04a9f72bbca7 4314
stevep 0:04a9f72bbca7 4315 bits is always 3
stevep 0:04a9f72bbca7 4316
stevep 0:04a9f72bbca7 4317 we can use this algorithm when the base is 4 or 16 too
stevep 0:04a9f72bbca7 4318 but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16()
stevep 0:04a9f72bbca7 4319 */
stevep 0:04a9f72bbca7 4320 template<class string_type>
stevep 0:04a9f72bbca7 4321 uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man,
stevep 0:04a9f72bbca7 4322 UInt<man+1> & man_temp,
stevep 0:04a9f72bbca7 4323 uint len,
stevep 0:04a9f72bbca7 4324 uint bits) const
stevep 0:04a9f72bbca7 4325 {
stevep 0:04a9f72bbca7 4326 uint shift = TTMATH_BITS_PER_UINT - bits;
stevep 0:04a9f72bbca7 4327 uint mask = TTMATH_UINT_MAX_VALUE >> shift;
stevep 0:04a9f72bbca7 4328 uint i;
stevep 0:04a9f72bbca7 4329
stevep 0:04a9f72bbca7 4330 for( i=0 ; i<len ; i+=bits )
stevep 0:04a9f72bbca7 4331 {
stevep 0:04a9f72bbca7 4332 uint digit = man_temp.table[0] & mask;
stevep 0:04a9f72bbca7 4333 new_man.insert(new_man.begin(), static_cast<char>(Misc::DigitToChar(digit)));
stevep 0:04a9f72bbca7 4334
stevep 0:04a9f72bbca7 4335 man_temp.Rcr(bits);
stevep 0:04a9f72bbca7 4336 }
stevep 0:04a9f72bbca7 4337
stevep 0:04a9f72bbca7 4338 TTMATH_ASSERT( man_temp.IsZero() )
stevep 0:04a9f72bbca7 4339
stevep 0:04a9f72bbca7 4340 return 0;
stevep 0:04a9f72bbca7 4341 }
stevep 0:04a9f72bbca7 4342
stevep 0:04a9f72bbca7 4343
stevep 0:04a9f72bbca7 4344 /*!
stevep 0:04a9f72bbca7 4345 a special method used to calculate the new mantissa
stevep 0:04a9f72bbca7 4346 when the 'base' is equal 4 or 16
stevep 0:04a9f72bbca7 4347
stevep 0:04a9f72bbca7 4348 when the base is equal 4 or 16 the bits is 2 or 4
stevep 0:04a9f72bbca7 4349 and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4)
stevep 0:04a9f72bbca7 4350 then we can get digits from the end of our mantissa
stevep 0:04a9f72bbca7 4351 */
stevep 0:04a9f72bbca7 4352 template<class string_type>
stevep 0:04a9f72bbca7 4353 uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man,
stevep 0:04a9f72bbca7 4354 UInt<man+1> & man_temp,
stevep 0:04a9f72bbca7 4355 uint bits) const
stevep 0:04a9f72bbca7 4356 {
stevep 0:04a9f72bbca7 4357 TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 )
stevep 0:04a9f72bbca7 4358 TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 )
stevep 0:04a9f72bbca7 4359
stevep 0:04a9f72bbca7 4360 uint shift = TTMATH_BITS_PER_UINT - bits;
stevep 0:04a9f72bbca7 4361 uint mask = TTMATH_UINT_MAX_VALUE << shift;
stevep 0:04a9f72bbca7 4362 uint digit;
stevep 0:04a9f72bbca7 4363
stevep 0:04a9f72bbca7 4364 // table[man] - last word - is different from zero if we moved man_temp
stevep 0:04a9f72bbca7 4365 digit = man_temp.table[man];
stevep 0:04a9f72bbca7 4366
stevep 0:04a9f72bbca7 4367 if( digit != 0 )
stevep 0:04a9f72bbca7 4368 new_man += static_cast<char>(Misc::DigitToChar(digit));
stevep 0:04a9f72bbca7 4369
stevep 0:04a9f72bbca7 4370
stevep 0:04a9f72bbca7 4371 for( int i=man-1 ; i>=0 ; --i )
stevep 0:04a9f72bbca7 4372 {
stevep 0:04a9f72bbca7 4373 uint shift_local = shift;
stevep 0:04a9f72bbca7 4374 uint mask_local = mask;
stevep 0:04a9f72bbca7 4375
stevep 0:04a9f72bbca7 4376 while( mask_local != 0 )
stevep 0:04a9f72bbca7 4377 {
stevep 0:04a9f72bbca7 4378 digit = man_temp.table[i] & mask_local;
stevep 0:04a9f72bbca7 4379
stevep 0:04a9f72bbca7 4380 if( shift_local != 0 )
stevep 0:04a9f72bbca7 4381 digit = digit >> shift_local;
stevep 0:04a9f72bbca7 4382
stevep 0:04a9f72bbca7 4383 new_man += static_cast<char>(Misc::DigitToChar(digit));
stevep 0:04a9f72bbca7 4384 mask_local = mask_local >> bits;
stevep 0:04a9f72bbca7 4385 shift_local = shift_local - bits;
stevep 0:04a9f72bbca7 4386 }
stevep 0:04a9f72bbca7 4387 }
stevep 0:04a9f72bbca7 4388
stevep 0:04a9f72bbca7 4389 return 0;
stevep 0:04a9f72bbca7 4390 }
stevep 0:04a9f72bbca7 4391
stevep 0:04a9f72bbca7 4392
stevep 0:04a9f72bbca7 4393 /*!
stevep 0:04a9f72bbca7 4394 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4395 */
stevep 0:04a9f72bbca7 4396 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4397 bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4398 {
stevep 0:04a9f72bbca7 4399 // if new_exp is greater or equal to zero then we have an integer value,
stevep 0:04a9f72bbca7 4400 // if new_exp is equal -1 then we have only one digit after the comma
stevep 0:04a9f72bbca7 4401 // and after rounding it would be an integer value
stevep 0:04a9f72bbca7 4402 if( !new_exp.IsSign() || new_exp == -1 )
stevep 0:04a9f72bbca7 4403 return true;
stevep 0:04a9f72bbca7 4404
stevep 0:04a9f72bbca7 4405 if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 )
stevep 0:04a9f72bbca7 4406 return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding
stevep 0:04a9f72bbca7 4407
stevep 0:04a9f72bbca7 4408 uint i = 0;
stevep 0:04a9f72bbca7 4409 char_type digit;
stevep 0:04a9f72bbca7 4410
stevep 0:04a9f72bbca7 4411 if( new_exp >= -sint(new_man.size()) )
stevep 0:04a9f72bbca7 4412 {
stevep 0:04a9f72bbca7 4413 uint new_exp_abs = -new_exp.ToInt();
stevep 0:04a9f72bbca7 4414 i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator
stevep 0:04a9f72bbca7 4415 }
stevep 0:04a9f72bbca7 4416
stevep 0:04a9f72bbca7 4417 if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 )
stevep 0:04a9f72bbca7 4418 {
stevep 0:04a9f72bbca7 4419 if( new_exp < -sint(new_man.size()) )
stevep 0:04a9f72bbca7 4420 {
stevep 0:04a9f72bbca7 4421 // there are some zeroes after the comma operator
stevep 0:04a9f72bbca7 4422 // (between the comma and the first digit from the mantissa)
stevep 0:04a9f72bbca7 4423 // and the result value will never be an integer
stevep 0:04a9f72bbca7 4424 return false;
stevep 0:04a9f72bbca7 4425 }
stevep 0:04a9f72bbca7 4426
stevep 0:04a9f72bbca7 4427 digit = static_cast<char_type>( Misc::DigitToChar(conv.base-1) );
stevep 0:04a9f72bbca7 4428 }
stevep 0:04a9f72bbca7 4429 else
stevep 0:04a9f72bbca7 4430 {
stevep 0:04a9f72bbca7 4431 digit = '0';
stevep 0:04a9f72bbca7 4432 }
stevep 0:04a9f72bbca7 4433
stevep 0:04a9f72bbca7 4434 for( ; i < new_man.size()-1 ; ++i)
stevep 0:04a9f72bbca7 4435 if( new_man[i] != digit )
stevep 0:04a9f72bbca7 4436 return false; // it will not be an integer
stevep 0:04a9f72bbca7 4437
stevep 0:04a9f72bbca7 4438 return true; // it will be integer after rounding
stevep 0:04a9f72bbca7 4439 }
stevep 0:04a9f72bbca7 4440
stevep 0:04a9f72bbca7 4441
stevep 0:04a9f72bbca7 4442 /*!
stevep 0:04a9f72bbca7 4443 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4444 (when this is integer)
stevep 0:04a9f72bbca7 4445
stevep 0:04a9f72bbca7 4446 after floating point calculating the new mantissa can consist of some fraction
stevep 0:04a9f72bbca7 4447 so if our value is integer we should check the new mantissa
stevep 0:04a9f72bbca7 4448 (after the decimal point there should be only zeroes)
stevep 0:04a9f72bbca7 4449
stevep 0:04a9f72bbca7 4450 often this is a last digit different from zero
stevep 0:04a9f72bbca7 4451 ToString_BaseRound would not get rid of it because the method make a test against
stevep 0:04a9f72bbca7 4452 an integer value (ToString_RoundMantissaWouldBeInteger) and returns immediately
stevep 0:04a9f72bbca7 4453 */
stevep 0:04a9f72bbca7 4454 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4455 void ToString_CheckMantissaInteger(string_type & new_man, const Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4456 {
stevep 0:04a9f72bbca7 4457 if( !new_exp.IsSign() )
stevep 0:04a9f72bbca7 4458 return; // return if new_exp >= 0
stevep 0:04a9f72bbca7 4459
stevep 0:04a9f72bbca7 4460 uint i = 0;
stevep 0:04a9f72bbca7 4461 uint man_size = new_man.size();
stevep 0:04a9f72bbca7 4462
stevep 0:04a9f72bbca7 4463 if( man_size >= TTMATH_UINT_HIGHEST_BIT )
stevep 0:04a9f72bbca7 4464 return; // ops, the mantissa is too long
stevep 0:04a9f72bbca7 4465
stevep 0:04a9f72bbca7 4466 sint sman_size = -sint(man_size);
stevep 0:04a9f72bbca7 4467
stevep 0:04a9f72bbca7 4468 if( new_exp >= sman_size )
stevep 0:04a9f72bbca7 4469 {
stevep 0:04a9f72bbca7 4470 sint e = new_exp.ToInt();
stevep 0:04a9f72bbca7 4471 e = -e;
stevep 0:04a9f72bbca7 4472 // now e means how many last digits from the mantissa should be equal zero
stevep 0:04a9f72bbca7 4473
stevep 0:04a9f72bbca7 4474 i = man_size - uint(e);
stevep 0:04a9f72bbca7 4475 }
stevep 0:04a9f72bbca7 4476
stevep 0:04a9f72bbca7 4477 for( ; i<man_size ; ++i)
stevep 0:04a9f72bbca7 4478 new_man[i] = '0';
stevep 0:04a9f72bbca7 4479 }
stevep 0:04a9f72bbca7 4480
stevep 0:04a9f72bbca7 4481
stevep 0:04a9f72bbca7 4482 /*!
stevep 0:04a9f72bbca7 4483 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4484
stevep 0:04a9f72bbca7 4485 this method is used for base!=2, base!=4, base!=8 and base!=16
stevep 0:04a9f72bbca7 4486 we do the rounding when the value has fraction (is not an integer)
stevep 0:04a9f72bbca7 4487 */
stevep 0:04a9f72bbca7 4488 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4489 uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4490 {
stevep 0:04a9f72bbca7 4491 // we must have minimum two characters
stevep 0:04a9f72bbca7 4492 if( new_man.size() < 2 )
stevep 0:04a9f72bbca7 4493 return 0;
stevep 0:04a9f72bbca7 4494
stevep 0:04a9f72bbca7 4495 // assert that there will not be an integer after rounding
stevep 0:04a9f72bbca7 4496 if( ToString_RoundMantissaWouldBeInteger<string_type, char_type>(new_man, conv, new_exp) )
stevep 0:04a9f72bbca7 4497 return 0;
stevep 0:04a9f72bbca7 4498
stevep 0:04a9f72bbca7 4499 typename string_type::size_type i = new_man.length() - 1;
stevep 0:04a9f72bbca7 4500
stevep 0:04a9f72bbca7 4501 // we're erasing the last character
stevep 0:04a9f72bbca7 4502 uint digit = Misc::CharToDigit( new_man[i] );
stevep 0:04a9f72bbca7 4503 new_man.erase(i, 1);
stevep 0:04a9f72bbca7 4504 uint c = new_exp.AddOne();
stevep 0:04a9f72bbca7 4505
stevep 0:04a9f72bbca7 4506 // if the last character is greater or equal 'base/2'
stevep 0:04a9f72bbca7 4507 // we are adding one into the new mantissa
stevep 0:04a9f72bbca7 4508 if( digit >= conv.base / 2 )
stevep 0:04a9f72bbca7 4509 ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4510
stevep 0:04a9f72bbca7 4511 return c;
stevep 0:04a9f72bbca7 4512 }
stevep 0:04a9f72bbca7 4513
stevep 0:04a9f72bbca7 4514
stevep 0:04a9f72bbca7 4515 /*!
stevep 0:04a9f72bbca7 4516 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4517
stevep 0:04a9f72bbca7 4518 this method addes one into the new mantissa
stevep 0:04a9f72bbca7 4519 */
stevep 0:04a9f72bbca7 4520 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4521 void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const
stevep 0:04a9f72bbca7 4522 {
stevep 0:04a9f72bbca7 4523 if( new_man.empty() )
stevep 0:04a9f72bbca7 4524 return;
stevep 0:04a9f72bbca7 4525
stevep 0:04a9f72bbca7 4526 sint i = sint( new_man.length() ) - 1;
stevep 0:04a9f72bbca7 4527 bool was_carry = true;
stevep 0:04a9f72bbca7 4528
stevep 0:04a9f72bbca7 4529 for( ; i>=0 && was_carry ; --i )
stevep 0:04a9f72bbca7 4530 {
stevep 0:04a9f72bbca7 4531 // we can have the comma as well because
stevep 0:04a9f72bbca7 4532 // we're using this method later in ToString_CorrectDigitsAfterComma_Round()
stevep 0:04a9f72bbca7 4533 // (we're only ignoring it)
stevep 0:04a9f72bbca7 4534 if( new_man[i] == static_cast<char_type>(conv.comma) )
stevep 0:04a9f72bbca7 4535 continue;
stevep 0:04a9f72bbca7 4536
stevep 0:04a9f72bbca7 4537 // we're adding one
stevep 0:04a9f72bbca7 4538 uint digit = Misc::CharToDigit( new_man[i] ) + 1;
stevep 0:04a9f72bbca7 4539
stevep 0:04a9f72bbca7 4540 if( digit == conv.base )
stevep 0:04a9f72bbca7 4541 digit = 0;
stevep 0:04a9f72bbca7 4542 else
stevep 0:04a9f72bbca7 4543 was_carry = false;
stevep 0:04a9f72bbca7 4544
stevep 0:04a9f72bbca7 4545 new_man[i] = static_cast<char_type>( Misc::DigitToChar(digit) );
stevep 0:04a9f72bbca7 4546 }
stevep 0:04a9f72bbca7 4547
stevep 0:04a9f72bbca7 4548 if( i<0 && was_carry )
stevep 0:04a9f72bbca7 4549 new_man.insert( new_man.begin() , '1' );
stevep 0:04a9f72bbca7 4550 }
stevep 0:04a9f72bbca7 4551
stevep 0:04a9f72bbca7 4552
stevep 0:04a9f72bbca7 4553
stevep 0:04a9f72bbca7 4554 /*!
stevep 0:04a9f72bbca7 4555 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4556
stevep 0:04a9f72bbca7 4557 this method sets the comma operator and/or puts the exponent
stevep 0:04a9f72bbca7 4558 into the string
stevep 0:04a9f72bbca7 4559 */
stevep 0:04a9f72bbca7 4560 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4561 uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4562 {
stevep 0:04a9f72bbca7 4563 uint carry = 0;
stevep 0:04a9f72bbca7 4564
stevep 0:04a9f72bbca7 4565 if( new_man.empty() )
stevep 0:04a9f72bbca7 4566 return carry;
stevep 0:04a9f72bbca7 4567
stevep 0:04a9f72bbca7 4568 Int<exp+1> scientific_exp( new_exp );
stevep 0:04a9f72bbca7 4569
stevep 0:04a9f72bbca7 4570 // 'new_exp' depends on the 'new_man' which is stored like this e.g:
stevep 0:04a9f72bbca7 4571 // 32342343234 (the comma is at the end)
stevep 0:04a9f72bbca7 4572 // we'd like to show it in this way:
stevep 0:04a9f72bbca7 4573 // 3.2342343234 (the 'scientific_exp' is connected with this example)
stevep 0:04a9f72bbca7 4574
stevep 0:04a9f72bbca7 4575 sint offset = sint( new_man.length() ) - 1;
stevep 0:04a9f72bbca7 4576 carry += scientific_exp.Add( offset );
stevep 0:04a9f72bbca7 4577 // there shouldn't have been a carry because we're using
stevep 0:04a9f72bbca7 4578 // a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
stevep 0:04a9f72bbca7 4579
stevep 0:04a9f72bbca7 4580 bool print_scientific = conv.scient;
stevep 0:04a9f72bbca7 4581
stevep 0:04a9f72bbca7 4582 if( !print_scientific )
stevep 0:04a9f72bbca7 4583 {
stevep 0:04a9f72bbca7 4584 if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) )
stevep 0:04a9f72bbca7 4585 print_scientific = true;
stevep 0:04a9f72bbca7 4586 }
stevep 0:04a9f72bbca7 4587
stevep 0:04a9f72bbca7 4588 if( !print_scientific )
stevep 0:04a9f72bbca7 4589 ToString_SetCommaAndExponent_Normal<string_type, char_type>(new_man, conv, new_exp);
stevep 0:04a9f72bbca7 4590 else
stevep 0:04a9f72bbca7 4591 // we're passing the 'scientific_exp' instead of 'new_exp' here
stevep 0:04a9f72bbca7 4592 ToString_SetCommaAndExponent_Scientific<string_type, char_type>(new_man, conv, scientific_exp);
stevep 0:04a9f72bbca7 4593
stevep 0:04a9f72bbca7 4594 return (carry==0)? 0 : 1;
stevep 0:04a9f72bbca7 4595 }
stevep 0:04a9f72bbca7 4596
stevep 0:04a9f72bbca7 4597
stevep 0:04a9f72bbca7 4598 /*!
stevep 0:04a9f72bbca7 4599 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4600 */
stevep 0:04a9f72bbca7 4601 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4602 void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int<exp+1> & new_exp ) const
stevep 0:04a9f72bbca7 4603 {
stevep 0:04a9f72bbca7 4604 if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 )
stevep 0:04a9f72bbca7 4605 ToString_SetCommaAndExponent_Normal_AddingZero<string_type, char_type>(new_man, new_exp);
stevep 0:04a9f72bbca7 4606 else
stevep 0:04a9f72bbca7 4607 ToString_SetCommaAndExponent_Normal_SetCommaInside<string_type, char_type>(new_man, conv, new_exp);
stevep 0:04a9f72bbca7 4608
stevep 0:04a9f72bbca7 4609
stevep 0:04a9f72bbca7 4610 ToString_Group_man<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4611 }
stevep 0:04a9f72bbca7 4612
stevep 0:04a9f72bbca7 4613
stevep 0:04a9f72bbca7 4614 /*!
stevep 0:04a9f72bbca7 4615 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4616 */
stevep 0:04a9f72bbca7 4617 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4618 void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man,
stevep 0:04a9f72bbca7 4619 Int<exp+1> & new_exp) const
stevep 0:04a9f72bbca7 4620 {
stevep 0:04a9f72bbca7 4621 // we're adding zero characters at the end
stevep 0:04a9f72bbca7 4622 // 'i' will be smaller than 'when_scientific' (or equal)
stevep 0:04a9f72bbca7 4623 uint i = new_exp.ToInt();
stevep 0:04a9f72bbca7 4624
stevep 0:04a9f72bbca7 4625 if( new_man.length() + i > new_man.capacity() )
stevep 0:04a9f72bbca7 4626 // about 6 characters more (we'll need it for the comma or something)
stevep 0:04a9f72bbca7 4627 new_man.reserve( new_man.length() + i + 6 );
stevep 0:04a9f72bbca7 4628
stevep 0:04a9f72bbca7 4629 for( ; i>0 ; --i)
stevep 0:04a9f72bbca7 4630 new_man += '0';
stevep 0:04a9f72bbca7 4631 }
stevep 0:04a9f72bbca7 4632
stevep 0:04a9f72bbca7 4633
stevep 0:04a9f72bbca7 4634 /*!
stevep 0:04a9f72bbca7 4635 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4636 */
stevep 0:04a9f72bbca7 4637 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4638 void ToString_SetCommaAndExponent_Normal_SetCommaInside(
stevep 0:04a9f72bbca7 4639 string_type & new_man,
stevep 0:04a9f72bbca7 4640 const Conv & conv,
stevep 0:04a9f72bbca7 4641 Int<exp+1> & new_exp ) const
stevep 0:04a9f72bbca7 4642 {
stevep 0:04a9f72bbca7 4643 // new_exp is < 0
stevep 0:04a9f72bbca7 4644
stevep 0:04a9f72bbca7 4645 sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign
stevep 0:04a9f72bbca7 4646 sint e = -( new_exp.ToInt() ); // 'e' will be positive
stevep 0:04a9f72bbca7 4647
stevep 0:04a9f72bbca7 4648 if( new_exp > -new_man_len )
stevep 0:04a9f72bbca7 4649 {
stevep 0:04a9f72bbca7 4650 // we're setting the comma within the mantissa
stevep 0:04a9f72bbca7 4651
stevep 0:04a9f72bbca7 4652 sint index = new_man_len - e;
stevep 0:04a9f72bbca7 4653 new_man.insert( new_man.begin() + index, static_cast<char_type>(conv.comma));
stevep 0:04a9f72bbca7 4654 }
stevep 0:04a9f72bbca7 4655 else
stevep 0:04a9f72bbca7 4656 {
stevep 0:04a9f72bbca7 4657 // we're adding zero characters before the mantissa
stevep 0:04a9f72bbca7 4658
stevep 0:04a9f72bbca7 4659 uint how_many = e - new_man_len;
stevep 0:04a9f72bbca7 4660 string_type man_temp(how_many+1, '0');
stevep 0:04a9f72bbca7 4661
stevep 0:04a9f72bbca7 4662 man_temp.insert( man_temp.begin()+1, static_cast<char_type>(conv.comma));
stevep 0:04a9f72bbca7 4663 new_man.insert(0, man_temp);
stevep 0:04a9f72bbca7 4664 }
stevep 0:04a9f72bbca7 4665
stevep 0:04a9f72bbca7 4666 ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4667 }
stevep 0:04a9f72bbca7 4668
stevep 0:04a9f72bbca7 4669
stevep 0:04a9f72bbca7 4670 /*!
stevep 0:04a9f72bbca7 4671 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4672 */
stevep 0:04a9f72bbca7 4673 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4674 void ToString_SetCommaAndExponent_Scientific( string_type & new_man,
stevep 0:04a9f72bbca7 4675 const Conv & conv,
stevep 0:04a9f72bbca7 4676 Int<exp+1> & scientific_exp ) const
stevep 0:04a9f72bbca7 4677 {
stevep 0:04a9f72bbca7 4678 if( new_man.empty() )
stevep 0:04a9f72bbca7 4679 return;
stevep 0:04a9f72bbca7 4680
stevep 0:04a9f72bbca7 4681 if( new_man.size() > 1 )
stevep 0:04a9f72bbca7 4682 {
stevep 0:04a9f72bbca7 4683 new_man.insert( new_man.begin()+1, static_cast<char_type>(conv.comma) );
stevep 0:04a9f72bbca7 4684 ToString_CorrectDigitsAfterComma<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4685 }
stevep 0:04a9f72bbca7 4686
stevep 0:04a9f72bbca7 4687 ToString_Group_man<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4688
stevep 0:04a9f72bbca7 4689 if( conv.base == 10 )
stevep 0:04a9f72bbca7 4690 {
stevep 0:04a9f72bbca7 4691 new_man += 'e';
stevep 0:04a9f72bbca7 4692
stevep 0:04a9f72bbca7 4693 if( !scientific_exp.IsSign() )
stevep 0:04a9f72bbca7 4694 new_man += '+';
stevep 0:04a9f72bbca7 4695 }
stevep 0:04a9f72bbca7 4696 else
stevep 0:04a9f72bbca7 4697 {
stevep 0:04a9f72bbca7 4698 // the 10 here is meant as the base 'base'
stevep 0:04a9f72bbca7 4699 // (no matter which 'base' we're using there'll always be 10 here)
stevep 0:04a9f72bbca7 4700 Misc::AddString(new_man, "*10^");
stevep 0:04a9f72bbca7 4701 }
stevep 0:04a9f72bbca7 4702
stevep 0:04a9f72bbca7 4703 string_type temp_exp;
stevep 0:04a9f72bbca7 4704 scientific_exp.ToString( temp_exp, conv.base );
stevep 0:04a9f72bbca7 4705
stevep 0:04a9f72bbca7 4706 new_man += temp_exp;
stevep 0:04a9f72bbca7 4707 }
stevep 0:04a9f72bbca7 4708
stevep 0:04a9f72bbca7 4709
stevep 0:04a9f72bbca7 4710 /*!
stevep 0:04a9f72bbca7 4711 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4712 */
stevep 0:04a9f72bbca7 4713 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4714 void ToString_Group_man(string_type & new_man, const Conv & conv) const
stevep 0:04a9f72bbca7 4715 {
stevep 0:04a9f72bbca7 4716 typedef typename string_type::size_type StrSize;
stevep 0:04a9f72bbca7 4717
stevep 0:04a9f72bbca7 4718 if( conv.group == 0 )
stevep 0:04a9f72bbca7 4719 return;
stevep 0:04a9f72bbca7 4720
stevep 0:04a9f72bbca7 4721 // first we're looking for the comma operator
stevep 0:04a9f72bbca7 4722 StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
stevep 0:04a9f72bbca7 4723
stevep 0:04a9f72bbca7 4724 if( index == string_type::npos )
stevep 0:04a9f72bbca7 4725 index = new_man.size();
stevep 0:04a9f72bbca7 4726
stevep 0:04a9f72bbca7 4727 ToString_Group_man_before_comma<string_type, char_type>(new_man, conv, index);
stevep 0:04a9f72bbca7 4728 ToString_Group_man_after_comma<string_type, char_type>(new_man, conv, index+1);
stevep 0:04a9f72bbca7 4729 }
stevep 0:04a9f72bbca7 4730
stevep 0:04a9f72bbca7 4731
stevep 0:04a9f72bbca7 4732
stevep 0:04a9f72bbca7 4733 /*!
stevep 0:04a9f72bbca7 4734 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4735 */
stevep 0:04a9f72bbca7 4736 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4737 void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv,
stevep 0:04a9f72bbca7 4738 typename string_type::size_type & index) const
stevep 0:04a9f72bbca7 4739 {
stevep 0:04a9f72bbca7 4740 typedef typename string_type::size_type StrSize;
stevep 0:04a9f72bbca7 4741
stevep 0:04a9f72bbca7 4742 uint group = 0;
stevep 0:04a9f72bbca7 4743 StrSize i = index;
stevep 0:04a9f72bbca7 4744 uint group_digits = conv.group_digits;
stevep 0:04a9f72bbca7 4745
stevep 0:04a9f72bbca7 4746 if( group_digits < 1 )
stevep 0:04a9f72bbca7 4747 group_digits = 1;
stevep 0:04a9f72bbca7 4748
stevep 0:04a9f72bbca7 4749 // adding group characters before the comma operator
stevep 0:04a9f72bbca7 4750 // i>0 because on the first position we don't put any additional grouping characters
stevep 0:04a9f72bbca7 4751 for( ; i>0 ; --i, ++group)
stevep 0:04a9f72bbca7 4752 {
stevep 0:04a9f72bbca7 4753 if( group >= group_digits )
stevep 0:04a9f72bbca7 4754 {
stevep 0:04a9f72bbca7 4755 group = 0;
stevep 0:04a9f72bbca7 4756 new_man.insert(i, 1, static_cast<char_type>(conv.group));
stevep 0:04a9f72bbca7 4757 ++index;
stevep 0:04a9f72bbca7 4758 }
stevep 0:04a9f72bbca7 4759 }
stevep 0:04a9f72bbca7 4760 }
stevep 0:04a9f72bbca7 4761
stevep 0:04a9f72bbca7 4762
stevep 0:04a9f72bbca7 4763 /*!
stevep 0:04a9f72bbca7 4764 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4765 */
stevep 0:04a9f72bbca7 4766 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4767 void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv,
stevep 0:04a9f72bbca7 4768 typename string_type::size_type index) const
stevep 0:04a9f72bbca7 4769 {
stevep 0:04a9f72bbca7 4770 uint group = 0;
stevep 0:04a9f72bbca7 4771 uint group_digits = conv.group_digits;
stevep 0:04a9f72bbca7 4772
stevep 0:04a9f72bbca7 4773 if( group_digits < 1 )
stevep 0:04a9f72bbca7 4774 group_digits = 1;
stevep 0:04a9f72bbca7 4775
stevep 0:04a9f72bbca7 4776 for( ; index<new_man.size() ; ++index, ++group)
stevep 0:04a9f72bbca7 4777 {
stevep 0:04a9f72bbca7 4778 if( group >= group_digits )
stevep 0:04a9f72bbca7 4779 {
stevep 0:04a9f72bbca7 4780 group = 0;
stevep 0:04a9f72bbca7 4781 new_man.insert(index, 1, static_cast<char_type>(conv.group));
stevep 0:04a9f72bbca7 4782 ++index;
stevep 0:04a9f72bbca7 4783 }
stevep 0:04a9f72bbca7 4784 }
stevep 0:04a9f72bbca7 4785 }
stevep 0:04a9f72bbca7 4786
stevep 0:04a9f72bbca7 4787
stevep 0:04a9f72bbca7 4788 /*!
stevep 0:04a9f72bbca7 4789 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4790 */
stevep 0:04a9f72bbca7 4791 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4792 void ToString_CorrectDigitsAfterComma( string_type & new_man,
stevep 0:04a9f72bbca7 4793 const Conv & conv ) const
stevep 0:04a9f72bbca7 4794 {
stevep 0:04a9f72bbca7 4795 if( conv.round >= 0 )
stevep 0:04a9f72bbca7 4796 ToString_CorrectDigitsAfterComma_Round<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4797
stevep 0:04a9f72bbca7 4798 if( conv.trim_zeroes )
stevep 0:04a9f72bbca7 4799 ToString_CorrectDigitsAfterComma_CutOffZeroCharacters<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4800 }
stevep 0:04a9f72bbca7 4801
stevep 0:04a9f72bbca7 4802
stevep 0:04a9f72bbca7 4803 /*!
stevep 0:04a9f72bbca7 4804 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4805 */
stevep 0:04a9f72bbca7 4806 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4807 void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(
stevep 0:04a9f72bbca7 4808 string_type & new_man,
stevep 0:04a9f72bbca7 4809 const Conv & conv) const
stevep 0:04a9f72bbca7 4810 {
stevep 0:04a9f72bbca7 4811 // minimum two characters
stevep 0:04a9f72bbca7 4812 if( new_man.length() < 2 )
stevep 0:04a9f72bbca7 4813 return;
stevep 0:04a9f72bbca7 4814
stevep 0:04a9f72bbca7 4815 // we're looking for the index of the last character which is not zero
stevep 0:04a9f72bbca7 4816 uint i = uint( new_man.length() ) - 1;
stevep 0:04a9f72bbca7 4817 for( ; i>0 && new_man[i]=='0' ; --i );
stevep 0:04a9f72bbca7 4818
stevep 0:04a9f72bbca7 4819 // if there is another character than zero at the end
stevep 0:04a9f72bbca7 4820 // we're finishing
stevep 0:04a9f72bbca7 4821 if( i == new_man.length() - 1 )
stevep 0:04a9f72bbca7 4822 return;
stevep 0:04a9f72bbca7 4823
stevep 0:04a9f72bbca7 4824 // we must have a comma
stevep 0:04a9f72bbca7 4825 // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round
stevep 0:04a9f72bbca7 4826 // which is called before)
stevep 0:04a9f72bbca7 4827 if( new_man.find_last_of(static_cast<char_type>(conv.comma), i) == string_type::npos )
stevep 0:04a9f72bbca7 4828 return;
stevep 0:04a9f72bbca7 4829
stevep 0:04a9f72bbca7 4830 // if directly before the first zero is the comma operator
stevep 0:04a9f72bbca7 4831 // we're cutting it as well
stevep 0:04a9f72bbca7 4832 if( i>0 && new_man[i]==static_cast<char_type>(conv.comma) )
stevep 0:04a9f72bbca7 4833 --i;
stevep 0:04a9f72bbca7 4834
stevep 0:04a9f72bbca7 4835 new_man.erase(i+1, new_man.length()-i-1);
stevep 0:04a9f72bbca7 4836 }
stevep 0:04a9f72bbca7 4837
stevep 0:04a9f72bbca7 4838
stevep 0:04a9f72bbca7 4839 /*!
stevep 0:04a9f72bbca7 4840 an auxiliary method for converting into the string
stevep 0:04a9f72bbca7 4841 */
stevep 0:04a9f72bbca7 4842 template<class string_type, class char_type>
stevep 0:04a9f72bbca7 4843 void ToString_CorrectDigitsAfterComma_Round(
stevep 0:04a9f72bbca7 4844 string_type & new_man,
stevep 0:04a9f72bbca7 4845 const Conv & conv ) const
stevep 0:04a9f72bbca7 4846 {
stevep 0:04a9f72bbca7 4847 typedef typename string_type::size_type StrSize;
stevep 0:04a9f72bbca7 4848
stevep 0:04a9f72bbca7 4849 // first we're looking for the comma operator
stevep 0:04a9f72bbca7 4850 StrSize index = new_man.find(static_cast<char_type>(conv.comma), 0);
stevep 0:04a9f72bbca7 4851
stevep 0:04a9f72bbca7 4852 if( index == string_type::npos )
stevep 0:04a9f72bbca7 4853 // nothing was found (actually there can't be this situation)
stevep 0:04a9f72bbca7 4854 return;
stevep 0:04a9f72bbca7 4855
stevep 0:04a9f72bbca7 4856 // we're calculating how many digits there are at the end (after the comma)
stevep 0:04a9f72bbca7 4857 // 'after_comma' will be greater than zero because at the end
stevep 0:04a9f72bbca7 4858 // we have at least one digit
stevep 0:04a9f72bbca7 4859 StrSize after_comma = new_man.length() - index - 1;
stevep 0:04a9f72bbca7 4860
stevep 0:04a9f72bbca7 4861 // if 'max_digit_after_comma' is greater than 'after_comma' (or equal)
stevep 0:04a9f72bbca7 4862 // we don't have anything for cutting
stevep 0:04a9f72bbca7 4863 if( static_cast<StrSize>(conv.round) >= after_comma )
stevep 0:04a9f72bbca7 4864 return;
stevep 0:04a9f72bbca7 4865
stevep 0:04a9f72bbca7 4866 uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base );
stevep 0:04a9f72bbca7 4867
stevep 0:04a9f72bbca7 4868 // we're cutting the rest of the string
stevep 0:04a9f72bbca7 4869 new_man.erase(index + conv.round + 1, after_comma - conv.round);
stevep 0:04a9f72bbca7 4870
stevep 0:04a9f72bbca7 4871 if( conv.round == 0 )
stevep 0:04a9f72bbca7 4872 {
stevep 0:04a9f72bbca7 4873 // we're cutting the comma operator as well
stevep 0:04a9f72bbca7 4874 // (it's not needed now because we've cut the whole rest after the comma)
stevep 0:04a9f72bbca7 4875 new_man.erase(index, 1);
stevep 0:04a9f72bbca7 4876 }
stevep 0:04a9f72bbca7 4877
stevep 0:04a9f72bbca7 4878 if( last_digit >= conv.base / 2 )
stevep 0:04a9f72bbca7 4879 // we must round here
stevep 0:04a9f72bbca7 4880 ToString_RoundMantissa_AddOneIntoMantissa<string_type, char_type>(new_man, conv);
stevep 0:04a9f72bbca7 4881 }
stevep 0:04a9f72bbca7 4882
stevep 0:04a9f72bbca7 4883
stevep 0:04a9f72bbca7 4884
stevep 0:04a9f72bbca7 4885 public:
stevep 0:04a9f72bbca7 4886
stevep 0:04a9f72bbca7 4887 /*!
stevep 0:04a9f72bbca7 4888 a method for converting a string into its value
stevep 0:04a9f72bbca7 4889
stevep 0:04a9f72bbca7 4890 it returns 1 if the value is too big -- we cannot pass it into the range
stevep 0:04a9f72bbca7 4891 of our class Big<exp,man> (or if the base is incorrect)
stevep 0:04a9f72bbca7 4892
stevep 0:04a9f72bbca7 4893 that means only digits before the comma operator can make this value too big,
stevep 0:04a9f72bbca7 4894 all digits after the comma we can ignore
stevep 0:04a9f72bbca7 4895
stevep 0:04a9f72bbca7 4896 'source' - pointer to the string for parsing
stevep 0:04a9f72bbca7 4897
stevep 0:04a9f72bbca7 4898 if 'after_source' is set that when this method finishes
stevep 0:04a9f72bbca7 4899 it sets the pointer to the new first character after parsed value
stevep 0:04a9f72bbca7 4900
stevep 0:04a9f72bbca7 4901 'value_read' - if the pointer is provided that means the value_read will be true
stevep 0:04a9f72bbca7 4902 only when a value has been actually read, there can be situation where only such
stevep 0:04a9f72bbca7 4903 a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but
stevep 0:04a9f72bbca7 4904 no value has been read (there are no digits)
stevep 0:04a9f72bbca7 4905 on other words if 'value_read' is true -- there is at least one digit in the string
stevep 0:04a9f72bbca7 4906 */
stevep 0:04a9f72bbca7 4907 uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4908 {
stevep 0:04a9f72bbca7 4909 Conv conv;
stevep 0:04a9f72bbca7 4910 conv.base = base;
stevep 0:04a9f72bbca7 4911
stevep 0:04a9f72bbca7 4912 return FromStringBase(source, conv, after_source, value_read);
stevep 0:04a9f72bbca7 4913 }
stevep 0:04a9f72bbca7 4914
stevep 0:04a9f72bbca7 4915
stevep 0:04a9f72bbca7 4916 /*!
stevep 0:04a9f72bbca7 4917 a method for converting a string into its value
stevep 0:04a9f72bbca7 4918 */
stevep 0:04a9f72bbca7 4919 uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4920 {
stevep 0:04a9f72bbca7 4921 return FromStringBase(source, conv, after_source, value_read);
stevep 0:04a9f72bbca7 4922 }
stevep 0:04a9f72bbca7 4923
stevep 0:04a9f72bbca7 4924
stevep 0:04a9f72bbca7 4925 /*!
stevep 0:04a9f72bbca7 4926 a method for converting a string into its value
stevep 0:04a9f72bbca7 4927 */
stevep 0:04a9f72bbca7 4928 uint FromString(const std::string & string, uint base = 10, const char ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4929 {
stevep 0:04a9f72bbca7 4930 return FromString(string.c_str(), base, after_source, value_read);
stevep 0:04a9f72bbca7 4931 }
stevep 0:04a9f72bbca7 4932
stevep 0:04a9f72bbca7 4933
stevep 0:04a9f72bbca7 4934 /*!
stevep 0:04a9f72bbca7 4935 a method for converting a string into its value
stevep 0:04a9f72bbca7 4936 */
stevep 0:04a9f72bbca7 4937 uint FromString(const std::string & string, const Conv & conv, const char ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4938 {
stevep 0:04a9f72bbca7 4939 return FromString(string.c_str(), conv, after_source, value_read);
stevep 0:04a9f72bbca7 4940 }
stevep 0:04a9f72bbca7 4941
stevep 0:04a9f72bbca7 4942
stevep 0:04a9f72bbca7 4943 #ifndef TTMATH_DONT_USE_WCHAR
stevep 0:04a9f72bbca7 4944
stevep 0:04a9f72bbca7 4945 /*!
stevep 0:04a9f72bbca7 4946 a method for converting a string into its value
stevep 0:04a9f72bbca7 4947 */
stevep 0:04a9f72bbca7 4948 uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4949 {
stevep 0:04a9f72bbca7 4950 Conv conv;
stevep 0:04a9f72bbca7 4951 conv.base = base;
stevep 0:04a9f72bbca7 4952
stevep 0:04a9f72bbca7 4953 return FromStringBase(source, conv, after_source, value_read);
stevep 0:04a9f72bbca7 4954 }
stevep 0:04a9f72bbca7 4955
stevep 0:04a9f72bbca7 4956
stevep 0:04a9f72bbca7 4957 /*!
stevep 0:04a9f72bbca7 4958 a method for converting a string into its value
stevep 0:04a9f72bbca7 4959 */
stevep 0:04a9f72bbca7 4960 uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4961 {
stevep 0:04a9f72bbca7 4962 return FromStringBase(source, conv, after_source, value_read);
stevep 0:04a9f72bbca7 4963 }
stevep 0:04a9f72bbca7 4964
stevep 0:04a9f72bbca7 4965
stevep 0:04a9f72bbca7 4966 /*!
stevep 0:04a9f72bbca7 4967 a method for converting a string into its value
stevep 0:04a9f72bbca7 4968 */
stevep 0:04a9f72bbca7 4969 uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4970 {
stevep 0:04a9f72bbca7 4971 return FromString(string.c_str(), base, after_source, value_read);
stevep 0:04a9f72bbca7 4972 }
stevep 0:04a9f72bbca7 4973
stevep 0:04a9f72bbca7 4974
stevep 0:04a9f72bbca7 4975 /*!
stevep 0:04a9f72bbca7 4976 a method for converting a string into its value
stevep 0:04a9f72bbca7 4977 */
stevep 0:04a9f72bbca7 4978 uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4979 {
stevep 0:04a9f72bbca7 4980 return FromString(string.c_str(), conv, after_source, value_read);
stevep 0:04a9f72bbca7 4981 }
stevep 0:04a9f72bbca7 4982
stevep 0:04a9f72bbca7 4983 #endif
stevep 0:04a9f72bbca7 4984
stevep 0:04a9f72bbca7 4985
stevep 0:04a9f72bbca7 4986 private:
stevep 0:04a9f72bbca7 4987
stevep 0:04a9f72bbca7 4988
stevep 0:04a9f72bbca7 4989 /*!
stevep 0:04a9f72bbca7 4990 an auxiliary method for converting from a string
stevep 0:04a9f72bbca7 4991 */
stevep 0:04a9f72bbca7 4992 template<class char_type>
stevep 0:04a9f72bbca7 4993 uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0)
stevep 0:04a9f72bbca7 4994 {
stevep 0:04a9f72bbca7 4995 bool is_sign;
stevep 0:04a9f72bbca7 4996 bool value_read_temp = false;
stevep 0:04a9f72bbca7 4997
stevep 0:04a9f72bbca7 4998 if( conv.base<2 || conv.base>16 )
stevep 0:04a9f72bbca7 4999 {
stevep 0:04a9f72bbca7 5000 SetNan();
stevep 0:04a9f72bbca7 5001
stevep 0:04a9f72bbca7 5002 if( after_source )
stevep 0:04a9f72bbca7 5003 *after_source = source;
stevep 0:04a9f72bbca7 5004
stevep 0:04a9f72bbca7 5005 if( value_read )
stevep 0:04a9f72bbca7 5006 *value_read = value_read_temp;
stevep 0:04a9f72bbca7 5007
stevep 0:04a9f72bbca7 5008 return 1;
stevep 0:04a9f72bbca7 5009 }
stevep 0:04a9f72bbca7 5010
stevep 0:04a9f72bbca7 5011 SetZero();
stevep 0:04a9f72bbca7 5012 FromString_TestSign( source, is_sign );
stevep 0:04a9f72bbca7 5013
stevep 0:04a9f72bbca7 5014 uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp );
stevep 0:04a9f72bbca7 5015
stevep 0:04a9f72bbca7 5016 if( FromString_TestCommaOperator(source, conv) )
stevep 0:04a9f72bbca7 5017 c += FromString_ReadPartAfterComma( source, conv, value_read_temp );
stevep 0:04a9f72bbca7 5018
stevep 0:04a9f72bbca7 5019 if( value_read_temp && conv.base == 10 )
stevep 0:04a9f72bbca7 5020 c += FromString_ReadScientificIfExists( source );
stevep 0:04a9f72bbca7 5021
stevep 0:04a9f72bbca7 5022 if( is_sign && !IsZero() )
stevep 0:04a9f72bbca7 5023 ChangeSign();
stevep 0:04a9f72bbca7 5024
stevep 0:04a9f72bbca7 5025 if( after_source )
stevep 0:04a9f72bbca7 5026 *after_source = source;
stevep 0:04a9f72bbca7 5027
stevep 0:04a9f72bbca7 5028 if( value_read )
stevep 0:04a9f72bbca7 5029 *value_read = value_read_temp;
stevep 0:04a9f72bbca7 5030
stevep 0:04a9f72bbca7 5031 return CheckCarry(c);
stevep 0:04a9f72bbca7 5032 }
stevep 0:04a9f72bbca7 5033
stevep 0:04a9f72bbca7 5034
stevep 0:04a9f72bbca7 5035 /*!
stevep 0:04a9f72bbca7 5036 we're testing whether the value is with the sign
stevep 0:04a9f72bbca7 5037
stevep 0:04a9f72bbca7 5038 (this method is used from 'FromString_ReadPartScientific' too)
stevep 0:04a9f72bbca7 5039 */
stevep 0:04a9f72bbca7 5040 template<class char_type>
stevep 0:04a9f72bbca7 5041 void FromString_TestSign( const char_type * & source, bool & is_sign )
stevep 0:04a9f72bbca7 5042 {
stevep 0:04a9f72bbca7 5043 Misc::SkipWhiteCharacters(source);
stevep 0:04a9f72bbca7 5044
stevep 0:04a9f72bbca7 5045 is_sign = false;
stevep 0:04a9f72bbca7 5046
stevep 0:04a9f72bbca7 5047 if( *source == '-' )
stevep 0:04a9f72bbca7 5048 {
stevep 0:04a9f72bbca7 5049 is_sign = true;
stevep 0:04a9f72bbca7 5050 ++source;
stevep 0:04a9f72bbca7 5051 }
stevep 0:04a9f72bbca7 5052 else
stevep 0:04a9f72bbca7 5053 if( *source == '+' )
stevep 0:04a9f72bbca7 5054 {
stevep 0:04a9f72bbca7 5055 ++source;
stevep 0:04a9f72bbca7 5056 }
stevep 0:04a9f72bbca7 5057 }
stevep 0:04a9f72bbca7 5058
stevep 0:04a9f72bbca7 5059
stevep 0:04a9f72bbca7 5060 /*!
stevep 0:04a9f72bbca7 5061 we're testing whether there's a comma operator
stevep 0:04a9f72bbca7 5062 */
stevep 0:04a9f72bbca7 5063 template<class char_type>
stevep 0:04a9f72bbca7 5064 bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv)
stevep 0:04a9f72bbca7 5065 {
stevep 0:04a9f72bbca7 5066 if( (*source == static_cast<char_type>(conv.comma)) ||
stevep 0:04a9f72bbca7 5067 (*source == static_cast<char_type>(conv.comma2) && conv.comma2 != 0 ) )
stevep 0:04a9f72bbca7 5068 {
stevep 0:04a9f72bbca7 5069 ++source;
stevep 0:04a9f72bbca7 5070
stevep 0:04a9f72bbca7 5071 return true;
stevep 0:04a9f72bbca7 5072 }
stevep 0:04a9f72bbca7 5073
stevep 0:04a9f72bbca7 5074 return false;
stevep 0:04a9f72bbca7 5075 }
stevep 0:04a9f72bbca7 5076
stevep 0:04a9f72bbca7 5077
stevep 0:04a9f72bbca7 5078 /*!
stevep 0:04a9f72bbca7 5079 this method reads the first part of a string
stevep 0:04a9f72bbca7 5080 (before the comma operator)
stevep 0:04a9f72bbca7 5081 */
stevep 0:04a9f72bbca7 5082 template<class char_type>
stevep 0:04a9f72bbca7 5083 uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read )
stevep 0:04a9f72bbca7 5084 {
stevep 0:04a9f72bbca7 5085 sint character;
stevep 0:04a9f72bbca7 5086 Big<exp, man> temp;
stevep 0:04a9f72bbca7 5087 Big<exp, man> base_( conv.base );
stevep 0:04a9f72bbca7 5088
stevep 0:04a9f72bbca7 5089 Misc::SkipWhiteCharacters( source );
stevep 0:04a9f72bbca7 5090
stevep 0:04a9f72bbca7 5091 for( ; true ; ++source )
stevep 0:04a9f72bbca7 5092 {
stevep 0:04a9f72bbca7 5093 if( conv.group!=0 && *source==static_cast<char>(conv.group) )
stevep 0:04a9f72bbca7 5094 continue;
stevep 0:04a9f72bbca7 5095
stevep 0:04a9f72bbca7 5096 character = Misc::CharToDigit(*source, conv.base);
stevep 0:04a9f72bbca7 5097
stevep 0:04a9f72bbca7 5098 if( character == -1 )
stevep 0:04a9f72bbca7 5099 break;
stevep 0:04a9f72bbca7 5100
stevep 0:04a9f72bbca7 5101 value_read = true;
stevep 0:04a9f72bbca7 5102 temp = character;
stevep 0:04a9f72bbca7 5103
stevep 0:04a9f72bbca7 5104 if( Mul(base_) )
stevep 0:04a9f72bbca7 5105 return 1;
stevep 0:04a9f72bbca7 5106
stevep 0:04a9f72bbca7 5107 if( Add(temp) )
stevep 0:04a9f72bbca7 5108 return 1;
stevep 0:04a9f72bbca7 5109 }
stevep 0:04a9f72bbca7 5110
stevep 0:04a9f72bbca7 5111 return 0;
stevep 0:04a9f72bbca7 5112 }
stevep 0:04a9f72bbca7 5113
stevep 0:04a9f72bbca7 5114
stevep 0:04a9f72bbca7 5115 /*!
stevep 0:04a9f72bbca7 5116 this method reads the second part of a string
stevep 0:04a9f72bbca7 5117 (after the comma operator)
stevep 0:04a9f72bbca7 5118 */
stevep 0:04a9f72bbca7 5119 template<class char_type>
stevep 0:04a9f72bbca7 5120 uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read )
stevep 0:04a9f72bbca7 5121 {
stevep 0:04a9f72bbca7 5122 sint character;
stevep 0:04a9f72bbca7 5123 uint c = 0, power = 0;
stevep 0:04a9f72bbca7 5124 UInt<1> power_;
stevep 0:04a9f72bbca7 5125 Big<exp, man> sum, base_(conv.base);
stevep 0:04a9f72bbca7 5126
stevep 0:04a9f72bbca7 5127 // we don't remove any white characters here
stevep 0:04a9f72bbca7 5128 sum.SetZero();
stevep 0:04a9f72bbca7 5129
stevep 0:04a9f72bbca7 5130 for( ; sum.exponent.IsSign() || sum.exponent.IsZero() ; ++source )
stevep 0:04a9f72bbca7 5131 {
stevep 0:04a9f72bbca7 5132 if( conv.group!=0 && *source==static_cast<char>(conv.group) )
stevep 0:04a9f72bbca7 5133 continue;
stevep 0:04a9f72bbca7 5134
stevep 0:04a9f72bbca7 5135 character = Misc::CharToDigit(*source, conv.base);
stevep 0:04a9f72bbca7 5136
stevep 0:04a9f72bbca7 5137 if( character == -1 )
stevep 0:04a9f72bbca7 5138 break;
stevep 0:04a9f72bbca7 5139
stevep 0:04a9f72bbca7 5140 value_read = true;
stevep 0:04a9f72bbca7 5141
stevep 0:04a9f72bbca7 5142 // there actually shouldn't be a carry here
stevep 0:04a9f72bbca7 5143 c += sum.Mul(base_);
stevep 0:04a9f72bbca7 5144 c += sum.Add(character);
stevep 0:04a9f72bbca7 5145 power += 1;
stevep 0:04a9f72bbca7 5146
stevep 0:04a9f72bbca7 5147 if( power == 0 )
stevep 0:04a9f72bbca7 5148 c += 1;
stevep 0:04a9f72bbca7 5149 }
stevep 0:04a9f72bbca7 5150
stevep 0:04a9f72bbca7 5151 // we could break the parsing somewhere in the middle of the string,
stevep 0:04a9f72bbca7 5152 // but the result (value) still can be good
stevep 0:04a9f72bbca7 5153 // we should set a correct value of 'source' now
stevep 0:04a9f72bbca7 5154 for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source );
stevep 0:04a9f72bbca7 5155
stevep 0:04a9f72bbca7 5156 power_ = power;
stevep 0:04a9f72bbca7 5157 c += base_.Pow(power_);
stevep 0:04a9f72bbca7 5158 c += sum.Div(base_);
stevep 0:04a9f72bbca7 5159 c += Add(sum);
stevep 0:04a9f72bbca7 5160
stevep 0:04a9f72bbca7 5161 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 5162 }
stevep 0:04a9f72bbca7 5163
stevep 0:04a9f72bbca7 5164
stevep 0:04a9f72bbca7 5165 /*!
stevep 0:04a9f72bbca7 5166 this method checks whether there is a scientific part: [e|E][-|+]value
stevep 0:04a9f72bbca7 5167
stevep 0:04a9f72bbca7 5168 it is called when the base is 10 and some digits were read before
stevep 0:04a9f72bbca7 5169 */
stevep 0:04a9f72bbca7 5170 template<class char_type>
stevep 0:04a9f72bbca7 5171 uint FromString_ReadScientificIfExists(const char_type * & source)
stevep 0:04a9f72bbca7 5172 {
stevep 0:04a9f72bbca7 5173 uint c = 0;
stevep 0:04a9f72bbca7 5174
stevep 0:04a9f72bbca7 5175 bool scientific_read = false;
stevep 0:04a9f72bbca7 5176 const char_type * before_scientific = source;
stevep 0:04a9f72bbca7 5177
stevep 0:04a9f72bbca7 5178 if( FromString_TestScientific(source) )
stevep 0:04a9f72bbca7 5179 c += FromString_ReadPartScientific( source, scientific_read );
stevep 0:04a9f72bbca7 5180
stevep 0:04a9f72bbca7 5181 if( !scientific_read )
stevep 0:04a9f72bbca7 5182 source = before_scientific;
stevep 0:04a9f72bbca7 5183
stevep 0:04a9f72bbca7 5184 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 5185 }
stevep 0:04a9f72bbca7 5186
stevep 0:04a9f72bbca7 5187
stevep 0:04a9f72bbca7 5188
stevep 0:04a9f72bbca7 5189 /*!
stevep 0:04a9f72bbca7 5190 we're testing whether is there the character 'e'
stevep 0:04a9f72bbca7 5191
stevep 0:04a9f72bbca7 5192 this character is only allowed when we're using the base equals 10
stevep 0:04a9f72bbca7 5193 */
stevep 0:04a9f72bbca7 5194 template<class char_type>
stevep 0:04a9f72bbca7 5195 bool FromString_TestScientific(const char_type * & source)
stevep 0:04a9f72bbca7 5196 {
stevep 0:04a9f72bbca7 5197 Misc::SkipWhiteCharacters(source);
stevep 0:04a9f72bbca7 5198
stevep 0:04a9f72bbca7 5199 if( *source=='e' || *source=='E' )
stevep 0:04a9f72bbca7 5200 {
stevep 0:04a9f72bbca7 5201 ++source;
stevep 0:04a9f72bbca7 5202
stevep 0:04a9f72bbca7 5203 return true;
stevep 0:04a9f72bbca7 5204 }
stevep 0:04a9f72bbca7 5205
stevep 0:04a9f72bbca7 5206 return false;
stevep 0:04a9f72bbca7 5207 }
stevep 0:04a9f72bbca7 5208
stevep 0:04a9f72bbca7 5209
stevep 0:04a9f72bbca7 5210 /*!
stevep 0:04a9f72bbca7 5211 this method reads the exponent (after 'e' character) when there's a scientific
stevep 0:04a9f72bbca7 5212 format of value and only when we're using the base equals 10
stevep 0:04a9f72bbca7 5213 */
stevep 0:04a9f72bbca7 5214 template<class char_type>
stevep 0:04a9f72bbca7 5215 uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read )
stevep 0:04a9f72bbca7 5216 {
stevep 0:04a9f72bbca7 5217 uint c = 0;
stevep 0:04a9f72bbca7 5218 Big<exp, man> new_exponent, temp;
stevep 0:04a9f72bbca7 5219 bool was_sign = false;
stevep 0:04a9f72bbca7 5220
stevep 0:04a9f72bbca7 5221 FromString_TestSign( source, was_sign );
stevep 0:04a9f72bbca7 5222 c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read );
stevep 0:04a9f72bbca7 5223
stevep 0:04a9f72bbca7 5224 if( scientific_read )
stevep 0:04a9f72bbca7 5225 {
stevep 0:04a9f72bbca7 5226 if( was_sign )
stevep 0:04a9f72bbca7 5227 new_exponent.ChangeSign();
stevep 0:04a9f72bbca7 5228
stevep 0:04a9f72bbca7 5229 temp = 10;
stevep 0:04a9f72bbca7 5230 c += temp.Pow( new_exponent );
stevep 0:04a9f72bbca7 5231 c += Mul(temp);
stevep 0:04a9f72bbca7 5232 }
stevep 0:04a9f72bbca7 5233
stevep 0:04a9f72bbca7 5234 return (c==0)? 0 : 1;
stevep 0:04a9f72bbca7 5235 }
stevep 0:04a9f72bbca7 5236
stevep 0:04a9f72bbca7 5237
stevep 0:04a9f72bbca7 5238 /*!
stevep 0:04a9f72bbca7 5239 this method reads the value of the extra exponent when scientific format is used
stevep 0:04a9f72bbca7 5240 (only when base == 10)
stevep 0:04a9f72bbca7 5241 */
stevep 0:04a9f72bbca7 5242 template<class char_type>
stevep 0:04a9f72bbca7 5243 uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big<exp, man> & new_exponent, bool & scientific_read )
stevep 0:04a9f72bbca7 5244 {
stevep 0:04a9f72bbca7 5245 sint character;
stevep 0:04a9f72bbca7 5246 Big<exp, man> base, temp;
stevep 0:04a9f72bbca7 5247
stevep 0:04a9f72bbca7 5248 Misc::SkipWhiteCharacters(source);
stevep 0:04a9f72bbca7 5249
stevep 0:04a9f72bbca7 5250 new_exponent.SetZero();
stevep 0:04a9f72bbca7 5251 base = 10;
stevep 0:04a9f72bbca7 5252
stevep 0:04a9f72bbca7 5253 for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source )
stevep 0:04a9f72bbca7 5254 {
stevep 0:04a9f72bbca7 5255 scientific_read = true;
stevep 0:04a9f72bbca7 5256
stevep 0:04a9f72bbca7 5257 temp = character;
stevep 0:04a9f72bbca7 5258
stevep 0:04a9f72bbca7 5259 if( new_exponent.Mul(base) )
stevep 0:04a9f72bbca7 5260 return 1;
stevep 0:04a9f72bbca7 5261
stevep 0:04a9f72bbca7 5262 if( new_exponent.Add(temp) )
stevep 0:04a9f72bbca7 5263 return 1;
stevep 0:04a9f72bbca7 5264 }
stevep 0:04a9f72bbca7 5265
stevep 0:04a9f72bbca7 5266 return 0;
stevep 0:04a9f72bbca7 5267 }
stevep 0:04a9f72bbca7 5268
stevep 0:04a9f72bbca7 5269
stevep 0:04a9f72bbca7 5270 public:
stevep 0:04a9f72bbca7 5271
stevep 0:04a9f72bbca7 5272
stevep 0:04a9f72bbca7 5273 /*!
stevep 0:04a9f72bbca7 5274 a constructor for converting a string into this class
stevep 0:04a9f72bbca7 5275 */
stevep 0:04a9f72bbca7 5276 Big(const char * string)
stevep 0:04a9f72bbca7 5277 {
stevep 0:04a9f72bbca7 5278 FromString( string );
stevep 0:04a9f72bbca7 5279 }
stevep 0:04a9f72bbca7 5280
stevep 0:04a9f72bbca7 5281
stevep 0:04a9f72bbca7 5282 /*!
stevep 0:04a9f72bbca7 5283 a constructor for converting a string into this class
stevep 0:04a9f72bbca7 5284 */
stevep 0:04a9f72bbca7 5285 Big(const std::string & string)
stevep 0:04a9f72bbca7 5286 {
stevep 0:04a9f72bbca7 5287 FromString( string.c_str() );
stevep 0:04a9f72bbca7 5288 }
stevep 0:04a9f72bbca7 5289
stevep 0:04a9f72bbca7 5290
stevep 0:04a9f72bbca7 5291 /*!
stevep 0:04a9f72bbca7 5292 an operator= for converting a string into its value
stevep 0:04a9f72bbca7 5293 */
stevep 0:04a9f72bbca7 5294 Big<exp, man> & operator=(const char * string)
stevep 0:04a9f72bbca7 5295 {
stevep 0:04a9f72bbca7 5296 FromString( string );
stevep 0:04a9f72bbca7 5297
stevep 0:04a9f72bbca7 5298 return *this;
stevep 0:04a9f72bbca7 5299 }
stevep 0:04a9f72bbca7 5300
stevep 0:04a9f72bbca7 5301
stevep 0:04a9f72bbca7 5302 /*!
stevep 0:04a9f72bbca7 5303 an operator= for converting a string into its value
stevep 0:04a9f72bbca7 5304 */
stevep 0:04a9f72bbca7 5305 Big<exp, man> & operator=(const std::string & string)
stevep 0:04a9f72bbca7 5306 {
stevep 0:04a9f72bbca7 5307 FromString( string.c_str() );
stevep 0:04a9f72bbca7 5308
stevep 0:04a9f72bbca7 5309 return *this;
stevep 0:04a9f72bbca7 5310 }
stevep 0:04a9f72bbca7 5311
stevep 0:04a9f72bbca7 5312
stevep 0:04a9f72bbca7 5313
stevep 0:04a9f72bbca7 5314 #ifndef TTMATH_DONT_USE_WCHAR
stevep 0:04a9f72bbca7 5315
stevep 0:04a9f72bbca7 5316 /*!
stevep 0:04a9f72bbca7 5317 a constructor for converting a string into this class
stevep 0:04a9f72bbca7 5318 */
stevep 0:04a9f72bbca7 5319 Big(const wchar_t * string)
stevep 0:04a9f72bbca7 5320 {
stevep 0:04a9f72bbca7 5321 FromString( string );
stevep 0:04a9f72bbca7 5322 }
stevep 0:04a9f72bbca7 5323
stevep 0:04a9f72bbca7 5324
stevep 0:04a9f72bbca7 5325 /*!
stevep 0:04a9f72bbca7 5326 a constructor for converting a string into this class
stevep 0:04a9f72bbca7 5327 */
stevep 0:04a9f72bbca7 5328 Big(const std::wstring & string)
stevep 0:04a9f72bbca7 5329 {
stevep 0:04a9f72bbca7 5330 FromString( string.c_str() );
stevep 0:04a9f72bbca7 5331 }
stevep 0:04a9f72bbca7 5332
stevep 0:04a9f72bbca7 5333
stevep 0:04a9f72bbca7 5334 /*!
stevep 0:04a9f72bbca7 5335 an operator= for converting a string into its value
stevep 0:04a9f72bbca7 5336 */
stevep 0:04a9f72bbca7 5337 Big<exp, man> & operator=(const wchar_t * string)
stevep 0:04a9f72bbca7 5338 {
stevep 0:04a9f72bbca7 5339 FromString( string );
stevep 0:04a9f72bbca7 5340
stevep 0:04a9f72bbca7 5341 return *this;
stevep 0:04a9f72bbca7 5342 }
stevep 0:04a9f72bbca7 5343
stevep 0:04a9f72bbca7 5344
stevep 0:04a9f72bbca7 5345 /*!
stevep 0:04a9f72bbca7 5346 an operator= for converting a string into its value
stevep 0:04a9f72bbca7 5347 */
stevep 0:04a9f72bbca7 5348 Big<exp, man> & operator=(const std::wstring & string)
stevep 0:04a9f72bbca7 5349 {
stevep 0:04a9f72bbca7 5350 FromString( string.c_str() );
stevep 0:04a9f72bbca7 5351
stevep 0:04a9f72bbca7 5352 return *this;
stevep 0:04a9f72bbca7 5353 }
stevep 0:04a9f72bbca7 5354
stevep 0:04a9f72bbca7 5355
stevep 0:04a9f72bbca7 5356 #endif
stevep 0:04a9f72bbca7 5357
stevep 0:04a9f72bbca7 5358
stevep 0:04a9f72bbca7 5359
stevep 0:04a9f72bbca7 5360 /*!
stevep 0:04a9f72bbca7 5361 *
stevep 0:04a9f72bbca7 5362 * methods for comparing
stevep 0:04a9f72bbca7 5363 *
stevep 0:04a9f72bbca7 5364 */
stevep 0:04a9f72bbca7 5365
stevep 0:04a9f72bbca7 5366
stevep 0:04a9f72bbca7 5367 /*!
stevep 0:04a9f72bbca7 5368 this method performs the formula 'abs(this) < abs(ss2)'
stevep 0:04a9f72bbca7 5369 and returns the result
stevep 0:04a9f72bbca7 5370
stevep 0:04a9f72bbca7 5371 (in other words it treats 'this' and 'ss2' as values without a sign)
stevep 0:04a9f72bbca7 5372 we don't check the NaN flag
stevep 0:04a9f72bbca7 5373 */
stevep 0:04a9f72bbca7 5374 bool SmallerWithoutSignThan(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5375 {
stevep 0:04a9f72bbca7 5376 if( IsZero() )
stevep 0:04a9f72bbca7 5377 {
stevep 0:04a9f72bbca7 5378 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5379 // we've got two zeroes
stevep 0:04a9f72bbca7 5380 return false;
stevep 0:04a9f72bbca7 5381 else
stevep 0:04a9f72bbca7 5382 // this==0 and ss2!=0
stevep 0:04a9f72bbca7 5383 return true;
stevep 0:04a9f72bbca7 5384 }
stevep 0:04a9f72bbca7 5385
stevep 0:04a9f72bbca7 5386 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5387 // this!=0 and ss2==0
stevep 0:04a9f72bbca7 5388 return false;
stevep 0:04a9f72bbca7 5389
stevep 0:04a9f72bbca7 5390 // we're using the fact that all bits in mantissa are pushed
stevep 0:04a9f72bbca7 5391 // into the left side -- Standardizing()
stevep 0:04a9f72bbca7 5392 if( exponent == ss2.exponent )
stevep 0:04a9f72bbca7 5393 return mantissa < ss2.mantissa;
stevep 0:04a9f72bbca7 5394
stevep 0:04a9f72bbca7 5395 return exponent < ss2.exponent;
stevep 0:04a9f72bbca7 5396 }
stevep 0:04a9f72bbca7 5397
stevep 0:04a9f72bbca7 5398
stevep 0:04a9f72bbca7 5399 /*!
stevep 0:04a9f72bbca7 5400 this method performs the formula 'abs(this) > abs(ss2)'
stevep 0:04a9f72bbca7 5401 and returns the result
stevep 0:04a9f72bbca7 5402
stevep 0:04a9f72bbca7 5403 (in other words it treats 'this' and 'ss2' as values without a sign)
stevep 0:04a9f72bbca7 5404 we don't check the NaN flag
stevep 0:04a9f72bbca7 5405 */
stevep 0:04a9f72bbca7 5406 bool GreaterWithoutSignThan(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5407 {
stevep 0:04a9f72bbca7 5408 if( IsZero() )
stevep 0:04a9f72bbca7 5409 {
stevep 0:04a9f72bbca7 5410 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5411 // we've got two zeroes
stevep 0:04a9f72bbca7 5412 return false;
stevep 0:04a9f72bbca7 5413 else
stevep 0:04a9f72bbca7 5414 // this==0 and ss2!=0
stevep 0:04a9f72bbca7 5415 return false;
stevep 0:04a9f72bbca7 5416 }
stevep 0:04a9f72bbca7 5417
stevep 0:04a9f72bbca7 5418 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5419 // this!=0 and ss2==0
stevep 0:04a9f72bbca7 5420 return true;
stevep 0:04a9f72bbca7 5421
stevep 0:04a9f72bbca7 5422 // we're using the fact that all bits in mantissa are pushed
stevep 0:04a9f72bbca7 5423 // into the left side -- Standardizing()
stevep 0:04a9f72bbca7 5424 if( exponent == ss2.exponent )
stevep 0:04a9f72bbca7 5425 return mantissa > ss2.mantissa;
stevep 0:04a9f72bbca7 5426
stevep 0:04a9f72bbca7 5427 return exponent > ss2.exponent;
stevep 0:04a9f72bbca7 5428 }
stevep 0:04a9f72bbca7 5429
stevep 0:04a9f72bbca7 5430
stevep 0:04a9f72bbca7 5431 /*!
stevep 0:04a9f72bbca7 5432 this method performs the formula 'abs(this) == abs(ss2)'
stevep 0:04a9f72bbca7 5433 and returns the result
stevep 0:04a9f72bbca7 5434
stevep 0:04a9f72bbca7 5435 (in other words it treats 'this' and 'ss2' as values without a sign)
stevep 0:04a9f72bbca7 5436 we don't check the NaN flag
stevep 0:04a9f72bbca7 5437 */
stevep 0:04a9f72bbca7 5438 bool EqualWithoutSign(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5439 {
stevep 0:04a9f72bbca7 5440 if( IsZero() )
stevep 0:04a9f72bbca7 5441 {
stevep 0:04a9f72bbca7 5442 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5443 // we've got two zeroes
stevep 0:04a9f72bbca7 5444 return true;
stevep 0:04a9f72bbca7 5445 else
stevep 0:04a9f72bbca7 5446 // this==0 and ss2!=0
stevep 0:04a9f72bbca7 5447 return false;
stevep 0:04a9f72bbca7 5448 }
stevep 0:04a9f72bbca7 5449
stevep 0:04a9f72bbca7 5450 if( ss2.IsZero() )
stevep 0:04a9f72bbca7 5451 // this!=0 and ss2==0
stevep 0:04a9f72bbca7 5452 return false;
stevep 0:04a9f72bbca7 5453
stevep 0:04a9f72bbca7 5454 if( exponent==ss2.exponent && mantissa==ss2.mantissa )
stevep 0:04a9f72bbca7 5455 return true;
stevep 0:04a9f72bbca7 5456
stevep 0:04a9f72bbca7 5457 return false;
stevep 0:04a9f72bbca7 5458 }
stevep 0:04a9f72bbca7 5459
stevep 0:04a9f72bbca7 5460
stevep 0:04a9f72bbca7 5461 bool operator<(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5462 {
stevep 0:04a9f72bbca7 5463 if( IsSign() && !ss2.IsSign() )
stevep 0:04a9f72bbca7 5464 // this<0 and ss2>=0
stevep 0:04a9f72bbca7 5465 return true;
stevep 0:04a9f72bbca7 5466
stevep 0:04a9f72bbca7 5467 if( !IsSign() && ss2.IsSign() )
stevep 0:04a9f72bbca7 5468 // this>=0 and ss2<0
stevep 0:04a9f72bbca7 5469 return false;
stevep 0:04a9f72bbca7 5470
stevep 0:04a9f72bbca7 5471 // both signs are the same
stevep 0:04a9f72bbca7 5472
stevep 0:04a9f72bbca7 5473 if( IsSign() )
stevep 0:04a9f72bbca7 5474 return ss2.SmallerWithoutSignThan( *this );
stevep 0:04a9f72bbca7 5475
stevep 0:04a9f72bbca7 5476 return SmallerWithoutSignThan( ss2 );
stevep 0:04a9f72bbca7 5477 }
stevep 0:04a9f72bbca7 5478
stevep 0:04a9f72bbca7 5479
stevep 0:04a9f72bbca7 5480 bool operator==(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5481 {
stevep 0:04a9f72bbca7 5482 if( IsSign() != ss2.IsSign() )
stevep 0:04a9f72bbca7 5483 return false;
stevep 0:04a9f72bbca7 5484
stevep 0:04a9f72bbca7 5485 return EqualWithoutSign( ss2 );
stevep 0:04a9f72bbca7 5486 }
stevep 0:04a9f72bbca7 5487
stevep 0:04a9f72bbca7 5488
stevep 0:04a9f72bbca7 5489 bool operator>(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5490 {
stevep 0:04a9f72bbca7 5491 if( IsSign() && !ss2.IsSign() )
stevep 0:04a9f72bbca7 5492 // this<0 and ss2>=0
stevep 0:04a9f72bbca7 5493 return false;
stevep 0:04a9f72bbca7 5494
stevep 0:04a9f72bbca7 5495 if( !IsSign() && ss2.IsSign() )
stevep 0:04a9f72bbca7 5496 // this>=0 and ss2<0
stevep 0:04a9f72bbca7 5497 return true;
stevep 0:04a9f72bbca7 5498
stevep 0:04a9f72bbca7 5499 // both signs are the same
stevep 0:04a9f72bbca7 5500
stevep 0:04a9f72bbca7 5501 if( IsSign() )
stevep 0:04a9f72bbca7 5502 return ss2.GreaterWithoutSignThan( *this );
stevep 0:04a9f72bbca7 5503
stevep 0:04a9f72bbca7 5504 return GreaterWithoutSignThan( ss2 );
stevep 0:04a9f72bbca7 5505 }
stevep 0:04a9f72bbca7 5506
stevep 0:04a9f72bbca7 5507
stevep 0:04a9f72bbca7 5508 bool operator>=(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5509 {
stevep 0:04a9f72bbca7 5510 return !operator<( ss2 );
stevep 0:04a9f72bbca7 5511 }
stevep 0:04a9f72bbca7 5512
stevep 0:04a9f72bbca7 5513
stevep 0:04a9f72bbca7 5514 bool operator<=(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5515 {
stevep 0:04a9f72bbca7 5516 return !operator>( ss2 );
stevep 0:04a9f72bbca7 5517 }
stevep 0:04a9f72bbca7 5518
stevep 0:04a9f72bbca7 5519
stevep 0:04a9f72bbca7 5520 bool operator!=(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5521 {
stevep 0:04a9f72bbca7 5522 return !operator==(ss2);
stevep 0:04a9f72bbca7 5523 }
stevep 0:04a9f72bbca7 5524
stevep 0:04a9f72bbca7 5525
stevep 0:04a9f72bbca7 5526
stevep 0:04a9f72bbca7 5527
stevep 0:04a9f72bbca7 5528
stevep 0:04a9f72bbca7 5529 /*!
stevep 0:04a9f72bbca7 5530 *
stevep 0:04a9f72bbca7 5531 * standard mathematical operators
stevep 0:04a9f72bbca7 5532 *
stevep 0:04a9f72bbca7 5533 */
stevep 0:04a9f72bbca7 5534
stevep 0:04a9f72bbca7 5535
stevep 0:04a9f72bbca7 5536 /*!
stevep 0:04a9f72bbca7 5537 an operator for changing the sign
stevep 0:04a9f72bbca7 5538
stevep 0:04a9f72bbca7 5539 this method is not changing 'this' but the changed value is returned
stevep 0:04a9f72bbca7 5540 */
stevep 0:04a9f72bbca7 5541 Big<exp,man> operator-() const
stevep 0:04a9f72bbca7 5542 {
stevep 0:04a9f72bbca7 5543 Big<exp,man> temp(*this);
stevep 0:04a9f72bbca7 5544
stevep 0:04a9f72bbca7 5545 temp.ChangeSign();
stevep 0:04a9f72bbca7 5546
stevep 0:04a9f72bbca7 5547 return temp;
stevep 0:04a9f72bbca7 5548 }
stevep 0:04a9f72bbca7 5549
stevep 0:04a9f72bbca7 5550
stevep 0:04a9f72bbca7 5551 Big<exp,man> operator-(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5552 {
stevep 0:04a9f72bbca7 5553 Big<exp,man> temp(*this);
stevep 0:04a9f72bbca7 5554
stevep 0:04a9f72bbca7 5555 temp.Sub(ss2);
stevep 0:04a9f72bbca7 5556
stevep 0:04a9f72bbca7 5557 return temp;
stevep 0:04a9f72bbca7 5558 }
stevep 0:04a9f72bbca7 5559
stevep 0:04a9f72bbca7 5560 Big<exp,man> & operator-=(const Big<exp,man> & ss2)
stevep 0:04a9f72bbca7 5561 {
stevep 0:04a9f72bbca7 5562 Sub(ss2);
stevep 0:04a9f72bbca7 5563
stevep 0:04a9f72bbca7 5564 return *this;
stevep 0:04a9f72bbca7 5565 }
stevep 0:04a9f72bbca7 5566
stevep 0:04a9f72bbca7 5567
stevep 0:04a9f72bbca7 5568 Big<exp,man> operator+(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5569 {
stevep 0:04a9f72bbca7 5570 Big<exp,man> temp(*this);
stevep 0:04a9f72bbca7 5571
stevep 0:04a9f72bbca7 5572 temp.Add(ss2);
stevep 0:04a9f72bbca7 5573
stevep 0:04a9f72bbca7 5574 return temp;
stevep 0:04a9f72bbca7 5575 }
stevep 0:04a9f72bbca7 5576
stevep 0:04a9f72bbca7 5577
stevep 0:04a9f72bbca7 5578 Big<exp,man> & operator+=(const Big<exp,man> & ss2)
stevep 0:04a9f72bbca7 5579 {
stevep 0:04a9f72bbca7 5580 Add(ss2);
stevep 0:04a9f72bbca7 5581
stevep 0:04a9f72bbca7 5582 return *this;
stevep 0:04a9f72bbca7 5583 }
stevep 0:04a9f72bbca7 5584
stevep 0:04a9f72bbca7 5585
stevep 0:04a9f72bbca7 5586 Big<exp,man> operator*(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5587 {
stevep 0:04a9f72bbca7 5588 Big<exp,man> temp(*this);
stevep 0:04a9f72bbca7 5589
stevep 0:04a9f72bbca7 5590 temp.Mul(ss2);
stevep 0:04a9f72bbca7 5591
stevep 0:04a9f72bbca7 5592 return temp;
stevep 0:04a9f72bbca7 5593 }
stevep 0:04a9f72bbca7 5594
stevep 0:04a9f72bbca7 5595
stevep 0:04a9f72bbca7 5596 Big<exp,man> & operator*=(const Big<exp,man> & ss2)
stevep 0:04a9f72bbca7 5597 {
stevep 0:04a9f72bbca7 5598 Mul(ss2);
stevep 0:04a9f72bbca7 5599
stevep 0:04a9f72bbca7 5600 return *this;
stevep 0:04a9f72bbca7 5601 }
stevep 0:04a9f72bbca7 5602
stevep 0:04a9f72bbca7 5603
stevep 0:04a9f72bbca7 5604 Big<exp,man> operator/(const Big<exp,man> & ss2) const
stevep 0:04a9f72bbca7 5605 {
stevep 0:04a9f72bbca7 5606 Big<exp,man> temp(*this);
stevep 0:04a9f72bbca7 5607
stevep 0:04a9f72bbca7 5608 temp.Div(ss2);
stevep 0:04a9f72bbca7 5609
stevep 0:04a9f72bbca7 5610 return temp;
stevep 0:04a9f72bbca7 5611 }
stevep 0:04a9f72bbca7 5612
stevep 0:04a9f72bbca7 5613
stevep 0:04a9f72bbca7 5614 Big<exp,man> & operator/=(const Big<exp,man> & ss2)
stevep 0:04a9f72bbca7 5615 {
stevep 0:04a9f72bbca7 5616 Div(ss2);
stevep 0:04a9f72bbca7 5617
stevep 0:04a9f72bbca7 5618 return *this;
stevep 0:04a9f72bbca7 5619 }
stevep 0:04a9f72bbca7 5620
stevep 0:04a9f72bbca7 5621
stevep 0:04a9f72bbca7 5622 /*!
stevep 0:04a9f72bbca7 5623 Prefix operator e.g ++variable
stevep 0:04a9f72bbca7 5624 */
stevep 0:04a9f72bbca7 5625 Big<exp,man> & operator++()
stevep 0:04a9f72bbca7 5626 {
stevep 0:04a9f72bbca7 5627 AddOne();
stevep 0:04a9f72bbca7 5628
stevep 0:04a9f72bbca7 5629 return *this;
stevep 0:04a9f72bbca7 5630 }
stevep 0:04a9f72bbca7 5631
stevep 0:04a9f72bbca7 5632
stevep 0:04a9f72bbca7 5633 /*!
stevep 0:04a9f72bbca7 5634 Postfix operator e.g variable++
stevep 0:04a9f72bbca7 5635 */
stevep 0:04a9f72bbca7 5636 Big<exp,man> operator++(int)
stevep 0:04a9f72bbca7 5637 {
stevep 0:04a9f72bbca7 5638 Big<exp,man> temp( *this );
stevep 0:04a9f72bbca7 5639
stevep 0:04a9f72bbca7 5640 AddOne();
stevep 0:04a9f72bbca7 5641
stevep 0:04a9f72bbca7 5642 return temp;
stevep 0:04a9f72bbca7 5643 }
stevep 0:04a9f72bbca7 5644
stevep 0:04a9f72bbca7 5645
stevep 0:04a9f72bbca7 5646 Big<exp,man> & operator--()
stevep 0:04a9f72bbca7 5647 {
stevep 0:04a9f72bbca7 5648 SubOne();
stevep 0:04a9f72bbca7 5649
stevep 0:04a9f72bbca7 5650 return *this;
stevep 0:04a9f72bbca7 5651 }
stevep 0:04a9f72bbca7 5652
stevep 0:04a9f72bbca7 5653
stevep 0:04a9f72bbca7 5654 Big<exp,man> operator--(int)
stevep 0:04a9f72bbca7 5655 {
stevep 0:04a9f72bbca7 5656 Big<exp,man> temp( *this );
stevep 0:04a9f72bbca7 5657
stevep 0:04a9f72bbca7 5658 SubOne();
stevep 0:04a9f72bbca7 5659
stevep 0:04a9f72bbca7 5660 return temp;
stevep 0:04a9f72bbca7 5661 }
stevep 0:04a9f72bbca7 5662
stevep 0:04a9f72bbca7 5663
stevep 0:04a9f72bbca7 5664
stevep 0:04a9f72bbca7 5665 /*!
stevep 0:04a9f72bbca7 5666 *
stevep 0:04a9f72bbca7 5667 * bitwise operators
stevep 0:04a9f72bbca7 5668 * (we do not define bitwise not)
stevep 0:04a9f72bbca7 5669 */
stevep 0:04a9f72bbca7 5670
stevep 0:04a9f72bbca7 5671
stevep 0:04a9f72bbca7 5672 Big<exp,man> operator&(const Big<exp,man> & p2) const
stevep 0:04a9f72bbca7 5673 {
stevep 0:04a9f72bbca7 5674 Big<exp,man> temp( *this );
stevep 0:04a9f72bbca7 5675
stevep 0:04a9f72bbca7 5676 temp.BitAnd(p2);
stevep 0:04a9f72bbca7 5677
stevep 0:04a9f72bbca7 5678 return temp;
stevep 0:04a9f72bbca7 5679 }
stevep 0:04a9f72bbca7 5680
stevep 0:04a9f72bbca7 5681
stevep 0:04a9f72bbca7 5682 Big<exp,man> & operator&=(const Big<exp,man> & p2)
stevep 0:04a9f72bbca7 5683 {
stevep 0:04a9f72bbca7 5684 BitAnd(p2);
stevep 0:04a9f72bbca7 5685
stevep 0:04a9f72bbca7 5686 return *this;
stevep 0:04a9f72bbca7 5687 }
stevep 0:04a9f72bbca7 5688
stevep 0:04a9f72bbca7 5689
stevep 0:04a9f72bbca7 5690 Big<exp,man> operator|(const Big<exp,man> & p2) const
stevep 0:04a9f72bbca7 5691 {
stevep 0:04a9f72bbca7 5692 Big<exp,man> temp( *this );
stevep 0:04a9f72bbca7 5693
stevep 0:04a9f72bbca7 5694 temp.BitOr(p2);
stevep 0:04a9f72bbca7 5695
stevep 0:04a9f72bbca7 5696 return temp;
stevep 0:04a9f72bbca7 5697 }
stevep 0:04a9f72bbca7 5698
stevep 0:04a9f72bbca7 5699
stevep 0:04a9f72bbca7 5700 Big<exp,man> & operator|=(const Big<exp,man> & p2)
stevep 0:04a9f72bbca7 5701 {
stevep 0:04a9f72bbca7 5702 BitOr(p2);
stevep 0:04a9f72bbca7 5703
stevep 0:04a9f72bbca7 5704 return *this;
stevep 0:04a9f72bbca7 5705 }
stevep 0:04a9f72bbca7 5706
stevep 0:04a9f72bbca7 5707
stevep 0:04a9f72bbca7 5708 Big<exp,man> operator^(const Big<exp,man> & p2) const
stevep 0:04a9f72bbca7 5709 {
stevep 0:04a9f72bbca7 5710 Big<exp,man> temp( *this );
stevep 0:04a9f72bbca7 5711
stevep 0:04a9f72bbca7 5712 temp.BitXor(p2);
stevep 0:04a9f72bbca7 5713
stevep 0:04a9f72bbca7 5714 return temp;
stevep 0:04a9f72bbca7 5715 }
stevep 0:04a9f72bbca7 5716
stevep 0:04a9f72bbca7 5717
stevep 0:04a9f72bbca7 5718 Big<exp,man> & operator^=(const Big<exp,man> & p2)
stevep 0:04a9f72bbca7 5719 {
stevep 0:04a9f72bbca7 5720 BitXor(p2);
stevep 0:04a9f72bbca7 5721
stevep 0:04a9f72bbca7 5722 return *this;
stevep 0:04a9f72bbca7 5723 }
stevep 0:04a9f72bbca7 5724
stevep 0:04a9f72bbca7 5725
stevep 0:04a9f72bbca7 5726
stevep 0:04a9f72bbca7 5727
stevep 0:04a9f72bbca7 5728
stevep 0:04a9f72bbca7 5729
stevep 0:04a9f72bbca7 5730 /*!
stevep 0:04a9f72bbca7 5731 this method makes an integer value by skipping any fractions
stevep 0:04a9f72bbca7 5732
stevep 0:04a9f72bbca7 5733 for example:
stevep 0:04a9f72bbca7 5734 10.7 will be 10
stevep 0:04a9f72bbca7 5735 12.1 -- 12
stevep 0:04a9f72bbca7 5736 -20.2 -- 20
stevep 0:04a9f72bbca7 5737 -20.9 -- 20
stevep 0:04a9f72bbca7 5738 -0.7 -- 0
stevep 0:04a9f72bbca7 5739 0.8 -- 0
stevep 0:04a9f72bbca7 5740 */
stevep 0:04a9f72bbca7 5741 void SkipFraction()
stevep 0:04a9f72bbca7 5742 {
stevep 0:04a9f72bbca7 5743 if( IsNan() || IsZero() )
stevep 0:04a9f72bbca7 5744 return;
stevep 0:04a9f72bbca7 5745
stevep 0:04a9f72bbca7 5746 if( !exponent.IsSign() )
stevep 0:04a9f72bbca7 5747 // exponent >=0 -- the value don't have any fractions
stevep 0:04a9f72bbca7 5748 return;
stevep 0:04a9f72bbca7 5749
stevep 0:04a9f72bbca7 5750 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 5751 {
stevep 0:04a9f72bbca7 5752 // the value is from (-1,1), we return zero
stevep 0:04a9f72bbca7 5753 SetZero();
stevep 0:04a9f72bbca7 5754 return;
stevep 0:04a9f72bbca7 5755 }
stevep 0:04a9f72bbca7 5756
stevep 0:04a9f72bbca7 5757 // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
stevep 0:04a9f72bbca7 5758 sint e = exponent.ToInt();
stevep 0:04a9f72bbca7 5759
stevep 0:04a9f72bbca7 5760 mantissa.ClearFirstBits( -e );
stevep 0:04a9f72bbca7 5761
stevep 0:04a9f72bbca7 5762 // we don't have to standardize 'Standardizing()' the value because
stevep 0:04a9f72bbca7 5763 // there's at least one bit in the mantissa
stevep 0:04a9f72bbca7 5764 // (the highest bit which we didn't touch)
stevep 0:04a9f72bbca7 5765 }
stevep 0:04a9f72bbca7 5766
stevep 0:04a9f72bbca7 5767
stevep 0:04a9f72bbca7 5768 /*!
stevep 0:04a9f72bbca7 5769 this method remains only a fraction from the value
stevep 0:04a9f72bbca7 5770
stevep 0:04a9f72bbca7 5771 for example:
stevep 0:04a9f72bbca7 5772 30.56 will be 0.56
stevep 0:04a9f72bbca7 5773 -12.67 -- -0.67
stevep 0:04a9f72bbca7 5774 */
stevep 0:04a9f72bbca7 5775 void RemainFraction()
stevep 0:04a9f72bbca7 5776 {
stevep 0:04a9f72bbca7 5777 if( IsNan() || IsZero() )
stevep 0:04a9f72bbca7 5778 return;
stevep 0:04a9f72bbca7 5779
stevep 0:04a9f72bbca7 5780 if( !exponent.IsSign() )
stevep 0:04a9f72bbca7 5781 {
stevep 0:04a9f72bbca7 5782 // exponent >= 0 -- the value doesn't have any fractions
stevep 0:04a9f72bbca7 5783 // we return zero
stevep 0:04a9f72bbca7 5784 SetZero();
stevep 0:04a9f72bbca7 5785 return;
stevep 0:04a9f72bbca7 5786 }
stevep 0:04a9f72bbca7 5787
stevep 0:04a9f72bbca7 5788 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 5789 {
stevep 0:04a9f72bbca7 5790 // the value is from (-1,1)
stevep 0:04a9f72bbca7 5791 // we don't make anything with the value
stevep 0:04a9f72bbca7 5792 return;
stevep 0:04a9f72bbca7 5793 }
stevep 0:04a9f72bbca7 5794
stevep 0:04a9f72bbca7 5795 // e will be from (-man*TTMATH_BITS_PER_UINT, 0)
stevep 0:04a9f72bbca7 5796 sint e = exponent.ToInt();
stevep 0:04a9f72bbca7 5797
stevep 0:04a9f72bbca7 5798 sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative
stevep 0:04a9f72bbca7 5799 mantissa.Rcl( how_many_bits_leave, 0);
stevep 0:04a9f72bbca7 5800
stevep 0:04a9f72bbca7 5801 // there'll not be a carry because the exponent is too small
stevep 0:04a9f72bbca7 5802 exponent.Sub( how_many_bits_leave );
stevep 0:04a9f72bbca7 5803
stevep 0:04a9f72bbca7 5804 // we must call Standardizing() here
stevep 0:04a9f72bbca7 5805 Standardizing();
stevep 0:04a9f72bbca7 5806 }
stevep 0:04a9f72bbca7 5807
stevep 0:04a9f72bbca7 5808
stevep 0:04a9f72bbca7 5809
stevep 0:04a9f72bbca7 5810 /*!
stevep 0:04a9f72bbca7 5811 this method returns true if the value is integer
stevep 0:04a9f72bbca7 5812 (there is no a fraction)
stevep 0:04a9f72bbca7 5813
stevep 0:04a9f72bbca7 5814 (we don't check nan)
stevep 0:04a9f72bbca7 5815 */
stevep 0:04a9f72bbca7 5816 bool IsInteger() const
stevep 0:04a9f72bbca7 5817 {
stevep 0:04a9f72bbca7 5818 if( IsZero() )
stevep 0:04a9f72bbca7 5819 return true;
stevep 0:04a9f72bbca7 5820
stevep 0:04a9f72bbca7 5821 if( !exponent.IsSign() )
stevep 0:04a9f72bbca7 5822 // exponent >=0 -- the value don't have any fractions
stevep 0:04a9f72bbca7 5823 return true;
stevep 0:04a9f72bbca7 5824
stevep 0:04a9f72bbca7 5825 if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
stevep 0:04a9f72bbca7 5826 // the value is from (-1,1)
stevep 0:04a9f72bbca7 5827 return false;
stevep 0:04a9f72bbca7 5828
stevep 0:04a9f72bbca7 5829 // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
stevep 0:04a9f72bbca7 5830 sint e = exponent.ToInt();
stevep 0:04a9f72bbca7 5831 e = -e; // e means how many bits we must check
stevep 0:04a9f72bbca7 5832
stevep 0:04a9f72bbca7 5833 uint len = e / TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 5834 uint rest = e % TTMATH_BITS_PER_UINT;
stevep 0:04a9f72bbca7 5835 uint i = 0;
stevep 0:04a9f72bbca7 5836
stevep 0:04a9f72bbca7 5837 for( ; i<len ; ++i )
stevep 0:04a9f72bbca7 5838 if( mantissa.table[i] != 0 )
stevep 0:04a9f72bbca7 5839 return false;
stevep 0:04a9f72bbca7 5840
stevep 0:04a9f72bbca7 5841 if( rest > 0 )
stevep 0:04a9f72bbca7 5842 {
stevep 0:04a9f72bbca7 5843 uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest);
stevep 0:04a9f72bbca7 5844 if( (mantissa.table[i] & rest_mask) != 0 )
stevep 0:04a9f72bbca7 5845 return false;
stevep 0:04a9f72bbca7 5846 }
stevep 0:04a9f72bbca7 5847
stevep 0:04a9f72bbca7 5848 return true;
stevep 0:04a9f72bbca7 5849 }
stevep 0:04a9f72bbca7 5850
stevep 0:04a9f72bbca7 5851
stevep 0:04a9f72bbca7 5852 /*!
stevep 0:04a9f72bbca7 5853 this method rounds to the nearest integer value
stevep 0:04a9f72bbca7 5854 (it returns a carry if it was)
stevep 0:04a9f72bbca7 5855
stevep 0:04a9f72bbca7 5856 for example:
stevep 0:04a9f72bbca7 5857 2.3 = 2
stevep 0:04a9f72bbca7 5858 2.8 = 3
stevep 0:04a9f72bbca7 5859
stevep 0:04a9f72bbca7 5860 -2.3 = -2
stevep 0:04a9f72bbca7 5861 -2.8 = 3
stevep 0:04a9f72bbca7 5862 */
stevep 0:04a9f72bbca7 5863 uint Round()
stevep 0:04a9f72bbca7 5864 {
stevep 0:04a9f72bbca7 5865 Big<exp,man> half;
stevep 0:04a9f72bbca7 5866 uint c;
stevep 0:04a9f72bbca7 5867
stevep 0:04a9f72bbca7 5868 if( IsNan() )
stevep 0:04a9f72bbca7 5869 return 1;
stevep 0:04a9f72bbca7 5870
stevep 0:04a9f72bbca7 5871 if( IsZero() )
stevep 0:04a9f72bbca7 5872 return 0;
stevep 0:04a9f72bbca7 5873
stevep 0:04a9f72bbca7 5874 half.Set05();
stevep 0:04a9f72bbca7 5875
stevep 0:04a9f72bbca7 5876 if( IsSign() )
stevep 0:04a9f72bbca7 5877 {
stevep 0:04a9f72bbca7 5878 // 'this' is < 0
stevep 0:04a9f72bbca7 5879 c = Sub( half );
stevep 0:04a9f72bbca7 5880 }
stevep 0:04a9f72bbca7 5881 else
stevep 0:04a9f72bbca7 5882 {
stevep 0:04a9f72bbca7 5883 // 'this' is > 0
stevep 0:04a9f72bbca7 5884 c = Add( half );
stevep 0:04a9f72bbca7 5885 }
stevep 0:04a9f72bbca7 5886
stevep 0:04a9f72bbca7 5887 SkipFraction();
stevep 0:04a9f72bbca7 5888
stevep 0:04a9f72bbca7 5889 return CheckCarry(c);
stevep 0:04a9f72bbca7 5890 }
stevep 0:04a9f72bbca7 5891
stevep 0:04a9f72bbca7 5892
stevep 0:04a9f72bbca7 5893
stevep 0:04a9f72bbca7 5894 /*!
stevep 0:04a9f72bbca7 5895 *
stevep 0:04a9f72bbca7 5896 * input/output operators for standard streams
stevep 0:04a9f72bbca7 5897 *
stevep 0:04a9f72bbca7 5898 */
stevep 0:04a9f72bbca7 5899
stevep 0:04a9f72bbca7 5900 private:
stevep 0:04a9f72bbca7 5901
stevep 0:04a9f72bbca7 5902 /*!
stevep 0:04a9f72bbca7 5903 an auxiliary method for outputing to standard streams
stevep 0:04a9f72bbca7 5904 */
stevep 0:04a9f72bbca7 5905 template<class ostream_type, class string_type>
stevep 0:04a9f72bbca7 5906 static ostream_type & OutputToStream(ostream_type & s, const Big<exp,man> & l)
stevep 0:04a9f72bbca7 5907 {
stevep 0:04a9f72bbca7 5908 string_type ss;
stevep 0:04a9f72bbca7 5909
stevep 0:04a9f72bbca7 5910 l.ToString(ss);
stevep 0:04a9f72bbca7 5911 s << ss;
stevep 0:04a9f72bbca7 5912
stevep 0:04a9f72bbca7 5913 return s;
stevep 0:04a9f72bbca7 5914 }
stevep 0:04a9f72bbca7 5915
stevep 0:04a9f72bbca7 5916
stevep 0:04a9f72bbca7 5917 public:
stevep 0:04a9f72bbca7 5918
stevep 0:04a9f72bbca7 5919
stevep 0:04a9f72bbca7 5920 /*!
stevep 0:04a9f72bbca7 5921 output to standard streams
stevep 0:04a9f72bbca7 5922 */
stevep 0:04a9f72bbca7 5923 friend std::ostream & operator<<(std::ostream & s, const Big<exp,man> & l)
stevep 0:04a9f72bbca7 5924 {
stevep 0:04a9f72bbca7 5925 return OutputToStream<std::ostream, std::string>(s, l);
stevep 0:04a9f72bbca7 5926 }
stevep 0:04a9f72bbca7 5927
stevep 0:04a9f72bbca7 5928
stevep 0:04a9f72bbca7 5929 #ifndef TTMATH_DONT_USE_WCHAR
stevep 0:04a9f72bbca7 5930
stevep 0:04a9f72bbca7 5931 /*!
stevep 0:04a9f72bbca7 5932 output to standard streams
stevep 0:04a9f72bbca7 5933 */
stevep 0:04a9f72bbca7 5934 friend std::wostream & operator<<(std::wostream & s, const Big<exp,man> & l)
stevep 0:04a9f72bbca7 5935 {
stevep 0:04a9f72bbca7 5936 return OutputToStream<std::wostream, std::wstring>(s, l);
stevep 0:04a9f72bbca7 5937 }
stevep 0:04a9f72bbca7 5938
stevep 0:04a9f72bbca7 5939 #endif
stevep 0:04a9f72bbca7 5940
stevep 0:04a9f72bbca7 5941
stevep 0:04a9f72bbca7 5942
stevep 0:04a9f72bbca7 5943 private:
stevep 0:04a9f72bbca7 5944
stevep 0:04a9f72bbca7 5945 /*!
stevep 0:04a9f72bbca7 5946 an auxiliary method for converting from a string
stevep 0:04a9f72bbca7 5947 */
stevep 0:04a9f72bbca7 5948 template<class istream_type, class string_type, class char_type>
stevep 0:04a9f72bbca7 5949 static istream_type & InputFromStream(istream_type & s, Big<exp,man> & l)
stevep 0:04a9f72bbca7 5950 {
stevep 0:04a9f72bbca7 5951 string_type ss;
stevep 0:04a9f72bbca7 5952
stevep 0:04a9f72bbca7 5953 // char or wchar_t for operator>>
stevep 0:04a9f72bbca7 5954 char_type z, old_z;
stevep 0:04a9f72bbca7 5955 bool was_comma = false;
stevep 0:04a9f72bbca7 5956 bool was_e = false;
stevep 0:04a9f72bbca7 5957
stevep 0:04a9f72bbca7 5958
stevep 0:04a9f72bbca7 5959 // operator>> omits white characters if they're set for ommiting
stevep 0:04a9f72bbca7 5960 s >> z;
stevep 0:04a9f72bbca7 5961
stevep 0:04a9f72bbca7 5962 if( z=='-' || z=='+' )
stevep 0:04a9f72bbca7 5963 {
stevep 0:04a9f72bbca7 5964 ss += z;
stevep 0:04a9f72bbca7 5965 s >> z; // we're reading a next character (white characters can be ommited)
stevep 0:04a9f72bbca7 5966 }
stevep 0:04a9f72bbca7 5967
stevep 0:04a9f72bbca7 5968 old_z = 0;
stevep 0:04a9f72bbca7 5969
stevep 0:04a9f72bbca7 5970 // we're reading only digits (base=10) and only one comma operator
stevep 0:04a9f72bbca7 5971 for( ; s.good() ; z=static_cast<char_type>(s.get()) )
stevep 0:04a9f72bbca7 5972 {
stevep 0:04a9f72bbca7 5973 if( z=='.' || z==',' )
stevep 0:04a9f72bbca7 5974 {
stevep 0:04a9f72bbca7 5975 if( was_comma || was_e )
stevep 0:04a9f72bbca7 5976 // second comma operator or comma operator after 'e' character
stevep 0:04a9f72bbca7 5977 break;
stevep 0:04a9f72bbca7 5978
stevep 0:04a9f72bbca7 5979 was_comma = true;
stevep 0:04a9f72bbca7 5980 }
stevep 0:04a9f72bbca7 5981 else
stevep 0:04a9f72bbca7 5982 if( z == 'e' || z == 'E' )
stevep 0:04a9f72bbca7 5983 {
stevep 0:04a9f72bbca7 5984 if( was_e )
stevep 0:04a9f72bbca7 5985 // second 'e' character
stevep 0:04a9f72bbca7 5986 break;
stevep 0:04a9f72bbca7 5987
stevep 0:04a9f72bbca7 5988 was_e = true;
stevep 0:04a9f72bbca7 5989 }
stevep 0:04a9f72bbca7 5990 else
stevep 0:04a9f72bbca7 5991 if( z == '+' || z == '-' )
stevep 0:04a9f72bbca7 5992 {
stevep 0:04a9f72bbca7 5993 if( old_z != 'e' && old_z != 'E' )
stevep 0:04a9f72bbca7 5994 // '+' or '-' is allowed only after 'e' character
stevep 0:04a9f72bbca7 5995 break;
stevep 0:04a9f72bbca7 5996 }
stevep 0:04a9f72bbca7 5997 else
stevep 0:04a9f72bbca7 5998 if( Misc::CharToDigit(z, 10) < 0 )
stevep 0:04a9f72bbca7 5999 break;
stevep 0:04a9f72bbca7 6000
stevep 0:04a9f72bbca7 6001
stevep 0:04a9f72bbca7 6002 ss += z;
stevep 0:04a9f72bbca7 6003 old_z = z;
stevep 0:04a9f72bbca7 6004 }
stevep 0:04a9f72bbca7 6005
stevep 0:04a9f72bbca7 6006 // we're leaving the last read character
stevep 0:04a9f72bbca7 6007 // (it's not belonging to the value)
stevep 0:04a9f72bbca7 6008 s.unget();
stevep 0:04a9f72bbca7 6009
stevep 0:04a9f72bbca7 6010 l.FromString( ss );
stevep 0:04a9f72bbca7 6011
stevep 0:04a9f72bbca7 6012 return s;
stevep 0:04a9f72bbca7 6013 }
stevep 0:04a9f72bbca7 6014
stevep 0:04a9f72bbca7 6015
stevep 0:04a9f72bbca7 6016
stevep 0:04a9f72bbca7 6017 public:
stevep 0:04a9f72bbca7 6018
stevep 0:04a9f72bbca7 6019 /*!
stevep 0:04a9f72bbca7 6020 input from standard streams
stevep 0:04a9f72bbca7 6021 */
stevep 0:04a9f72bbca7 6022 friend std::istream & operator>>(std::istream & s, Big<exp,man> & l)
stevep 0:04a9f72bbca7 6023 {
stevep 0:04a9f72bbca7 6024 return InputFromStream<std::istream, std::string, char>(s, l);
stevep 0:04a9f72bbca7 6025 }
stevep 0:04a9f72bbca7 6026
stevep 0:04a9f72bbca7 6027
stevep 0:04a9f72bbca7 6028 #ifndef TTMATH_DONT_USE_WCHAR
stevep 0:04a9f72bbca7 6029
stevep 0:04a9f72bbca7 6030 /*!
stevep 0:04a9f72bbca7 6031 input from standard streams
stevep 0:04a9f72bbca7 6032 */
stevep 0:04a9f72bbca7 6033 friend std::wistream & operator>>(std::wistream & s, Big<exp,man> & l)
stevep 0:04a9f72bbca7 6034 {
stevep 0:04a9f72bbca7 6035 return InputFromStream<std::wistream, std::wstring, wchar_t>(s, l);
stevep 0:04a9f72bbca7 6036 }
stevep 0:04a9f72bbca7 6037
stevep 0:04a9f72bbca7 6038 #endif
stevep 0:04a9f72bbca7 6039
stevep 0:04a9f72bbca7 6040 };
stevep 0:04a9f72bbca7 6041
stevep 0:04a9f72bbca7 6042
stevep 0:04a9f72bbca7 6043 } // namespace
stevep 0:04a9f72bbca7 6044
stevep 0:04a9f72bbca7 6045 #endif
stevep 0:04a9f72bbca7 6046