Commit | Line | Data |
---|---|---|
6853e8af RL |
1 | # -*- mode: perl; -*- |
2 | ||
3 | # Binary, octal, and hexadecimal floating point literals were introduced in | |
4 | # v5.22.0. | |
5 | # | |
6 | # - It wasn't until v5.28.0 that binary, octal, and hexadecimal floating point | |
7 | # literals were converted to the correct value on perls compiled with quadmath | |
8 | # support. | |
9 | # | |
10 | # - It wasn't until v5.32.0 that binary and octal floating point literals worked | |
11 | # correctly with constant overloading. Before v5.32.0, it seems like the | |
12 | # second character is always silently converted to an "x", so, e.g., "0b1.1p8" | |
13 | # is passed to the overload::constant subroutine as "0x1.1p8", and "01.1p+8" | |
14 | # is passed as "0x.1p+8". | |
15 | # | |
16 | # - Octal floating point literals using the "0o" prefix were introduced in | |
17 | # v5.34.0. | |
18 | ||
19 | # Note that all numeric literals that should not be overloaded must be quoted. | |
20 | ||
21 | use strict; | |
22 | use warnings; | |
23 | ||
24 | use Test::More tests => "171"; | |
25 | ||
26 | use Math::BigRat ":constant"; | |
27 | ||
28 | my $class = "Math::BigRat"; | |
29 | my $x; | |
30 | ||
31 | ################################################################################ | |
32 | # The following tests should be identical for Math::BigInt, Math::BigFloat and | |
33 | # Math::BigRat. | |
34 | ||
35 | # These are handled by "binary". | |
36 | ||
37 | $x = 0xff; | |
38 | is($x, "255", "hexadecimal integer literal 0xff"); | |
39 | is(ref($x), $class, "value is a $class"); | |
40 | ||
41 | SKIP: { | |
42 | # Hexadecimal literals using the "0X" prefix require v5.14.0. | |
43 | skip "perl v5.14.0 required for hexadecimal integer literals" | |
44 | . " with '0X' prefix", "2" if $] < "5.014"; | |
45 | ||
46 | $x = eval "0XFF"; | |
47 | is($x, "255", "hexadecimal integer literal 0XFF"); | |
48 | is(ref($x), $class, "value is a $class"); | |
49 | } | |
50 | ||
51 | $x = 0377; | |
52 | is($x, "255", "octal integer literal 0377"); | |
53 | is(ref($x), $class, "value is a $class"); | |
54 | ||
55 | SKIP: { | |
56 | # Octal literals using the "0o" prefix requires v5.34.0. | |
57 | skip "perl v5.34.0 required for octal floating point literals" | |
58 | . " with '0o' prefix", "4" if $] < "5.034"; | |
59 | ||
60 | for my $str (qw/ 0o377 0O377 /) { | |
61 | $x = eval $str; | |
62 | is($x, "255", "octal integer literal $str"); | |
63 | is(ref($x), $class, "value is a $class"); | |
64 | } | |
65 | } | |
66 | ||
67 | $x = 0b11111111; | |
68 | is($x, "255", "binary integer literal 0b11111111"); | |
69 | is(ref($x), $class, "value is a $class"); | |
70 | ||
71 | SKIP: { | |
72 | # Binary literals using the "0B" prefix require v5.14.0. | |
73 | skip "perl v5.14.0 required for binary integer literals" | |
74 | . " with '0B' prefix", "2" if $] < "5.014"; | |
75 | ||
76 | $x = eval "0B11111111"; | |
77 | is($x, "255", "binary integer literal 0B11111111"); | |
78 | is(ref($x), $class, "value is a $class"); | |
79 | } | |
80 | ||
81 | # These are handled by "float". | |
82 | ||
83 | $x = 999999999999999999999999999999999999999999999999999999999999999999999999; | |
84 | is($x, | |
85 | "999999999999999999999999999999999999999999999999999999999999999999999999", | |
86 | "decimal integer literal " . ("9" x 72)); | |
87 | is(ref($x), $class, "value is a $class"); | |
88 | ||
89 | $x = 1e72 - 1; | |
90 | is($x, | |
91 | "999999999999999999999999999999999999999999999999999999999999999999999999", | |
92 | "literal 1e72 - 1"); | |
93 | is(ref($x), $class, "value is a $class"); | |
94 | ||
95 | # These are handled by "float". | |
96 | ||
97 | SKIP: { | |
98 | # Hexadecimal floating point literals require v5.28.0. | |
99 | skip "perl v5.28.0 required for hexadecimal floating point literals", | |
100 | "6" * "2" + "2" * "2" if $] < "5.028"; | |
101 | ||
102 | for my $str (qw/ 0x1.3ap+8 0X1.3AP+8 | |
103 | 0x1.3ap8 0X1.3AP8 | |
104 | 0x13a0p-4 0X13A0P-4 /) | |
105 | { | |
106 | $x = eval $str; | |
107 | is($x, "314", "hexadecimal floating point literal $str"); | |
108 | is(ref($x), $class, "value is a $class"); | |
109 | } | |
110 | ||
111 | for my $str (qw/ 0x0.0p+8 0X0.0P+8 /) | |
112 | { | |
113 | $x = eval $str; | |
114 | is($x, "0", "hexadecimal floating point literal $str"); | |
115 | is(ref($x), $class, "value is a $class"); | |
116 | } | |
117 | } | |
118 | ||
119 | SKIP: { | |
120 | # Octal floating point literals using the "0o" prefix require v5.34.0. | |
121 | skip "perl v5.34.0 required for octal floating point literals" | |
122 | . " with '0o' prefix", "6" * "2" + "6" * "2" if $] < "5.034"; | |
123 | ||
124 | for my $str (qw/ 0o1.164p+8 0O1.164P+8 | |
125 | 0o1.164p8 0O1.164P8 | |
126 | 0o11640p-4 0O11640P-4 /) | |
127 | { | |
128 | $x = eval $str; | |
129 | is($x, "314", "octal floating point literal $str"); | |
130 | is(ref($x), $class, "value is a $class"); | |
131 | } | |
132 | ||
133 | for my $str (qw/ 0o0.0p+8 0O0.0P+8 | |
134 | 0o0.0p8 0O0.0P8 | |
135 | 0o0.0p-8 0O0.0P-8 /) | |
136 | { | |
137 | $x = eval $str; | |
138 | is($x, "0", "octal floating point literal $str"); | |
139 | is(ref($x), $class, "value is a $class"); | |
140 | } | |
141 | } | |
142 | ||
143 | SKIP: { | |
144 | # Octal floating point literals using the "0" prefix require v5.32.0. | |
145 | skip "perl v5.32.0 required for octal floating point literals", | |
146 | "6" * "2" + "6" * "2" if $] < "5.032"; | |
147 | ||
148 | for my $str (qw/ 01.164p+8 01.164P+8 | |
149 | 01.164p8 01.164P8 | |
150 | 011640p-4 011640P-4 /) | |
151 | { | |
152 | $x = eval $str; | |
153 | is($x, "314", "octal floating point literal $str"); | |
154 | is(ref($x), $class, "value is a $class"); | |
155 | } | |
156 | ||
157 | for my $str (qw/ 00.0p+8 00.0P+8 | |
158 | 00.0p8 00.0P8 | |
159 | 00.0p-8 00.0P-8 /) | |
160 | { | |
161 | $x = eval $str; | |
162 | is($x, "0", "octal floating point literal $str"); | |
163 | is(ref($x), $class, "value is a $class"); | |
164 | } | |
165 | } | |
166 | ||
167 | SKIP: { | |
168 | # Binary floating point literals require v5.32.0. | |
169 | skip "perl v5.32.0 required for binary floating point literals", | |
170 | "6" * "2" + "6" * "2" if $] < "5.032"; | |
171 | ||
172 | for my $str (qw/ 0b1.0011101p+8 0B1.0011101P+8 | |
173 | 0b1.0011101p8 0B1.0011101P8 | |
174 | 0b10011101000p-2 0B10011101000P-2 /) | |
175 | { | |
176 | $x = eval $str; | |
177 | is($x, "314", "binary floating point literal $str"); | |
178 | is(ref($x), $class, "value is a $class"); | |
179 | } | |
180 | ||
181 | for my $str (qw/ 0b0p+8 0B0P+8 | |
182 | 0b0p8 0B0P8 | |
183 | 0b0p-8 0B0P-8 | |
184 | /) | |
185 | { | |
186 | $x = eval $str; | |
187 | is($x, "0", "binary floating point literal $str"); | |
188 | is(ref($x), $class, "value is a $class"); | |
189 | } | |
190 | } | |
191 | ||
192 | # These are handled by "integer". | |
193 | ||
194 | $x = 314; | |
195 | is($x, "314", "integer literal 314"); | |
196 | is(ref($x), $class, "value is a $class"); | |
197 | ||
198 | $x = 0; | |
199 | is($x, "0", "integer literal 0"); | |
200 | is(ref($x), $class, "value is a $class"); | |
201 | ||
202 | $x = 2 ** 255; | |
203 | is($x, | |
204 | "578960446186580977117854925043439539266" | |
205 | . "34992332820282019728792003956564819968", | |
206 | "2 ** 255"); | |
207 | is(ref($x), $class, "value is a $class"); | |
208 | ||
209 | # These are handled by "binary". | |
210 | ||
211 | { | |
212 | no warnings "portable"; # protect against "non-portable" warnings | |
213 | ||
214 | # hexadecimal constant | |
215 | $x = 0x123456789012345678901234567890; | |
216 | is($x, | |
217 | "94522879687365475552814062743484560", | |
218 | "hexadecimal constant 0x123456789012345678901234567890"); | |
219 | is(ref($x), $class, "value is a $class"); | |
220 | ||
221 | # octal constant | |
222 | $x = 012345676543210123456765432101234567654321; | |
223 | is($x, | |
224 | "1736132869400711976876385488263403729", | |
225 | "octal constant 012345676543210123456765432101234567654321"); | |
226 | is(ref($x), $class, "value is a $class"); | |
227 | ||
228 | # binary constant | |
229 | $x = 0b01010100011001010110110001110011010010010110000101101101; | |
230 | is($x, | |
231 | "23755414508757357", | |
232 | "binary constant 0b0101010001100101011011000111" | |
233 | . "0011010010010110000101101101"); | |
234 | is(ref($x), $class, "value is a $class"); | |
235 | } | |
236 | ||
237 | ################################################################################ | |
238 | # The following tests are unique to $class. | |
239 | ||
240 | # These are handled by "float". | |
241 | ||
242 | $x = 0.999999999999999999999999999999999999999999999999999999999999999999999999; | |
243 | is($x, | |
244 | "999999999999999999999999999999999999999999999999999999999999999999999999" . | |
245 | "/1000000000000000000000000000000000000000000000000000000000000000000000000", | |
246 | "decimal floating point literal 0." . ("9" x 72)); | |
247 | is(ref($x), $class, "value is a $class"); | |
248 | ||
249 | $x = 1e72 - 0.1; | |
250 | is($x, | |
251 | "9999999999999999999999999999999999999999999999999999999999999999999999999" | |
252 | . "/10", | |
253 | "literal 1e72 - 0.1"); | |
254 | is(ref($x), $class, "value is a $class"); | |
255 | ||
256 | # These are handled by "float". | |
257 | ||
258 | SKIP: { | |
259 | # Hexadecimal floating point literals require v5.28.0. | |
260 | skip "perl v5.28.0 required for hexadecimal floating point literals", | |
261 | "6" * "2" if $] < "5.028"; | |
262 | ||
263 | for my $str (qw/ 0x1.92p+1 0X1.92P+1 | |
264 | 0x1.92p1 0X1.92P1 | |
265 | 0x19.2p-3 0X19.2P-3 /) | |
266 | { | |
267 | $x = eval $str; | |
268 | is($x, "201/64", "hexadecimal floating point literal $str"); | |
269 | is(ref($x), $class, "value is a $class"); | |
270 | } | |
271 | } | |
272 | ||
273 | SKIP: { | |
274 | # Octal floating point literals using the "0o" prefix require v5.34.0. | |
275 | skip "perl v5.34.0 required for octal floating point literals" | |
276 | . " with '0o' prefix", "6" * "2" if $] < "5.034"; | |
277 | ||
278 | for my $str (qw/ 0o1.444p+1 0O1.444P+1 | |
279 | 0o1.444p1 0O1.444P1 | |
280 | 0o14.44p-2 0O14.44P-2 /) | |
281 | { | |
282 | $x = eval $str; | |
283 | is($x, "201/64", "octal floating point literal $str"); | |
284 | is(ref($x), $class, "value is a $class"); | |
285 | } | |
286 | } | |
287 | ||
288 | SKIP: { | |
289 | # Octal floating point literals using the "0" prefix require v5.32.0. | |
290 | skip "perl v5.32.0 required for octal floating point literals", | |
291 | "6" * "2" if $] < "5.032"; | |
292 | ||
293 | for my $str (qw/ 01.444p+1 01.444P+1 | |
294 | 01.444p1 01.444P1 | |
295 | 014.44p-2 014.44P-2 /) | |
296 | { | |
297 | $x = eval $str; | |
298 | is($x, "201/64", "octal floating point literal $str"); | |
299 | is(ref($x), $class, "value is a $class"); | |
300 | } | |
301 | } | |
302 | ||
303 | SKIP: { | |
304 | # Binary floating point literals require v5.32.0. | |
305 | skip "perl v5.32.0 required for binary floating point literals", | |
306 | "6" * "2" if $] < "5.032"; | |
307 | ||
308 | for my $str (qw/ 0b1.1001001p+1 0B1.1001001P+1 | |
309 | 0b1.1001001p1 0B1.1001001P1 | |
310 | 0b110.01001p-1 0B110.01001P-1 /) | |
311 | { | |
312 | $x = eval $str; | |
313 | is($x, "201/64", "binary floating point literal $str"); | |
314 | is(ref($x), $class, "value is a $class"); | |
315 | } | |
316 | } | |
317 | ||
318 | is(1.0 / 3.0, "1/3", | |
319 | "1.0 / 3.0 = 1/3"); |