setExponent sets d's Exponent to the sum of xs. Each value and the sum of xs must fit within an int32. An error occurs if the sum is outside of the MaxExponent or MinExponent range. nd is the number of digits in d, as computed by NumDigits. Callers can pass unknownNumDigits to indicate that they hav
(c *Context, nd int64, res Condition, xs ...int64)
| 303 | // do so. res is any Condition previously set for this operation, which can |
| 304 | // cause Underflow to be set if, for example, Inexact is already set. |
| 305 | func (d *Decimal) setExponent(c *Context, nd int64, res Condition, xs ...int64) Condition { |
| 306 | var sum int64 |
| 307 | for _, x := range xs { |
| 308 | if x > MaxExponent { |
| 309 | return SystemOverflow | Overflow |
| 310 | } |
| 311 | if x < MinExponent { |
| 312 | return SystemUnderflow | Underflow |
| 313 | } |
| 314 | sum += x |
| 315 | } |
| 316 | r := int32(sum) |
| 317 | |
| 318 | if nd == unknownNumDigits { |
| 319 | nd = d.NumDigits() |
| 320 | } |
| 321 | // adj is the adjusted exponent: exponent + clength - 1 |
| 322 | adj := sum + nd - 1 |
| 323 | // Make sure it is less than the system limits. |
| 324 | if adj > MaxExponent { |
| 325 | return SystemOverflow | Overflow |
| 326 | } |
| 327 | if adj < MinExponent { |
| 328 | return SystemUnderflow | Underflow |
| 329 | } |
| 330 | v := int32(adj) |
| 331 | |
| 332 | // d is subnormal. |
| 333 | if v < c.MinExponent { |
| 334 | if !d.IsZero() { |
| 335 | res |= Subnormal |
| 336 | } |
| 337 | Etiny := c.MinExponent - (int32(c.Precision) - 1) |
| 338 | // Only need to round if exponent < Etiny. |
| 339 | if r < Etiny { |
| 340 | // We need to take off (r - Etiny) digits. Split up d.Coeff into integer and |
| 341 | // fractional parts and do operations similar Round. We avoid calling Round |
| 342 | // directly because it calls setExponent and modifies the result's exponent |
| 343 | // and coeff in ways that would be wrong here. |
| 344 | var tmp Decimal |
| 345 | tmp.Coeff.Set(&d.Coeff) |
| 346 | tmp.Exponent = r - Etiny |
| 347 | var integ, frac Decimal |
| 348 | tmp.Modf(&integ, &frac) |
| 349 | frac.Abs(&frac) |
| 350 | if !frac.IsZero() { |
| 351 | res |= Inexact |
| 352 | if c.Rounding.ShouldAddOne(&integ.Coeff, integ.Negative, frac.Cmp(decimalHalf)) { |
| 353 | integ.Coeff.Add(&integ.Coeff, bigOne) |
| 354 | } |
| 355 | } |
| 356 | if integ.IsZero() { |
| 357 | res |= Clamped |
| 358 | } |
| 359 | r = Etiny |
| 360 | d.Coeff.Set(&integ.Coeff) |
| 361 | res |= Rounded |
| 362 | } |