1// Copyright 2016 The Cockroach Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12// implied. See the License for the specific language governing
13// permissions and limitations under the License.
14
15package apd_test
16
17import (
18	"fmt"
19
20	"github.com/cockroachdb/apd"
21)
22
23// ExampleOverflow demonstrates how to detect or error on overflow.
24func ExampleContext_overflow() {
25	// Create a context that will overflow at 1e3.
26	c := apd.Context{
27		MaxExponent: 2,
28		Traps:       apd.Overflow,
29	}
30	one := apd.New(1, 0)
31	d := apd.New(997, 0)
32	for {
33		res, err := c.Add(d, d, one)
34		fmt.Printf("d: %8s, overflow: %5v, err: %v\n", d, res.Overflow(), err)
35		if err != nil {
36			return
37		}
38	}
39	// Output: d:      998, overflow: false, err: <nil>
40	// d:      999, overflow: false, err: <nil>
41	// d: Infinity, overflow:  true, err: overflow
42}
43
44// ExampleInexact demonstrates how to detect inexact operations.
45func ExampleContext_inexact() {
46	d := apd.New(27, 0)
47	three := apd.New(3, 0)
48	c := apd.BaseContext.WithPrecision(5)
49	for {
50		res, err := c.Quo(d, d, three)
51		fmt.Printf("d: %7s, inexact: %5v, err: %v\n", d, res.Inexact(), err)
52		if err != nil {
53			return
54		}
55		if res.Inexact() {
56			return
57		}
58	}
59	// Output: d:       9, inexact: false, err: <nil>
60	// d:       3, inexact: false, err: <nil>
61	// d:       1, inexact: false, err: <nil>
62	// d: 0.33333, inexact:  true, err: <nil>
63}
64
65func ExampleContext_Quantize() {
66	input, _, _ := apd.NewFromString("123.45")
67	output := new(apd.Decimal)
68	c := apd.BaseContext.WithPrecision(10)
69	for i := int32(-3); i <= 3; i++ {
70		res, _ := c.Quantize(output, input, i)
71		fmt.Printf("%2v: %s", i, output)
72		if res != 0 {
73			fmt.Printf(" (%s)", res)
74		}
75		fmt.Println()
76	}
77	// Output: -3: 123.450
78	// -2: 123.45
79	// -1: 123.5 (inexact, rounded)
80	//  0: 123 (inexact, rounded)
81	//  1: 1.2E+2 (inexact, rounded)
82	//  2: 1E+2 (inexact, rounded)
83	//  3: 0E+3 (inexact, rounded)
84}
85
86func ExampleErrDecimal() {
87	c := apd.BaseContext.WithPrecision(5)
88	ed := apd.MakeErrDecimal(c)
89	d := apd.New(10, 0)
90	fmt.Printf("%s, err: %v\n", d, ed.Err())
91	ed.Add(d, d, apd.New(2, 1)) // add 20
92	fmt.Printf("%s, err: %v\n", d, ed.Err())
93	ed.Quo(d, d, apd.New(0, 0)) // divide by zero
94	fmt.Printf("%s, err: %v\n", d, ed.Err())
95	ed.Sub(d, d, apd.New(1, 0)) // attempt to subtract 1
96	// The subtraction doesn't occur and doesn't change the error.
97	fmt.Printf("%s, err: %v\n", d, ed.Err())
98	// Output: 10, err: <nil>
99	// 30, err: <nil>
100	// Infinity, err: division by zero
101	// Infinity, err: division by zero
102}
103
104// ExampleRoundToIntegralExact demonstrates how to use RoundToIntegralExact to
105// check if a number is an integer or not. Note the variations between integer
106// (which allows zeros after the decimal point) and strict (which does not). See
107// the documentation on Inexact and Rounded.
108func ExampleContext_RoundToIntegralExact() {
109	inputs := []string{
110		"123.4",
111		"123.0",
112		"123",
113		"12E1",
114		"120E-1",
115		"120E-2",
116	}
117	for _, input := range inputs {
118		d, _, _ := apd.NewFromString(input)
119		res, _ := apd.BaseContext.RoundToIntegralExact(d, d)
120		integer := !res.Inexact()
121		strict := !res.Rounded()
122		fmt.Printf("input: % 6s, output: %3s, integer: %5t, strict: %5t, res:", input, d, integer, strict)
123		if res != 0 {
124			fmt.Printf(" %s", res)
125		}
126		fmt.Println()
127	}
128	// Output: input:  123.4, output: 123, integer: false, strict: false, res: inexact, rounded
129	// input:  123.0, output: 123, integer:  true, strict: false, res: rounded
130	// input:    123, output: 123, integer:  true, strict:  true, res:
131	// input:   12E1, output: 120, integer:  true, strict:  true, res:
132	// input: 120E-1, output:  12, integer:  true, strict: false, res: rounded
133	// input: 120E-2, output:   1, integer: false, strict: false, res: inexact, rounded
134}
135