1# -*- mode: perl; -*-
2
3use strict;
4use warnings;
5
6use Test::More tests => 139;
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::BigFloat'; }
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    $in0  = eval $in0  if $in0  =~ m|/|;
38    $in1  = eval $in1  if $in1  =~ m|/|;
39    $out0 = eval $out0 if $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
93__END__
94
95# base = -inf
96
97-inf:-inf:NaN:undefined:
98-4:-inf:0::
99-2:-inf:0::
100-1:-inf:0::
101-1/2:-inf:0::
1020:-inf:NaN:undefined:
1031/2:-inf:0::
1041:-inf:0::
1052:-inf:0::
1064:-inf:0::
107inf:-inf:NaN:undefined:
108NaN:-inf:NaN:undefined:
109
110# base = -4
111
112-4:-4:1::
113-2:-4:NaN:non-real and finite:(log(2)+i pi)/(log(4)+i pi)
1140:-4:NaN:non-real (directed) infinity:(-sqrt(pi^2+log^2(4))/(log(4)+i pi))infinity
1151/2:-4:NaN:non-real and finite:-(log(2))/(log(4)+i pi)
1161:-4:0::
1172:-4:NaN:non-real and finite:(log(2))/(log(4)+i pi)
1184:-4:NaN:non-real and finite:(log(4))/(log(4)+i pi)
119NaN:-4:NaN:undefined:
120
121# base = -2
122
123-inf:-2:NaN:non-real (directed) infinity:sqrt(pi^2+log^2(2))/(log(2)+i pi)infinity
124-4:-2:NaN:non-real and finite:(log(4)+i pi)/(log(2)+i pi)
125-2:-2:1::
126-1:-2:NaN:non-real and finite:(i pi)/(log(2)+i pi)
127-1/2:-2:NaN:non-real and finite:(-log(2)+i pi)/(log(2)+i pi)
1280:-2:NaN:complex infinity:
1291/2:-2:NaN:non-real and finite:-(log(2))/(log(2)+i pi)
1301:-2:0::
1312:-2:NaN:non-real and finite:(log(2))/(log(2)+i pi)
1324:-2:NaN:non-real and finite:(log(4))/(log(2)+i pi)
133inf:-2:NaN:non-real (directed) infinity:
134NaN:-2:NaN:undefined:
135
136# base = -1
137
138-inf:-1:NaN:non-real (directed) infinity:
139-4:-1:NaN:non-real and finite:-(i (log(4)+i pi))/pi
140-2:-1:NaN:non-real and finite:-(i (log(2)+i pi))/pi
141-1:-1:1::
142-1/2:-1:NaN:non-real and finite:-(i (-log(2)+i pi))/pi
1430:-1:NaN:complex infinity:
1441:-1:0::
1451/2:-1:NaN:non-real and finite:(i log(2))/pi
1462:-1:NaN:non-real and finite:-(i log(2))/pi
1474:-1:NaN:non-real and finite:-(i log(4))/pi
148inf:-1:NaN:non-real (directed) infinity:
149NaN:-1:NaN:undefined:
150
151# base = -1/2
152
153-inf:-1/2:NaN:non-real (directed) infinity:
154-4:-1/2:NaN:non-real and finite:(log(4)+i pi)/(-log(2)+i pi)
155-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
156-1:-1/2:NaN:non-real and finite:(i pi)/(-log(2)+i pi)
157-1/2:-1/2:1::
1580:-1/2:NaN:complex infinity:
1591:-1/2:0::
1601/2:-1/2:NaN:non-real and finite:-(log(2))/(-log(2)+i pi)
1612:-1/2:NaN:non-real and finite:(log(2))/(-log(2)+i pi)
1624:-1/2:NaN:non-real and finite:(log(4))/(-log(2)+i pi)
163inf:-1/2:NaN:non-real (directed) infinity:
164NaN:-1/2:NaN:undefined:
165
166# base = 0
167
168-inf:0:NaN:undefined:
169-4:0:0::
170-2:0:0::
171-1:0:0::
172-1/2:0:0::
1730:0:NaN:undefined:
1741/2:0:0::
1751:0:0::
1762:0:0::
1774:0:0::
178inf:0:NaN:undefined:
179NaN:0:NaN:undefined:
180
181# base = 1/2
182
183-inf:1/2:-inf::
184-2:-1/2:NaN:non-real and finite:(log(2)+i pi)/(-log(2)+i pi)
185-1:1/2:NaN:non-real and finite:-(i pi)/(log(2))
186-1/2:1/2:NaN:non-real and finite:-(-log(2)+i pi)/(log(2))
1870:1/2:inf::
1881/2:1/2:1::
1891:1/2:0::
1902:1/2:-1::
191inf:1/2:-inf::
192NaN:1/2:NaN:undefined:
193
194# base = 1
195
196-inf:1:NaN:complex infinity:
197-4:1:NaN:complex infinity:
198-2:1:NaN:complex infinity:
199-1:1:NaN:complex infinity:
200-1/2:1:NaN:complex infinity:
2010:1:NaN:complex infinity:
2021/2:1:NaN:complex infinity:
2031:1:NaN:undefined:
2042:1:NaN:complex infinity:
2054:1:NaN:complex infinity:
206inf:1:NaN:complex infinity:
207NaN:1:NaN:undefined:
208
209# base = 2
210
211-inf:2:inf::
212-4:2:NaN:non-real and finite:(log(4)+i pi)/(log(2))
213-2:2:NaN:non-real and finite:(log(2)+i pi)/(log(2))
214-1:2:NaN:non-real and finite:(i pi)/(log(2))
215-1/2:2:NaN:non-real and finite:(-log(2)+i pi)/(log(2))
2160:2:-inf::
2171/2:2:-1::
2181:2:0::
2192:2:1::
2204:2:2::
2214:4:1::
222inf:2:inf::
223NaN:2:NaN:undefined:
224
225# base = 4
226
227-inf:4:inf::
228-4:4:NaN:non-real and finite:(log(4)+i pi)/(log(4))
229-2:4:NaN:non-real and finite:(log(2)+i pi)/(log(4))
230-1/2:4:NaN:non-real and finite:(-log(2)+i pi)/(log(4))
2310:4:-inf::
2321:4:0::
2331/2:4:-1/2::
2342:4:1/2::
2354:4:1::
236inf:4:inf::
237NaN:4:NaN:undefined:
238
239# base = inf
240
241-inf:inf:NaN:undefined:
242-4:inf:0::
243-2:inf:0::
244-1:inf:0::
245-1/2:inf:0::
2460:inf:NaN:undefined:
2471:inf:0::
2481/2:inf:0::
2492:inf:0::
2504:inf:0::
251inf:inf:NaN:undefined:
252NaN:inf:NaN:undefined:
253
254# base is NaN
255
256-inf:NaN:NaN:undefined:
257-4:NaN:NaN:undefined:
258-2:NaN:NaN:undefined:
259-1:NaN:NaN:undefined:
260-1/2:NaN:NaN:undefined:
2610:NaN:NaN:undefined:
2621:NaN:NaN:undefined:
2631/2:NaN:NaN:undefined:
2642:NaN:NaN:undefined:
2654:NaN:NaN:undefined:
266inf:NaN:NaN:undefined:
267NaN:NaN:NaN:undefined:
268