1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 func TestZeroRat(t
*testing
.T
) {
17 t
.Errorf("x and y should be both equal and zero")
20 if s
:= x
.String(); s
!= "0/1" {
21 t
.Errorf("got x = %s, want 0/1", s
)
24 if s
:= x
.RatString(); s
!= "0" {
25 t
.Errorf("got x = %s, want 0", s
)
29 if s
:= z
.RatString(); s
!= "0" {
30 t
.Errorf("got x+y = %s, want 0", s
)
34 if s
:= z
.RatString(); s
!= "0" {
35 t
.Errorf("got x-y = %s, want 0", s
)
39 if s
:= z
.RatString(); s
!= "0" {
40 t
.Errorf("got x*y = %s, want 0", s
)
43 // check for division by zero
45 if s
:= recover(); s
== nil || s
.(string) != "division by zero" {
52 func TestRatSign(t
*testing
.T
) {
54 for _
, a
:= range setStringTests
{
55 x
, ok
:= new(Rat
).SetString(a
.in
)
62 t
.Errorf("got %d; want %d for z = %v", s
, e
, &x
)
67 var ratCmpTests
= []struct {
76 {"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
77 {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
78 {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
79 {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
82 func TestRatCmp(t
*testing
.T
) {
83 for i
, test
:= range ratCmpTests
{
84 x
, _
:= new(Rat
).SetString(test
.rat1
)
85 y
, _
:= new(Rat
).SetString(test
.rat2
)
89 t
.Errorf("#%d got out = %v; want %v", i
, out
, test
.out
)
94 func TestIsInt(t
*testing
.T
) {
96 for _
, a
:= range setStringTests
{
97 x
, ok
:= new(Rat
).SetString(a
.in
)
102 e
:= x
.Denom().Cmp(one
) == 0
104 t
.Errorf("got IsInt(%v) == %v; want %v", x
, i
, e
)
109 func TestRatAbs(t
*testing
.T
) {
111 for _
, a
:= range setStringTests
{
112 x
, ok
:= new(Rat
).SetString(a
.in
)
122 t
.Errorf("got Abs(%v) = %v; want %v", x
, z
, e
)
127 func TestRatNeg(t
*testing
.T
) {
129 for _
, a
:= range setStringTests
{
130 x
, ok
:= new(Rat
).SetString(a
.in
)
134 e
:= new(Rat
).Sub(zero
, x
)
137 t
.Errorf("got Neg(%v) = %v; want %v", x
, z
, e
)
142 func TestRatInv(t
*testing
.T
) {
144 for _
, a
:= range setStringTests
{
145 x
, ok
:= new(Rat
).SetString(a
.in
)
149 if x
.Cmp(zero
) == 0 {
150 continue // avoid division by zero
152 e
:= new(Rat
).SetFrac(x
.Denom(), x
.Num())
155 t
.Errorf("got Inv(%v) = %v; want %v", x
, z
, e
)
160 type ratBinFun
func(z
, x
, y
*Rat
) *Rat
161 type ratBinArg
struct {
165 func testRatBin(t
*testing
.T
, i
int, name
string, f ratBinFun
, a ratBinArg
) {
166 x
, _
:= new(Rat
).SetString(a
.x
)
167 y
, _
:= new(Rat
).SetString(a
.y
)
168 z
, _
:= new(Rat
).SetString(a
.z
)
169 out
:= f(new(Rat
), x
, y
)
172 t
.Errorf("%s #%d got %s want %s", name
, i
, out
, z
)
176 var ratBinTests
= []struct {
180 {"0", "0", "0", "0"},
181 {"0", "1", "1", "0"},
182 {"-1", "0", "-1", "0"},
183 {"-1", "1", "0", "-1"},
184 {"1", "1", "2", "1"},
185 {"1/2", "1/2", "1", "1/4"},
186 {"1/4", "1/3", "7/12", "1/12"},
187 {"2/5", "-14/3", "-64/15", "-28/15"},
188 {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
189 {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
190 {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
191 {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
192 {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
193 {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
194 {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
195 {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
196 {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
197 {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
200 func TestRatBin(t
*testing
.T
) {
201 for i
, test
:= range ratBinTests
{
202 arg
:= ratBinArg
{test
.x
, test
.y
, test
.sum
}
203 testRatBin(t
, i
, "Add", (*Rat
).Add
, arg
)
205 arg
= ratBinArg
{test
.y
, test
.x
, test
.sum
}
206 testRatBin(t
, i
, "Add symmetric", (*Rat
).Add
, arg
)
208 arg
= ratBinArg
{test
.sum
, test
.x
, test
.y
}
209 testRatBin(t
, i
, "Sub", (*Rat
).Sub
, arg
)
211 arg
= ratBinArg
{test
.sum
, test
.y
, test
.x
}
212 testRatBin(t
, i
, "Sub symmetric", (*Rat
).Sub
, arg
)
214 arg
= ratBinArg
{test
.x
, test
.y
, test
.prod
}
215 testRatBin(t
, i
, "Mul", (*Rat
).Mul
, arg
)
217 arg
= ratBinArg
{test
.y
, test
.x
, test
.prod
}
218 testRatBin(t
, i
, "Mul symmetric", (*Rat
).Mul
, arg
)
221 arg
= ratBinArg
{test
.prod
, test
.x
, test
.y
}
222 testRatBin(t
, i
, "Quo", (*Rat
).Quo
, arg
)
226 arg
= ratBinArg
{test
.prod
, test
.y
, test
.x
}
227 testRatBin(t
, i
, "Quo symmetric", (*Rat
).Quo
, arg
)
232 func TestIssue820(t
*testing
.T
) {
238 t
.Errorf("got %s want %s", z
, q
)
246 t
.Errorf("got %s want %s", z
, q
)
253 t
.Errorf("got %s want %s", z
, q
)
257 var setFrac64Tests
= []struct {
267 {-9223372036854775808, -9223372036854775808, "1"},
270 func TestRatSetFrac64Rat(t
*testing
.T
) {
271 for i
, test
:= range setFrac64Tests
{
272 x
:= new(Rat
).SetFrac64(test
.a
, test
.b
)
273 if x
.RatString() != test
.out
{
274 t
.Errorf("#%d got %s want %s", i
, x
.RatString(), test
.out
)
279 func TestIssue2379(t
*testing
.T
) {
283 x
.SetFrac(NewInt(3), NewInt(2))
285 t
.Errorf("1) got %s want %s", x
, q
)
288 // 2) aliasing of numerator
290 x
.SetFrac(NewInt(3), x
.Num())
292 t
.Errorf("2) got %s want %s", x
, q
)
295 // 3) aliasing of denominator
297 x
.SetFrac(x
.Denom(), NewInt(2))
299 t
.Errorf("3) got %s want %s", x
, q
)
302 // 4) aliasing of numerator and denominator
304 x
.SetFrac(x
.Denom(), x
.Num())
306 t
.Errorf("4) got %s want %s", x
, q
)
309 // 5) numerator and denominator are the same
315 t
.Errorf("5) got %s want %s", x
, q
)
319 func TestIssue3521(t
*testing
.T
) {
322 a
.SetString("64375784358435883458348587", 0)
323 b
.SetString("4789759874531", 0)
325 // 0) a raw zero value has 1 as denominator
328 if zero
.Denom().Cmp(one
) != 0 {
329 t
.Errorf("0) got %s want %s", zero
.Denom(), one
)
332 // 1a) the denominator of an (uninitialized) zero value is not shared with the value
336 t
.Errorf("1a) got %s (%p) == %s (%p) want different *Int values", d
, d
, s
, s
)
339 // 1b) the denominator of an (uninitialized) value is a new 1 each time
343 t
.Errorf("1b) got %s (%p) == %s (%p) want different *Int values", d1
, d1
, d2
, d2
)
346 // 1c) the denominator of an initialized zero value is shared with the value
348 x
.Set(x
) // initialize x (any operation that sets x explicitly will do)
352 t
.Errorf("1c) got %s (%p) != %s (%p) want identical *Int values", d
, d
, s
, s
)
355 // 1d) a zero value remains zero independent of denominator
356 x
.Denom().Set(new(Int
).Neg(b
))
357 if x
.Cmp(zero
) != 0 {
358 t
.Errorf("1d) got %s want %s", x
, zero
)
361 // 1e) a zero value may have a denominator != 0 and != 1
363 qab
:= new(Rat
).SetFrac(a
, b
)
365 t
.Errorf("1e) got %s want %s", x
, qab
)
368 // 2a) an integral value becomes a fraction depending on denominator
370 x
.Denom().SetInt64(3)
373 t
.Errorf("2a) got %s want %s", x
, q53
)
376 // 2b) an integral value becomes a fraction depending on denominator
378 x
.Denom().SetInt64(3)
380 t
.Errorf("2b) got %s want %s", x
, q53
)
383 // 3) changing the numerator/denominator of a Rat changes the Rat
390 t
.Errorf("3) got %s want %s", x
, q53
)
394 func TestFloat32Distribution(t
*testing
.T
) {
395 // Generate a distribution of (sign, mantissa, exp) values
396 // broader than the float32 range, and check Rat.Float32()
397 // always picks the closest float32 approximation.
407 var winc
, einc
= uint64(5), 15 // quick test (~60ms on x86-64)
409 winc
, einc
= uint64(1), 1 // soak test (~1.5s on x86-64)
412 for _
, sign
:= range "+-" {
413 for _
, a
:= range add
{
414 for wid
:= uint64(0); wid
< 30; wid
+= winc
{
419 for exp
:= -150; exp
< 150; exp
+= einc
{
420 num
, den
:= NewInt(b
), NewInt(1)
422 num
.Lsh(num
, uint(exp
))
424 den
.Lsh(den
, uint(-exp
))
426 r
:= new(Rat
).SetFrac(num
, den
)
429 if !checkIsBestApprox32(t
, f
, r
) {
430 // Append context information.
431 t
.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
432 b
, exp
, f
, f
, math
.Ldexp(float64(b
), exp
), r
)
435 checkNonLossyRoundtrip32(t
, f
)
442 func TestFloat64Distribution(t
*testing
.T
) {
443 // Generate a distribution of (sign, mantissa, exp) values
444 // broader than the float64 range, and check Rat.Float64()
445 // always picks the closest float64 approximation.
455 var winc
, einc
= uint64(10), 500 // quick test (~12ms on x86-64)
457 winc
, einc
= uint64(1), 1 // soak test (~75s on x86-64)
460 for _
, sign
:= range "+-" {
461 for _
, a
:= range add
{
462 for wid
:= uint64(0); wid
< 60; wid
+= winc
{
467 for exp
:= -1100; exp
< 1100; exp
+= einc
{
468 num
, den
:= NewInt(b
), NewInt(1)
470 num
.Lsh(num
, uint(exp
))
472 den
.Lsh(den
, uint(-exp
))
474 r
:= new(Rat
).SetFrac(num
, den
)
477 if !checkIsBestApprox64(t
, f
, r
) {
478 // Append context information.
479 t
.Errorf("(input was mantissa %#x, exp %d; f = %g (%b); f ~ %g; r = %v)",
480 b
, exp
, f
, f
, math
.Ldexp(float64(b
), exp
), r
)
483 checkNonLossyRoundtrip64(t
, f
)
490 // TestSetFloat64NonFinite checks that SetFloat64 of a non-finite value
492 func TestSetFloat64NonFinite(t
*testing
.T
) {
493 for _
, f
:= range []float64{math
.NaN(), math
.Inf(+1), math
.Inf(-1)} {
495 if r2
:= r
.SetFloat64(f
); r2
!= nil {
496 t
.Errorf("SetFloat64(%g) was %v, want nil", f
, r2
)
501 // checkNonLossyRoundtrip32 checks that a float->Rat->float roundtrip is
502 // non-lossy for finite f.
503 func checkNonLossyRoundtrip32(t
*testing
.T
, f
float32) {
504 if !isFinite(float64(f
)) {
507 r
:= new(Rat
).SetFloat64(float64(f
))
509 t
.Errorf("Rat.SetFloat64(float64(%g) (%b)) == nil", f
, f
)
512 f2
, exact
:= r
.Float32()
513 if f
!= f2 ||
!exact
{
514 t
.Errorf("Rat.SetFloat64(float64(%g)).Float32() = %g (%b), %v, want %g (%b), %v; delta = %b",
515 f
, f2
, f2
, exact
, f
, f
, true, f2
-f
)
519 // checkNonLossyRoundtrip64 checks that a float->Rat->float roundtrip is
520 // non-lossy for finite f.
521 func checkNonLossyRoundtrip64(t
*testing
.T
, f
float64) {
525 r
:= new(Rat
).SetFloat64(f
)
527 t
.Errorf("Rat.SetFloat64(%g (%b)) == nil", f
, f
)
530 f2
, exact
:= r
.Float64()
531 if f
!= f2 ||
!exact
{
532 t
.Errorf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b",
533 f
, f2
, f2
, exact
, f
, f
, true, f2
-f
)
537 // delta returns the absolute difference between r and f.
538 func delta(r
*Rat
, f
float64) *Rat
{
539 d
:= new(Rat
).Sub(r
, new(Rat
).SetFloat64(f
))
543 // checkIsBestApprox32 checks that f is the best possible float32
544 // approximation of r.
545 // Returns true on success.
546 func checkIsBestApprox32(t
*testing
.T
, f
float32, r
*Rat
) bool {
547 if math
.Abs(float64(f
)) >= math
.MaxFloat32
{
548 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32).
549 // But we have tests for these special cases.
553 // r must be strictly between f0 and f1, the floats bracketing f.
554 f0
:= math
.Nextafter32(f
, float32(math
.Inf(-1)))
555 f1
:= math
.Nextafter32(f
, float32(math
.Inf(+1)))
557 // For f to be correct, r must be closer to f than to f0 or f1.
558 df
:= delta(r
, float64(f
))
559 df0
:= delta(r
, float64(f0
))
560 df1
:= delta(r
, float64(f1
))
562 t
.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r
, f
, f
, f0
, f0
)
566 t
.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r
, f
, f
, f1
, f1
)
569 if df
.Cmp(df0
) == 0 && !isEven32(f
) {
570 t
.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r
, f
, f
, f0
, f0
)
573 if df
.Cmp(df1
) == 0 && !isEven32(f
) {
574 t
.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r
, f
, f
, f1
, f1
)
580 // checkIsBestApprox64 checks that f is the best possible float64
581 // approximation of r.
582 // Returns true on success.
583 func checkIsBestApprox64(t
*testing
.T
, f
float64, r
*Rat
) bool {
584 if math
.Abs(f
) >= math
.MaxFloat64
{
585 // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64).
586 // But we have tests for these special cases.
590 // r must be strictly between f0 and f1, the floats bracketing f.
591 f0
:= math
.Nextafter(f
, math
.Inf(-1))
592 f1
:= math
.Nextafter(f
, math
.Inf(+1))
594 // For f to be correct, r must be closer to f than to f0 or f1.
599 t
.Errorf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r
, f
, f
, f0
, f0
)
603 t
.Errorf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r
, f
, f
, f1
, f1
)
606 if df
.Cmp(df0
) == 0 && !isEven64(f
) {
607 t
.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r
, f
, f
, f0
, f0
)
610 if df
.Cmp(df1
) == 0 && !isEven64(f
) {
611 t
.Errorf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r
, f
, f
, f1
, f1
)
617 func isEven32(f
float32) bool { return math
.Float32bits(f
)&1 == 0 }
618 func isEven64(f
float64) bool { return math
.Float64bits(f
)&1 == 0 }
620 func TestIsFinite(t
*testing
.T
) {
621 finites
:= []float64{
623 4891559871276714924261e+222,
625 math
.SmallestNonzeroFloat64
,
627 -math
.SmallestNonzeroFloat64
,
629 for _
, f
:= range finites
{
631 t
.Errorf("!IsFinite(%g (%b))", f
, f
)
634 nonfinites
:= []float64{
639 for _
, f
:= range nonfinites
{
641 t
.Errorf("IsFinite(%g, (%b))", f
, f
)
646 func TestRatSetInt64(t
*testing
.T
) {
647 var testCases
= []int64{
657 for i
, want
:= range testCases
{
660 t
.Errorf("#%d: Rat.SetInt64(%d) is not an integer", i
, want
)
664 t
.Errorf("#%d: Rat.SetInt64(%d) numerator is not an int64", i
, want
)
668 t
.Errorf("#%d: Rat.SetInt64(%d) = %d, but expected %d", i
, want
, got
, want
)
673 func TestRatSetUint64(t
*testing
.T
) {
674 var testCases
= []uint64{
681 for i
, want
:= range testCases
{
684 t
.Errorf("#%d: Rat.SetUint64(%d) is not an integer", i
, want
)
688 t
.Errorf("#%d: Rat.SetUint64(%d) numerator is not a uint64", i
, want
)
692 t
.Errorf("#%d: Rat.SetUint64(%d) = %d, but expected %d", i
, want
, got
, want
)
697 func BenchmarkRatCmp(b
*testing
.B
) {
698 x
, y
:= NewRat(4, 1), NewRat(7, 2)
699 for i
:= 0; i
< b
.N
; i
++ {
704 // TestIssue34919 verifies that a Rat's denominator is not modified
705 // when simply accessing the Rat value.
706 func TestIssue34919(t
*testing
.T
) {
707 for _
, acc
:= range []struct {
711 {"Float32", func(x
*Rat
) { x
.Float32() }},
712 {"Float64", func(x
*Rat
) { x
.Float64() }},
713 {"Inv", func(x
*Rat
) { new(Rat
).Inv(x
) }},
714 {"Sign", func(x
*Rat
) { x
.Sign() }},
715 {"IsInt", func(x
*Rat
) { x
.IsInt() }},
716 {"Num", func(x
*Rat
) { x
.Num() }},
717 // {"Denom", func(x *Rat) { x.Denom() }}, TODO(gri) should we change the API? See issue #33792.
719 // A denominator of length 0 is interpreted as 1. Make sure that
720 // "materialization" of the denominator doesn't lead to setting
721 // the underlying array element 0 to 1.
722 r
:= &Rat
{Int
{abs
: nat
{991}}, Int
{abs
: make(nat
, 0, 1)}}
724 if d
:= r
.b
.abs
[:1][0]; d
!= 0 {
725 t
.Errorf("%s modified denominator: got %d, want 0", acc
.name
, d
)
730 func TestDenomRace(t
*testing
.T
) {
733 c
:= make(chan bool, N
)
734 for i
:= 0; i
< N
; i
++ {
736 // Denom (also used by Float.SetRat) used to mutate x unnecessarily,
737 // provoking race reports when run in the race detector.
743 for i
:= 0; i
< N
; i
++ {