Documentation
¶
Overview ¶
Package context provides IEEE-754 style contexts for Decimals.
All factory functions of the form
func (c *Context) NewT(x T) *decimal.Decimal
create a new decimal.Decimal set to the value of x, and rounded using c's precision and rounding mode.
Operators that set a receiver z to a function of other decimal arguments like:
func (c *Context) UnaryOp(z, x *decimal.Decimal) *decimal.Decimal func (c *Context) BinaryOp(z, x, y *decimal.Decimal) *decimal.Decimal
set z to the result of z.Op(args), rounded using the c's precision and rounding mode and return z. Caveat: rounding occurs *before* doing the operation, as a result, if z is also one of the arguments, this may lead to incorrect results (1.349 -> 1.35 -> 1.4 instead of 1.3).
Operations on a Context are panic free: if an operation generates a NaN, the operation will silently succeed with an undefined result (they simply return the receiver z, but its value is undefined). Further operations with the context will be no-ops until (Context).Err is called to check for errors.
Although it does not exactly provide IEEE-754 NaNs, it provides a form of support for quiet NaNs.
The idiomatic use is to think of operations between calls to (Context).Err as a transaction. Operations are done in batches uintil a result is to be output (or re-used in the next iteration of a loop). Calling (Context).Err at this point determines if the last batch was successful and the result usable. This also readies the Context for the next transaction.
Example ¶
Example demonstrates various features of Contexts.
package main import ( "errors" "fmt" "github.com/db47h/decimal" "github.com/db47h/decimal/context" ) var _four = new(decimal.Decimal).SetPrec(1).SetInt64(-4) var two = new(decimal.Decimal).SetPrec(1).SetInt64(2) // solve solves the quadratic equation ax² + bx + c = 0, using ctx's rounding // mode and precision. It can fail with various combinations of inputs, for // example a = 0, b = 2, c = -3 will result in dividing zero by zero when // computing x0. So we need to check errors. func solve(ctx context.Context, a, b, c *decimal.Decimal) (x0, x1 *decimal.Decimal, err error) { d := ctx.New() // compute discriminant ctx.Mul(d, a, _four) // d = a × -4 ctx.Mul(d, d, c) // × c ctx.FMA(d, b, b, d) // + b × b if err != nil { return nil, nil, fmt.Errorf("error computing discriminant: %w", err) } if d.Sign() < 0 { return nil, nil, errors.New("no real roots") } // d = √d ctx.Sqrt(d, d) twoA := ctx.Mul(ctx.New(), a, two) negB := ctx.Neg(ctx.New(), b) x0 = ctx.Add(ctx.New(), negB, d) ctx.Quo(x0, x0, twoA) x1 = ctx.Sub(ctx.New(), negB, d) ctx.Quo(x1, x1, twoA) if err = ctx.Err(); err != nil { return nil, nil, fmt.Errorf("error computing roots: %w", err) } return } // Example demonstrates various features of Contexts. func main() { ctx := context.New(0, decimal.ToNearestEven) a, b, c := ctx.NewInt64(1), ctx.NewInt64(2), ctx.NewInt64(-3) x0, x1, err := solve(ctx, a, b, c) if err != nil { fmt.Printf("failed to solve %g×x²%+gx%+g: %v\n", a, b, c, err) return } fmt.Printf("roots of %g×x²%+gx%+g: %g, %g\n", a, b, c, x0, x1) a = ctx.New() // zero x0, x1, err = solve(ctx, a, b, c) if err != nil { // obviously, our solve() algorithm cannot handle a == 0 fmt.Printf("failed to solve %g×x²%+gx%+g: %v\n", a, b, c, err) return } fmt.Printf("roots of %g×x²%+gx%+g: %g, %g\n", a, b, c, x0, x1) }
Output: roots of 1×x²+2x-3: 1, -3 failed to solve 0×x²+2x-3: error computing roots: division of zero by zero or infinity by infinity
Index ¶
- type Context
- func (c *Context) Abs(z, x *decimal.Decimal) *decimal.Decimal
- func (c *Context) Add(z, x, y *decimal.Decimal) (r *decimal.Decimal)
- func (c *Context) Err() (err error)
- func (c *Context) FMA(z, x, y, u *decimal.Decimal) (r *decimal.Decimal)
- func (c *Context) Mode() decimal.RoundingMode
- func (c *Context) Mul(z, x, y *decimal.Decimal) (r *decimal.Decimal)
- func (c *Context) Neg(z, x *decimal.Decimal) *decimal.Decimal
- func (c *Context) New() *decimal.Decimal
- func (c *Context) NewFloat(x *big.Float) *decimal.Decimal
- func (c *Context) NewFloat64(x float64) *decimal.Decimal
- func (c *Context) NewInt(x *big.Int) *decimal.Decimal
- func (c *Context) NewInt64(x int64) *decimal.Decimal
- func (c *Context) NewRat(x *big.Rat) *decimal.Decimal
- func (c *Context) NewString(s string) (d *decimal.Decimal, success bool)
- func (c *Context) NewUint64(x uint64) *decimal.Decimal
- func (c *Context) ParseDecimal(s string, base int) (f *decimal.Decimal, b int, err error)
- func (c *Context) Prec() uint
- func (c *Context) Quo(z, x, y *decimal.Decimal) (r *decimal.Decimal)
- func (c *Context) Round(z, x *decimal.Decimal) *decimal.Decimal
- func (c *Context) SetMode(mode decimal.RoundingMode) *Context
- func (c *Context) SetPrec(prec uint) *Context
- func (c *Context) Sqrt(z, x *decimal.Decimal) (r *decimal.Decimal)
- func (c *Context) Sub(z, x, y *decimal.Decimal) (r *decimal.Decimal)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
A Context is a wrapper around Decimals that facilitates management of rounding modes, precision and error handling.
func New ¶
func New(prec uint, mode decimal.RoundingMode) Context
New creates a new context with the given precision and rounding mode. If prec is 0, it will be set to decimal.DefaultRoundingMode.
func (*Context) Abs ¶
Abs sets z to the (possibly rounded) value |x| (the absolute value of x) and returns z.
func (*Context) Err ¶
Err returns the first error encountered since the last call to Err and clears the error state.
func (*Context) FMA ¶
FMA sets z to x * y + u, computed with only one rounding. That is, FMA performs the fused multiply-add of x, y, and u.
func (*Context) Mode ¶
func (c *Context) Mode() decimal.RoundingMode
Mode returns the rounding mode of c.
func (*Context) Neg ¶
Neg sets z to the (possibly rounded) value of x with its sign negated, and returns z.
func (*Context) New ¶
New returns a new decimal.Decimal with value 0, precision and rounding mode set to c's precision and rounding mode.
func (*Context) NewFloat ¶
NewFloat returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) NewFloat64 ¶
NewFloat64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) NewInt ¶
NewInt returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) NewInt64 ¶
NewInt64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) NewRat ¶
NewRat returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) NewString ¶
NewFromString returns a new Decimal with the value of s and a boolean indicating success. s must be a floating-point number of the same format as accepted by (*decimal.Decimal).Parse, with base argument 0. The entire string (not just a prefix) must be valid for success. If the operation failed, the value of d is undefined but the returned value is nil. d's precision and rounding mode are set to c's precision and rounding mode.
func (*Context) NewUint64 ¶
NewUint64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.
func (*Context) ParseDecimal ¶
ParseDecimal is like d.Parse(s, base) with d set to the given precision and rounding mode.
func (*Context) Prec ¶
Prec returns the mantissa precision of x in decimal digits. The result may be 0 for |x| == 0 and |x| == Inf.
func (*Context) Round ¶
Round sets z's to the value of x and returns z rounded using c's precision and rounding mode.
func (*Context) SetMode ¶
func (c *Context) SetMode(mode decimal.RoundingMode) *Context
SetMode sets c's rounding mode to mode and returns c.
func (*Context) SetPrec ¶
SetPrec sets c's precision to prec and returns c.
If prec > MaxPrec, it is set to MaxPrec. If prec == 0, it is set to decimal.DefaultDecimalPrec.