This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update bignum, Math::BigInt, Math::BigInt::FastCalc, and Math::BigRat
[perl5.git] / cpan / Math-BigRat / t / const-mbr.t
CommitLineData
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
21use strict;
22use warnings;
23
24use Test::More tests => "171";
25
26use Math::BigRat ":constant";
27
28my $class = "Math::BigRat";
29my $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;
38is($x, "255", "hexadecimal integer literal 0xff");
39is(ref($x), $class, "value is a $class");
40
41SKIP: {
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;
52is($x, "255", "octal integer literal 0377");
53is(ref($x), $class, "value is a $class");
54
55SKIP: {
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;
68is($x, "255", "binary integer literal 0b11111111");
69is(ref($x), $class, "value is a $class");
70
71SKIP: {
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;
84is($x,
85 "999999999999999999999999999999999999999999999999999999999999999999999999",
86 "decimal integer literal " . ("9" x 72));
87is(ref($x), $class, "value is a $class");
88
89$x = 1e72 - 1;
90is($x,
91 "999999999999999999999999999999999999999999999999999999999999999999999999",
92 "literal 1e72 - 1");
93is(ref($x), $class, "value is a $class");
94
95# These are handled by "float".
96
97SKIP: {
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
119SKIP: {
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
143SKIP: {
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
167SKIP: {
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;
195is($x, "314", "integer literal 314");
196is(ref($x), $class, "value is a $class");
197
198$x = 0;
199is($x, "0", "integer literal 0");
200is(ref($x), $class, "value is a $class");
201
202$x = 2 ** 255;
203is($x,
204 "578960446186580977117854925043439539266"
205 . "34992332820282019728792003956564819968",
206 "2 ** 255");
207is(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;
243is($x,
244 "999999999999999999999999999999999999999999999999999999999999999999999999" .
245 "/1000000000000000000000000000000000000000000000000000000000000000000000000",
246 "decimal floating point literal 0." . ("9" x 72));
247is(ref($x), $class, "value is a $class");
248
249$x = 1e72 - 0.1;
250is($x,
251 "9999999999999999999999999999999999999999999999999999999999999999999999999"
252 . "/10",
253 "literal 1e72 - 0.1");
254is(ref($x), $class, "value is a $class");
255
256# These are handled by "float".
257
258SKIP: {
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
273SKIP: {
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
288SKIP: {
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
303SKIP: {
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
318is(1.0 / 3.0, "1/3",
319 "1.0 / 3.0 = 1/3");