1# -*- mode: perl; -*-
2
3use strict;
4use warnings;
5
6use Test::More tests => 97;
7
8my $scalar_util_ok = eval { require Scalar::Util; };
9Scalar::Util -> import('refaddr') if $scalar_util_ok;
10
11diag "Skipping some tests since Scalar::Util is not installed."
12  unless $scalar_util_ok;
13
14my $class;
15
16BEGIN { $class = 'Math::BigInt'; }
17BEGIN { use_ok($class) }
18
19while (<DATA>) {
20    s/#.*$//;                   # remove comments
21    s/\s+$//;                   # remove trailing whitespace
22    next unless length;         # skip empty lines
23
24    # $in0 - the x value
25    # $in1 - the base
26    # $out0 - the wanted output value
27    # $type - the type of the wanted number (real, non-real, ...)
28    # $expr - mathematical expression of the wanted number
29
30    my ($in0, $in1, $out0, $type, $expr) = split /:/;
31
32    # Some of the test data use rational numbers.
33    # - with Math::BigInt, we skip them
34    # - with Math::BigFloat, we convert them to floats
35    # - with Math::BigRat, we use them as they are
36
37    next if ($in0  =~ m|/| ||
38             $in1  =~ m|/| ||
39             $out0 =~ m|/|);
40
41    my ($x, $y);        # input values as objects
42    my ($yo);           # copy of input value
43    my ($got);          # test output
44
45    my $test = qq|\$x = $class -> new("$in0"); | .
46               qq|\$y = $class -> new("$in1"); | .
47               qq|\$yo = \$y -> copy(); | .
48               qq|\$got = \$x -> blog(\$y);|;
49
50    my $desc = "logarithm of $in0 to base $in1";
51
52    print("#\n",
53          "# Now about to execute the following test.\n",
54          "#\n",
55          "# $test\n",
56          "#\n");
57
58    if ($in0 ne 'NaN' && $in1 ne 'NaN') {
59        print("# Enter log($in1, $in0) into Wolfram Alpha",
60              " (http://www.wolframalpha.com/), and it says that the result",
61              " is ", length($type) ? $type : "real",
62              length($expr) ? ": $expr" : "",
63              ".", "\n",
64              "#\n");
65    }
66
67    eval $test;
68    die $@ if $@;       # this should never happen
69
70    subtest $desc, sub {
71        plan tests => 5;
72
73        # Check output.
74
75        is(ref($got), $class, "output arg is a $class");
76        is($got, $out0, 'output arg has the right value');
77
78      SKIP: {
79            skip "Scalar::Util not available", 1 unless $scalar_util_ok;
80
81            is(refaddr($got), refaddr($x), 'output arg is the invocand');
82        }
83
84        # The second argument (if the invocand is the first) shall *not* be
85        # modified.
86
87        is(ref($y), $class, "second input arg is still a $class");
88        is_deeply($y, $yo, 'second input arg is unmodified');
89    };
90}
91
92__END__
93
94# base = -inf
95
96-inf:-inf:NaN:undefined:
97-4:-inf:0::
98-2:-inf:0::
99-1:-inf:0::
100-1/2:-inf:0::
1010:-inf:NaN:undefined:
1021/2:-inf:0::
1031:-inf:0::
1042:-inf:0::
1054:-inf:0::
106inf:-inf:NaN:undefined:
107NaN:-inf:NaN:undefined:
108
109# base = -4
110
111-4:-4:1::
112-2:-4:NaN:non-real and finite:(log(2)+i pi)/(log(4)+i pi)
1130:-4:NaN:non-real (directed) infinity:(-sqrt(pi^2+log^2(4))/(log(4)+i pi))infinity
1141/2:-4:NaN:non-real and finite:-(log(2))/(log(4)+i pi)
1151:-4:0::
1162:-4:NaN:non-real and finite:(log(2))/(log(4)+i pi)
1174:-4:NaN:non-real and finite:(log(4))/(log(4)+i pi)
118NaN:-4:NaN:undefined:
119
120# base = -2
121
122-inf:-2:NaN:non-real (directed) infinity:sqrt(pi^2+log^2(2))/(log(2)+i pi)infinity
123-4:-2:NaN:non-real and finite:(log(4)+i pi)/(log(2)+i pi)
124-2:-2:1::
125-1:-2:NaN:non-real and finite:(i pi)/(log(2)+i pi)
126-1/2:-2:NaN:non-real and finite:(-log(2)+i pi)/(log(2)+i pi)
1270:-2:NaN:complex infinity:
1281/2:-2:NaN:non-real and finite:-(log(2))/(log(2)+i pi)
1291:-2:0::
1302:-2:NaN:non-real and finite:(log(2))/(log(2)+i pi)
1314:-2:NaN:non-real and finite:(log(4))/(log(2)+i pi)
132inf:-2:NaN:non-real (directed) infinity:
133NaN:-2:NaN:undefined:
134
135# base = -1
136
137-inf:-1:NaN:non-real (directed) infinity:
138-4:-1:NaN:non-real and finite:-(i (log(4)+i pi))/pi
139-2:-1:NaN:non-real and finite:-(i (log(2)+i pi))/pi
140-1:-1:1::
141-1/2:-1:NaN:non-real and finite:-(i (-log(2)+i pi))/pi
1420:-1:NaN:complex infinity:
1431:-1:0::
1441/2:-1:NaN:non-real and finite:(i log(2))/pi
1452:-1:NaN:non-real and finite:-(i log(2))/pi
1464:-1:NaN:non-real and finite:-(i log(4))/pi
147inf:-1:NaN:non-real (directed) infinity:
148NaN:-1:NaN:undefined:
149
150# base = -1/2
151
152-inf:-1/2:NaN:non-real (directed) infinity:
153-4:-1/2:NaN:non-real and finite:(log(4)+i pi)/(-log(2)+i pi)
154-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
155-1:-1/2:NaN:non-real and finite:(i pi)/(-log(2)+i pi)
156-1/2:-1/2:1::
1570:-1/2:NaN:complex infinity:
1581:-1/2:0::
1591/2:-1/2:NaN:non-real and finite:-(log(2))/(-log(2)+i pi)
1602:-1/2:NaN:non-real and finite:(log(2))/(-log(2)+i pi)
1614:-1/2:NaN:non-real and finite:(log(4))/(-log(2)+i pi)
162inf:-1/2:NaN:non-real (directed) infinity:
163NaN:-1/2:NaN:undefined:
164
165# base = 0
166
167-inf:0:NaN:undefined:
168-4:0:0::
169-2:0:0::
170-1:0:0::
171-1/2:0:0::
1720:0:NaN:undefined:
1731/2:0:0::
1741:0:0::
1752:0:0::
1764:0:0::
177inf:0:NaN:undefined:
178NaN:0:NaN:undefined:
179
180# base = 1/2
181
182-inf:1/2:-inf::
183-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
184-1:1/2:NaN:non-real and finite:-(i pi)/(log(2))
185-1/2:1/2:NaN:non-real and finite:-(-log(2)+i pi)/(log(2))
1860:1/2:inf::
1871/2:1/2:1::
1881:1/2:0::
1892:1/2:-1::
190inf:1/2:-inf::
191NaN:1/2:NaN:undefined:
192
193# base = 1
194
195-inf:1:NaN:complex infinity:
196-4:1:NaN:complex infinity:
197-2:1:NaN:complex infinity:
198-1:1:NaN:complex infinity:
199-1/2:1:NaN:complex infinity:
2000:1:NaN:complex infinity:
2011/2:1:NaN:complex infinity:
2021:1:NaN:undefined:
2032:1:NaN:complex infinity:
2044:1:NaN:complex infinity:
205inf:1:NaN:complex infinity:
206NaN:1:NaN:undefined:
207
208# base = 2
209
210-inf:2:inf::
211-4:2:NaN:non-real and finite:(log(4)+i pi)/(log(2))
212-2:2:NaN:non-real and finite:(log(2)+i pi)/(log(2))
213-1:2:NaN:non-real and finite:(i pi)/(log(2))
214-1/2:2:NaN:non-real and finite:(-log(2)+i pi)/(log(2))
2150:2:-inf::
2161/2:2:-1::
2171:2:0::
2182:2:1::
2194:2:2::
2204:4:1::
221inf:2:inf::
222NaN:2:NaN:undefined:
223
224# base = 4
225
226-inf:4:inf::
227-4:4:NaN:non-real and finite:(log(4)+i pi)/(log(4))
228-2:4:NaN:non-real and finite:(log(2)+i pi)/(log(4))
229-1/2:4:NaN:non-real and finite:(-log(2)+i pi)/(log(4))
2300:4:-inf::
2311:4:0::
2321/2:4:-1/2::
2332:4:1/2::
2344:4:1::
235inf:4:inf::
236NaN:4:NaN:undefined:
237
238# base = inf
239
240-inf:inf:NaN:undefined:
241-4:inf:0::
242-2:inf:0::
243-1:inf:0::
244-1/2:inf:0::
2450:inf:NaN:undefined:
2461:inf:0::
2471/2:inf:0::
2482:inf:0::
2494:inf:0::
250inf:inf:NaN:undefined:
251NaN:inf:NaN:undefined:
252
253# base is NaN
254
255-inf:NaN:NaN:undefined:
256-4:NaN:NaN:undefined:
257-2:NaN:NaN:undefined:
258-1:NaN:NaN:undefined:
259-1/2:NaN:NaN:undefined:
2600:NaN:NaN:undefined:
2611:NaN:NaN:undefined:
2621/2:NaN:NaN:undefined:
2632:NaN:NaN:undefined:
2644:NaN:NaN:undefined:
265inf:NaN:NaN:undefined:
266NaN:NaN:NaN:undefined:
267