xref: /openbsd-src/gnu/usr.bin/perl/cpan/bignum/t/const-bignum.t (revision 256a93a44f36679bee503f12e49566c2183f6181)
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 bignum;
27
28my $class = "Math::BigFloat";
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");
39like(ref($x), qr/^Math::BigInt(::Lite)?$/,
40     "value is a Math::BigInt or Math::BigInt::Lite");
41
42SKIP: {
43    # Hexadecimal literals using the "0X" prefix require v5.14.0.
44    skip "perl v5.14.0 required for hexadecimal integer literals"
45      . " with '0X' prefix", "2" if $] < "5.014";
46
47    $x = eval "0XFF";
48    is($x, "255", "hexadecimal integer literal 0XFF");
49    like(ref($x), qr/^Math::BigInt(::Lite)?$/,
50         "value is a Math::BigInt or Math::BigInt::Lite");
51}
52
53$x = 0377;
54is($x, "255", "octal integer literal 0377");
55like(ref($x), qr/^Math::BigInt(::Lite)?$/,
56     "value is a Math::BigInt or Math::BigInt::Lite");
57
58SKIP: {
59    # Octal literals using the "0o" prefix require v5.34.0.
60    skip "perl v5.34.0 required for octal floating point literals"
61      . " with '0o' prefix", "4" if $] < "5.034";
62
63    for my $str (qw/ 0o377 0O377 /) {
64        $x = eval $str;
65        is($x, "255", "octal integer literal $str");
66        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
67             "value is a Math::BigInt or Math::BigInt::Lite");
68    }
69}
70
71$x = 0b11111111;
72is($x, "255", "binary integer literal 0b11111111");
73like(ref($x), qr/^Math::BigInt(::Lite)?$/,
74     "value is a Math::BigInt or Math::BigInt::Lite");
75
76SKIP: {
77    # Binary literals using the "0B" prefix require v5.14.0.
78    skip "perl v5.14.0 required for binary integer literals"
79      . " with '0B' prefix", "2" if $] < "5.014";
80
81    $x = eval "0B11111111";
82    is($x, "255", "binary integer literal 0B11111111");
83    like(ref($x), qr/^Math::BigInt(::Lite)?$/,
84         "value is a Math::BigInt or Math::BigInt::Lite");
85}
86
87# These are handled by "float".
88
89$x = 999999999999999999999999999999999999999999999999999999999999999999999999;
90is($x,
91   "999999999999999999999999999999999999999999999999999999999999999999999999",
92   "decimal integer literal " . ("9" x 72));
93like(ref($x), qr/^Math::BigInt(::Lite)?$/,
94     "value is a Math::BigInt or Math::BigInt::Lite");
95
96$x = 1e72 - 1;
97is($x,
98   "999999999999999999999999999999999999999999999999999999999999999999999999",
99   "literal 1e72 - 1");
100like(ref($x), qr/^Math::BigInt(::Lite)?$/,
101     "value is a Math::BigInt or Math::BigInt::Lite");
102
103# These are handled by "float".
104
105SKIP: {
106    # Hexadecimal floating point literals require v5.28.0.
107    skip "perl v5.28.0 required for hexadecimal floating point literals",
108      "6" * "2" + "2" * "2" if $] < "5.028";
109
110    for my $str (qw/ 0x1.3ap+8 0X1.3AP+8
111                     0x1.3ap8  0X1.3AP8
112                     0x13a0p-4 0X13A0P-4 /)
113    {
114        $x = eval $str;
115        is($x, "314", "hexadecimal floating point literal $str");
116        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
117             "value is a Math::BigInt or Math::BigInt::Lite");
118    }
119
120    for my $str (qw/ 0x0.0p+8 0X0.0P+8 /)
121    {
122        $x = eval $str;
123        is($x, "0", "hexadecimal floating point literal $str");
124        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
125             "value is a Math::BigInt or Math::BigInt::Lite");
126    }
127}
128
129SKIP: {
130    # Octal floating point literals using the "0o" prefix require v5.34.0.
131    skip "perl v5.34.0 required for octal floating point literals"
132      . " with '0o' prefix", "6" * "2" + "6" * "2" if $] < "5.034";
133
134    for my $str (qw/ 0o1.164p+8 0O1.164P+8
135                     0o1.164p8  0O1.164P8
136                     0o11640p-4 0O11640P-4 /)
137    {
138        $x = eval $str;
139        is($x, "314", "octal floating point literal $str");
140        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
141             "value is a Math::BigInt or Math::BigInt::Lite");
142    }
143
144    for my $str (qw/ 0o0.0p+8 0O0.0P+8
145                     0o0.0p8  0O0.0P8
146                     0o0.0p-8 0O0.0P-8 /)
147    {
148        $x = eval $str;
149        is($x, "0", "octal floating point literal $str");
150        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
151             "value is a Math::BigInt or Math::BigInt::Lite");
152    }
153}
154
155SKIP: {
156    # Octal floating point literals using the "0" prefix require v5.32.0.
157    skip "perl v5.32.0 required for octal floating point literals",
158      "6" * "2" + "6" * "2" if $] < "5.032";
159
160    for my $str (qw/ 01.164p+8 01.164P+8
161                     01.164p8  01.164P8
162                     011640p-4 011640P-4 /)
163    {
164        $x = eval $str;
165        is($x, "314", "octal floating point literal $str");
166        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
167             "value is a Math::BigInt or Math::BigInt::Lite");
168    }
169
170    for my $str (qw/ 00.0p+8 00.0P+8
171                     00.0p8 00.0P8
172                     00.0p-8 00.0P-8 /)
173    {
174        $x = eval $str;
175        is($x, "0", "octal floating point literal $str");
176        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
177             "value is a Math::BigInt or Math::BigInt::Lite");
178    }
179}
180
181SKIP: {
182    # Binary floating point literals require v5.32.0.
183    skip "perl v5.32.0 required for binary floating point literals",
184      "6" * "2" + "6" * "2" if $] < "5.032";
185
186    for my $str (qw/ 0b1.0011101p+8   0B1.0011101P+8
187                     0b1.0011101p8    0B1.0011101P8
188                     0b10011101000p-2 0B10011101000P-2 /)
189    {
190        $x = eval $str;
191        is($x, "314", "binary floating point literal $str");
192        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
193             "value is a Math::BigInt or Math::BigInt::Lite");
194    }
195
196    for my $str (qw/ 0b0p+8 0B0P+8
197                     0b0p8 0B0P8
198                     0b0p-8 0B0P-8
199                   /)
200    {
201        $x = eval $str;
202        is($x, "0", "binary floating point literal $str");
203        like(ref($x), qr/^Math::BigInt(::Lite)?$/,
204             "value is a Math::BigInt or Math::BigInt::Lite");
205    }
206}
207
208# These are handled by "integer".
209
210$x = 314;
211is($x, "314", "integer literal 314");
212like(ref($x), qr/^Math::BigInt(::Lite)?$/,
213     "value is a Math::BigInt or Math::BigInt::Lite");
214
215$x = 0;
216is($x, "0", "integer literal 0");
217like(ref($x), qr/^Math::BigInt(::Lite)?$/,
218     "value is a Math::BigInt or Math::BigInt::Lite");
219
220$x = 2 ** 255;
221is($x,
222   "578960446186580977117854925043439539266"
223   . "34992332820282019728792003956564819968",
224   "2 ** 255");
225like(ref($x), qr/^Math::BigInt(::Lite)?$/,
226     "value is a Math::BigInt or Math::BigInt::Lite");
227
228# These are handled by "binary".
229
230{
231    no warnings "portable";     # protect against "non-portable" warnings
232
233    # hexadecimal constant
234    $x = 0x123456789012345678901234567890;
235    is($x,
236       "94522879687365475552814062743484560",
237       "hexadecimal constant 0x123456789012345678901234567890");
238    like(ref($x), qr/^Math::BigInt(::Lite)?$/,
239         "value is a Math::BigInt or Math::BigInt::Lite");
240
241    # octal constant
242    $x = 012345676543210123456765432101234567654321;
243    is($x,
244       "1736132869400711976876385488263403729",
245       "octal constant 012345676543210123456765432101234567654321");
246    like(ref($x), qr/^Math::BigInt(::Lite)?$/,
247         "value is a Math::BigInt or Math::BigInt::Lite");
248
249    # binary constant
250    $x = 0b01010100011001010110110001110011010010010110000101101101;
251    is($x,
252       "23755414508757357",
253       "binary constant 0b0101010001100101011011000111"
254       . "0011010010010110000101101101");
255    like(ref($x), qr/^Math::BigInt(::Lite)?$/,
256         "value is a Math::BigInt or Math::BigInt::Lite");
257}
258
259################################################################################
260# The following tests are unique to $class.
261
262# These are handled by "float".
263
264$x = 0.999999999999999999999999999999999999999999999999999999999999999999999999;
265is($x,
266   "0.999999999999999999999999999999999999999999999999999999999999999999999999",
267   "decimal floating point literal 0." . ("9" x 72));
268is(ref($x), $class, "value is a $class");
269
270$x = 1e72 - 0.1;
271is($x,
272   "999999999999999999999999999999999999999999999999999999999999999999999999.9",
273   "literal 1e72 - 0.1");
274is(ref($x), $class, "value is a $class");
275
276# These are handled by "float".
277
278SKIP: {
279    # Hexadecimal floating point literals require v5.28.0.
280    skip "perl v5.22.0 required for hexadecimal floating point literals",
281      "6" * "2" if $] < "5.028";
282
283    for my $str (qw/ 0x1.92p+1 0X1.92P+1
284                     0x1.92p1 0X1.92P1
285                     0x19.2p-3 0X19.2P-3 /)
286    {
287        $x = eval $str;
288        is($x, "3.140625", "hexadecimal floating point literal $str");
289        is(ref($x), $class, "value is a $class");
290    }
291}
292
293SKIP: {
294    # Octal floating point literals using the "0o" prefix require v5.34.0.
295    skip "perl v5.34.0 required for octal floating point literals"
296      . " with '0o' prefix", "6" * "2" if $] < "5.034";
297
298    for my $str (qw/ 0o1.444p+1 0O1.444P+1
299                     0o1.444p1  0O1.444P1
300                     0o14.44p-2 0O14.44P-2 /)
301    {
302        $x = eval $str;
303        is($x, "3.140625", "octal floating point literal $str");
304        is(ref($x), $class, "value is a $class");
305    }
306}
307
308SKIP: {
309    # Octal floating point literals using the "0" prefix require v5.32.0.
310    skip "perl v5.32.0 required for octal floating point literals",
311      "6" * "2" if $] < "5.032";
312
313    for my $str (qw/ 01.444p+1 01.444P+1
314                     01.444p1  01.444P1
315                     014.44p-2 014.44P-2 /)
316    {
317        $x = eval $str;
318        is($x, "3.140625", "octal floating point literal $str");
319        is(ref($x), $class, "value is a $class");
320    }
321}
322
323SKIP: {
324    # Binary floating point literals require v5.32.0.
325    skip "perl v5.32.0 required for binary floating point literals",
326      "6" * "2" if $] < "5.032";
327
328    for my $str (qw/ 0b1.1001001p+1 0B1.1001001P+1
329                     0b1.1001001p1  0B1.1001001P1
330                     0b110.01001p-1 0B110.01001P-1 /)
331    {
332        $x = eval $str;
333        is($x, "3.140625", "binary floating point literal $str");
334        is(ref($x), $class, "value is a $class");
335    }
336}
337
338is(1.0 / 3.0, "0.3333333333333333333333333333333333333333",
339   "1.0 / 3.0 = 0.3333333333333333333333333333333333333333");
340