done reports whether the loop is done. If it does not converge after the maximum number of iterations, it returns an error.
(z *Decimal)
| 46 | // done reports whether the loop is done. If it does not converge |
| 47 | // after the maximum number of iterations, it returns an error. |
| 48 | func (l *loop) done(z *Decimal) (bool, error) { |
| 49 | if _, err := l.c.Sub(&l.delta, &l.prevZ, z); err != nil { |
| 50 | return false, err |
| 51 | } |
| 52 | sign := l.delta.Sign() |
| 53 | if sign == 0 { |
| 54 | return true, nil |
| 55 | } |
| 56 | if sign < 0 { |
| 57 | // Convergence can oscillate when the calculation is nearly |
| 58 | // done and we're running out of bits. This stops that. |
| 59 | // See next comment. |
| 60 | l.delta.Neg(&l.delta) |
| 61 | } |
| 62 | |
| 63 | // We stop if the delta is smaller than a change of 1 in the |
| 64 | // (l.precision)-th digit of z. Examples: |
| 65 | // |
| 66 | // p = 4 |
| 67 | // z = 12345.678 = 12345678 * 10^-3 |
| 68 | // eps = 10.000 = 10^(-4+8-3) |
| 69 | // |
| 70 | // p = 3 |
| 71 | // z = 0.001234 = 1234 * 10^-6 |
| 72 | // eps = 0.00001 = 10^(-3+4-6) |
| 73 | var eps Decimal |
| 74 | eps.Coeff.Set(bigOne) |
| 75 | eps.Exponent = -l.precision + int32(z.NumDigits()) + z.Exponent |
| 76 | if l.delta.Cmp(&eps) <= 0 { |
| 77 | return true, nil |
| 78 | } |
| 79 | l.i++ |
| 80 | if l.i == l.maxIterations { |
| 81 | return false, fmt.Errorf( |
| 82 | "%s %s: did not converge after %d iterations; prev,last result %s,%s delta %s precision: %d", |
| 83 | l.name, l.arg.String(), l.maxIterations, z.String(), l.prevZ.String(), l.delta.String(), l.precision, |
| 84 | ) |
| 85 | } |
| 86 | l.prevZ.Set(z) |
| 87 | return false, nil |
| 88 | } |