libgo: update to Go1.16.5 release
[official-gcc.git] / libgo / go / math / big / ratconv_test.go
blob15d206cb386ab41dd0e79c2e5e01869413158763
1 // Copyright 2015 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.
5 package big
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "math"
12 "strconv"
13 "strings"
14 "testing"
17 var exponentTests = []struct {
18 s string // string to be scanned
19 base2ok bool // true if 'p'/'P' exponents are accepted
20 sepOk bool // true if '_' separators are accepted
21 x int64 // expected exponent
22 b int // expected exponent base
23 err error // expected error
24 next rune // next character (or 0, if at EOF)
26 // valid, without separators
27 {"", false, false, 0, 10, nil, 0},
28 {"1", false, false, 0, 10, nil, '1'},
29 {"e0", false, false, 0, 10, nil, 0},
30 {"E1", false, false, 1, 10, nil, 0},
31 {"e+10", false, false, 10, 10, nil, 0},
32 {"e-10", false, false, -10, 10, nil, 0},
33 {"e123456789a", false, false, 123456789, 10, nil, 'a'},
34 {"p", false, false, 0, 10, nil, 'p'},
35 {"P+100", false, false, 0, 10, nil, 'P'},
36 {"p0", true, false, 0, 2, nil, 0},
37 {"P-123", true, false, -123, 2, nil, 0},
38 {"p+0a", true, false, 0, 2, nil, 'a'},
39 {"p+123__", true, false, 123, 2, nil, '_'}, // '_' is not part of the number anymore
41 // valid, with separators
42 {"e+1_0", false, true, 10, 10, nil, 0},
43 {"e-1_0", false, true, -10, 10, nil, 0},
44 {"e123_456_789a", false, true, 123456789, 10, nil, 'a'},
45 {"P+1_00", false, true, 0, 10, nil, 'P'},
46 {"p-1_2_3", true, true, -123, 2, nil, 0},
48 // invalid: no digits
49 {"e", false, false, 0, 10, errNoDigits, 0},
50 {"ef", false, false, 0, 10, errNoDigits, 'f'},
51 {"e+", false, false, 0, 10, errNoDigits, 0},
52 {"E-x", false, false, 0, 10, errNoDigits, 'x'},
53 {"p", true, false, 0, 2, errNoDigits, 0},
54 {"P-", true, false, 0, 2, errNoDigits, 0},
55 {"p+e", true, false, 0, 2, errNoDigits, 'e'},
56 {"e+_x", false, true, 0, 10, errNoDigits, 'x'},
58 // invalid: incorrect use of separator
59 {"e0_", false, true, 0, 10, errInvalSep, 0},
60 {"e_0", false, true, 0, 10, errInvalSep, 0},
61 {"e-1_2__3", false, true, -123, 10, errInvalSep, 0},
64 func TestScanExponent(t *testing.T) {
65 for _, a := range exponentTests {
66 r := strings.NewReader(a.s)
67 x, b, err := scanExponent(r, a.base2ok, a.sepOk)
68 if err != a.err {
69 t.Errorf("scanExponent%+v\n\tgot error = %v; want %v", a, err, a.err)
71 if x != a.x {
72 t.Errorf("scanExponent%+v\n\tgot z = %v; want %v", a, x, a.x)
74 if b != a.b {
75 t.Errorf("scanExponent%+v\n\tgot b = %d; want %d", a, b, a.b)
77 next, _, err := r.ReadRune()
78 if err == io.EOF {
79 next = 0
80 err = nil
82 if err == nil && next != a.next {
83 t.Errorf("scanExponent%+v\n\tgot next = %q; want %q", a, next, a.next)
88 type StringTest struct {
89 in, out string
90 ok bool
93 var setStringTests = []StringTest{
94 // invalid
95 {in: "1e"},
96 {in: "1.e"},
97 {in: "1e+14e-5"},
98 {in: "1e4.5"},
99 {in: "r"},
100 {in: "a/b"},
101 {in: "a.b"},
102 {in: "1/0"},
103 {in: "4/3/2"}, // issue 17001
104 {in: "4/3/"},
105 {in: "4/3."},
106 {in: "4/"},
108 // valid
109 {"0", "0", true},
110 {"-0", "0", true},
111 {"1", "1", true},
112 {"-1", "-1", true},
113 {"1.", "1", true},
114 {"1e0", "1", true},
115 {"1.e1", "10", true},
116 {"-0.1", "-1/10", true},
117 {"-.1", "-1/10", true},
118 {"2/4", "1/2", true},
119 {".25", "1/4", true},
120 {"-1/5", "-1/5", true},
121 {"8129567.7690E14", "812956776900000000000", true},
122 {"78189e+4", "781890000", true},
123 {"553019.8935e+8", "55301989350000", true},
124 {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
125 {"9877861857500000E-7", "3951144743/4", true},
126 {"2169378.417e-3", "2169378417/1000000", true},
127 {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
128 {"53/70893980658822810696", "53/70893980658822810696", true},
129 {"106/141787961317645621392", "53/70893980658822810696", true},
130 {"204211327800791583.81095", "4084226556015831676219/20000", true},
131 {"0e9999999999", "0", true}, // issue #16176
134 // These are not supported by fmt.Fscanf.
135 var setStringTests2 = []StringTest{
136 // invalid
137 {in: "4/3x"},
138 {in: "0/-1"},
139 {in: "-1/-1"},
141 // invalid with separators
142 // (smoke tests only - a comprehensive set of tests is in natconv_test.go)
143 {in: "10_/1"},
144 {in: "_10/1"},
145 {in: "1/1__0"},
147 // valid
148 {"0b1000/3", "8/3", true},
149 {"0B1000/0x8", "1", true},
150 {"-010/1", "-8", true}, // 0-prefix indicates octal in this case
151 {"-010.0", "-10", true},
152 {"-0o10/1", "-8", true},
153 {"0x10/1", "16", true},
154 {"0x10/0x20", "1/2", true},
156 {"0010", "10", true}, // 0-prefix is ignored in this case (not a fraction)
157 {"0x10.0", "16", true},
158 {"0x1.8", "3/2", true},
159 {"0X1.8p4", "24", true},
160 {"0x1.1E2", "2289/2048", true}, // E is part of hex mantissa, not exponent
161 {"0b1.1E2", "150", true},
162 {"0B1.1P3", "12", true},
163 {"0o10e-2", "2/25", true},
164 {"0O10p-3", "1", true},
166 // valid with separators
167 // (smoke tests only - a comprehensive set of tests is in natconv_test.go)
168 {"0b_1000/3", "8/3", true},
169 {"0B_10_00/0x8", "1", true},
170 {"0xdead/0B1101_1110_1010_1101", "1", true},
171 {"0B1101_1110_1010_1101/0XD_E_A_D", "1", true},
172 {"1_000.0", "1000", true},
174 {"0x_10.0", "16", true},
175 {"0x1_0.0", "16", true},
176 {"0x1.8_0", "3/2", true},
177 {"0X1.8p0_4", "24", true},
178 {"0b1.1_0E2", "150", true},
179 {"0o1_0e-2", "2/25", true},
180 {"0O_10p-3", "1", true},
183 func TestRatSetString(t *testing.T) {
184 var tests []StringTest
185 tests = append(tests, setStringTests...)
186 tests = append(tests, setStringTests2...)
188 for i, test := range tests {
189 x, ok := new(Rat).SetString(test.in)
191 if ok {
192 if !test.ok {
193 t.Errorf("#%d SetString(%q) expected failure", i, test.in)
194 } else if x.RatString() != test.out {
195 t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
197 } else {
198 if test.ok {
199 t.Errorf("#%d SetString(%q) expected success", i, test.in)
200 } else if x != nil {
201 t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
207 func TestRatScan(t *testing.T) {
208 var buf bytes.Buffer
209 for i, test := range setStringTests {
210 x := new(Rat)
211 buf.Reset()
212 buf.WriteString(test.in)
214 _, err := fmt.Fscanf(&buf, "%v", x)
215 if err == nil != test.ok {
216 if test.ok {
217 t.Errorf("#%d (%s) error: %s", i, test.in, err)
218 } else {
219 t.Errorf("#%d (%s) expected error", i, test.in)
221 continue
223 if err == nil && x.RatString() != test.out {
224 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
229 var floatStringTests = []struct {
230 in string
231 prec int
232 out string
234 {"0", 0, "0"},
235 {"0", 4, "0.0000"},
236 {"1", 0, "1"},
237 {"1", 2, "1.00"},
238 {"-1", 0, "-1"},
239 {"0.05", 1, "0.1"},
240 {"-0.05", 1, "-0.1"},
241 {".25", 2, "0.25"},
242 {".25", 1, "0.3"},
243 {".25", 3, "0.250"},
244 {"-1/3", 3, "-0.333"},
245 {"-2/3", 4, "-0.6667"},
246 {"0.96", 1, "1.0"},
247 {"0.999", 2, "1.00"},
248 {"0.9", 0, "1"},
249 {".25", -1, "0"},
250 {".55", -1, "1"},
253 func TestFloatString(t *testing.T) {
254 for i, test := range floatStringTests {
255 x, _ := new(Rat).SetString(test.in)
257 if x.FloatString(test.prec) != test.out {
258 t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
263 // Test inputs to Rat.SetString. The prefix "long:" causes the test
264 // to be skipped except in -long mode. (The threshold is about 500us.)
265 var float64inputs = []string{
266 // Constants plundered from strconv/testfp.txt.
268 // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
269 "5e+125",
270 "69e+267",
271 "999e-026",
272 "7861e-034",
273 "75569e-254",
274 "928609e-261",
275 "9210917e+080",
276 "84863171e+114",
277 "653777767e+273",
278 "5232604057e-298",
279 "27235667517e-109",
280 "653532977297e-123",
281 "3142213164987e-294",
282 "46202199371337e-072",
283 "231010996856685e-073",
284 "9324754620109615e+212",
285 "78459735791271921e+049",
286 "272104041512242479e+200",
287 "6802601037806061975e+198",
288 "20505426358836677347e-221",
289 "836168422905420598437e-234",
290 "4891559871276714924261e+222",
292 // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
293 "9e-265",
294 "85e-037",
295 "623e+100",
296 "3571e+263",
297 "81661e+153",
298 "920657e-023",
299 "4603285e-024",
300 "87575437e-309",
301 "245540327e+122",
302 "6138508175e+120",
303 "83356057653e+193",
304 "619534293513e+124",
305 "2335141086879e+218",
306 "36167929443327e-159",
307 "609610927149051e-255",
308 "3743626360493413e-165",
309 "94080055902682397e-242",
310 "899810892172646163e+283",
311 "7120190517612959703e+120",
312 "25188282901709339043e-252",
313 "308984926168550152811e-052",
314 "6372891218502368041059e+064",
316 // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
317 "5e-20",
318 "67e+14",
319 "985e+15",
320 "7693e-42",
321 "55895e-16",
322 "996622e-44",
323 "7038531e-32",
324 "60419369e-46",
325 "702990899e-20",
326 "6930161142e-48",
327 "25933168707e+13",
328 "596428896559e+20",
330 // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
331 "3e-23",
332 "57e+18",
333 "789e-35",
334 "2539e-18",
335 "76173e+28",
336 "887745e-11",
337 "5382571e-37",
338 "82381273e-35",
339 "750486563e-38",
340 "3752432815e-39",
341 "75224575729e-45",
342 "459926601011e+15",
344 // Constants plundered from strconv/atof_test.go.
346 "0",
347 "1",
348 "+1",
349 "1e23",
350 "1E23",
351 "100000000000000000000000",
352 "1e-100",
353 "123456700",
354 "99999999999999974834176",
355 "100000000000000000000001",
356 "100000000000000008388608",
357 "100000000000000016777215",
358 "100000000000000016777216",
359 "-1",
360 "-0.1",
361 "-0", // NB: exception made for this input
362 "1e-20",
363 "625e-3",
365 // largest float64
366 "1.7976931348623157e308",
367 "-1.7976931348623157e308",
368 // next float64 - too large
369 "1.7976931348623159e308",
370 "-1.7976931348623159e308",
371 // the border is ...158079
372 // borderline - okay
373 "1.7976931348623158e308",
374 "-1.7976931348623158e308",
375 // borderline - too large
376 "1.797693134862315808e308",
377 "-1.797693134862315808e308",
379 // a little too large
380 "1e308",
381 "2e308",
382 "1e309",
384 // way too large
385 "1e310",
386 "-1e310",
387 "1e400",
388 "-1e400",
389 "long:1e400000",
390 "long:-1e400000",
392 // denormalized
393 "1e-305",
394 "1e-306",
395 "1e-307",
396 "1e-308",
397 "1e-309",
398 "1e-310",
399 "1e-322",
400 // smallest denormal
401 "5e-324",
402 "4e-324",
403 "3e-324",
404 // too small
405 "2e-324",
406 // way too small
407 "1e-350",
408 "long:1e-400000",
409 // way too small, negative
410 "-1e-350",
411 "long:-1e-400000",
413 // try to overflow exponent
414 // [Disabled: too slow and memory-hungry with rationals.]
415 // "1e-4294967296",
416 // "1e+4294967296",
417 // "1e-18446744073709551616",
418 // "1e+18446744073709551616",
420 // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
421 "2.2250738585072012e-308",
422 // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
423 "2.2250738585072011e-308",
425 // A very large number (initially wrongly parsed by the fast algorithm).
426 "4.630813248087435e+307",
428 // A different kind of very large number.
429 "22.222222222222222",
430 "long:2." + strings.Repeat("2", 4000) + "e+1",
432 // Exactly halfway between 1 and math.Nextafter(1, 2).
433 // Round to even (down).
434 "1.00000000000000011102230246251565404236316680908203125",
435 // Slightly lower; still round down.
436 "1.00000000000000011102230246251565404236316680908203124",
437 // Slightly higher; round up.
438 "1.00000000000000011102230246251565404236316680908203126",
439 // Slightly higher, but you have to read all the way to the end.
440 "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
442 // Smallest denormal, 2^(-1022-52)
443 "4.940656458412465441765687928682213723651e-324",
444 // Half of smallest denormal, 2^(-1022-53)
445 "2.470328229206232720882843964341106861825e-324",
446 // A little more than the exact half of smallest denormal
447 // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
448 "2.470328302827751011111470718709768633275e-324",
449 // The exact halfway between smallest normal and largest denormal:
450 // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
451 "2.225073858507201136057409796709131975935e-308",
453 "1152921504606846975", // 1<<60 - 1
454 "-1152921504606846975", // -(1<<60 - 1)
455 "1152921504606846977", // 1<<60 + 1
456 "-1152921504606846977", // -(1<<60 + 1)
458 "1/3",
461 // isFinite reports whether f represents a finite rational value.
462 // It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
463 func isFinite(f float64) bool {
464 return math.Abs(f) <= math.MaxFloat64
467 func TestFloat32SpecialCases(t *testing.T) {
468 for _, input := range float64inputs {
469 if strings.HasPrefix(input, "long:") {
470 if !*long {
471 continue
473 input = input[len("long:"):]
476 r, ok := new(Rat).SetString(input)
477 if !ok {
478 t.Errorf("Rat.SetString(%q) failed", input)
479 continue
481 f, exact := r.Float32()
483 // 1. Check string -> Rat -> float32 conversions are
484 // consistent with strconv.ParseFloat.
485 // Skip this check if the input uses "a/b" rational syntax.
486 if !strings.Contains(input, "/") {
487 e64, _ := strconv.ParseFloat(input, 32)
488 e := float32(e64)
490 // Careful: negative Rats too small for
491 // float64 become -0, but Rat obviously cannot
492 // preserve the sign from SetString("-0").
493 switch {
494 case math.Float32bits(e) == math.Float32bits(f):
495 // Ok: bitwise equal.
496 case f == 0 && r.Num().BitLen() == 0:
497 // Ok: Rat(0) is equivalent to both +/- float64(0).
498 default:
499 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
503 if !isFinite(float64(f)) {
504 continue
507 // 2. Check f is best approximation to r.
508 if !checkIsBestApprox32(t, f, r) {
509 // Append context information.
510 t.Errorf("(input was %q)", input)
513 // 3. Check f->R->f roundtrip is non-lossy.
514 checkNonLossyRoundtrip32(t, f)
516 // 4. Check exactness using slow algorithm.
517 if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
518 t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
523 func TestFloat64SpecialCases(t *testing.T) {
524 for _, input := range float64inputs {
525 if strings.HasPrefix(input, "long:") {
526 if !*long {
527 continue
529 input = input[len("long:"):]
532 r, ok := new(Rat).SetString(input)
533 if !ok {
534 t.Errorf("Rat.SetString(%q) failed", input)
535 continue
537 f, exact := r.Float64()
539 // 1. Check string -> Rat -> float64 conversions are
540 // consistent with strconv.ParseFloat.
541 // Skip this check if the input uses "a/b" rational syntax.
542 if !strings.Contains(input, "/") {
543 e, _ := strconv.ParseFloat(input, 64)
545 // Careful: negative Rats too small for
546 // float64 become -0, but Rat obviously cannot
547 // preserve the sign from SetString("-0").
548 switch {
549 case math.Float64bits(e) == math.Float64bits(f):
550 // Ok: bitwise equal.
551 case f == 0 && r.Num().BitLen() == 0:
552 // Ok: Rat(0) is equivalent to both +/- float64(0).
553 default:
554 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
558 if !isFinite(f) {
559 continue
562 // 2. Check f is best approximation to r.
563 if !checkIsBestApprox64(t, f, r) {
564 // Append context information.
565 t.Errorf("(input was %q)", input)
568 // 3. Check f->R->f roundtrip is non-lossy.
569 checkNonLossyRoundtrip64(t, f)
571 // 4. Check exactness using slow algorithm.
572 if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
573 t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
578 func TestIssue31184(t *testing.T) {
579 var x Rat
580 for _, want := range []string{
581 "-213.090",
582 "8.192",
583 "16.000",
585 x.SetString(want)
586 got := x.FloatString(3)
587 if got != want {
588 t.Errorf("got %s, want %s", got, want)
593 func TestIssue45910(t *testing.T) {
594 var x Rat
595 for _, test := range []struct {
596 input string
597 want bool
599 {"1e-1000001", false},
600 {"1e-1000000", true},
601 {"1e+1000000", true},
602 {"1e+1000001", false},
604 {"0p1000000000000", true},
605 {"1p-10000001", false},
606 {"1p-10000000", true},
607 {"1p+10000000", true},
608 {"1p+10000001", false},
609 {"1.770p02041010010011001001", false}, // test case from issue
611 _, got := x.SetString(test.input)
612 if got != test.want {
613 t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)