atoc_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright 2020 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. package strconv_test
  5. import (
  6. "math"
  7. "math/cmplx"
  8. "reflect"
  9. . "strconv"
  10. "testing"
  11. )
  12. var (
  13. infp0 = complex(math.Inf(+1), 0)
  14. infm0 = complex(math.Inf(-1), 0)
  15. inf0p = complex(0, math.Inf(+1))
  16. inf0m = complex(0, math.Inf(-1))
  17. infpp = complex(math.Inf(+1), math.Inf(+1))
  18. infpm = complex(math.Inf(+1), math.Inf(-1))
  19. infmp = complex(math.Inf(-1), math.Inf(+1))
  20. infmm = complex(math.Inf(-1), math.Inf(-1))
  21. )
  22. type atocTest struct {
  23. in string
  24. out complex128
  25. err error
  26. }
  27. func TestParseComplex(t *testing.T) {
  28. tests := []atocTest{
  29. // Clearly invalid
  30. {"", 0, ErrSyntax},
  31. {" ", 0, ErrSyntax},
  32. {"(", 0, ErrSyntax},
  33. {")", 0, ErrSyntax},
  34. {"i", 0, ErrSyntax},
  35. {"+i", 0, ErrSyntax},
  36. {"-i", 0, ErrSyntax},
  37. {"1I", 0, ErrSyntax},
  38. {"10 + 5i", 0, ErrSyntax},
  39. {"3+", 0, ErrSyntax},
  40. {"3+5", 0, ErrSyntax},
  41. {"3+5+5i", 0, ErrSyntax},
  42. // Parentheses
  43. {"()", 0, ErrSyntax},
  44. {"(i)", 0, ErrSyntax},
  45. {"(0)", 0, nil},
  46. {"(1i)", 1i, nil},
  47. {"(3.0+5.5i)", 3.0 + 5.5i, nil},
  48. {"(1)+1i", 0, ErrSyntax},
  49. {"(3.0+5.5i", 0, ErrSyntax},
  50. {"3.0+5.5i)", 0, ErrSyntax},
  51. // NaNs
  52. {"NaN", complex(math.NaN(), 0), nil},
  53. {"NANi", complex(0, math.NaN()), nil},
  54. {"nan+nAni", complex(math.NaN(), math.NaN()), nil},
  55. {"+NaN", 0, ErrSyntax},
  56. {"-NaN", 0, ErrSyntax},
  57. {"NaN-NaNi", 0, ErrSyntax},
  58. // Infs
  59. {"Inf", infp0, nil},
  60. {"+inf", infp0, nil},
  61. {"-inf", infm0, nil},
  62. {"Infinity", infp0, nil},
  63. {"+INFINITY", infp0, nil},
  64. {"-infinity", infm0, nil},
  65. {"+infi", inf0p, nil},
  66. {"0-infinityi", inf0m, nil},
  67. {"Inf+Infi", infpp, nil},
  68. {"+Inf-Infi", infpm, nil},
  69. {"-Infinity+Infi", infmp, nil},
  70. {"inf-inf", 0, ErrSyntax},
  71. // Zeros
  72. {"0", 0, nil},
  73. {"0i", 0, nil},
  74. {"-0.0i", 0, nil},
  75. {"0+0.0i", 0, nil},
  76. {"0e+0i", 0, nil},
  77. {"0e-0+0i", 0, nil},
  78. {"-0.0-0.0i", 0, nil},
  79. {"0e+012345", 0, nil},
  80. {"0x0p+012345i", 0, nil},
  81. {"0x0.00p-012345i", 0, nil},
  82. {"+0e-0+0e-0i", 0, nil},
  83. {"0e+0+0e+0i", 0, nil},
  84. {"-0e+0-0e+0i", 0, nil},
  85. // Regular non-zeroes
  86. {"0.1", 0.1, nil},
  87. {"0.1i", 0 + 0.1i, nil},
  88. {"0.123", 0.123, nil},
  89. {"0.123i", 0 + 0.123i, nil},
  90. {"0.123+0.123i", 0.123 + 0.123i, nil},
  91. {"99", 99, nil},
  92. {"+99", 99, nil},
  93. {"-99", -99, nil},
  94. {"+1i", 1i, nil},
  95. {"-1i", -1i, nil},
  96. {"+3+1i", 3 + 1i, nil},
  97. {"30+3i", 30 + 3i, nil},
  98. {"+3e+3-3e+3i", 3e+3 - 3e+3i, nil},
  99. {"+3e+3+3e+3i", 3e+3 + 3e+3i, nil},
  100. {"+3e+3+3e+3i+", 0, ErrSyntax},
  101. // Separators
  102. {"0.1", 0.1, nil},
  103. {"0.1i", 0 + 0.1i, nil},
  104. {"0.1_2_3", 0.123, nil},
  105. {"+0x_3p3i", 0x3p3i, nil},
  106. {"0_0+0x_0p0i", 0, nil},
  107. {"0x_10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
  108. {"+0x_1_0.3p-8+0x_3_0p3i", 0x10.3p-8 + 0x30p3i, nil},
  109. {"0x1_0.3p+8-0x_3p3i", 0x10.3p+8 - 0x3p3i, nil},
  110. // Hexadecimals
  111. {"0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
  112. {"+0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
  113. {"0x10.3p+8-0x3p3i", 0x10.3p+8 - 0x3p3i, nil},
  114. {"0x1p0", 1, nil},
  115. {"0x1p1", 2, nil},
  116. {"0x1p-1", 0.5, nil},
  117. {"0x1ep-1", 15, nil},
  118. {"-0x1ep-1", -15, nil},
  119. {"-0x2p3", -16, nil},
  120. {"0x1e2", 0, ErrSyntax},
  121. {"1p2", 0, ErrSyntax},
  122. {"0x1e2i", 0, ErrSyntax},
  123. // ErrRange
  124. // next float64 - too large
  125. {"+0x1p1024", infp0, ErrRange},
  126. {"-0x1p1024", infm0, ErrRange},
  127. {"+0x1p1024i", inf0p, ErrRange},
  128. {"-0x1p1024i", inf0m, ErrRange},
  129. {"+0x1p1024+0x1p1024i", infpp, ErrRange},
  130. {"+0x1p1024-0x1p1024i", infpm, ErrRange},
  131. {"-0x1p1024+0x1p1024i", infmp, ErrRange},
  132. {"-0x1p1024-0x1p1024i", infmm, ErrRange},
  133. // the border is ...158079
  134. // borderline - okay
  135. {"+0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 + 1.7976931348623157e+308i, nil},
  136. {"+0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 - 1.7976931348623157e+308i, nil},
  137. {"-0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 + 1.7976931348623157e+308i, nil},
  138. {"-0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 - 1.7976931348623157e+308i, nil},
  139. // borderline - too large
  140. {"+0x1.fffffffffffff8p1023", infp0, ErrRange},
  141. {"-0x1fffffffffffff.8p+971", infm0, ErrRange},
  142. {"+0x1.fffffffffffff8p1023i", inf0p, ErrRange},
  143. {"-0x1fffffffffffff.8p+971i", inf0m, ErrRange},
  144. {"+0x1.fffffffffffff8p1023+0x1.fffffffffffff8p1023i", infpp, ErrRange},
  145. {"+0x1.fffffffffffff8p1023-0x1.fffffffffffff8p1023i", infpm, ErrRange},
  146. {"-0x1fffffffffffff.8p+971+0x1fffffffffffff.8p+971i", infmp, ErrRange},
  147. {"-0x1fffffffffffff8p+967-0x1fffffffffffff8p+967i", infmm, ErrRange},
  148. // a little too large
  149. {"1e308+1e308i", 1e+308 + 1e+308i, nil},
  150. {"2e308+2e308i", infpp, ErrRange},
  151. {"1e309+1e309i", infpp, ErrRange},
  152. {"0x1p1025+0x1p1025i", infpp, ErrRange},
  153. {"2e308", infp0, ErrRange},
  154. {"1e309", infp0, ErrRange},
  155. {"0x1p1025", infp0, ErrRange},
  156. {"2e308i", inf0p, ErrRange},
  157. {"1e309i", inf0p, ErrRange},
  158. {"0x1p1025i", inf0p, ErrRange},
  159. // way too large
  160. {"+1e310+1e310i", infpp, ErrRange},
  161. {"+1e310-1e310i", infpm, ErrRange},
  162. {"-1e310+1e310i", infmp, ErrRange},
  163. {"-1e310-1e310i", infmm, ErrRange},
  164. // under/overflow exponent
  165. {"1e-4294967296", 0, nil},
  166. {"1e-4294967296i", 0, nil},
  167. {"1e-4294967296+1i", 1i, nil},
  168. {"1+1e-4294967296i", 1, nil},
  169. {"1e-4294967296+1e-4294967296i", 0, nil},
  170. {"1e+4294967296", infp0, ErrRange},
  171. {"1e+4294967296i", inf0p, ErrRange},
  172. {"1e+4294967296+1e+4294967296i", infpp, ErrRange},
  173. {"1e+4294967296-1e+4294967296i", infpm, ErrRange},
  174. }
  175. for i := range tests {
  176. test := &tests[i]
  177. if test.err != nil {
  178. test.err = &NumError{Func: "ParseComplex", Num: test.in, Err: test.err}
  179. }
  180. got, err := ParseComplex(test.in, 128)
  181. if !reflect.DeepEqual(err, test.err) {
  182. t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
  183. }
  184. if !(cmplx.IsNaN(test.out) && cmplx.IsNaN(got)) && got != test.out {
  185. t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
  186. }
  187. if complex128(complex64(test.out)) == test.out {
  188. got, err := ParseComplex(test.in, 64)
  189. if !reflect.DeepEqual(err, test.err) {
  190. t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
  191. }
  192. got64 := complex64(got)
  193. if complex128(got64) != test.out {
  194. t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
  195. }
  196. }
  197. }
  198. }
  199. // Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons
  200. func TestParseComplexIncorrectBitSize(t *testing.T) {
  201. const s = "1.5e308+1.0e307i"
  202. const want = 1.5e308 + 1.0e307i
  203. for _, bitSize := range []int{0, 10, 100, 256} {
  204. c, err := ParseComplex(s, bitSize)
  205. if err != nil {
  206. t.Fatalf("ParseComplex(%q, %d) gave error %s", s, bitSize, err)
  207. }
  208. if c != want {
  209. t.Fatalf("ParseComplex(%q, %d) = %g (expected %g)", s, bitSize, c, want)
  210. }
  211. }
  212. }