This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
More robust inf/nan recognition and generation.
[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 $inf_tests = 9 + 3 * @PInf + 3 * @NInf + 5;
26 my $nan_tests = 7 + 2 * @NaN + 3;
27
28 my $infnan_tests = 4;
29
30 plan tests => $inf_tests + $nan_tests + $infnan_tests;
31
32 my $has_inf;
33 my $has_nan;
34
35 SKIP: {
36   if ($PInf == 1 && $NInf == 1) {
37     skip $inf_tests, "no infinity found";
38   }
39
40   $has_inf = 1;
41
42   cmp_ok($PInf, '>', 0, "positive infinity");
43   cmp_ok($NInf, '<', 0, "negative infinity");
44
45   cmp_ok($PInf, '>', $NInf, "positive > negative");
46   cmp_ok($NInf, '==', -$PInf, "negative == -positive");
47   cmp_ok(-$NInf, '==', $PInf, "--negative == positive");
48
49   is($PInf,  "Inf", "$PInf value stringifies as Inf");
50   is($NInf, "-Inf", "$NInf value stringifies as -Inf");
51
52   is(sprintf("%g", $PInf), "Inf", "$PInf sprintf %g is Inf");
53   is(sprintf("%a", $PInf), "Inf", "$PInf sprintf %a is Inf");
54
55   for my $i (@PInf) {
56     cmp_ok($i + 0 , '==', $PInf, "$i is +Inf");
57     cmp_ok($i, '>', 0, "$i is positive");
58     is("@{[$i+0]}", "Inf", "$i value stringifies as Inf");
59   }
60
61   for my $i (@NInf) {
62     cmp_ok($i + 0, '==', $NInf, "$i is -Inf");
63     cmp_ok($i, '<', 0, "$i is negative");
64     is("@{[$i+0]}", "-Inf", "$i value stringifies as -Inf");
65   }
66
67   is($PInf + $PInf, $PInf, "+inf plus +inf is +inf");
68   is($NInf + $NInf, $NInf, "-inf plus -inf is -inf");
69
70   is(1/$PInf, 0, "one per +Inf is zero");
71   is(1/$NInf, 0, "one per -Inf is zero");
72
73   is(9**9**9, $PInf, "9**9**9 is Inf");
74 }
75
76 SKIP: {
77   if ($NaN == 1) {
78     skip $nan_tests, "no nan found";
79   }
80
81   $has_nan = 1;
82
83   cmp_ok($NaN, '!=', $NaN, "NaN is NaN numerically (by not being NaN)");
84   ok($NaN eq $NaN, "NaN is NaN stringifically");
85
86   is("$NaN", "NaN", "$NaN value stringies as NaN");
87
88   is("+NaN" + 0, "NaN", "+NaN is NaN");
89   is("-NaN" + 0, "NaN", "-NaN is NaN");
90
91   is(sprintf("%g", $NaN), "NaN", "$NaN sprintf %g is NaN");
92   is(sprintf("%a", $NaN), "NaN", "$NaN sprintf %a is NaN");
93
94   for my $i (@NaN) {
95     cmp_ok($i + 0, '!=', $i + 0, "$i is NaN numerically (by not being NaN)");
96     is("@{[$i+0]}", "NaN", "$i value stringifies as NaN");
97   }
98
99   # is() okay with $NaN because it uses eq.
100   is($NaN * 0, $NaN, "NaN times zero is NaN");
101   is($NaN * 2, $NaN, "NaN times two is NaN");
102
103   is(sin(9**9**9), $NaN, "sin(9**9**9) is NaN");
104 }
105
106 SKIP: {
107   unless ($has_inf && $has_nan) {
108     skip $infnan_tests, "no both Inf and Nan";
109   }
110
111   # is() okay with $NaN because it uses eq.
112   is($PInf * 0,     $NaN, "Inf times zero is NaN");
113   is($PInf * $NaN,  $NaN, "Inf times NaN is NaN");
114   is($PInf + $NaN,  $NaN, "Inf plus NaN is NaN");
115   is($PInf - $PInf, $NaN, "Inf minus inf is NaN");
116 }