Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / strconv / fp_test.go
1 // Copyright 2009 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.
4
5 package strconv_test
6
7 import (
8         "bufio"
9         "fmt"
10         "io"
11         "os"
12         "strconv"
13         "strings"
14         "testing"
15 )
16
17 func pow2(i int) float64 {
18         switch {
19         case i < 0:
20                 return 1 / pow2(-i)
21         case i == 0:
22                 return 1
23         case i == 1:
24                 return 2
25         }
26         return pow2(i/2) * pow2(i-i/2)
27 }
28
29 // Wrapper around strconv.ParseFloat(x, 64).  Handles dddddp+ddd (binary exponent)
30 // itself, passes the rest on to strconv.ParseFloat.
31 func myatof64(s string) (f float64, ok bool) {
32         a := strings.SplitN(s, "p", 2)
33         if len(a) == 2 {
34                 n, err := strconv.ParseInt(a[0], 10, 64)
35                 if err != nil {
36                         return 0, false
37                 }
38                 e, err1 := strconv.Atoi(a[1])
39                 if err1 != nil {
40                         println("bad e", a[1])
41                         return 0, false
42                 }
43                 v := float64(n)
44                 // We expect that v*pow2(e) fits in a float64,
45                 // but pow2(e) by itself may not.  Be careful.
46                 if e <= -1000 {
47                         v *= pow2(-1000)
48                         e += 1000
49                         for e < 0 {
50                                 v /= 2
51                                 e++
52                         }
53                         return v, true
54                 }
55                 if e >= 1000 {
56                         v *= pow2(1000)
57                         e -= 1000
58                         for e > 0 {
59                                 v *= 2
60                                 e--
61                         }
62                         return v, true
63                 }
64                 return v * pow2(e), true
65         }
66         f1, err := strconv.ParseFloat(s, 64)
67         if err != nil {
68                 return 0, false
69         }
70         return f1, true
71 }
72
73 // Wrapper around strconv.ParseFloat(x, 32).  Handles dddddp+ddd (binary exponent)
74 // itself, passes the rest on to strconv.ParseFloat.
75 func myatof32(s string) (f float32, ok bool) {
76         a := strings.SplitN(s, "p", 2)
77         if len(a) == 2 {
78                 n, err := strconv.Atoi(a[0])
79                 if err != nil {
80                         println("bad n", a[0])
81                         return 0, false
82                 }
83                 e, err1 := strconv.Atoi(a[1])
84                 if err1 != nil {
85                         println("bad p", a[1])
86                         return 0, false
87                 }
88                 return float32(float64(n) * pow2(e)), true
89         }
90         f64, err1 := strconv.ParseFloat(s, 32)
91         f1 := float32(f64)
92         if err1 != nil {
93                 return 0, false
94         }
95         return f1, true
96 }
97
98 func TestFp(t *testing.T) {
99         f, err := os.Open("testdata/testfp.txt")
100         if err != nil {
101                 t.Fatal("testfp: open testdata/testfp.txt:", err)
102         }
103         defer f.Close()
104
105         b := bufio.NewReader(f)
106
107         lineno := 0
108         for {
109                 line, err2 := b.ReadString('\n')
110                 if err2 == io.EOF {
111                         break
112                 }
113                 if err2 != nil {
114                         t.Fatal("testfp: read testdata/testfp.txt: " + err2.Error())
115                 }
116                 line = line[0 : len(line)-1]
117                 lineno++
118                 if len(line) == 0 || line[0] == '#' {
119                         continue
120                 }
121                 a := strings.Split(line, " ")
122                 if len(a) != 4 {
123                         t.Error("testdata/testfp.txt:", lineno, ": wrong field count")
124                         continue
125                 }
126                 var s string
127                 var v float64
128                 switch a[0] {
129                 case "float64":
130                         var ok bool
131                         v, ok = myatof64(a[2])
132                         if !ok {
133                                 t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2])
134                                 continue
135                         }
136                         s = fmt.Sprintf(a[1], v)
137                 case "float32":
138                         v1, ok := myatof32(a[2])
139                         if !ok {
140                                 t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2])
141                                 continue
142                         }
143                         s = fmt.Sprintf(a[1], v1)
144                         v = float64(v1)
145                 }
146                 if s != a[3] {
147                         t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
148                                 "want ", a[3], " got ", s)
149                 }
150         }
151 }