pax_global_header00006660000000000000000000000064132562262240014516gustar00rootroot0000000000000052 comment=d2d2541c53f18d2a059457998ce2876cc8e67cbf inf-0.9.1/000077500000000000000000000000001325622622400123015ustar00rootroot00000000000000inf-0.9.1/LICENSE000066400000000000000000000027641325622622400133170ustar00rootroot00000000000000Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. inf-0.9.1/benchmark_test.go000066400000000000000000000101731325622622400156230ustar00rootroot00000000000000package inf import ( "fmt" "math/big" "math/rand" "sync" "testing" ) const maxcap = 1024 * 1024 const bits = 256 const maxscale = 32 var once sync.Once var decInput [][2]Dec var intInput [][2]big.Int var initBench = func() { decInput = make([][2]Dec, maxcap) intInput = make([][2]big.Int, maxcap) max := new(big.Int).Lsh(big.NewInt(1), bits) r := rand.New(rand.NewSource(0)) for i := 0; i < cap(decInput); i++ { decInput[i][0].SetUnscaledBig(new(big.Int).Rand(r, max)). SetScale(Scale(r.Int31n(int32(2*maxscale-1)) - int32(maxscale))) decInput[i][1].SetUnscaledBig(new(big.Int).Rand(r, max)). SetScale(Scale(r.Int31n(int32(2*maxscale-1)) - int32(maxscale))) } for i := 0; i < cap(intInput); i++ { intInput[i][0].Rand(r, max) intInput[i][1].Rand(r, max) } } func doBenchmarkDec1(b *testing.B, f func(z *Dec)) { once.Do(initBench) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { f(&decInput[i%maxcap][0]) } } func doBenchmarkDec2(b *testing.B, f func(x, y *Dec)) { once.Do(initBench) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { f(&decInput[i%maxcap][0], &decInput[i%maxcap][1]) } } func doBenchmarkInt1(b *testing.B, f func(z *big.Int)) { once.Do(initBench) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { f(&intInput[i%maxcap][0]) } } func doBenchmarkInt2(b *testing.B, f func(x, y *big.Int)) { once.Do(initBench) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { f(&intInput[i%maxcap][0], &intInput[i%maxcap][1]) } } func Benchmark_Dec_String(b *testing.B) { doBenchmarkDec1(b, func(x *Dec) { x.String() }) } func Benchmark_Dec_StringScan(b *testing.B) { doBenchmarkDec1(b, func(x *Dec) { s := x.String() d := new(Dec) fmt.Sscan(s, d) }) } func Benchmark_Dec_GobEncode(b *testing.B) { doBenchmarkDec1(b, func(x *Dec) { x.GobEncode() }) } func Benchmark_Dec_GobEnDecode(b *testing.B) { doBenchmarkDec1(b, func(x *Dec) { g, _ := x.GobEncode() new(Dec).GobDecode(g) }) } func Benchmark_Dec_Add(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { ys := y.Scale() y.SetScale(x.Scale()) _ = new(Dec).Add(x, y) y.SetScale(ys) }) } func Benchmark_Dec_AddMixed(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { _ = new(Dec).Add(x, y) }) } func Benchmark_Dec_Sub(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { ys := y.Scale() y.SetScale(x.Scale()) _ = new(Dec).Sub(x, y) y.SetScale(ys) }) } func Benchmark_Dec_SubMixed(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { _ = new(Dec).Sub(x, y) }) } func Benchmark_Dec_Mul(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { _ = new(Dec).Mul(x, y) }) } func Benchmark_Dec_Mul_QuoExact(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { v := new(Dec).Mul(x, y) _ = new(Dec).QuoExact(v, y) }) } func Benchmark_Dec_QuoRound_Fixed_Down(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { _ = new(Dec).QuoRound(x, y, 0, RoundDown) }) } func Benchmark_Dec_QuoRound_Fixed_HalfUp(b *testing.B) { doBenchmarkDec2(b, func(x, y *Dec) { _ = new(Dec).QuoRound(x, y, 0, RoundHalfUp) }) } func Benchmark_Int_String(b *testing.B) { doBenchmarkInt1(b, func(x *big.Int) { x.String() }) } func Benchmark_Int_StringScan(b *testing.B) { doBenchmarkInt1(b, func(x *big.Int) { s := x.String() d := new(big.Int) fmt.Sscan(s, d) }) } func Benchmark_Int_GobEncode(b *testing.B) { doBenchmarkInt1(b, func(x *big.Int) { x.GobEncode() }) } func Benchmark_Int_GobEnDecode(b *testing.B) { doBenchmarkInt1(b, func(x *big.Int) { g, _ := x.GobEncode() new(big.Int).GobDecode(g) }) } func Benchmark_Int_Add(b *testing.B) { doBenchmarkInt2(b, func(x, y *big.Int) { _ = new(big.Int).Add(x, y) }) } func Benchmark_Int_Sub(b *testing.B) { doBenchmarkInt2(b, func(x, y *big.Int) { _ = new(big.Int).Sub(x, y) }) } func Benchmark_Int_Mul(b *testing.B) { doBenchmarkInt2(b, func(x, y *big.Int) { _ = new(big.Int).Mul(x, y) }) } func Benchmark_Int_Quo(b *testing.B) { doBenchmarkInt2(b, func(x, y *big.Int) { _ = new(big.Int).Quo(x, y) }) } func Benchmark_Int_QuoRem(b *testing.B) { doBenchmarkInt2(b, func(x, y *big.Int) { _, _ = new(big.Int).QuoRem(x, y, new(big.Int)) }) } inf-0.9.1/dec.go000066400000000000000000000403401325622622400133640ustar00rootroot00000000000000// Package inf (type inf.Dec) implements "infinite-precision" decimal // arithmetic. // "Infinite precision" describes two characteristics: practically unlimited // precision for decimal number representation and no support for calculating // with any specific fixed precision. // (Although there is no practical limit on precision, inf.Dec can only // represent finite decimals.) // // This package is currently in experimental stage and the API may change. // // This package does NOT support: // - rounding to specific precisions (as opposed to specific decimal positions) // - the notion of context (each rounding must be explicit) // - NaN and Inf values, and distinguishing between positive and negative zero // - conversions to and from float32/64 types // // Features considered for possible addition: // + formatting options // + Exp method // + combined operations such as AddRound/MulAdd etc // + exchanging data in decimal32/64/128 formats // package inf // import "gopkg.in/inf.v0" // TODO: // - avoid excessive deep copying (quo and rounders) import ( "fmt" "io" "math/big" "strings" ) // A Dec represents a signed arbitrary-precision decimal. // It is a combination of a sign, an arbitrary-precision integer coefficient // value, and a signed fixed-precision exponent value. // The sign and the coefficient value are handled together as a signed value // and referred to as the unscaled value. // (Positive and negative zero values are not distinguished.) // Since the exponent is most commonly non-positive, it is handled in negated // form and referred to as scale. // // The mathematical value of a Dec equals: // // unscaled * 10**(-scale) // // Note that different Dec representations may have equal mathematical values. // // unscaled scale String() // ------------------------- // 0 0 "0" // 0 2 "0.00" // 0 -2 "0" // 1 0 "1" // 100 2 "1.00" // 10 0 "10" // 1 -1 "10" // // The zero value for a Dec represents the value 0 with scale 0. // // Operations are typically performed through the *Dec type. // The semantics of the assignment operation "=" for "bare" Dec values is // undefined and should not be relied on. // // Methods are typically of the form: // // func (z *Dec) Op(x, y *Dec) *Dec // // and implement operations z = x Op y with the result as receiver; if it // is one of the operands it may be overwritten (and its memory reused). // To enable chaining of operations, the result is also returned. Methods // returning a result other than *Dec take one of the operands as the receiver. // // A "bare" Quo method (quotient / division operation) is not provided, as the // result is not always a finite decimal and thus in general cannot be // represented as a Dec. // Instead, in the common case when rounding is (potentially) necessary, // QuoRound should be used with a Scale and a Rounder. // QuoExact or QuoRound with RoundExact can be used in the special cases when it // is known that the result is always a finite decimal. // type Dec struct { unscaled big.Int scale Scale } // Scale represents the type used for the scale of a Dec. type Scale int32 const scaleSize = 4 // bytes in a Scale value // Scaler represents a method for obtaining the scale to use for the result of // an operation on x and y. type scaler interface { Scale(x *Dec, y *Dec) Scale } var bigInt = [...]*big.Int{ big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4), big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9), big.NewInt(10), } var exp10cache [64]big.Int = func() [64]big.Int { e10, e10i := [64]big.Int{}, bigInt[1] for i := range e10 { e10[i].Set(e10i) e10i = new(big.Int).Mul(e10i, bigInt[10]) } return e10 }() // NewDec allocates and returns a new Dec set to the given int64 unscaled value // and scale. func NewDec(unscaled int64, scale Scale) *Dec { return new(Dec).SetUnscaled(unscaled).SetScale(scale) } // NewDecBig allocates and returns a new Dec set to the given *big.Int unscaled // value and scale. func NewDecBig(unscaled *big.Int, scale Scale) *Dec { return new(Dec).SetUnscaledBig(unscaled).SetScale(scale) } // Scale returns the scale of x. func (x *Dec) Scale() Scale { return x.scale } // Unscaled returns the unscaled value of x for u and true for ok when the // unscaled value can be represented as int64; otherwise it returns an undefined // int64 value for u and false for ok. Use x.UnscaledBig().Int64() to avoid // checking the validity of the value when the check is known to be redundant. func (x *Dec) Unscaled() (u int64, ok bool) { u = x.unscaled.Int64() var i big.Int ok = i.SetInt64(u).Cmp(&x.unscaled) == 0 return } // UnscaledBig returns the unscaled value of x as *big.Int. func (x *Dec) UnscaledBig() *big.Int { return &x.unscaled } // SetScale sets the scale of z, with the unscaled value unchanged, and returns // z. // The mathematical value of the Dec changes as if it was multiplied by // 10**(oldscale-scale). func (z *Dec) SetScale(scale Scale) *Dec { z.scale = scale return z } // SetUnscaled sets the unscaled value of z, with the scale unchanged, and // returns z. func (z *Dec) SetUnscaled(unscaled int64) *Dec { z.unscaled.SetInt64(unscaled) return z } // SetUnscaledBig sets the unscaled value of z, with the scale unchanged, and // returns z. func (z *Dec) SetUnscaledBig(unscaled *big.Int) *Dec { z.unscaled.Set(unscaled) return z } // Set sets z to the value of x and returns z. // It does nothing if z == x. func (z *Dec) Set(x *Dec) *Dec { if z != x { z.SetUnscaledBig(x.UnscaledBig()) z.SetScale(x.Scale()) } return z } // Sign returns: // // -1 if x < 0 // 0 if x == 0 // +1 if x > 0 // func (x *Dec) Sign() int { return x.UnscaledBig().Sign() } // Neg sets z to -x and returns z. func (z *Dec) Neg(x *Dec) *Dec { z.SetScale(x.Scale()) z.UnscaledBig().Neg(x.UnscaledBig()) return z } // Cmp compares x and y and returns: // // -1 if x < y // 0 if x == y // +1 if x > y // func (x *Dec) Cmp(y *Dec) int { xx, yy := upscale(x, y) return xx.UnscaledBig().Cmp(yy.UnscaledBig()) } // Abs sets z to |x| (the absolute value of x) and returns z. func (z *Dec) Abs(x *Dec) *Dec { z.SetScale(x.Scale()) z.UnscaledBig().Abs(x.UnscaledBig()) return z } // Add sets z to the sum x+y and returns z. // The scale of z is the greater of the scales of x and y. func (z *Dec) Add(x, y *Dec) *Dec { xx, yy := upscale(x, y) z.SetScale(xx.Scale()) z.UnscaledBig().Add(xx.UnscaledBig(), yy.UnscaledBig()) return z } // Sub sets z to the difference x-y and returns z. // The scale of z is the greater of the scales of x and y. func (z *Dec) Sub(x, y *Dec) *Dec { xx, yy := upscale(x, y) z.SetScale(xx.Scale()) z.UnscaledBig().Sub(xx.UnscaledBig(), yy.UnscaledBig()) return z } // Mul sets z to the product x*y and returns z. // The scale of z is the sum of the scales of x and y. func (z *Dec) Mul(x, y *Dec) *Dec { z.SetScale(x.Scale() + y.Scale()) z.UnscaledBig().Mul(x.UnscaledBig(), y.UnscaledBig()) return z } // Round sets z to the value of x rounded to Scale s using Rounder r, and // returns z. func (z *Dec) Round(x *Dec, s Scale, r Rounder) *Dec { return z.QuoRound(x, NewDec(1, 0), s, r) } // QuoRound sets z to the quotient x/y, rounded using the given Rounder to the // specified scale. // // If the rounder is RoundExact but the result can not be expressed exactly at // the specified scale, QuoRound returns nil, and the value of z is undefined. // // There is no corresponding Div method; the equivalent can be achieved through // the choice of Rounder used. // func (z *Dec) QuoRound(x, y *Dec, s Scale, r Rounder) *Dec { return z.quo(x, y, sclr{s}, r) } func (z *Dec) quo(x, y *Dec, s scaler, r Rounder) *Dec { scl := s.Scale(x, y) var zzz *Dec if r.UseRemainder() { zz, rA, rB := new(Dec).quoRem(x, y, scl, true, new(big.Int), new(big.Int)) zzz = r.Round(new(Dec), zz, rA, rB) } else { zz, _, _ := new(Dec).quoRem(x, y, scl, false, nil, nil) zzz = r.Round(new(Dec), zz, nil, nil) } if zzz == nil { return nil } return z.Set(zzz) } // QuoExact sets z to the quotient x/y and returns z when x/y is a finite // decimal. Otherwise it returns nil and the value of z is undefined. // // The scale of a non-nil result is "x.Scale() - y.Scale()" or greater; it is // calculated so that the remainder will be zero whenever x/y is a finite // decimal. func (z *Dec) QuoExact(x, y *Dec) *Dec { return z.quo(x, y, scaleQuoExact{}, RoundExact) } // quoRem sets z to the quotient x/y with the scale s, and if useRem is true, // it sets remNum and remDen to the numerator and denominator of the remainder. // It returns z, remNum and remDen. // // The remainder is normalized to the range -1 < r < 1 to simplify rounding; // that is, the results satisfy the following equation: // // x / y = z + (remNum/remDen) * 10**(-z.Scale()) // // See Rounder for more details about rounding. // func (z *Dec) quoRem(x, y *Dec, s Scale, useRem bool, remNum, remDen *big.Int) (*Dec, *big.Int, *big.Int) { // difference (required adjustment) compared to "canonical" result scale shift := s - (x.Scale() - y.Scale()) // pointers to adjusted unscaled dividend and divisor var ix, iy *big.Int switch { case shift > 0: // increased scale: decimal-shift dividend left ix = new(big.Int).Mul(x.UnscaledBig(), exp10(shift)) iy = y.UnscaledBig() case shift < 0: // decreased scale: decimal-shift divisor left ix = x.UnscaledBig() iy = new(big.Int).Mul(y.UnscaledBig(), exp10(-shift)) default: ix = x.UnscaledBig() iy = y.UnscaledBig() } // save a copy of iy in case it to be overwritten with the result iy2 := iy if iy == z.UnscaledBig() { iy2 = new(big.Int).Set(iy) } // set scale z.SetScale(s) // set unscaled if useRem { // Int division _, intr := z.UnscaledBig().QuoRem(ix, iy, new(big.Int)) // set remainder remNum.Set(intr) remDen.Set(iy2) } else { z.UnscaledBig().Quo(ix, iy) } return z, remNum, remDen } type sclr struct{ s Scale } func (s sclr) Scale(x, y *Dec) Scale { return s.s } type scaleQuoExact struct{} func (sqe scaleQuoExact) Scale(x, y *Dec) Scale { rem := new(big.Rat).SetFrac(x.UnscaledBig(), y.UnscaledBig()) f2, f5 := factor2(rem.Denom()), factor(rem.Denom(), bigInt[5]) var f10 Scale if f2 > f5 { f10 = Scale(f2) } else { f10 = Scale(f5) } return x.Scale() - y.Scale() + f10 } func factor(n *big.Int, p *big.Int) int { // could be improved for large factors d, f := n, 0 for { dd, dm := new(big.Int).DivMod(d, p, new(big.Int)) if dm.Sign() == 0 { f++ d = dd } else { break } } return f } func factor2(n *big.Int) int { // could be improved for large factors f := 0 for ; n.Bit(f) == 0; f++ { } return f } func upscale(a, b *Dec) (*Dec, *Dec) { if a.Scale() == b.Scale() { return a, b } if a.Scale() > b.Scale() { bb := b.rescale(a.Scale()) return a, bb } aa := a.rescale(b.Scale()) return aa, b } func exp10(x Scale) *big.Int { if int(x) < len(exp10cache) { return &exp10cache[int(x)] } return new(big.Int).Exp(bigInt[10], big.NewInt(int64(x)), nil) } func (x *Dec) rescale(newScale Scale) *Dec { shift := newScale - x.Scale() switch { case shift < 0: e := exp10(-shift) return NewDecBig(new(big.Int).Quo(x.UnscaledBig(), e), newScale) case shift > 0: e := exp10(shift) return NewDecBig(new(big.Int).Mul(x.UnscaledBig(), e), newScale) } return x } var zeros = []byte("00000000000000000000000000000000" + "00000000000000000000000000000000") var lzeros = Scale(len(zeros)) func appendZeros(s []byte, n Scale) []byte { for i := Scale(0); i < n; i += lzeros { if n > i+lzeros { s = append(s, zeros...) } else { s = append(s, zeros[0:n-i]...) } } return s } func (x *Dec) String() string { if x == nil { return "" } scale := x.Scale() s := []byte(x.UnscaledBig().String()) if scale <= 0 { if scale != 0 && x.unscaled.Sign() != 0 { s = appendZeros(s, -scale) } return string(s) } negbit := Scale(-((x.Sign() - 1) / 2)) // scale > 0 lens := Scale(len(s)) if lens-negbit <= scale { ss := make([]byte, 0, scale+2) if negbit == 1 { ss = append(ss, '-') } ss = append(ss, '0', '.') ss = appendZeros(ss, scale-lens+negbit) ss = append(ss, s[negbit:]...) return string(ss) } // lens > scale ss := make([]byte, 0, lens+1) ss = append(ss, s[:lens-scale]...) ss = append(ss, '.') ss = append(ss, s[lens-scale:]...) return string(ss) } // Format is a support routine for fmt.Formatter. It accepts the decimal // formats 'd' and 'f', and handles both equivalently. // Width, precision, flags and bases 2, 8, 16 are not supported. func (x *Dec) Format(s fmt.State, ch rune) { if ch != 'd' && ch != 'f' && ch != 'v' && ch != 's' { fmt.Fprintf(s, "%%!%c(dec.Dec=%s)", ch, x.String()) return } fmt.Fprintf(s, x.String()) } func (z *Dec) scan(r io.RuneScanner) (*Dec, error) { unscaled := make([]byte, 0, 256) // collects chars of unscaled as bytes dp, dg := -1, -1 // indexes of decimal point, first digit loop: for { ch, _, err := r.ReadRune() if err == io.EOF { break loop } if err != nil { return nil, err } switch { case ch == '+' || ch == '-': if len(unscaled) > 0 || dp >= 0 { // must be first character r.UnreadRune() break loop } case ch == '.': if dp >= 0 { r.UnreadRune() break loop } dp = len(unscaled) continue // don't add to unscaled case ch >= '0' && ch <= '9': if dg == -1 { dg = len(unscaled) } default: r.UnreadRune() break loop } unscaled = append(unscaled, byte(ch)) } if dg == -1 { return nil, fmt.Errorf("no digits read") } if dp >= 0 { z.SetScale(Scale(len(unscaled) - dp)) } else { z.SetScale(0) } _, ok := z.UnscaledBig().SetString(string(unscaled), 10) if !ok { return nil, fmt.Errorf("invalid decimal: %s", string(unscaled)) } return z, nil } // SetString sets z to the value of s, interpreted as a decimal (base 10), // and returns z and a boolean indicating success. The scale of z is the // number of digits after the decimal point (including any trailing 0s), // or 0 if there is no decimal point. If SetString fails, the value of z // is undefined but the returned value is nil. func (z *Dec) SetString(s string) (*Dec, bool) { r := strings.NewReader(s) _, err := z.scan(r) if err != nil { return nil, false } _, _, err = r.ReadRune() if err != io.EOF { return nil, false } // err == io.EOF => scan consumed all of s return z, true } // Scan is a support routine for fmt.Scanner; it sets z to the value of // the scanned number. It accepts the decimal formats 'd' and 'f', and // handles both equivalently. Bases 2, 8, 16 are not supported. // The scale of z is the number of digits after the decimal point // (including any trailing 0s), or 0 if there is no decimal point. func (z *Dec) Scan(s fmt.ScanState, ch rune) error { if ch != 'd' && ch != 'f' && ch != 's' && ch != 'v' { return fmt.Errorf("Dec.Scan: invalid verb '%c'", ch) } s.SkipSpace() _, err := z.scan(s) return err } // Gob encoding version const decGobVersion byte = 1 func scaleBytes(s Scale) []byte { buf := make([]byte, scaleSize) i := scaleSize for j := 0; j < scaleSize; j++ { i-- buf[i] = byte(s) s >>= 8 } return buf } func scale(b []byte) (s Scale) { for j := 0; j < scaleSize; j++ { s <<= 8 s |= Scale(b[j]) } return } // GobEncode implements the gob.GobEncoder interface. func (x *Dec) GobEncode() ([]byte, error) { buf, err := x.UnscaledBig().GobEncode() if err != nil { return nil, err } buf = append(append(buf, scaleBytes(x.Scale())...), decGobVersion) return buf, nil } // GobDecode implements the gob.GobDecoder interface. func (z *Dec) GobDecode(buf []byte) error { if len(buf) == 0 { return fmt.Errorf("Dec.GobDecode: no data") } b := buf[len(buf)-1] if b != decGobVersion { return fmt.Errorf("Dec.GobDecode: encoding version %d not supported", b) } l := len(buf) - scaleSize - 1 err := z.UnscaledBig().GobDecode(buf[:l]) if err != nil { return err } z.SetScale(scale(buf[l : l+scaleSize])) return nil } // MarshalText implements the encoding.TextMarshaler interface. func (x *Dec) MarshalText() ([]byte, error) { return []byte(x.String()), nil } // UnmarshalText implements the encoding.TextUnmarshaler interface. func (z *Dec) UnmarshalText(data []byte) error { _, ok := z.SetString(string(data)) if !ok { return fmt.Errorf("invalid inf.Dec") } return nil } inf-0.9.1/dec_go1_2_test.go000066400000000000000000000012451325622622400154130ustar00rootroot00000000000000// +build go1.2 package inf import ( "encoding" "encoding/json" "testing" ) var _ encoding.TextMarshaler = new(Dec) var _ encoding.TextUnmarshaler = new(Dec) type Obj struct { Val *Dec } func TestDecJsonMarshalUnmarshal(t *testing.T) { o := Obj{Val: NewDec(123, 2)} js, err := json.Marshal(o) if err != nil { t.Fatalf("json.Marshal(%v): got %v, want ok", o, err) } o2 := &Obj{} err = json.Unmarshal(js, o2) if err != nil { t.Fatalf("json.Unmarshal(%#q): got %v, want ok", js, err) } if o.Val.Scale() != o2.Val.Scale() || o.Val.UnscaledBig().Cmp(o2.Val.UnscaledBig()) != 0 { t.Fatalf("json.Unmarshal(json.Marshal(%v)): want %v, got %v", o, o, o2) } } inf-0.9.1/dec_internal_test.go000066400000000000000000000026231325622622400163210ustar00rootroot00000000000000package inf import ( "math/big" "testing" ) var decQuoRemZZZ = []struct { z, x, y *Dec r *big.Rat srA, srB int }{ // basic examples {NewDec(1, 0), NewDec(2, 0), NewDec(2, 0), big.NewRat(0, 1), 0, 1}, {NewDec(15, 1), NewDec(3, 0), NewDec(2, 0), big.NewRat(0, 1), 0, 1}, {NewDec(1, 1), NewDec(1, 0), NewDec(10, 0), big.NewRat(0, 1), 0, 1}, {NewDec(0, 0), NewDec(2, 0), NewDec(3, 0), big.NewRat(2, 3), 1, 1}, {NewDec(0, 0), NewDec(2, 0), NewDec(6, 0), big.NewRat(1, 3), 1, 1}, {NewDec(1, 1), NewDec(2, 0), NewDec(12, 0), big.NewRat(2, 3), 1, 1}, // examples from the Go Language Specification {NewDec(1, 0), NewDec(5, 0), NewDec(3, 0), big.NewRat(2, 3), 1, 1}, {NewDec(-1, 0), NewDec(-5, 0), NewDec(3, 0), big.NewRat(-2, 3), -1, 1}, {NewDec(-1, 0), NewDec(5, 0), NewDec(-3, 0), big.NewRat(-2, 3), 1, -1}, {NewDec(1, 0), NewDec(-5, 0), NewDec(-3, 0), big.NewRat(2, 3), -1, -1}, } func TestDecQuoRem(t *testing.T) { for i, a := range decQuoRemZZZ { z, rA, rB := new(Dec), new(big.Int), new(big.Int) s := scaleQuoExact{}.Scale(a.x, a.y) z.quoRem(a.x, a.y, s, true, rA, rB) if a.z.Cmp(z) != 0 || a.r.Cmp(new(big.Rat).SetFrac(rA, rB)) != 0 { t.Errorf("#%d QuoRemZZZ got %v, %v, %v; expected %v, %v", i, z, rA, rB, a.z, a.r) } if a.srA != rA.Sign() || a.srB != rB.Sign() { t.Errorf("#%d QuoRemZZZ wrong signs, got %v, %v; expected %v, %v", i, rA.Sign(), rB.Sign(), a.srA, a.srB) } } } inf-0.9.1/dec_test.go000066400000000000000000000250601325622622400144250ustar00rootroot00000000000000package inf_test import ( "bytes" "encoding/gob" "fmt" "math/big" "strings" "testing" "gopkg.in/inf.v0" ) type decFunZZ func(z, x, y *inf.Dec) *inf.Dec type decArgZZ struct { z, x, y *inf.Dec } var decSumZZ = []decArgZZ{ {inf.NewDec(0, 0), inf.NewDec(0, 0), inf.NewDec(0, 0)}, {inf.NewDec(1, 0), inf.NewDec(1, 0), inf.NewDec(0, 0)}, {inf.NewDec(1111111110, 0), inf.NewDec(123456789, 0), inf.NewDec(987654321, 0)}, {inf.NewDec(-1, 0), inf.NewDec(-1, 0), inf.NewDec(0, 0)}, {inf.NewDec(864197532, 0), inf.NewDec(-123456789, 0), inf.NewDec(987654321, 0)}, {inf.NewDec(-1111111110, 0), inf.NewDec(-123456789, 0), inf.NewDec(-987654321, 0)}, {inf.NewDec(12, 2), inf.NewDec(1, 1), inf.NewDec(2, 2)}, } var decProdZZ = []decArgZZ{ {inf.NewDec(0, 0), inf.NewDec(0, 0), inf.NewDec(0, 0)}, {inf.NewDec(0, 0), inf.NewDec(1, 0), inf.NewDec(0, 0)}, {inf.NewDec(1, 0), inf.NewDec(1, 0), inf.NewDec(1, 0)}, {inf.NewDec(-991*991, 0), inf.NewDec(991, 0), inf.NewDec(-991, 0)}, {inf.NewDec(2, 3), inf.NewDec(1, 1), inf.NewDec(2, 2)}, {inf.NewDec(2, -3), inf.NewDec(1, -1), inf.NewDec(2, -2)}, {inf.NewDec(2, 3), inf.NewDec(1, 1), inf.NewDec(2, 2)}, } func TestDecSignZ(t *testing.T) { var zero inf.Dec for _, a := range decSumZZ { s := a.z.Sign() e := a.z.Cmp(&zero) if s != e { t.Errorf("got %d; want %d for z = %v", s, e, a.z) } } } func TestDecAbsZ(t *testing.T) { var zero inf.Dec for _, a := range decSumZZ { var z inf.Dec z.Abs(a.z) var e inf.Dec e.Set(a.z) if e.Cmp(&zero) < 0 { e.Sub(&zero, &e) } if z.Cmp(&e) != 0 { t.Errorf("got z = %v; want %v", z, e) } } } func testDecFunZZ(t *testing.T, msg string, f decFunZZ, a decArgZZ) { var z inf.Dec f(&z, a.x, a.y) if (&z).Cmp(a.z) != 0 { t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z) } } func TestDecSumZZ(t *testing.T) { AddZZ := func(z, x, y *inf.Dec) *inf.Dec { return z.Add(x, y) } SubZZ := func(z, x, y *inf.Dec) *inf.Dec { return z.Sub(x, y) } for _, a := range decSumZZ { arg := a testDecFunZZ(t, "AddZZ", AddZZ, arg) arg = decArgZZ{a.z, a.y, a.x} testDecFunZZ(t, "AddZZ symmetric", AddZZ, arg) arg = decArgZZ{a.x, a.z, a.y} testDecFunZZ(t, "SubZZ", SubZZ, arg) arg = decArgZZ{a.y, a.z, a.x} testDecFunZZ(t, "SubZZ symmetric", SubZZ, arg) } } func TestDecProdZZ(t *testing.T) { MulZZ := func(z, x, y *inf.Dec) *inf.Dec { return z.Mul(x, y) } for _, a := range decProdZZ { arg := a testDecFunZZ(t, "MulZZ", MulZZ, arg) arg = decArgZZ{a.z, a.y, a.x} testDecFunZZ(t, "MulZZ symmetric", MulZZ, arg) } } var decUnscaledTests = []struct { d *inf.Dec u int64 // ignored when ok == false ok bool }{ {new(inf.Dec), 0, true}, {inf.NewDec(-1<<63, 0), -1 << 63, true}, {inf.NewDec(-(-1<<63 + 1), 0), -(-1<<63 + 1), true}, {new(inf.Dec).Neg(inf.NewDec(-1<<63, 0)), 0, false}, {new(inf.Dec).Sub(inf.NewDec(-1<<63, 0), inf.NewDec(1, 0)), 0, false}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), 0, false}, } func TestDecUnscaled(t *testing.T) { for i, tt := range decUnscaledTests { u, ok := tt.d.Unscaled() if ok != tt.ok { t.Errorf("#%d Unscaled: got %v, expected %v", i, ok, tt.ok) } else if ok && u != tt.u { t.Errorf("#%d Unscaled: got %v, expected %v", i, u, tt.u) } } } var decRoundTests = [...]struct { in *inf.Dec s inf.Scale r inf.Rounder exp *inf.Dec }{ {inf.NewDec(123424999999999993, 15), 2, inf.RoundHalfUp, inf.NewDec(12342, 2)}, {inf.NewDec(123425000000000001, 15), 2, inf.RoundHalfUp, inf.NewDec(12343, 2)}, {inf.NewDec(123424999999999993, 15), 15, inf.RoundHalfUp, inf.NewDec(123424999999999993, 15)}, {inf.NewDec(123424999999999993, 15), 16, inf.RoundHalfUp, inf.NewDec(1234249999999999930, 16)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -1, inf.RoundHalfUp, inf.NewDec(1844674407370955162, -1)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -2, inf.RoundHalfUp, inf.NewDec(184467440737095516, -2)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -3, inf.RoundHalfUp, inf.NewDec(18446744073709552, -3)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -4, inf.RoundHalfUp, inf.NewDec(1844674407370955, -4)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -5, inf.RoundHalfUp, inf.NewDec(184467440737096, -5)}, {inf.NewDecBig(new(big.Int).Lsh(big.NewInt(1), 64), 0), -6, inf.RoundHalfUp, inf.NewDec(18446744073710, -6)}, } func TestDecRound(t *testing.T) { for i, tt := range decRoundTests { z := new(inf.Dec).Round(tt.in, tt.s, tt.r) if tt.exp.Cmp(z) != 0 { t.Errorf("#%d Round got %v; expected %v", i, z, tt.exp) } } } var decStringTests = []struct { in string out string val int64 scale inf.Scale // skip SetString if negative ok bool scanOk bool }{ {in: "", ok: false, scanOk: false}, {in: "a", ok: false, scanOk: false}, {in: "z", ok: false, scanOk: false}, {in: "+", ok: false, scanOk: false}, {in: "-", ok: false, scanOk: false}, {in: "g", ok: false, scanOk: false}, {in: ".", ok: false, scanOk: false}, {in: ".-0", ok: false, scanOk: false}, {in: ".+0", ok: false, scanOk: false}, // Scannable but not SetStringable {"0b", "ignored", 0, 0, false, true}, {"0x", "ignored", 0, 0, false, true}, {"0xg", "ignored", 0, 0, false, true}, {"0.0g", "ignored", 0, 1, false, true}, // examples from godoc for Dec {"0", "0", 0, 0, true, true}, {"0.00", "0.00", 0, 2, true, true}, {"ignored", "0", 0, -2, true, false}, {"1", "1", 1, 0, true, true}, {"1.00", "1.00", 100, 2, true, true}, {"10", "10", 10, 0, true, true}, {"ignored", "10", 1, -1, true, false}, // other tests {"+0", "0", 0, 0, true, true}, {"-0", "0", 0, 0, true, true}, {"0.0", "0.0", 0, 1, true, true}, {"0.1", "0.1", 1, 1, true, true}, {"0.", "0", 0, 0, true, true}, {"-10", "-10", -1, -1, true, true}, {"-1", "-1", -1, 0, true, true}, {"-0.1", "-0.1", -1, 1, true, true}, {"-0.01", "-0.01", -1, 2, true, true}, {"+0.", "0", 0, 0, true, true}, {"-0.", "0", 0, 0, true, true}, {".0", "0.0", 0, 1, true, true}, {"+.0", "0.0", 0, 1, true, true}, {"-.0", "0.0", 0, 1, true, true}, {"0.0000000000", "0.0000000000", 0, 10, true, true}, {"0.0000000001", "0.0000000001", 1, 10, true, true}, {"-0.0000000000", "0.0000000000", 0, 10, true, true}, {"-0.0000000001", "-0.0000000001", -1, 10, true, true}, {"-10", "-10", -10, 0, true, true}, {"+10", "10", 10, 0, true, true}, {"00", "0", 0, 0, true, true}, {"023", "23", 23, 0, true, true}, // decimal, not octal {"-02.3", "-2.3", -23, 1, true, true}, // decimal, not octal } func TestDecGetString(t *testing.T) { z := new(inf.Dec) for i, test := range decStringTests { if !test.ok { continue } z.SetUnscaled(test.val) z.SetScale(test.scale) s := z.String() if s != test.out { t.Errorf("#%da got %s; want %s", i, s, test.out) } s = fmt.Sprintf("%d", z) if s != test.out { t.Errorf("#%db got %s; want %s", i, s, test.out) } } } func TestDecSetString(t *testing.T) { tmp := new(inf.Dec) for i, test := range decStringTests { if test.scale < 0 { // SetString only supports scale >= 0 continue } // initialize to a non-zero value so that issues with parsing // 0 are detected tmp.Set(inf.NewDec(1234567890, 123)) n1, ok1 := new(inf.Dec).SetString(test.in) n2, ok2 := tmp.SetString(test.in) expected := inf.NewDec(test.val, test.scale) if ok1 != test.ok || ok2 != test.ok { t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok) continue } if !ok1 { if n1 != nil { t.Errorf("#%d (input '%s') n1 != nil", i, test.in) } continue } if !ok2 { if n2 != nil { t.Errorf("#%d (input '%s') n2 != nil", i, test.in) } continue } if n1.Cmp(expected) != 0 { t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val) } if n2.Cmp(expected) != 0 { t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val) } } } func TestDecScan(t *testing.T) { tmp := new(inf.Dec) for i, test := range decStringTests { if test.scale < 0 { // SetString only supports scale >= 0 continue } // initialize to a non-zero value so that issues with parsing // 0 are detected tmp.Set(inf.NewDec(1234567890, 123)) n1, n2 := new(inf.Dec), tmp nn1, err1 := fmt.Sscan(test.in, n1) nn2, err2 := fmt.Sscan(test.in, n2) if !test.scanOk { if err1 == nil || err2 == nil { t.Errorf("#%d (input '%s') ok incorrect, should be %t", i, test.in, test.scanOk) } continue } expected := inf.NewDec(test.val, test.scale) if nn1 != 1 || err1 != nil || nn2 != 1 || err2 != nil { t.Errorf("#%d (input '%s') error %d %v, %d %v", i, test.in, nn1, err1, nn2, err2) continue } if n1.Cmp(expected) != 0 { t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val) } if n2.Cmp(expected) != 0 { t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val) } } } var decScanNextTests = []struct { in string ok bool next rune }{ {"", false, 0}, {"a", false, 'a'}, {"z", false, 'z'}, {"+", false, 0}, {"-", false, 0}, {"g", false, 'g'}, {".", false, 0}, {".-0", false, '-'}, {".+0", false, '+'}, {"0b", true, 'b'}, {"0x", true, 'x'}, {"0xg", true, 'x'}, {"0.0g", true, 'g'}, } func TestDecScanNext(t *testing.T) { for i, test := range decScanNextTests { rdr := strings.NewReader(test.in) n1 := new(inf.Dec) nn1, _ := fmt.Fscan(rdr, n1) if (test.ok && nn1 == 0) || (!test.ok && nn1 > 0) { t.Errorf("#%d (input '%s') ok incorrect should be %t", i, test.in, test.ok) continue } r := rune(0) nn2, err := fmt.Fscanf(rdr, "%c", &r) if test.next != r { t.Errorf("#%d (input '%s') next incorrect, got %c should be %c, %d, %v", i, test.in, r, test.next, nn2, err) } } } var decGobEncodingTests = []string{ "0", "1", "2", "10", "42", "1234567890", "298472983472983471903246121093472394872319615612417471234712061", } func TestDecGobEncoding(t *testing.T) { var medium bytes.Buffer enc := gob.NewEncoder(&medium) dec := gob.NewDecoder(&medium) for i, test := range decGobEncodingTests { for j := 0; j < 2; j++ { for k := inf.Scale(-5); k <= 5; k++ { medium.Reset() // empty buffer for each test case (in case of failures) stest := test if j != 0 { // negative numbers stest = "-" + test } var tx inf.Dec tx.SetString(stest) tx.SetScale(k) // test with positive, negative, and zero scale if err := enc.Encode(&tx); err != nil { t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err) } var rx inf.Dec if err := dec.Decode(&rx); err != nil { t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err) } if rx.Cmp(&tx) != 0 { t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx) } } } } } inf-0.9.1/example_test.go000066400000000000000000000031471325622622400153270ustar00rootroot00000000000000package inf_test import ( "fmt" "log" ) import "gopkg.in/inf.v0" func ExampleDec_SetString() { d := new(inf.Dec) d.SetString("012345.67890") // decimal; leading 0 ignored; trailing 0 kept fmt.Println(d) // Output: 12345.67890 } func ExampleDec_Scan() { // The Scan function is rarely used directly; // the fmt package recognizes it as an implementation of fmt.Scanner. d := new(inf.Dec) _, err := fmt.Sscan("184467440.73709551617", d) if err != nil { log.Println("error scanning value:", err) } else { fmt.Println(d) } // Output: 184467440.73709551617 } func ExampleDec_QuoRound_scale2RoundDown() { // 10 / 3 is an infinite decimal; it has no exact Dec representation x, y := inf.NewDec(10, 0), inf.NewDec(3, 0) // use 2 digits beyond the decimal point, round towards 0 z := new(inf.Dec).QuoRound(x, y, 2, inf.RoundDown) fmt.Println(z) // Output: 3.33 } func ExampleDec_QuoRound_scale2RoundCeil() { // -42 / 400 is an finite decimal with 3 digits beyond the decimal point x, y := inf.NewDec(-42, 0), inf.NewDec(400, 0) // use 2 digits beyond decimal point, round towards positive infinity z := new(inf.Dec).QuoRound(x, y, 2, inf.RoundCeil) fmt.Println(z) // Output: -0.10 } func ExampleDec_QuoExact_ok() { // 1 / 25 is a finite decimal; it has exact Dec representation x, y := inf.NewDec(1, 0), inf.NewDec(25, 0) z := new(inf.Dec).QuoExact(x, y) fmt.Println(z) // Output: 0.04 } func ExampleDec_QuoExact_fail() { // 1 / 3 is an infinite decimal; it has no exact Dec representation x, y := inf.NewDec(1, 0), inf.NewDec(3, 0) z := new(inf.Dec).QuoExact(x, y) fmt.Println(z) // Output: } inf-0.9.1/rounder.go000066400000000000000000000074401325622622400143130ustar00rootroot00000000000000package inf import ( "math/big" ) // Rounder represents a method for rounding the (possibly infinite decimal) // result of a division to a finite Dec. It is used by Dec.Round() and // Dec.Quo(). // // See the Example for results of using each Rounder with some sample values. // type Rounder rounder // See http://speleotrove.com/decimal/damodel.html#refround for more detailed // definitions of these rounding modes. var ( RoundDown Rounder // towards 0 RoundUp Rounder // away from 0 RoundFloor Rounder // towards -infinity RoundCeil Rounder // towards +infinity RoundHalfDown Rounder // to nearest; towards 0 if same distance RoundHalfUp Rounder // to nearest; away from 0 if same distance RoundHalfEven Rounder // to nearest; even last digit if same distance ) // RoundExact is to be used in the case when rounding is not necessary. // When used with Quo or Round, it returns the result verbatim when it can be // expressed exactly with the given precision, and it returns nil otherwise. // QuoExact is a shorthand for using Quo with RoundExact. var RoundExact Rounder type rounder interface { // When UseRemainder() returns true, the Round() method is passed the // remainder of the division, expressed as the numerator and denominator of // a rational. UseRemainder() bool // Round sets the rounded value of a quotient to z, and returns z. // quo is rounded down (truncated towards zero) to the scale obtained from // the Scaler in Quo(). // // When the remainder is not used, remNum and remDen are nil. // When used, the remainder is normalized between -1 and 1; that is: // // -|remDen| < remNum < |remDen| // // remDen has the same sign as y, and remNum is zero or has the same sign // as x. Round(z, quo *Dec, remNum, remDen *big.Int) *Dec } type rndr struct { useRem bool round func(z, quo *Dec, remNum, remDen *big.Int) *Dec } func (r rndr) UseRemainder() bool { return r.useRem } func (r rndr) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec { return r.round(z, quo, remNum, remDen) } var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)} func roundHalf(f func(c int, odd uint) (roundUp bool)) func(z, q *Dec, rA, rB *big.Int) *Dec { return func(z, q *Dec, rA, rB *big.Int) *Dec { z.Set(q) brA, brB := rA.BitLen(), rB.BitLen() if brA < brB-1 { // brA < brB-1 => |rA| < |rB/2| return z } roundUp := false srA, srB := rA.Sign(), rB.Sign() s := srA * srB if brA == brB-1 { rA2 := new(big.Int).Lsh(rA, 1) if s < 0 { rA2.Neg(rA2) } roundUp = f(rA2.Cmp(rB)*srB, z.UnscaledBig().Bit(0)) } else { // brA > brB-1 => |rA| > |rB/2| roundUp = true } if roundUp { z.UnscaledBig().Add(z.UnscaledBig(), intSign[s+1]) } return z } } func init() { RoundExact = rndr{true, func(z, q *Dec, rA, rB *big.Int) *Dec { if rA.Sign() != 0 { return nil } return z.Set(q) }} RoundDown = rndr{false, func(z, q *Dec, rA, rB *big.Int) *Dec { return z.Set(q) }} RoundUp = rndr{true, func(z, q *Dec, rA, rB *big.Int) *Dec { z.Set(q) if rA.Sign() != 0 { z.UnscaledBig().Add(z.UnscaledBig(), intSign[rA.Sign()*rB.Sign()+1]) } return z }} RoundFloor = rndr{true, func(z, q *Dec, rA, rB *big.Int) *Dec { z.Set(q) if rA.Sign()*rB.Sign() < 0 { z.UnscaledBig().Add(z.UnscaledBig(), intSign[0]) } return z }} RoundCeil = rndr{true, func(z, q *Dec, rA, rB *big.Int) *Dec { z.Set(q) if rA.Sign()*rB.Sign() > 0 { z.UnscaledBig().Add(z.UnscaledBig(), intSign[2]) } return z }} RoundHalfDown = rndr{true, roundHalf( func(c int, odd uint) bool { return c > 0 })} RoundHalfUp = rndr{true, roundHalf( func(c int, odd uint) bool { return c >= 0 })} RoundHalfEven = rndr{true, roundHalf( func(c int, odd uint) bool { return c > 0 || c == 0 && odd == 1 })} } inf-0.9.1/rounder_example_test.go000066400000000000000000000046431325622622400170670ustar00rootroot00000000000000package inf_test import ( "fmt" "os" "text/tabwriter" "gopkg.in/inf.v0" ) // This example displays the results of Dec.Round with each of the Rounders. // func ExampleRounder() { var vals = []struct { x string s inf.Scale }{ {"-0.18", 1}, {"-0.15", 1}, {"-0.12", 1}, {"-0.10", 1}, {"-0.08", 1}, {"-0.05", 1}, {"-0.02", 1}, {"0.00", 1}, {"0.02", 1}, {"0.05", 1}, {"0.08", 1}, {"0.10", 1}, {"0.12", 1}, {"0.15", 1}, {"0.18", 1}, } var rounders = []struct { name string rounder inf.Rounder }{ {"RoundDown", inf.RoundDown}, {"RoundUp", inf.RoundUp}, {"RoundCeil", inf.RoundCeil}, {"RoundFloor", inf.RoundFloor}, {"RoundHalfDown", inf.RoundHalfDown}, {"RoundHalfUp", inf.RoundHalfUp}, {"RoundHalfEven", inf.RoundHalfEven}, {"RoundExact", inf.RoundExact}, } fmt.Println("The results of new(inf.Dec).Round(x, s, inf.RoundXXX):") fmt.Println() w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight) fmt.Fprint(w, "x\ts\t|\t") for _, r := range rounders { fmt.Fprintf(w, "%s\t", r.name[5:]) } fmt.Fprintln(w) for _, v := range vals { fmt.Fprintf(w, "%s\t%d\t|\t", v.x, v.s) for _, r := range rounders { x, _ := new(inf.Dec).SetString(v.x) z := new(inf.Dec).Round(x, v.s, r.rounder) fmt.Fprintf(w, "%d\t", z) } fmt.Fprintln(w) } w.Flush() // Output: // The results of new(inf.Dec).Round(x, s, inf.RoundXXX): // // x s | Down Up Ceil Floor HalfDown HalfUp HalfEven Exact // -0.18 1 | -0.1 -0.2 -0.1 -0.2 -0.2 -0.2 -0.2 // -0.15 1 | -0.1 -0.2 -0.1 -0.2 -0.1 -0.2 -0.2 // -0.12 1 | -0.1 -0.2 -0.1 -0.2 -0.1 -0.1 -0.1 // -0.10 1 | -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 // -0.08 1 | 0.0 -0.1 0.0 -0.1 -0.1 -0.1 -0.1 // -0.05 1 | 0.0 -0.1 0.0 -0.1 0.0 -0.1 0.0 // -0.02 1 | 0.0 -0.1 0.0 -0.1 0.0 0.0 0.0 // 0.00 1 | 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 // 0.02 1 | 0.0 0.1 0.1 0.0 0.0 0.0 0.0 // 0.05 1 | 0.0 0.1 0.1 0.0 0.0 0.1 0.0 // 0.08 1 | 0.0 0.1 0.1 0.0 0.1 0.1 0.1 // 0.10 1 | 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 // 0.12 1 | 0.1 0.2 0.2 0.1 0.1 0.1 0.1 // 0.15 1 | 0.1 0.2 0.2 0.1 0.1 0.2 0.2 // 0.18 1 | 0.1 0.2 0.2 0.1 0.2 0.2 0.2 } inf-0.9.1/rounder_test.go000066400000000000000000000105461325622622400153530ustar00rootroot00000000000000package inf_test import ( "math/big" "testing" "gopkg.in/inf.v0" ) var decRounderInputs = [...]struct { quo *inf.Dec rA, rB *big.Int }{ // examples from go language spec {inf.NewDec(1, 0), big.NewInt(2), big.NewInt(3)}, // 5 / 3 {inf.NewDec(-1, 0), big.NewInt(-2), big.NewInt(3)}, // -5 / 3 {inf.NewDec(-1, 0), big.NewInt(2), big.NewInt(-3)}, // 5 / -3 {inf.NewDec(1, 0), big.NewInt(-2), big.NewInt(-3)}, // -5 / -3 // examples from godoc {inf.NewDec(-1, 1), big.NewInt(-8), big.NewInt(10)}, {inf.NewDec(-1, 1), big.NewInt(-5), big.NewInt(10)}, {inf.NewDec(-1, 1), big.NewInt(-2), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(-8), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(-5), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(-2), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(0), big.NewInt(1)}, {inf.NewDec(0, 1), big.NewInt(2), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(5), big.NewInt(10)}, {inf.NewDec(0, 1), big.NewInt(8), big.NewInt(10)}, {inf.NewDec(1, 1), big.NewInt(2), big.NewInt(10)}, {inf.NewDec(1, 1), big.NewInt(5), big.NewInt(10)}, {inf.NewDec(1, 1), big.NewInt(8), big.NewInt(10)}, } var decRounderResults = [...]struct { rounder inf.Rounder results [len(decRounderInputs)]*inf.Dec }{ {inf.RoundExact, [...]*inf.Dec{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, inf.NewDec(0, 1), nil, nil, nil, nil, nil, nil}}, {inf.RoundDown, [...]*inf.Dec{ inf.NewDec(1, 0), inf.NewDec(-1, 0), inf.NewDec(-1, 0), inf.NewDec(1, 0), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1)}}, {inf.RoundUp, [...]*inf.Dec{ inf.NewDec(2, 0), inf.NewDec(-2, 0), inf.NewDec(-2, 0), inf.NewDec(2, 0), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(2, 1), inf.NewDec(2, 1), inf.NewDec(2, 1)}}, {inf.RoundHalfDown, [...]*inf.Dec{ inf.NewDec(2, 0), inf.NewDec(-2, 0), inf.NewDec(-2, 0), inf.NewDec(2, 0), inf.NewDec(-2, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(2, 1)}}, {inf.RoundHalfUp, [...]*inf.Dec{ inf.NewDec(2, 0), inf.NewDec(-2, 0), inf.NewDec(-2, 0), inf.NewDec(2, 0), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(2, 1), inf.NewDec(2, 1)}}, {inf.RoundHalfEven, [...]*inf.Dec{ inf.NewDec(2, 0), inf.NewDec(-2, 0), inf.NewDec(-2, 0), inf.NewDec(2, 0), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(2, 1), inf.NewDec(2, 1)}}, {inf.RoundFloor, [...]*inf.Dec{ inf.NewDec(1, 0), inf.NewDec(-2, 0), inf.NewDec(-2, 0), inf.NewDec(1, 0), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-2, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1)}}, {inf.RoundCeil, [...]*inf.Dec{ inf.NewDec(2, 0), inf.NewDec(-1, 0), inf.NewDec(-1, 0), inf.NewDec(2, 0), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(-1, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(0, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(1, 1), inf.NewDec(2, 1), inf.NewDec(2, 1), inf.NewDec(2, 1)}}, } func TestDecRounders(t *testing.T) { for i, a := range decRounderResults { for j, input := range decRounderInputs { q := new(inf.Dec).Set(input.quo) rA, rB := new(big.Int).Set(input.rA), new(big.Int).Set(input.rB) res := a.rounder.Round(new(inf.Dec), q, rA, rB) if a.results[j] == nil && res == nil { continue } if (a.results[j] == nil && res != nil) || (a.results[j] != nil && res == nil) || a.results[j].Cmp(res) != 0 { t.Errorf("#%d,%d Rounder got %v; expected %v", i, j, res, a.results[j]) } } } }