This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pack c/C on inf/nan.
[perl5.git] / t / op / infnan.t
1 #!./perl -w
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     require './test.pl';
7 }
8
9 use strict;
10
11 my $PInf = "Inf"  + 0;
12 my $NInf = "-Inf" + 0;
13 my $NaN  = "NaN"  + 0;
14
15 my @PInf = ("Inf", "inf", "INF", "+Inf",
16             "Infinity", "INFINITE",
17             "1.#INF", "1#INF");
18 my @NInf = map { "-$_" } grep { ! /^\+/ } @PInf;
19
20 my @NaN = ("NAN", "nan", "qnan", "SNAN", "NanQ", "NANS",
21            "1.#QNAN", "+1#SNAN", "-1.#NAN", "1#IND",
22            "NaN123", "NAN(123)", "nan%",
23            "nanonano"); # RIP, Robin Williams.
24
25 my @num_fmt = qw(e f g a d u o b x p);
26
27 my $inf_tests = 11 + @num_fmt + 8 + 3 * @PInf + 3 * @NInf + 5 + 3;
28 my $nan_tests =  7 + @num_fmt + 4 + 2 * @NaN + 3;
29
30 my $infnan_tests = 4;
31
32 plan tests => $inf_tests + $nan_tests + $infnan_tests;
33
34 my $has_inf;
35 my $has_nan;
36
37 SKIP: {
38   if ($PInf == 1 && $NInf == 1) {
39     skip $inf_tests, "no infinity found";
40   }
41
42   $has_inf = 1;
43
44   cmp_ok($PInf, '>', 0, "positive infinity");
45   cmp_ok($NInf, '<', 0, "negative infinity");
46
47   cmp_ok($PInf, '>', $NInf, "positive > negative");
48   cmp_ok($NInf, '==', -$PInf, "negative == -positive");
49   cmp_ok(-$NInf, '==', $PInf, "--negative == positive");
50
51   is($PInf,  "Inf", "$PInf value stringifies as Inf");
52   is($NInf, "-Inf", "$NInf value stringifies as -Inf");
53
54   cmp_ok($PInf * 2, '==', $PInf, "twice Inf is Inf");
55   cmp_ok($PInf / 2, '==', $PInf, "half of Inf is Inf");
56
57   is(sprintf("%g", $PInf), "Inf", "$PInf sprintf %g is Inf");
58   is(sprintf("%a", $PInf), "Inf", "$PInf sprintf %a is Inf");
59
60   for my $f (@num_fmt) {
61       is(sprintf("%$f", $PInf), "Inf", "$PInf sprintf %$f is Inf");
62   }
63
64   {
65       local $^W = 0;
66
67       is(sprintf("%c", $PInf), chr(0xFFFD), "$PInf sprintf %c is Inf");
68       is(chr($PInf), chr(0xFFFD), "$PInf chr() is U+FFFD");
69
70       is(sprintf("%c", $NInf), chr(0xFFFD), "$NInf sprintf %c is Inf");
71       is(chr($NInf), chr(0xFFFD), "$NInf chr() is U+FFFD");
72
73       is(pack('C', $PInf), chr(0xFF), "$PInf pack C is 0xFF byte");
74       is(pack('c', $PInf), chr(0xFF), "$PInf pack c is 0xFF byte");
75
76       is(pack('C', $NInf), chr(0xFF), "$NInf pack C is 0xFF byte");
77       is(pack('c', $NInf), chr(0xFF), "$NInf pack c is 0xFF byte");
78   }
79
80   for my $i (@PInf) {
81     cmp_ok($i + 0 , '==', $PInf, "$i is +Inf");
82     cmp_ok($i, '>', 0, "$i is positive");
83     is("@{[$i+0]}", "Inf", "$i value stringifies as Inf");
84   }
85
86   for my $i (@NInf) {
87     cmp_ok($i + 0, '==', $NInf, "$i is -Inf");
88     cmp_ok($i, '<', 0, "$i is negative");
89     is("@{[$i+0]}", "-Inf", "$i value stringifies as -Inf");
90   }
91
92   is($PInf + $PInf, $PInf, "+inf plus +inf is +inf");
93   is($NInf + $NInf, $NInf, "-inf plus -inf is -inf");
94
95   is(1/$PInf, 0, "one per +Inf is zero");
96   is(1/$NInf, 0, "one per -Inf is zero");
97
98   is(9**9**9, $PInf, "9**9**9 is Inf");
99 }
100
101 {
102     # Silence "isn't numeric in addition", that's kind of the point.
103     local $^W = 0;
104     for my $i (qw(Info Infiniti Infinityz)) {
105         cmp_ok("$i" + 0, '==', 0, "false infinity $i");
106     }
107 }
108
109 SKIP: {
110   if ($NaN == 1) {
111     skip $nan_tests, "no nan found";
112   }
113
114   $has_nan = 1;
115
116   cmp_ok($NaN, '!=', $NaN, "NaN is NaN numerically (by not being NaN)");
117   ok($NaN eq $NaN, "NaN is NaN stringifically");
118
119   is("$NaN", "NaN", "$NaN value stringifies as NaN");
120
121   is("+NaN" + 0, "NaN", "+NaN is NaN");
122   is("-NaN" + 0, "NaN", "-NaN is NaN");
123
124   is($NaN * 2, $NaN, "twice NaN is NaN");
125   is($NaN / 2, $NaN, "half of NaN is NaN");
126
127   for my $f (@num_fmt) {
128       is(sprintf("%$f", $NaN), "NaN", "$NaN sprintf %$f is NaN");
129   }
130
131   {
132       local $^W = 0;
133
134       is(sprintf("%c", $NaN), chr(0xFFFD), "$NaN sprintf %c is Inf");
135       is(chr($NaN), chr(0xFFFD), "$NaN chr() is U+FFFD");
136
137       is(pack('C', $NaN), chr(0xFF), "$NaN pack C is 0xFF byte");
138       is(pack('c', $NaN), chr(0xFF), "$NaN pack c is 0xFF");
139   }
140
141   for my $i (@NaN) {
142     cmp_ok($i + 0, '!=', $i + 0, "$i is NaN numerically (by not being NaN)");
143     is("@{[$i+0]}", "NaN", "$i value stringifies as NaN");
144   }
145
146   # is() okay with $NaN because it uses eq.
147   is($NaN * 0, $NaN, "NaN times zero is NaN");
148   is($NaN * 2, $NaN, "NaN times two is NaN");
149
150   is(sin(9**9**9), $NaN, "sin(9**9**9) is NaN");
151 }
152
153 SKIP: {
154   unless ($has_inf && $has_nan) {
155     skip $infnan_tests, "no both Inf and Nan";
156   }
157
158   # is() okay with $NaN because it uses eq.
159   is($PInf * 0,     $NaN, "Inf times zero is NaN");
160   is($PInf * $NaN,  $NaN, "Inf times NaN is NaN");
161   is($PInf + $NaN,  $NaN, "Inf plus NaN is NaN");
162   is($PInf - $PInf, $NaN, "Inf minus inf is NaN");
163 }