Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(187)

Side by Side Diff: src/pkg/math/big/rat_test.go

Issue 6930059: code review 6930059: math/big: add Rat.{,Set}Float64 methods for IEEE 754 co... (Closed)
Patch Set: diff -r 2888e5323790 https://code.google.com/p/go/ Created 11 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2010 The Go Authors. All rights reserved. 1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package big 5 package big
6 6
7 import ( 7 import (
8 "bufio"
8 "bytes" 9 "bytes"
9 "encoding/gob" 10 "encoding/gob"
10 "fmt" 11 "fmt"
12 "io"
13 "math"
14 "os"
15 "strconv"
16 "strings"
11 "testing" 17 "testing"
12 ) 18 )
13 19
14 func TestZeroRat(t *testing.T) { 20 func TestZeroRat(t *testing.T) {
15 var x, y, z Rat 21 var x, y, z Rat
16 y.SetFrac64(0, 42) 22 y.SetFrac64(0, 42)
17 23
18 if x.Cmp(&y) != 0 { 24 if x.Cmp(&y) != 0 {
19 t.Errorf("x and y should be both equal and zero") 25 t.Errorf("x and y should be both equal and zero")
20 } 26 }
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 // 3) changing the numerator/denominator of a Rat changes the Rat 495 // 3) changing the numerator/denominator of a Rat changes the Rat
490 x.SetFrac(a, b) 496 x.SetFrac(a, b)
491 a = x.Num() 497 a = x.Num()
492 b = x.Denom() 498 b = x.Denom()
493 a.SetInt64(5) 499 a.SetInt64(5)
494 b.SetInt64(3) 500 b.SetInt64(3)
495 if x.Cmp(q53) != 0 { 501 if x.Cmp(q53) != 0 {
496 t.Errorf("3) got %s want %s", x, q53) 502 t.Errorf("3) got %s want %s", x, q53)
497 } 503 }
498 } 504 }
505
506 // This test uses the same file of input data as strconv_test.
507 func TestIEEE754(t *testing.T) {
508 // TODO(adonovan): is this ok? Or should I copy the file, or even
remyoudompheng 2012/12/13 07:37:38 I'm not sure testfp.txt is a good input file for t
rsc 2012/12/13 14:41:58 You can read the file directly, that's fine. As fo
adonovan 2012/12/14 23:22:43 Done.
509 // move the constants into the code?
510 f, err := os.Open("../../strconv/testfp.txt")
511 if err != nil {
512 t.Fatal("testfp: open ../../strconv/testfp.txt:", err)
513 }
514 defer f.Close()
515
516 b := bufio.NewReader(f)
517
518 lineno := 0
519 for {
520 line, err2 := b.ReadString('\n')
521 if err2 == io.EOF {
522 break
523 }
524 if err2 != nil {
525 t.Fatal("testfp: read testfp.txt: " + err2.Error())
526 }
527 line = line[0 : len(line)-1]
528 lineno++
529 if len(line) == 0 || line[0] == '#' {
530 continue
531 }
532 a := strings.Split(line, " ")
533 if len(a) != 4 {
534 t.Error("testfp.txt:", lineno, ": wrong field count")
535 continue
536 }
537 var v float64
538 switch a[0] {
539 case "float32", "float64":
540 var ok bool
541 v, ok = myatof64(a[2])
542 if !ok {
543 t.Error("testfp.txt:", lineno, ": cannot atof64" , a[2])
544 continue
545 }
546
547 var r Rat
548 r.SetFloat64(v)
549 v2, exact := r.Float64()
550 if v != v2 {
551 t.Error("testfp.txt:", lineno, ": float64 <=> Ra t roundtrip yielded different value for", a[2], "epsilon=", v2-v)
552 continue
553 }
554 if !exact {
555 t.Error("testfp.txt:", lineno, ": float64 <=> Ra t roundtrip was inexact for", a[2])
556 continue
557 }
558 }
559
560 }
561
562 // Some rationals are not exactly representable by IEEE 754.
563 inexact := []struct {
564 rat string
565 expected float64
566 }{
567 {"1/3", 1.0 / 3},
568 {"1.23456788e1234", math.Inf(+1)},
569 {"-1.23456788e1234", math.Inf(-1)},
570 {"1.23456788e-1234", 0.0},
571 {"-1.23456788e-1234", 0.0},
572 }
573 for _, s := range inexact {
574 rat, ok := new(Rat).SetString(s.rat)
575 if !ok {
576 t.Error("Rat.SetString(\"" + s.rat + "\") failed")
577 }
578 v, exact := rat.Float64()
579 if exact {
580 t.Error("Rat.Float64() returned exact=true for inexact r ational", s.rat, v)
581 }
582 if v != s.expected {
583 t.Error("Rat.Float64() returned incorrect value", s.rat, v, s.expected, "delta=", v-s.expected)
584 }
585 }
586 }
587
588 // TODO(adonovan): plundered from strconv_test. What to do?
589 func pow2(i int) float64 {
590 switch {
591 case i < 0:
592 return 1 / pow2(-i)
593 case i == 0:
594 return 1
595 case i == 1:
596 return 2
597 }
598 return pow2(i/2) * pow2(i-i/2)
599 }
600
601 // TODO(adonovan): plundered from strconv_test. What to do?
602 //
603 // Wrapper around strconv.ParseFloat(x, 64). Handles dddddp+ddd (binary exponen t)
604 // itself, passes the rest on to strconv.ParseFloat.
605 func myatof64(s string) (f float64, ok bool) {
606 a := strings.SplitN(s, "p", 2)
607 if len(a) == 2 {
608 n, err := strconv.ParseInt(a[0], 10, 64)
609 if err != nil {
610 return 0, false
611 }
612 e, err1 := strconv.Atoi(a[1])
613 if err1 != nil {
614 println("bad e", a[1])
615 return 0, false
616 }
617 v := float64(n)
618 // We expect that v*pow2(e) fits in a float64,
619 // but pow2(e) by itself may not. Be careful.
620 if e <= -1000 {
621 v *= pow2(-1000)
622 e += 1000
623 for e < 0 {
624 v /= 2
625 e++
626 }
627 return v, true
628 }
629 if e >= 1000 {
630 v *= pow2(1000)
631 e -= 1000
632 for e > 0 {
633 v *= 2
634 e--
635 }
636 return v, true
637 }
638 return v * pow2(e), true
639 }
640 f1, err := strconv.ParseFloat(s, 64)
641 if err != nil {
642 return 0, false
643 }
644 return f1, true
645 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b