func (a *Mpint) SetFloat(b *Mpflt) int { // avoid converting huge floating-point numbers to integers // (2*Mpprec is large enough to permit all tests to pass) if b.Val.MantExp(nil) > 2*Mpprec { return -1 } if _, acc := b.Val.Int(&a.Val); acc == big.Exact { return 0 } const delta = 16 // a reasonably small number of bits > 0 var t big.Float t.SetPrec(Mpprec - delta) // try rounding down a little t.SetMode(big.ToZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { return 0 } // try rounding up a little t.SetMode(big.AwayFromZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { return 0 } return -1 }
// ToInt converts x to an Int value if x is representable as an Int. // Otherwise it returns an Unknown. func ToInt(x Value) Value { switch x := x.(type) { case int64Val, intVal: return x case ratVal: if x.val.IsInt() { return makeInt(x.val.Num()) } case floatVal: // avoid creation of huge integers // (Existing tests require permitting exponents of at least 1024; // allow any value that would also be permissible as a fraction.) if smallRat(x.val) { i := newInt() if _, acc := x.val.Int(i); acc == big.Exact { return makeInt(i) } // If we can get an integer by rounding up or down, // assume x is not an integer because of rounding // errors in prior computations. const delta = 4 // a small number of bits > 0 var t big.Float t.SetPrec(prec - delta) // try rounding down a little t.SetMode(big.ToZero) t.Set(x.val) if _, acc := t.Int(i); acc == big.Exact { return makeInt(i) } // try rounding up a little t.SetMode(big.AwayFromZero) t.Set(x.val) if _, acc := t.Int(i); acc == big.Exact { return makeInt(i) } } case complexVal: if re := ToFloat(x); re.Kind() == Float { return ToInt(re) } } return unknownVal{} }