context

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 30, 2020 License: BSD-2-Clause Imports: 3 Imported by: 0

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

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

func (c *Context) Abs(z, x *decimal.Decimal) *decimal.Decimal

Abs sets z to the (possibly rounded) value |x| (the absolute value of x) and returns z.

func (*Context) Add

func (c *Context) Add(z, x, y *decimal.Decimal) (r *decimal.Decimal)

Add sets z to the rounded sum x+y and returns z.

func (*Context) Err

func (c *Context) Err() (err error)

Err returns the first error encountered since the last call to Err and clears the error state.

func (*Context) FMA

func (c *Context) FMA(z, x, y, u *decimal.Decimal) (r *decimal.Decimal)

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) Mul

func (c *Context) Mul(z, x, y *decimal.Decimal) (r *decimal.Decimal)

Mul sets z to the rounded product x×y and returns z.

func (*Context) Neg

func (c *Context) Neg(z, x *decimal.Decimal) *decimal.Decimal

Neg sets z to the (possibly rounded) value of x with its sign negated, and returns z.

func (*Context) New

func (c *Context) New() *decimal.Decimal

New returns a new decimal.Decimal with value 0, precision and rounding mode set to c's precision and rounding mode.

func (*Context) NewFloat

func (c *Context) NewFloat(x *big.Float) *decimal.Decimal

NewFloat returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) NewFloat64

func (c *Context) NewFloat64(x float64) *decimal.Decimal

NewFloat64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) NewInt

func (c *Context) NewInt(x *big.Int) *decimal.Decimal

NewInt returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) NewInt64

func (c *Context) NewInt64(x int64) *decimal.Decimal

NewInt64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) NewRat

func (c *Context) NewRat(x *big.Rat) *decimal.Decimal

NewRat returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) NewString

func (c *Context) NewString(s string) (d *decimal.Decimal, success bool)

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

func (c *Context) NewUint64(x uint64) *decimal.Decimal

NewUint64 returns a new *decimal.Decimal set to the (possibly rounded) value of x.

func (*Context) ParseDecimal

func (c *Context) ParseDecimal(s string, base int) (f *decimal.Decimal, b int, err error)

ParseDecimal is like d.Parse(s, base) with d set to the given precision and rounding mode.

func (*Context) Prec

func (c *Context) Prec() uint

Prec returns the mantissa precision of x in decimal digits. The result may be 0 for |x| == 0 and |x| == Inf.

func (*Context) Quo

func (c *Context) Quo(z, x, y *decimal.Decimal) (r *decimal.Decimal)

Quo sets z to the rounded quotient x/y and returns z.

func (*Context) Round

func (c *Context) Round(z, x *decimal.Decimal) *decimal.Decimal

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

func (c *Context) SetPrec(prec uint) *Context

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.

func (*Context) Sqrt

func (c *Context) Sqrt(z, x *decimal.Decimal) (r *decimal.Decimal)

Sqrt sets z to the rounded square root of x, and returns z.

func (*Context) Sub

func (c *Context) Sub(z, x, y *decimal.Decimal) (r *decimal.Decimal)

Sub sets z to the rounded difference x+y and returns z.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL