#!/usr/bin/env perl6

use Test;
use lib 'lib';
use Math::Libgsl::Function :ALL;
use Math::Libgsl::Constants;

subtest {
  is-approx Ai(0, GSL_PREC_DOUBLE), 0.355028053887817, :rel-tol(10⁻¹⁵), 'Ai';
  my ($val, $err);
  lives-ok { ($val, $err) = Ai-e(0, GSL_PREC_DOUBLE) }, 'Ai with error check';
  is-approx $val, 0.355028053887817, :rel-tol(10⁻¹⁵), 'Ai: value';
  ok $err < 10⁻¹⁶, 'Ai: error';
  is-approx Bi(0, GSL_PREC_DOUBLE), 0.614926627446001, :rel-tol(10⁻¹⁵), 'Bi';
  lives-ok { ($val, $err) = Bi-e(0, GSL_PREC_DOUBLE) }, 'Bi with error check';
  is-approx $val, 0.614926627446001, :rel-tol(10⁻¹⁵), 'Bi: value';
  ok $err < 10⁻¹⁵, 'Bi: error';
  is-approx Ai-scaled(10, GSL_PREC_DOUBLE), 0.158123666854346, :rel-tol(10⁻¹⁵), 'Ai scaled';
  lives-ok { ($val, $err) = Ai-scaled-e(10, GSL_PREC_DOUBLE) }, 'Ai scaled with error check';
  is-approx $val, 0.158123666854346, :rel-tol(10⁻¹⁵), 'Ai scaled: value';
  is-approx Bi-scaled(10, GSL_PREC_DOUBLE), 0.318340105336734, 10⁻¹⁵, 'Bi scaled';
  lives-ok { ($val, $err) = Bi-scaled-e(10, GSL_PREC_DOUBLE) }, 'Bi scaled with error check';
  is-approx $val, 0.318340105336734, 10⁻¹⁵, 'Bi scaled: value';
  is-approx Ai-deriv(0, GSL_PREC_DOUBLE), -0.258819403792807, :rel-tol(10⁻¹⁵), 'Ai deriv';
  lives-ok { ($val, $err) = Ai-deriv-e(0, GSL_PREC_DOUBLE) }, 'Ai deriv with error check';
  is-approx $val, -0.258819403792807, :rel-tol(10⁻¹⁵), 'Ai deriv: value';
  is-approx Bi-deriv(0, GSL_PREC_DOUBLE), 0.448288357353826, :rel-tol(10⁻¹⁵), 'Bi deriv';
  lives-ok { ($val, $err) = Bi-deriv-e(0, GSL_PREC_DOUBLE) }, 'Bi deriv with error check';
  is-approx $val, 0.448288357353826, :rel-tol(10⁻¹⁵), 'Bi deriv: value';
  is-approx Ai-deriv-scaled(10, GSL_PREC_DOUBLE), -0.503909360711311, :rel-tol(10⁻¹⁵), 'Ai deriv scaled';
  lives-ok { ($val, $err) = Ai-deriv-scaled-e(10, GSL_PREC_DOUBLE) }, 'Ai deriv scaled with error check';
  is-approx $val, -0.503909360711311, :rel-tol(10⁻¹⁵), 'Ai deriv scaled: value';
  is-approx Bi-deriv-scaled(10, GSL_PREC_DOUBLE), 0.998555942673837, :rel-tol(10⁻¹⁵), 'Bi deriv scaled';
  lives-ok { ($val, $err) = Bi-deriv-scaled-e(10, GSL_PREC_DOUBLE) }, 'Bi deriv scaled with error check';
  is-approx $val, 0.998555942673837, :rel-tol(10⁻¹⁵), 'Bi deriv scaled: value';
  is-approx Ai-zero(1), -2.338107410459767, :rel-tol(10⁻¹⁵), 'zero of Ai';
  lives-ok { ($val, $err) = Ai-zero-e(1) }, 'zero of Ai with error check';
  is-approx $val, -2.338107410459767, :rel-tol(10⁻¹⁵), 'zero of Ai: value';
  is-approx Bi-zero(1), -1.173713222709128, 10⁻¹⁵, 'zero of Bi';
  lives-ok { ($val, $err) = Bi-zero-e(1) }, 'zero of Bi with error check';
  is-approx $val, -1.173713222709128, 10⁻¹⁵, 'zero of Bi: value';
  is-approx Ai-deriv-zero(1), -1.018792971647471, :rel-tol(10⁻¹⁵), 'zero of Ai deriv';
  lives-ok { ($val, $err) = Ai-deriv-zero-e(1) }, 'zero of Ai deriv with error check';
  is-approx $val, -1.018792971647471, :rel-tol(10⁻¹⁵), 'zero of Ai deriv: value';
  is-approx Bi-deriv-zero(1), -2.294439682614123, 10⁻¹⁵, 'zero of Bi deriv';
  lives-ok { ($val, $err) = Bi-deriv-zero-e(1) }, 'zero of Bi deriv with error check';
  is-approx $val, -2.294439682614123, 10⁻¹⁵, 'zero of Bi deriv: value';
}, 'Airy functions';

subtest {
  my ($val, $err);
  ok J0(0) == 1, 'J0';
  lives-ok { ($val, $err) = J0-e(2) }, 'J0 with error check';
  is-approx $val, 0.223890779141236, 10⁻¹⁴, 'J0 with error check: value';
  ok J1(0) == 0, 'J1';
  lives-ok { ($val, $err) = J1-e(2) }, 'J1 with error check';
  is-approx $val, 0.576724807756873, 10⁻¹⁴, 'J1 with error check: value';
  ok Jn(2, 0) == 0, 'Jn';
  lives-ok { ($val, $err) = Jn-e(4, .1) }, 'Jn with error check';
  is-approx $val, 2.602864854568404e-07, 10⁻¹⁵, 'Jn with error check: value';
  my @out;
  lives-ok { @out = Jn-array(0, 2, 0) }, 'Jn array';
  is-deeply @out, [1e0, 0e0, 0e0], 'Jn array: values';
  ok Y0(.1) == -1.534238651350367, 'Y0';
  lives-ok { ($val, $err) = Y0-e(.1) }, 'Y0 with error check';
  is-approx $val, -1.534238651350367, 10⁻¹⁴, 'Y0 with error check: value';
  is-approx Y1(.1), -6.458951094702026, 10⁻¹⁴, 'Y1';
  lives-ok { ($val, $err) = Y1-e(.1) }, 'Y1 with error check';
  is-approx $val, -6.458951094702026, 10⁻¹⁴, 'Y1 with error check: value';
  is-approx Yn(4, .1), -305832.2979335312, 10⁻¹⁴, 'Yn';
  lives-ok { ($val, $err) = Yn-e(4, .1) }, 'Yn with error check';
  is-approx $val, -305832.2979335312, 10⁻¹⁴, 'Yn with error check: value';
  lives-ok { @out = Yn-array(0, 2, .1) }, 'Yn array';
  is-deeply @out».round(10⁻¹⁵), [-1.534238651350367, -6.458951094702026, -127.644783242690176], 'Yn array: values';
  is-approx I0(.1), 1.002501562934096, 10⁻¹⁴, 'I0';
  lives-ok { ($val, $err) = I0-e(.1) }, 'I0 with error check';
  is-approx $val, 1.002501562934096, 10⁻¹⁴, 'I0 with error check: value';
  is-approx I1(.1), 0.050062526047092694, 10⁻¹⁴, 'I1';
  lives-ok { ($val, $err) = I1-e(.1) }, 'I1 with error check';
  is-approx $val, 0.050062526047092694, 10⁻¹⁴, 'I1 with error check: value';
  is-approx In(-4, .1), 2.6054690212996574e-07, 10⁻¹⁴, 'In';
  lives-ok { ($val, $err) = In-e(-4, .1) }, 'In with error check';
  is-approx $val, 2.6054690212996574e-07, 10⁻¹⁴, 'In with error check: value';
  lives-ok { @out = In-array(0, 2, .1) }, 'In array';
  is-deeply @out».round(10⁻¹⁵), [1.002501562934096, 0.050062526047093, 0.001251041992242], 'In array: values';
  is-approx I0-scaled(.1), 0.9071009257823011, 10⁻¹⁴, 'I0 scaled';
  lives-ok { ($val, $err) = I0-scaled-e(.1) }, 'I0 scaled with error check';
  is-approx $val, 0.9071009257823011, 10⁻¹⁴, 'I0 scaled with error check: value';
  is-approx I1-scaled(.1), 0.045298446808809324, 10⁻¹⁴, 'I1 scaled';
  lives-ok { ($val, $err) = I1-scaled-e(.1) }, 'I1 scaled with error check';
  is-approx $val, 0.045298446808809324, 10⁻¹⁴, 'I1 scaled with error check: value';
  is-approx In-scaled(-4, .1), 2.3575258620054605e-07, 10⁻¹⁴, 'In scaled';
  lives-ok { ($val, $err) = In-scaled-e(-4, .1) }, 'In scaled with error check';
  is-approx $val, 2.3575258620054605e-07, 10⁻¹⁴, 'In scaled with error check: value';
  lives-ok { @out = In-scaled-array(0, 2, .1) }, 'In scaled array';
  is-deeply @out».round(10⁻¹⁵), [0.907100925782301, 0.045298446808809, 0.001131989606115], 'In scaled array: values';
  is-approx K0(.1), 2.427069024702017, 10⁻¹⁴, 'K0';
  lives-ok { ($val, $err) = K0-e(.1) }, 'K0 with error check';
  is-approx $val, 2.427069024702017, 10⁻¹⁴, 'K0 with error check: value';
  is-approx K1(.1), 9.853844780870606, 10⁻¹⁴, 'K1';
  lives-ok { ($val, $err) = K1-e(.1) }, 'K1 with error check';
  is-approx $val, 9.853844780870606, 10⁻¹⁴, 'K1 with error check: value';
  is-approx Kn(0, .1), 2.427069024702017, 10⁻¹⁴, 'Kn';
  lives-ok { ($val, $err) = Kn-e(0, .1) }, 'Kn with error check';
  is-approx $val, 2.427069024702017, 10⁻¹⁴, 'Kn with error check: value';
  lives-ok { @out = Kn-array(0, 2, .1) }, 'Kn array';
  is-deeply @out».round(10⁻¹⁵), [2.427069024702017, 9.853844780870606, 199.503964642114144], 'Kn array: values';
  is-approx K0-scaled(.1), 2.682326102262895, 10⁻¹⁴, 'K0 scaled';
  lives-ok { ($val, $err) = K0-scaled-e(.1) }, 'K0 scaled with error check';
  is-approx $val, 2.682326102262895, 10⁻¹⁴, 'K0 scaled with error check: value';
  is-approx K1-scaled(.1), 10.890182683049698, 10⁻¹⁴, 'K1 scaled';
  lives-ok { ($val, $err) = K1-scaled-e(.1) }, 'K1 scaled with error check';
  is-approx $val, 10.890182683049698, 10⁻¹⁴, 'K1 scaled with error check: value';
  is-approx Kn-scaled(5, 2), 69.68655087607676, :rel-tol(10⁻¹⁵), 'Kn scaled';
  lives-ok { ($val, $err) = Kn-scaled-e(5, 2) }, 'Kn scaled with error check';
  is-approx $val, 69.68655087607676, :rel-tol(10⁻¹⁵), 'Kn scaled with error check: value';
  lives-ok { @out = Kn-scaled-array(5, 8, 2) }, 'Kn scaled array';
  is-deeply @out».round(10⁻¹⁵), [69.68655087607676, 364.658500356566016, 2257.63755301547264, 16168.121371464876032], 'Kn scaled array: values';
  is-approx j0(1), 0.841470984807897, 10⁻¹⁴, 'j0';
  lives-ok { ($val, $err) = j0-e(1) }, 'j0 with error check';
  is-approx $val, 0.841470984807897, 10⁻¹⁴, 'j0 with error check: value';
  is-approx j1(1), 0.301168678939757, 10⁻¹⁴, 'j1';
  lives-ok { ($val, $err) = j1-e(1) }, 'j1 with error check';
  is-approx $val, 0.301168678939757, 10⁻¹⁴, 'j1 with error check: value';
  is-approx j2(1), 0.06203505201137386, 10⁻¹⁴, 'j2';
  lives-ok { ($val, $err) = j2-e(1) }, 'j2 with error check';
  is-approx $val, 0.06203505201137386, 10⁻¹⁴, 'j2 with error check: value';
  is-approx jl(0, 0), 1, 10⁻¹⁴, 'jl';
  lives-ok { ($val, $err) = jl-e(0, 0) }, 'jl with error check';
  is-approx $val, 1, 10⁻¹⁴, 'jl with error check: value';
  lives-ok { @out = jl-array(2, 0) }, 'jl array';
  is-deeply @out».round(10⁻¹⁵), [1.0, 0.0, 0.0], 'jl array: values';
  lives-ok { @out = jl-steed-array(2, 0) }, 'jl steed array';
  is-deeply @out».round(10⁻¹⁵), [1.0, 0.0, 0.0], 'jl steed array: values';
  is-approx y0(1), -0.54030230586814, 10⁻¹⁴, 'y0';
  lives-ok { ($val, $err) = y0-e(1) }, 'y0 with error check';
  is-approx $val, -0.54030230586814, 10⁻¹⁴, 'y0 with error check: value';
  is-approx y1(1), -1.381773290676036, 10⁻¹⁴, 'y1';
  lives-ok { ($val, $err) = y1-e(1) }, 'y1 with error check';
  is-approx $val, -1.381773290676036, 10⁻¹⁴, 'y1 with error check: value';
  is-approx y2(1), -3.605017566159968, 10⁻¹⁴, 'y2';
  lives-ok { ($val, $err) = y2-e(1) }, 'y2 with error check';
  is-approx $val, -3.605017566159968, 10⁻¹⁴, 'y2 with error check: value';
  is-approx yl(0, 1), -0.54030230586814, 10⁻¹⁴, 'yl';
  lives-ok { ($val, $err) = yl-e(0, 1) }, 'yl with error check';
  is-approx $val, -0.54030230586814, 10⁻¹⁴, 'yl with error check: value';
  lives-ok { @out = yl-array(0, 1) }, 'yl array';
  is-deeply @out».round(10⁻¹⁵), [ -0.54030230586814 ], 'yl array: values';
  ok i0-scaled(0) == 1, 'i0 scaled';
  lives-ok { ($val, $err) = i0-scaled-e(0) }, 'i0 scaled with error check';
  ok $val == 1, 'i0 scaled with error check: value';
  ok i1-scaled(0) == 0, 'i1 scaled';
  lives-ok { ($val, $err) = i1-scaled-e(0) }, 'i1 scaled with error check';
  ok $val == 0, 'i1 scaled with error check: value';
  ok i2-scaled(0) == 0, 'i2 scaled';
  lives-ok { ($val, $err) = i2-scaled-e(0) }, 'i2 scaled with error check';
  ok $val == 0, 'i2 scaled with error check: value';
  ok il-scaled(0, 0) == 1, 'il scaled';
  lives-ok { ($val, $err) = il-scaled-e(0, 0) }, 'il scaled with error check';
  ok $val == 1, 'il scaled with error check: value';
  lives-ok { @out = il-scaled-array(3, 0) }, 'il scaled array';
  is-deeply @out».round(10⁻¹⁵), [ 1.0, 0.0, 0.0, 0.0 ], 'il scaled array: values';
  is-approx k0-scaled(2), 0.785398163397448, 10⁻¹⁵, 'k0 scaled';
  lives-ok { ($val, $err) = k0-scaled-e(2) }, 'k0 scaled with error check';
  is-approx $val, 0.785398163397448, 10⁻¹⁵, 'k0 scaled with error check: value';
  is-approx k1-scaled(2), 1.178097245096172, 10⁻¹⁵, 'k1 scaled';
  lives-ok { ($val, $err) = k1-scaled-e(2) }, 'k1 scaled with error check';
  is-approx $val, 1.178097245096172, 10⁻¹⁵, 'k1 scaled with error check: value';
  is-approx k2-scaled(2), 2.552544031041707, 10⁻¹⁵, 'k2 scaled';
  lives-ok { ($val, $err) = k2-scaled-e(2) }, 'k2 scaled with error check';
  is-approx $val, 2.552544031041707, 10⁻¹⁵, 'k2 scaled with error check: value';
  is-approx kl-scaled(5, 2), 138.107358294920048, 10⁻¹⁵, 'kl scaled';
  lives-ok { ($val, $err) = kl-scaled-e(5, 2) }, 'kl scaled with error check';
  is-approx $val, 138.107358294920048, 10⁻¹⁵, 'kl scaled with error check: value';
  lives-ok { @out = kl-scaled-array(2, 2) }, 'kl scaled array';
  is-deeply @out».round(10⁻¹⁵), [ 0.785398163397448, 1.178097245096172, 2.552544031041707 ], 'kl scaled array: values';
  is-approx Jnu(.75, 1), 0.558652493204891, 10⁻¹⁴, 'Jν';
  lives-ok { ($val, $err) = Jnu-e(.75, 1) }, 'Jν with error check';
  is-approx $val, 0.558652493204891, 10⁻¹⁴, 'Jν with error check: value';
  lives-ok { @out = Jnu-sequence(2, GSL_MODE_DEFAULT, (.1, .2 … 10)) }, 'Jν sequence';
  is-approx @out[0], 0.0012489586587999192, :rel-tol(10⁻¹⁵), 'Jν sequence: value [0]';
  is-approx @out[20], 0.3746236251505604, :rel-tol(10⁻¹⁵), 'Jν sequence: value [20]';
  is-approx Ynu(.0001, 1), 0.08813676933044477, :rel-tol(10⁻¹⁵), 'Yν';
  lives-ok { ($val, $err) = Ynu-e(.0001, 1) }, 'Yν with error check';
  is-approx $val, 0.08813676933044477, :rel-tol(10⁻¹⁵), 'Yν with error check: value';
  is-approx Inu(1, 1), 0.565159103992485, :rel-tol(10⁻¹⁵), 'Iν';
  lives-ok { ($val, $err) = Inu-e(1, 1) }, 'Iν with error check';
  is-approx $val, 0.565159103992485, :rel-tol(10⁻¹⁵), 'Iν with error check: value';
  is-approx Inu-scaled(1, 1), 0.20791041534970847, :rel-tol(10⁻¹⁵), 'Iν scaled';
  lives-ok { ($val, $err) = Inu-scaled-e(1, 1) }, 'Iν scaled with error check';
  is-approx $val, 0.20791041534970847, :rel-tol(10⁻¹⁵), 'Iν scaled with error check: value';
  is-approx Knu(1, 1), 0.601907230197235, :rel-tol(10⁻¹⁵), 'Kν';
  lives-ok { ($val, $err) = Knu-e(1, 1) }, 'Kν with error check';
  is-approx $val, 0.601907230197235, :rel-tol(10⁻¹⁵), 'Kν with error check: value';
  is-approx lnKnu(1, 1), -0.507651948210752, :rel-tol(10⁻¹⁵), 'lnKν';
  lives-ok { ($val, $err) = lnKnu-e(1, 1) }, 'lnKν with error check';
  is-approx $val, -0.507651948210752, :rel-tol(10⁻¹⁵), 'lnKν with error check: value';
  is-approx Knu-scaled(1, 1), 1.636153486263258, :rel-tol(10⁻¹⁵), 'Kν scaled';
  lives-ok { ($val, $err) = Knu-scaled-e(1, 1) }, 'Kν scaled with error check';
  is-approx $val, 1.636153486263258, :rel-tol(10⁻¹⁵), 'Kν scaled with error check: value';
  is-approx J0-zero(1), 2.404825557695771, :rel-tol(10⁻¹⁵), 'J0 n-th root';
  lives-ok { ($val, $err) = J0-zero-e(1) }, 'J0 n-th root with error check';
  is-approx $val, 2.404825557695771, :rel-tol(10⁻¹⁵), 'J0 n-th root with error check: value';
  is-approx J1-zero(1), 3.831705970207503, :rel-tol(10⁻¹⁵), 'J1 n-th root';
  lives-ok { ($val, $err) = J1-zero-e(1) }, 'J1 n-th root with error check';
  is-approx $val, 3.831705970207503, :rel-tol(10⁻¹⁵), 'J1 n-th root with error check: value';
  is-approx Jnu-zero(0, 1), 2.404825557695775, :rel-tol(10⁻¹⁵), 'Jn n-th root';
  lives-ok { ($val, $err) = Jnu-zero-e(0, 1) }, 'Jν n-th root with error check';
  is-approx $val, 2.404825557695775, :rel-tol(10⁻¹⁵), 'Jν n-th root with error check: value';
}, 'Bessel functions';

subtest {
  my ($val, $err);
  is-approx clausen(π/20), 0.447888244813355, :rel-tol(10⁻¹⁵), 'Clausen';
  lives-ok { ($val, $err) = clausen-e(π/20) }, 'Clausen with error check';
  is-approx $val, 0.447888244813355, :rel-tol(10⁻¹⁵), 'Clausen with error check: value';
}, 'Clausen functions';

subtest {
  my ($val, $err);
  is-approx hydrogenic-R1(3, 2), 0.025759948256148472, :rel-tol(10⁻¹⁵), 'hydrogenic R 1';
  lives-ok { ($val, $err) = hydrogenic-R1-e(3, 2) }, 'hydrogenic R 1 with error check';
  is-approx $val, 0.025759948256148472, :rel-tol(10⁻¹⁵), 'hydrogenic R 1 with error check: value';
  is-approx hydrogenic-R(4, 1, 3, 0), 0, :rel-tol(10⁻¹⁵), 'hydrogenic R';
  lives-ok { ($val, $err) = hydrogenic-R-e(4, 1, 3, 0) }, 'hydrogenic R with error check';
  is-approx $val, 0, :rel-tol(10⁻¹⁵), 'hydrogenic R with error check: value';

  my %res;
  lives-ok { %res = coulomb-wave-FG-e(1, 5, 0, 0) }, 'coulomb-wave-FG-e';
  is-approx %res<Fval>, 0.684937412005944, :rel-tol(10⁻¹⁵), 'F: value';
  is-approx %res<Fpval>, -0.723642386255606, :rel-tol(10⁻¹⁵), "F': value";
  is-approx %res<Gval>, -0.8984143590920198, :rel-tol(10⁻¹⁵), 'G: value';
  is-approx %res<Gpval>, -0.510804758519035, :rel-tol(10⁻¹⁵), "G': value";
  ok %res<overflow> == False, 'no overflow';

  lives-ok { %res = coulomb-wave-F-array(1, 3, 1, 5) }, 'coulomb-wave-F-array';
  is-deeply %res<outF>».round(10⁻¹⁵), (1.092881104936675, 1.186370500609351, 0.904222651420796, 0.526623050054267)».round(10⁻¹⁵), 'F array results';
  ok %res<overflow> == False, 'no overflow';
  ok %res<expF> == 0, 'overflow exponent';

  lives-ok { %res = coulomb-wave-FG-array(1, 3, 1, 5) }, 'coulomb-wave-FG-array';
  is-deeply %res<outF>».round(10⁻¹⁵), (1.092881104936676, 1.186370500609353, 0.904222651420797, 0.526623050054267)».round(10⁻¹⁵), 'F array results';
  is-deeply %res<outG>».round(10⁻¹⁵), (-0.401136354144034, 0.382961011797984, 1.091535333071877, 1.708616969572756)».round(10⁻¹⁵), 'G array results';
  ok %res<overflow> == False, 'no overflow';
  ok %res<expF> == 0, 'F overflow exponent';
  ok %res<expG> == 0, 'G overflow exponent';

  lives-ok { %res = coulomb-wave-FGp-array(1, 3, 1, 5) }, 'coulomb-wave-FGp-array';
  is-deeply %res<outF>».round(10⁻¹⁵), (1.092881104936676, 1.186370500609353, 0.904222651420797, 0.526623050054267)».round(10⁻¹⁵), 'F array results';
  is-deeply %res<outG>».round(10⁻¹⁵), (-0.401136354144034, 0.382961011797984, 1.091535333071877, 1.708616969572756)».round(10⁻¹⁵), 'G array results';
  is-deeply %res<outFp>».round(10⁻¹⁵), (-0.342809548488476, 0.154144770433327, 0.406603168927167, 0.37909717266402)».round(10⁻¹⁵), "F' array results";
  is-deeply %res<outGp>».round(10⁻¹⁵), (-0.789186146285826, -0.79314898867443, -0.615089960092336, -0.668918949964118)».round(10⁻¹⁵), "G' array results";
  ok %res<overflow> == False, 'no overflow';
  ok %res<expF> == 0, 'F overflow exponent';
  ok %res<expG> == 0, 'G overflow exponent';

  lives-ok { %res = coulomb-wave-sphF-array(1, 3, 1, 5) }, 'coulomb-wave-sphF-array';
  is-deeply %res<outF>».round(10⁻¹⁵), (0.218576220987335, 0.23727410012187, 0.180844530284159, 0.105324610010853)».round(10⁻¹⁵), 'F array results';
  ok %res<overflow> == False, 'no overflow';
  ok %res<expF> == 0, 'F overflow exponent';

  lives-ok { ($val, $err) = coulomb-CL-e(2, 1) }, 'Normalization Constant';
  is-approx $val, 0.011428736368066569, :rel-tol(10⁻¹⁵), 'Normalization Constant: value';
  my @out;
  lives-ok { @out = coulomb-CL-array(1, 3, 1) }, 'Normalization Constant';
  is-deeply @out».round(10⁻¹⁵), [ 0.051110862831842, 0.011428736368067, 0.001720992271461, 0.000197106469892 ], 'Normalization Constant array: values';
}, 'Coulomb functions';

subtest {
  my ($val, $err);
  ok coupling3j(0, 1, 1, 0,  1, -1) == sqrt(½), '3-j';
  lives-ok { ($val, $err) = coupling3j-e(0, 1, 1, 0,  1, -1) }, '3-j with error check';
  ok $val == sqrt(½), '3-j with error check: value';
  ok coupling6j(2, 2, 4, 2,  2, 2) == ⅙, '6-j';
  lives-ok { ($val, $err) = coupling6j-e(2, 2, 4, 2,  2, 2) }, '6-j with error check';
  ok $val == ⅙, '6-j with error check: value';
  is-approx coupling9j(4, 2, 4, 3, 3, 2, 1, 1, 2), -sqrt(⅙) / 10, :rel-tol(10⁻¹⁵), '9-j';
  lives-ok { ($val, $err) = coupling9j-e(4, 2, 4, 3, 3, 2, 1, 1, 2) }, '9-j with error check';
  is-approx $val, -sqrt(⅙) / 10, :rel-tol(10⁻¹⁵), '9-j with error check: value';
}, 'Coupling coefficients';

subtest {
  my ($val, $err);
  is-approx dawson(.5), 0.424436383502022, :rel-tol(10⁻¹⁵), 'Dawson';
  lives-ok { ($val, $err) = dawson-e(.5) }, 'Dawson with error check';
  is-approx $val, 0.424436383502022, :rel-tol(10⁻¹⁵), 'Dawson with error check: value';
}, 'Dawson function';

subtest {
  my ($val, $err);
  is-approx debye1(.1), 0.975277750004723, :rel-tol(10⁻¹⁵), 'Debye 1';
  lives-ok { ($val, $err) = debye1-e(.1) }, 'Debye 1 with error check';
  is-approx $val, 0.975277750004723, :rel-tol(10⁻¹⁵), 'Debye 1 with error check: value';
  is-approx debye2(0.1e0), 0.967083287045303, :rel-tol(10⁻¹⁵), 'Debye 2';
  lives-ok { ($val, $err) = debye2-e(.1) }, 'Debye 2 with error check';
  is-approx $val, 0.967083287045303, :rel-tol(10⁻¹⁵), 'Debye 2 with error check: value';
  is-approx debye3(.1), 0.962999940487211, :rel-tol(10⁻¹⁵), 'Debye 3';
  lives-ok { ($val, $err) = debye3-e(.1) }, 'Debye 3 with error check';
  is-approx $val, 0.962999940487211, :rel-tol(10⁻¹⁵), 'Debye 3 with error check: value';
  is-approx debye4(.1), 0.960555486124336, :rel-tol(10⁻¹⁵), 'Debye 4';
  lives-ok { ($val, $err) = debye4-e(.1) }, 'Debye 4 with error check';
  is-approx $val, 0.960555486124336, :rel-tol(10⁻¹⁵), 'Debye 4 with error check: value';
  is-approx debye5(0.1e0), 0.958928494283106, :rel-tol(10⁻¹⁵), 'Debye 5';
  lives-ok { ($val, $err) = debye5-e(.1) }, 'Debye 5 with error check';
  is-approx $val, 0.958928494283106, :rel-tol(10⁻¹⁵), 'Debye 5 with error check: value';
  is-approx debye6(0.1e0), 0.957767773826055, :rel-tol(10⁻¹⁵), 'Debye 6';
  lives-ok { ($val, $err) = debye6-e(.1) }, 'Debye 6 with error check';
  is-approx $val, 0.957767773826055, :rel-tol(10⁻¹⁵), 'Debye 6 with error check: value';
}, 'Debye functions';

subtest {
  my ($val, $err, $errre, $errim);
  is-approx dilog(.1), 0.10261779109939113, :rel-tol(10⁻¹⁵), 'real dilogarithm';
  lives-ok { ($val, $err) = dilog-e(.1) }, 'real dilogarithm with error check';
  is-approx $val, 0.10261779109939113, :rel-tol(10⁻¹⁵), 'real dilogarithm with error check: value';
  lives-ok { ($val, $errre, $errim) = complex-dilog-xy-e(0, -.5) }, 'complex dilogarithm';
  is-approx $val, -0.058975074421566 -i * 0.487222358294522, :rel-tol(10⁻¹⁵), 'complex dilogarithm: value';
  lives-ok { ($val, $errre, $errim) = complex-dilog-e(.98, π/2) }, 'complex dilogarithm, polar coord';
  is-approx $val, -0.198716383777859 + i * 0.900200458829818, :rel-tol(10⁻¹⁵), 'complex dilogarithm, polar coord: value';
  lives-ok { ($val, $errre, $errim) = complex-spence-xy-e(-.5, 0) }, 'Spence dilogarithm';
  is-approx $val, 2.374395270272480 - i * 1.273806204919600, :rel-tol(10⁻¹⁵), 'Spence dilogarithm: value';
}, 'Dilogarithms';

subtest {
  my ($val, $err);
  ok multiply(-3, 2) == -6, 'multiplication';
  lives-ok { ($val, $err) = multiply-e(-3, 2) }, 'multiplication with error check';
  ok $val == -6, 'multiplication with error check: value';
  lives-ok { ($val, $err) = multiply-err-e(-3, .001, 2, .001) }, 'multiplication with abs errors';
  ok $val == -6, 'multiplication with abs errors: value';
  is-approx $err, 0.005000000000002665, :rel-tol(10⁻¹⁵), 'multiplication with abs errors: error';
}, 'multiplication with error propagation';

subtest {
  my ($val, $err);
  is-approx Kcomp(.99, GSL_MODE_DEFAULT), 3.356600523361192, :rel-tol(10⁻¹⁵), 'Legendre K';
  lives-ok { ($val, $err) = Kcomp-e(.99, GSL_MODE_DEFAULT) }, 'Legendre K with error check';
  is-approx $val, 3.356600523361192, :rel-tol(10⁻¹⁵), 'Legendre K with error check: value';
  is-approx Ecomp(.99, GSL_MODE_DEFAULT), 1.028475809028804, :rel-tol(10⁻¹⁵), 'Legendre E';
  lives-ok { ($val, $err) = Ecomp-e(.99, GSL_MODE_DEFAULT) }, 'Legendre E with error check';
  is-approx $val, 1.028475809028804, :rel-tol(10⁻¹⁵), 'Legendre E with error check: value';
  is-approx Pcomp(.99, .1, GSL_MODE_DEFAULT), 3.137926123518364, :rel-tol(10⁻¹⁵), 'Legendre P';
  lives-ok { ($val, $err) = Pcomp-e(.99, .1, GSL_MODE_DEFAULT) }, 'Legendre P with error check';
  is-approx $val, 3.137926123518364, :rel-tol(10⁻¹⁵), 'Legendre P with error check: value';
  is-approx Dcomp(.99, GSL_MODE_DEFAULT), 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre D';
  lives-ok { ($val, $err) = Dcomp-e(.99, GSL_MODE_DEFAULT) }, 'Legendre D with error check';
  is-approx $val, 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre D with error check: value';
  is-approx F(π/3, .99, GSL_MODE_DEFAULT), 1.306533339273877, :rel-tol(10⁻¹⁵), 'Legendre incomplete F';
  lives-ok { ($val, $err) = F-e(π/3, .99, GSL_MODE_DEFAULT) }, 'Legendre incomplete F with error check';
  is-approx $val, 1.306533339273877, :rel-tol(10⁻¹⁵), 'Legendre incomplete F with error check: value';
  is-approx E(π/3, .99, GSL_MODE_DEFAULT), 0.870481922037794, :rel-tol(10⁻¹⁵), 'Legendre incomplete E';
  lives-ok { ($val, $err) = E-e(π/3, .99, GSL_MODE_DEFAULT) }, 'Legendre incomplete E with error check';
  is-approx $val, 0.870481922037794, :rel-tol(10⁻¹⁵), 'Legendre incomplete E with error check: value';
  is-approx P(π/3, .99, .5, GSL_MODE_DEFAULT), 1.12887265987641, :rel-tol(10⁻¹⁵), 'Legendre incomplete P';
  lives-ok { ($val, $err) = P-e(π/3, .99, .5, GSL_MODE_DEFAULT) }, 'Legendre incomplete P with error check';
  is-approx $val, 1.12887265987641, :rel-tol(10⁻¹⁵), 'Legendre incomplete P with error check: value';
  is-approx D(π/2, .99, GSL_MODE_DEFAULT), 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre incomplete D';
  lives-ok { ($val, $err) = D-e(π/2, .99e0, GSL_MODE_DEFAULT) }, 'Legendre incomplete D with error check';
  is-approx $val, 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre incomplete D with error check: value';
  is-approx RC(1, 2, GSL_MODE_DEFAULT), 0.785398163397448, :rel-tol(10⁻¹⁵), 'Legendre incomplete RC';
  lives-ok { ($val, $err) = RC-e(1e0, 2e0, GSL_MODE_DEFAULT) }, 'Legendre incomplete RC with error check';
  is-approx $val, 0.785398163397448, :rel-tol(10⁻¹⁵), 'Legendre incomplete RC with error check: value';
  is-approx RD(1, 2, 3, GSL_MODE_DEFAULT), 0.29046028102899063, :rel-tol(10⁻¹⁵), 'Legendre incomplete RD';
  lives-ok { ($val, $err) = RD-e(1e0, 2e0, 3e0, GSL_MODE_DEFAULT) }, 'Legendre incomplete RD with error check';
  is-approx $val, 0.29046028102899063, :rel-tol(10⁻¹⁵), 'Legendre incomplete RD with error check: value';
  is-approx RF(1, 2, 3, GSL_MODE_DEFAULT), 0.726945935468908, :rel-tol(10⁻¹⁵), 'Legendre incomplete RF';
  lives-ok { ($val, $err) = RF-e(1, 2, 3, GSL_MODE_DEFAULT) }, 'Legendre incomplete RF with error check';
  is-approx $val, 0.726945935468908, :rel-tol(10⁻¹⁵), 'Legendre incomplete RF with error check: value';
  is-approx RJ(2, 3, 4, 5, GSL_MODE_DEFAULT), 0.1429757966715675, :rel-tol(10⁻¹⁵), 'Legendre incomplete RJ';
  lives-ok { ($val, $err) = RJ-e(2, 3, 4, 5, GSL_MODE_DEFAULT) }, 'Legendre incomplete RJ with error check';
  is-approx $val, 0.1429757966715675, :rel-tol(10⁻¹⁵), 'Legendre incomplete RJ with error check: value';
}, 'elliptic integrals';

subtest {
  my ($sn, $cn, $dn);
  lives-ok { ($sn, $cn, $dn) = elljac-e(.5, .5) }, 'Jacobi';
  is-approx $sn, 0.4707504736556575, :rel-tol(10⁻¹⁵), 'Jacobi sn: value';
  is-approx $cn, 0.882266394890440, :rel-tol(10⁻¹⁵), 'Jacobi cn: value';
  is-approx $dn, 0.942972425777386, :rel-tol(10⁻¹⁵), 'Jacobi dn: value';
}, 'elliptic functions';

subtest {
  my ($val, $err);
  ok erf(-10e0) == -1, 'erf';
  lives-ok { ($val, $err) = erf-e(-10) }, 'erf with error check';
  ok $val == -1, 'erf with error check: value';
  ok erfc(-10e0) == 2, 'erfc';
  lives-ok { ($val, $err) = erfc-e(-10) }, 'erfc with error check';
  ok $val == 2, 'erfc with error check: value';
  is-approx log-erfc(-.1), 0.1065764005865225, :rel-tol(10⁻¹⁵), 'log erfc';
  lives-ok { ($val, $err) = log-erfc-e(-.1) }, 'log erfc with error check';
  is-approx $val, 0.1065764005865225, :rel-tol(10⁻¹⁵), 'log erfc with error check: value';
  is-approx erf-Z(1), 0.24197072451914334, :rel-tol(10⁻¹⁵), 'erf Z';
  lives-ok { ($val, $err) = erf-Z-e(1) }, 'erf Z with error check';
  is-approx $val, 0.24197072451914334, :rel-tol(10⁻¹⁵), 'erf Z with error check: value';
  is-approx erf-Q(1), 0.158655253931457, :rel-tol(10⁻¹⁵), 'erf Q';
  lives-ok { ($val, $err) = erf-Q-e(1) }, 'erf Q with error check';
  is-approx $val, 0.158655253931457, :rel-tol(10⁻¹⁵), 'erf Q with error check: value';
  is-approx hazard(-1), 0.2875999709391784, :rel-tol(10⁻¹⁵), 'hazard';
  lives-ok { ($val, $err) = hazard-e(-1) }, 'erf Q with error check';
  is-approx $val, 0.2875999709391784, :rel-tol(10⁻¹⁵), 'hazard with error check: value';
}, 'error functions';

subtest {
  my ($val, $err, $e10);
  ok gexp(10) == exp(10), 'exp';
  lives-ok { ($val, $err) = gexp-e(10) }, 'exp with error check';
  ok $val == exp(10), 'exp with error check: value';
  lives-ok { ($val, $err, $e10) = gexp-e10(10) }, 'exp with extended range error check';
  ok $val == exp(10), 'exp with extended range error check: value';
  ok gexp-mult(10, -2) == -2 * exp(10), 'exp mult';
  lives-ok { ($val, $err) = gexp-mult-e(10, -2) }, 'exp mult with error check';
  ok $val == -2 * exp(10), 'exp mult with error check: value';
  lives-ok { ($val, $err, $e10) = gexp-mult-e10(10, -2) }, 'exp mult with extended range error check';
  ok $val == -2 * exp(10), 'exp mult with extended range error check: value';
  ok gexpm1(-10) == exp(-10) - 1, 'exp(x) - 1';
  lives-ok { ($val, $err) = gexpm1-e(-10) }, 'exp(x) - 1 with error check';
  ok $val == exp(-10) - 1, 'exp(x) - 1 with error check: value';
  is-approx gexprel(-10), 0.09999546000702375, :rel-tol(10⁻¹⁵), '(exp(x) - 1) / x';
  lives-ok { ($val, $err) = gexprel-e(-10) }, '(exp(x) - 1) / x with error check';
  is-approx $val, 0.09999546000702375, :rel-tol(10⁻¹⁵), '(exp(x) - 1) / x with error check: value';
  is-approx gexprel2(-10), 0.18000090799859525, :rel-tol(10⁻¹⁵), '2 * (exp(x) - 1 - x) / x²';
  lives-ok { ($val, $err) = gexprel2-e(-10) }, '2 * (exp(x) - 1 - x) / x² with error check';
  is-approx $val, 0.18000090799859525, :rel-tol(10⁻¹⁵), '2 * (exp(x) - 1 - x) / x² with error check: value';
  is-approx gexprel-n(3, -10), 0.24599972760042138, :rel-tol(10⁻¹⁵), 'N relative exponential';
  lives-ok { ($val, $err) = gexprel-n-e(3, -10) }, 'N relative exponential with error check';
  is-approx $val, 0.24599972760042138, :rel-tol(10⁻¹⁵), 'N relative exponential with error check: value';
  lives-ok { ($val, $err) = gexp-err-e(-10, 16 * 2.2204460492503131e-16) }, 'exp with absolute error';
  ok $val == exp(-10), 'exp with absolute error: value';
  lives-ok { ($val, $err, $e10) = gexp-err-e10(1, 16 * 2.2204460492503131e-16) }, 'exp with extended range error check';
  ok $val == 𝑒, 'exp with extended range error check: value';
  lives-ok { ($val, $err) = gexp-mult-err-e(-10, 2 * 2.2204460492503131e-16, 2, 2 * 2.2204460492503131e-16) }, 'y * exp(x) with absolute error';
  ok $val == 2 * exp(-10), 'y * exp(x) with absolute error: value';
  lives-ok { ($val, $err, $e10) = gexp-mult-err-e10(-10, 2 * 2.2204460492503131e-16, 2, 2 * 2.2204460492503131e-16) }, 'y * exp(x) with extended range error check';
  ok $val == 2 * exp(-10), 'y * exp(x) with extended range error check: value';
}, 'exponential functions';

subtest {
  my ($val, $err);
  is-approx E1(1), 0.21938393439552029, :rel-tol(10⁻¹⁵), 'E₁(x)';
  lives-ok { ($val, $err) = E1-e(1) }, 'E₁(x) with error check';
  is-approx $val, 0.21938393439552029, :rel-tol(10⁻¹⁵), 'E₁(x) with error check: value';
  is-approx E2(1), 0.148495506775922, :rel-tol(10⁻¹⁵), 'E₂(x)';
  lives-ok { ($val, $err) = E2-e(1) }, 'E₂(x) with error check';
  is-approx $val, 0.148495506775922, :rel-tol(10⁻¹⁵), 'E₂(x) with error check: value';
  is-approx En(1, 1), 0.21938393439552029, :rel-tol(10⁻¹⁵), 'Eₙ(x)';
  lives-ok { ($val, $err) = En-e(1, 1) }, 'Eₙ(x) with error check';
  is-approx $val, 0.21938393439552029, :rel-tol(10⁻¹⁵), 'Eₙ(x) with error check: value';
  is-approx Ei(1), 1.895117816355937, :rel-tol(10⁻¹⁵), 'Eᵢ(x)';
  lives-ok { ($val, $err) = Ei-e(1) }, 'Eᵢ(x) with error check';
  is-approx $val, 1.895117816355937, :rel-tol(10⁻¹⁵), 'Eᵢ(x) with error check: value';
  is-approx Shi(.1), 0.100055572225057, :rel-tol(10⁻¹⁵), 'Shi(x)';
  lives-ok { ($val, $err) = Shi-e(.1) }, 'Shi(x) with error check';
  is-approx $val, 0.100055572225057, :rel-tol(10⁻¹⁵), 'Shi(x) with error check: value';
  is-approx Chi(1), 0.837866940980208, :rel-tol(10⁻¹⁵), 'Chi(x)';
  lives-ok { ($val, $err) = Chi-e(1) }, 'Chi(x) with error check';
  is-approx $val, 0.837866940980208, :rel-tol(10⁻¹⁵), 'Chi(x) with error check: value';
  is-approx expint3(1), 0.807511182139672, :rel-tol(10⁻¹⁵), 'Ei₃(x)';
  lives-ok { ($val, $err) = expint3-e(1) }, 'Ei₃(x) with error check';
  is-approx $val, 0.807511182139672, :rel-tol(10⁻¹⁵), 'Ei₃(x) with error check: value';
  is-approx Si(1), 0.946083070367183, :rel-tol(10⁻¹⁵), 'Si(x)';
  lives-ok { ($val, $err) = Si-e(1) }, 'Si(x) with error check';
  is-approx $val, 0.946083070367183, :rel-tol(10⁻¹⁵), 'Si(x) with error check: value';
  is-approx Ci(1), 0.337403922900968, :rel-tol(10⁻¹⁵), 'Ci(x)';
  lives-ok { ($val, $err) = Ci-e(1) }, 'Ci(x) with error check';
  is-approx $val, 0.337403922900968, :rel-tol(10⁻¹⁵), 'Ci(x) with error check: value';
  is-approx atanint(1), 0.915965594177219, :rel-tol(10⁻¹⁵), 'atanint(x)';
  lives-ok { ($val, $err) = atanint-e(1) }, 'atanint(x) with error check';
  is-approx $val, 0.915965594177219, :rel-tol(10⁻¹⁵), 'atanint(x) with error check: value';
}, 'exponential integrals';

subtest {
  my ($val, $err);
  is-approx fd-m1(1), 0.731058578630005, :rel-tol(10⁻¹⁵), 'F₋₁(x)';
  lives-ok { ($val, $err) = fd-m1-e(1) }, 'F₋₁(x) with error check';
  is-approx $val, 0.731058578630005, :rel-tol(10⁻¹⁵), 'F₋₁(x) with error check: value';
  is-approx fd0(1), 1.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x)';
  lives-ok { ($val, $err) = fd0-e(1) }, 'F₀(x) with error check';
  is-approx $val, 1.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x) with error check: value';
  is-approx fd1(1), 1.806286070444775, :rel-tol(10⁻¹⁵), 'F₁(x)';
  lives-ok { ($val, $err) = fd1-e(1) }, 'F₁(x) with error check';
  is-approx $val, 1.806286070444775, :rel-tol(10⁻¹⁵), 'F₁(x) with error check: value';
  is-approx fd2(1), 2.164165612812701, :rel-tol(10⁻¹⁵), 'F₂(x)';
  lives-ok { ($val, $err) = fd2-e(1) }, 'F₂(x) with error check';
  is-approx $val, 2.164165612812701, :rel-tol(10⁻¹⁵), 'F₂(x) with error check: value';
  is-approx fd-int(3, 1), 2.39822608224894, :rel-tol(10⁻¹⁵), 'Fⱼ(x)';
  lives-ok { ($val, $err) = fd-int-e(3, 1) }, 'Fⱼ(x) with error check';
  is-approx $val, 2.39822608224894, :rel-tol(10⁻¹⁵), 'Fⱼ(x) with error check: value';
  is-approx fd-mhalf(1), 1.027057125474351, :rel-tol(10⁻¹⁵), 'F-1/2(x)';
  lives-ok { ($val, $err) = fd-mhalf-e(1) }, 'F-1/2(x) with error check';
  is-approx $val, 1.027057125474351, :rel-tol(10⁻¹⁵), 'F-1/2(x) with error check: value';
  is-approx fd-half(1), 1.575640776151300, :rel-tol(10⁻¹⁵), 'F1/2(x)';
  lives-ok { ($val, $err) = fd-half-e(1) }, 'F1/2(x) with error check';
  is-approx $val, 1.575640776151300, :rel-tol(10⁻¹⁵), 'F1/2(x) with error check: value';
  is-approx fd-half3(1), 2.002258148778464, :rel-tol(10⁻¹⁵), 'F3/2(x)';
  lives-ok { ($val, $err) = fd-half3-e(1) }, 'F3/2(x) with error check';
  is-approx $val, 2.002258148778464, :rel-tol(10⁻¹⁵), 'F3/2(x) with error check: value';
  is-approx fd-inc0(1, 2), 0.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x,b)';
  lives-ok { ($val, $err) = fd-inc0-e(1, 2) }, 'F₀(x,b) with error check';
  is-approx $val, 0.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x,b) with error check: value';
}, 'Fermi-Dirac integrals';

subtest {
  my ($val, $err, $vali, $erri);
  ok gamma(9) == 40320, 'Γ(x)';
  lives-ok { ($val, $err) = gamma-e(9) }, 'Γ(x) with error check';
  ok $val == 40320, 'Γ(x) with error check: value';
  is-approx lngamma(.1), 2.252712651734205, :rel-tol(10⁻¹⁵), 'log(|Γ(x)|)';
  lives-ok { ($val, $err) = lngamma-e(.1) }, 'log(|Γ(x)|) with error check';
  is-approx $val, 2.252712651734205, :rel-tol(10⁻¹⁵), 'log(|Γ(x)|) with error check: value';
  my $sgn;
  lives-ok { ($val, $err, $sgn) = lngamma-sgn-e(-.1) }, 'log(|Γ(x)|) with error check and sign';
  is-approx $val, 2.368961332728788, :rel-tol(10⁻¹⁵), 'log(|Γ(x)|) with error check and sign: value';
  ok $sgn == -1, 'log(|Γ(x)|) with error check: sign';
  is-approx gammastar(9), 1.009298426421819, :rel-tol(10⁻¹⁵), 'Γ*(x)';
  lives-ok { ($val, $err) = gammastar-e(9) }, 'Γ*(x) with error check';
  is-approx $val, 1.009298426421819, :rel-tol(10⁻¹⁵), 'Γ*(x) with error check: value';
  ok gammainv(3) == .5, '1/Γ(x)';
  lives-ok { ($val, $err) = gammainv-e(3) }, '1/Γ(x) with error check';
  ok $val == .5, '1/Γ(x) with error check: value';
  lives-ok { ($val, $err, $vali, $erri) = lngamma-complex-e(5, 2) }, 'log(Γ(z)) with error check';
  is-approx $val, 2.748701756133804, :rel-tol(10⁻¹⁵), 'log(Γ(z)) with error check: re value';
  is-approx $vali, 3.073843410049702, :rel-tol(10⁻¹⁵), 'log(Γ(z)) with error check: im value';
  ok fact(8) == 40320, 'n!';
  dies-ok { fact(300) }, '300! overflows';
  lives-ok { ($val, $err) = fact-e(8) }, 'n! with error check';
  ok $val == 40320, 'n! with error check: value';
  ok doublefact(7) == 105, 'n!!';
  dies-ok { doublefact(300) }, '300!! overflows';
  lives-ok { ($val, $err) = doublefact-e(7) }, 'n!! with error check';
  ok $val == 105, 'n!! with error check: value';
  is-approx lnfact(7), 8.525161361065414, :rel-tol(10⁻¹⁵), 'log(n!)';
  lives-ok { ($val, $err) = lnfact-e(7) }, 'log(n!) with error check';
  is-approx $val, 8.525161361065414, :rel-tol(10⁻¹⁵), 'log(n!) with error check: value';
  is-approx lndoublefact(7), 4.653960350157524, :rel-tol(10⁻¹⁵), 'log(n!!)';
  lives-ok { ($val, $err) = lndoublefact-e(7) }, 'log(n!!) with error check';
  is-approx $val, 4.653960350157524, :rel-tol(10⁻¹⁵), 'log(n!!) with error check: value';
  ok choose(7, 3) == 35, 'n!/(m!(n-m)!)';
  lives-ok { ($val, $err) = choose-e(7, 3) }, 'n!/(m!(n-m)!) with error check';
  ok $val == 35, 'n!/(m!(n-m)!) with error check: value';
  is-approx lnchoose(7, 3), 3.555348061489414, :rel-tol(10⁻¹⁵), 'log(n!)-log(m!)-log((n-m)!)';
  lives-ok { ($val, $err) = lnchoose-e(7, 3) }, 'log(n!)-log(m!)-log((n-m)!) with error check';
  is-approx $val, 3.555348061489414, :rel-tol(10⁻¹⁵), 'log(n!)-log(m!)-log((n-m)!) with error check: value';
  is-approx taylorcoeff(10, 5), 2.691144455467373, :rel-tol(10⁻¹⁵), 'xⁿ/n!';
  dies-ok { taylorcoeff(10, -5) }, 'xⁿ/n! dies when x<0';
  lives-ok { ($val, $err) = taylorcoeff-e(10, 5) }, 'xⁿ/n! with error check';
  is-approx $val, 2.691144455467373, :rel-tol(10⁻¹⁵), 'xⁿ/n! with error check: value';
  ok poch(5, 0) == 1, '(a)ₓ';
  lives-ok { ($val, $err) = poch-e(5, 0) }, '(a)ₓ with error check';
  ok $val == 1, '(a)ₓ with error check: value';
  ok lnpoch(5, 0) == 0, 'log((a)ₓ)';
  lives-ok { ($val, $err) = lnpoch-e(5, 0) }, 'log((a)ₓ) with error check';
  ok $val == 0, 'log((a)ₓ) with error check: value';
  lives-ok { ($val, $err, $sgn) = lnpoch-sgn-e(5, 0)}, 'log((a)ₓ) with error check and sign';
  ok $val == 0, 'log((a)ₓ) with error check and sign: value';
  ok $sgn == 1, 'log((a)ₓ) with error check and sign: sign';
  is-approx pochrel(5, 0), 1.506117668431801, :rel-tol(10⁻¹⁵), '((a)ₓ-1)/x';
  lives-ok { ($val, $err) = pochrel-e(5, 0) }, '((a)ₓ-1)/x with error check';
  is-approx $val, 1.506117668431801, :rel-tol(10⁻¹⁵), '((a)ₓ-1)/x with error check: value';
  is-approx gamma-inc(1, 1), 0.367879441171442, :rel-tol(10⁻¹⁵), 'Γ(a,x)';
  lives-ok { ($val, $err) = gamma-inc-e(1, 1) }, 'Γ(a,x) with error check';
  is-approx $val, 0.367879441171442, :rel-tol(10⁻¹⁵), 'Γ(a,x) with error check: value';
  is-approx gamma-inc-Q(1, 1.01), 0.364218979571523, :rel-tol(10⁻¹⁵), 'Q(a,x)';
  lives-ok { ($val, $err) = gamma-inc-Q-e(1, 1.01) }, 'Q(a,x) with error check';
  is-approx $val, 0.364218979571523, :rel-tol(10⁻¹⁵), 'Q(a,x) with error check: value';
  is-approx gamma-inc-P(100, 99), 0.473304330399461, :rel-tol(10⁻¹⁵), 'P(a,x)';
  lives-ok { ($val, $err) = gamma-inc-P-e(100, 99) }, 'P(a,x) with error check';
  is-approx $val, 0.473304330399461, :rel-tol(10⁻¹⁵), 'P(a,x) with error check: value';
  ok beta(1, 1) == 1, 'B(a,b)';
  lives-ok { ($val, $err) = beta-e(1, 1) }, 'B(a,b) with error check';
  ok $val == 1, 'B(a,b) with error check: value';
  is-approx lnbeta(1, 1.01), -0.009950330853168186, :rel-tol(10⁻¹⁵), 'log(B(a,b))';
  lives-ok { ($val, $err) = lnbeta-e(1, 1.01) }, 'log(B(a,b)) with error check';
  is-approx $val, -0.009950330853168186, :rel-tol(10⁻¹⁵), 'log(B(a,b)) with error check: value';
  ok beta-inc(1, 1, 1) == 1, 'Iₓ(a,b)';
  dies-ok { beta-inc(1, 1, -1) }, 'Iₓ(a,b) dies when x<0';
  dies-ok { beta-inc(1, 1, 2) }, 'Iₓ(a,b) dies when x>1';
  dies-ok { beta-inc(0, 1, 1) }, 'Iₓ(a,b) dies when a=0';
  dies-ok { beta-inc(1, 0, 1) }, 'Iₓ(a,b) dies when b=0';
  lives-ok { ($val, $err) = beta-inc-e(1, 1, 1) }, 'Iₓ(a,b) with error check';
  ok $val == 1, 'Iₓ(a,b) with error check: value';
}, 'gamma e beta functions';

subtest {
  my ($val, $err);
  is-approx gegenpoly1(0, 1), 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=1';
  lives-ok { ($val, $err) = gegenpoly1-e(0, 1) }, 'Cₙ(λ)(x) n=1 with error check';
  is-approx $val, 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=1 with error check: value';
  is-approx gegenpoly2(0, 1), 1, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=2';
  lives-ok { ($val, $err) = gegenpoly2-e(0, 1) }, 'Cₙ(λ)(x) n=2 with error check';
  is-approx $val, 1, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=2 with error check: value';
  is-approx gegenpoly3(1, 1), 4, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=3';
  lives-ok { ($val, $err) = gegenpoly3-e(1, 1) }, 'Cₙ(λ)(x) n=3 with error check';
  is-approx $val, 4, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=3 with error check: value';
  is-approx gegenpolyn(1, 1, 1), 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x)';
  dies-ok { gegenpolyn(1, -1, 1) }, 'Cₙ(λ)(x) dies when λ < -½';
  lives-ok { ($val, $err) = gegenpolyn-e(1, 1, 1) }, 'Cₙ(λ)(x) with error check';
  is-approx $val, 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) with error check: value';
  my @res;
  lives-ok { @res = gegenpoly-array(11, 5, 1) }, 'Cₙ(λ)(x) for n=0,1,2…nmax';
  ok @res[1] == 10, 'Cₙ(λ)(x) n=1';
  ok @res[10] == 9.23780e+4, 'Cₙ(λ)(x) n=10';
}, 'Gegenbauer functions';

subtest {
  my ($val, $err);
  ok hermite(0, .75) == 1, 'Hₙ(x)';
  lives-ok { ($val, $err) = hermite-e(0, .75) }, 'Hₙ(x) with error check';
  ok $val == 1, 'Hₙ(x) with error check: value';
  my @out;
  lives-ok { @out = hermite-array(0, .75) }, 'Hₙ(x) array';
  ok @out[0] == 1, 'Hₙ(x) array: results';
  my @a = 1,;
  @a[$_] = @a[$_-1]/2 for 1…10;
  is-approx hermite-series(10, .75, @a), 29.591702461242672, :rel-tol(10⁻¹⁵), 'sum(aₙHₙ(x))';
  lives-ok { ($val, $err) = hermite-series-e(10, .75, @a) }, 'sum(aₙHₙ(x)) with error check';
  is-approx $val, 29.591702461242672, :rel-tol(10⁻¹⁵), 'Hₙ(x) with error check: value';
  ok hermite-prob(0, .75) == 1, 'Heₙ(x)';
  lives-ok { ($val, $err) = hermite-prob-e(0, .75) }, 'Heₙ(x) with error check';
  ok $val == 1, 'Heₙ(x) with error check: value';
  lives-ok { @out = hermite-prob-array(0, .75) }, 'Heₙ(x) array';
  ok @out[0] == 1, 'Heₙ(x) array: results';
  is-approx hermite-prob-series(10, .75, @a), 2.087602422572672, :rel-tol(10⁻¹⁵), 'sum(aₙHeₙ(x))';
  lives-ok { ($val, $err) = hermite-prob-series-e(10, .75, @a) }, 'sum(aₙHeₙ(x)) with error check';
  is-approx $val, 2.087602422572672, :rel-tol(10⁻¹⁵), 'sum(aₙHeₙ(x)) with error check: value';
  ok hermite-der(225, 128, .75) == 0, 'm-derivative of Hₙ(x)';
  lives-ok { ($val, $err) = hermite-der-e(225, 128, .75) }, 'm-derivative of Hₙ(x) with error check';
  ok $val == 0, 'm-derivative of Hₙ(x) with error check: value';
  lives-ok { @out = hermite-array-der(0, 10, .75) }, 'm-derivative of Hₙ(x) array';
  ok @out[0] == 1, 'm-derivative of Hₙ(x) array [0]';
  is-approx @out[10], 38740.4384765625, :rel-tol(10⁻¹⁵), 'm-derivative of Hₙ(x) array [10]';
  lives-ok { @out = hermite-der-array(10, 50, .75) }, 'derivatives of Hₙ(x) array';
  is-approx @out[0], -8.26632218305863100726861832e38, :rel-tol(10⁻¹⁵), 'derivatives of Hₙ(x) array [0]';
  is-approx @out[1], 2.40954750392844799126151557e40, :rel-tol(10⁻¹⁵), 'derivatives of Hₙ(x) array [1]';
  ok hermite-prob-der(225, 128, .75) == 0, 'm-derivative of probabilistic Heₙ(x)';
  lives-ok { ($val, $err) = hermite-prob-der-e(225, 128, .75) }, 'm-derivative of probabilistic Heₙ(x) with error check';
  ok $val == 0, 'm-derivative of probabilistic Heₙ(x) with error check: value';
  lives-ok { @out = hermite-prob-array-der(0, 10, .75) }, 'm-derivative of probabilistic Heₙ(x) array';
  is-approx @out[10], 823.810509681701660156250, :rel-tol(10⁻¹⁵), 'm-derivative of Heₙ(x) array [10]';
  lives-ok { @out = hermite-prob-der-array(10, 50, .75) }, 'derivatives of probabilistic Heₙ(x) array';
  is-approx @out[10], 7.9614368698398116765703194e38, :rel-tol(10⁻¹⁵), 'derivatives of Heₙ(x) array [10]';
  is-approx hermite-func(0, 1.3), 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x)';
  lives-ok { ($val, $err) = hermite-func-e(0, 1.3) }, 'ψₙ(x) with error check';
  is-approx $val, 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x) with error check: value';
  lives-ok { @out = hermite-func-array(1, 1.3) }, 'ψₙ(x) array';
  is-approx @out[0], 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x) array: value';
  is-approx hermite-func-series(10, .75, @a), 0.8171775729199896, :rel-tol(10⁻¹⁵), 'sum(aₙψₙ(x))';
  lives-ok { ($val, $err) = hermite-func-series-e(10, .75, @a) }, 'sum(aₙψₙ(x)) with error check';
  is-approx $val, 0.8171775729199896, :rel-tol(10⁻¹⁵), 'sum(aₙψₙ(x)) with error check: value';
  is-approx hermite-func-der(0, 28, .75), 0.235262808086212406493191404, :rel-tol(10⁻¹⁵), 'm-derivative of ψₙ(x)';
  lives-ok { ($val, $err) = hermite-func-der-e(0, 28,.75) }, 'm-derivative of ψₙ(x) with error check';
  is-approx $val, 0.235262808086212406493191404, :rel-tol(10⁻¹⁵), 'm-derivative of ψₙ(x) with error check: value';
  ok hermite-zero(17, 1) == 0.531633001342654731349086553718, 's-th zero of Hₙ(x)';
  lives-ok { ($val, $err) = hermite-zero-e(17, 1) }, 's-th zero of Hₙ(x) with error check';
  ok $val == 0.531633001342654731349086553718, 's-th zero of Hₙ(x) with error check: value';
  ok hermite-prob-zero(24, 1) == 0.317370096629452319318170455994, 's-th zero of probabilistic Hₙ(x)';
  lives-ok { ($val, $err) = hermite-prob-zero-e(24, 1) }, 's-th zero of probabilistic Hₙ(x) with error check';
  ok $val == 0.317370096629452319318170455994, 's-th zero of probabilistic Hₙ(x) with error check: value';
  ok hermite-func-zero(24, 1) == 0.22441454747251557, 's-th zero of ψₙ(x)';
  lives-ok { ($val, $err) = hermite-func-zero-e(24, 1) }, 's-th zero of ψₙ(x) with error check';
  ok $val == 0.22441454747251557, 's-th zero of ψₙ(x) with error check: value';
}, 'Hermite polynomials and functions';

subtest {
  my ($val, $err, $e10);
  is-approx F01(1, .5), 1.5660829297563505373, :rel-tol(10⁻¹⁵), '₀F₁(c,x)';
  lives-ok { ($val, $err) = F01-e(1, .5) }, '₀F₁(c,x) with error check';
  is-approx $val, 1.5660829297563505373, :rel-tol(10⁻¹⁵), '₀F₁(c,x) with error check: value';
  is-approx F11-int(1, 1, .5), 1.6487212707001281468, :rel-tol(10⁻¹⁵), '₁F₁(m,n,x)';
  lives-ok { ($val, $err) = F11-int-e(1, 1, .5) }, '₁F₁(m,n,x) with error check';
  is-approx $val, 1.6487212707001281468, :rel-tol(10⁻¹⁵), '₁F₁(m,n,x) with error check: value';
  is-approx F11(1, 1.5, 1), 2.0300784692787049755, :rel-tol(10⁻¹⁵), '₁F₁(a,b,x)';
  lives-ok { ($val, $err) = F11-e(1, 1.5, 1) }, '₁F₁(a,b,x) with error check';
  is-approx $val, 2.0300784692787049755, :rel-tol(10⁻¹⁵), '₁F₁(a,b,x) with error check: value';
  is-approx U-int(1, 1, 2), 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x)';
  lives-ok { ($val, $err) = U-int-e(1, 1, 2) }, 'U(m,n,x) with error check';
  is-approx $val, 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x) with error check: value';
  lives-ok { ($val, $err, $e10) = U-int-e10(1, 1, 2) }, 'U(m,n,x) with extended range error check';
  is-approx $val, 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x) with extended range error check: value';
  is-approx U(1, 1.2, 2), 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x)';
  lives-ok { ($val, $err) = U-e(1, 1.2, 2) }, 'U(a,b,x) with error check';
  is-approx $val, 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x) with error check: value';
  lives-ok { ($val, $err, $e10) = U-e10(1, 1.2, 2) }, 'U(a,b,x) with extended range error check';
  is-approx $val, 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x) with extended range error check: value';
  is-approx F21(1, 1, 1, .5), 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)';
  lives-ok { ($val, $err) = F21-e(1, 1, 1, .5) }, '₂F₁(a,b,c,x) with error check';
  is-approx $val, 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x) with error check: value';
  is-approx F21-conj(1, 1, 1, .5), 3.352857095662929028, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)';
  lives-ok { ($val, $err) = F21-conj-e(1, 1, 1, .5) }, '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x) with error check';
  is-approx $val, 3.352857095662929028, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x) with error check: value';
  is-approx F21-renorm(1, 1, 1, .5), 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)/Γ(c)';
  lives-ok { ($val, $err) = F21-renorm-e(1, 1, 1, .5) }, '₂F₁(a,b,c,x)/Γ(c) with error check';
  is-approx $val, 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)/Γ(c) with error check: value';
  is-approx F21-conj-renorm(9, 9, -1.5, -.99), 0.10834020229476124874, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c)';
  lives-ok { ($val, $err) = F21-conj-renorm-e(9, 9, -1.5, -.99) }, '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c) with error check';
  is-approx $val, 0.10834020229476124874, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c) with error check: value';
  is-approx F20(.1, .5, -.02), .99901595171179281891589794, :rel-tol(10⁻¹⁵), '₂F₀(a,b,x)';
  lives-ok { ($val, $err) = F20-e(.1, .5, -.02) }, '₂F₀(a,b,x) with error check';
  is-approx $val, .99901595171179281891589794, :rel-tol(10⁻¹⁵), '₂F₀(a,b,x) with error check: value';
}, 'Hypergeometric functions';

subtest {
  my ($val, $err);
  is-approx laguerre1(1, 1), 1, :rel-tol(10⁻¹⁵), 'Lʲ₁(x)';
  lives-ok { ($val, $err) = laguerre1-e(1, 1) }, 'Lʲ₁(x) with error check';
  is-approx $val, 1, :rel-tol(10⁻¹⁵), 'Lʲ₁(x) with error check: value';
  is-approx laguerre2(1, 1), .5, :rel-tol(10⁻¹⁵), 'Lʲ₂(x)';
  lives-ok { ($val, $err) = laguerre2-e(1, 1) }, 'Lʲ₂(x) with error check';
  is-approx $val, .5, :rel-tol(10⁻¹⁵), 'Lʲ₂(x) with error check: value';
  is-approx laguerre3(2, 1), 2.3333333333333333333, :rel-tol(10⁻¹⁵), 'Lʲ₃(x)';
  lives-ok { ($val, $err) = laguerre3-e(2, 1) }, 'Lʲ₃(x) with error check';
  is-approx $val, 2.3333333333333333333, :rel-tol(10⁻¹⁵), 'Lʲ₃(x) with error check: value';
  is-approx laguerre-n(1, .5, 1), .5, :rel-tol(10⁻¹⁵), 'Lʲₙ(x)';
  lives-ok { ($val, $err) = laguerre-n-e(1, .5, 1) }, 'Lʲₙ(x) with error check';
  is-approx $val, .5, :rel-tol(10⁻¹⁵), 'Lʲₙ(x) with error check: value';
}, 'Laguerre functions';

subtest {
  my ($val, $err);
  is-approx lambert-W0(0), 0, :rel-tol(10⁻¹⁵), 'W₀(x)';
  lives-ok { ($val, $err) = lambert-W0-e(0) }, 'W₀(x) with error check';
  is-approx $val, 0, :rel-tol(10⁻¹⁵), 'W₀(x) with error check: value';
  is-approx lambert-Wm1(0), 0, :rel-tol(10⁻¹⁵), 'W₋₁(x)';
  lives-ok { ($val, $err) = lambert-Wm1-e(0) }, 'W₋₁(x) with error check';
  is-approx $val, 0, :rel-tol(10⁻¹⁵), 'W₋₁(x) with error check: value';
}, 'Lambert functions';

subtest {
  my ($val, $err);
  is-approx legendre-P1(0.5), 0.5, :rel-tol(10⁻¹⁵), 'P₁(x)';
  lives-ok { ($val, $err) = legendre-P1-e(.5) }, 'P₁(x) with error check';
  is-approx $val, 0.5, :rel-tol(10⁻¹⁵), 'P₁(x) with error check: value';
  is-approx legendre-P2(.5), -0.125, :rel-tol(10⁻¹⁵), 'P₂(x)';
  lives-ok { ($val, $err) = legendre-P2-e(.5) }, 'P₂(x) with error check';
  is-approx $val, -0.125, :rel-tol(10⁻¹⁵), 'P₂(x) with error check: value';
  is-approx legendre-P3(.5), -0.4375, :rel-tol(10⁻¹⁵), 'P₃(x)';
  lives-ok { ($val, $err) = legendre-P3-e(.5) }, 'P₃(x) with error check';
  is-approx $val, -0.4375, :rel-tol(10⁻¹⁵), 'P₃(x) with error check: value';
  is-approx legendre-Pl(1, .5), .5, :rel-tol(10⁻¹⁵), 'Pₗ(x)';
  lives-ok { ($val, $err) = legendre-Pl-e(1, .5) }, 'Pₗ(x) with error check';
  is-approx $val, .5, :rel-tol(10⁻¹⁵), 'Pₗ(x) with error check: value';
  my @out;
  lives-ok { @out = legendre-Pl-array(10, .5) }, 'Pₗ(x) array';
  is-approx @out[0], 1, :rel-tol(10⁻¹⁵), 'Pₗ(x) array [0]: value';
  my %res;
  lives-ok { %res = legendre-Pl-deriv-array(10, .5) }, 'Pₗ(x) and dPₗ(x)/dx array';
  is-approx %res<out>[0], 1, :rel-tol(10⁻¹⁵), 'Pₗ(x) and dPₗ(x)/dx array Pₗ(x)[0]: value';
  is-approx %res<derout>[0], 0, :rel-tol(10⁻¹⁵), 'Pₗ(x) and dPₗ(x)/dx array dPₗ(x)/dx[0]: value';
  is-approx legendre-Q0(0), 0, :rel-tol(10⁻¹⁵), 'Q₀(x)';
  lives-ok { ($val, $err) = legendre-Q0-e(0) }, 'Q₀(x) with error check';
  is-approx $val, 0, :rel-tol(10⁻¹⁵), 'Q₀(x) with error check: value';
  is-approx legendre-Q1(0), -1, :rel-tol(10⁻¹⁵), 'Q₁(x)';
  lives-ok { ($val, $err) = legendre-Q1-e(0) }, 'Q₁(x) with error check';
  is-approx $val, -1, :rel-tol(10⁻¹⁵), 'Q₁(x) with error check: value';
  is-approx legendre-Ql(10, .5), 0.29165813966586752393, :rel-tol(10⁻¹⁵), 'Qₗ(x)';
  lives-ok { ($val, $err) = legendre-Ql-e(10, .5) }, 'Qₗ(x) with error check';
  is-approx $val, 0.29165813966586752393, :rel-tol(10⁻¹⁵), 'Qₗ(x) with error check: value';
  ok legendre-array-index(3, 3) == 9, 'position in a Legendre array';
  lives-ok { @out = legendre-array(GSL_SF_LEGENDRE_SCHMIDT, 10, .5) }, 'Pₗⁿ(x) array';
  is-approx @out[0], 1, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) array: value';
  lives-ok { @out = legendre-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .5, 1) }, 'Pₗⁿ(x) array with error check';
  is-approx @out[legendre-array-index(3, 3)], 0.513489897661093, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) array with error check: value';
  dies-ok { @out = legendre-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .5, 3) }, 'Pₗⁿ(x) array with error check dies with csphase ≠ 1|-1';
  lives-ok { %res = legendre-deriv-array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15) }, 'dPₗⁿ(x)/dx array';
  is-approx %res<derout>[legendre-array-index(1, 0)], 1, :rel-tol(10⁻¹⁵), 'dPₗⁿ(x)/dx array: value';
  lives-ok { %res = legendre-deriv-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15, 1) }, 'dPₗⁿ(x)/dx array with error check';
  is-approx %res<derout>[legendre-array-index(1, 0)], 1, :rel-tol(10⁻¹⁵), 'dPₗⁿ(x)/dx array with error check: value';
  lives-ok { %res = legendre-deriv-alt-array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15) }, 'alt dPₗⁿ(x)/dx array';
  is-approx %res<derout>[legendre-array-index(1, 0)], -0.9886859966642594, :rel-tol(10⁻¹⁵), 'alt dPₗⁿ(x)/dx array: value';
  lives-ok { %res = legendre-deriv-alt-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15, 1) }, 'alt dPₗⁿ(x)/dx array with error check';
  is-approx %res<derout>[legendre-array-index(1, 0)], -0.9886859966642594, :rel-tol(10⁻¹⁵), 'alt dPₗⁿ(x)/dx array with error check: value';
  lives-ok { %res = legendre-deriv2-array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15) }, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array';
  is-approx %res<derout2>[legendre-array-index(1, 0)], 0, 10⁻¹⁵, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array: value';
  lives-ok { %res = legendre-deriv2-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15, 1) }, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check';
  is-approx %res<derout2>[legendre-array-index(1, 0)], 0, 10⁻¹⁵, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check: value';
  lives-ok { %res = legendre-deriv2-alt-array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15) }, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array';
  is-approx %res<derout2>[legendre-array-index(1, 0)], -.15, 10⁻¹⁵, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array: value';
  lives-ok { %res = legendre-deriv2-alt-array-e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15, 1) }, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check';
  is-approx %res<derout2>[legendre-array-index(1, 0)], -.15, 10⁻¹⁵, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check: value';
  is-approx legendre-Plm(10, 0, -.5), -0.18822860717773437500, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x)';
  dies-ok { legendre-Plm(10, 20, -.5) }, 'Pₗⁿ(x) dies when l < m';
  lives-ok { ($val, $err) =legendre-Plm-e(10, 0, -.5) }, 'Pₗⁿ(x) with error check';
  is-approx $val, -0.18822860717773437500, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) with error check: value';
  is-approx legendre-sphPlm(10, 0, -.5e0), -0.24332702369300135, :rel-tol(10⁻¹⁵), 'spherical harmonics';
  lives-ok { ($val, $err) = legendre-sphPlm-e(10, 0, -.5) }, 'spherical harmonics with error check';
  is-approx $val, -0.24332702369300135, :rel-tol(10⁻¹⁵), 'spherical harmonics with error check: value';
  is-approx conicalP-half(0, .5), 0.8573827581049917129, :rel-tol(10⁻¹⁵), 'irregular Spherical Conical Function';
  lives-ok { ($val, $err) = conicalP-half-e(0, .5) }, 'irregular Spherical Conical Function with error check';
  is-approx $val, 0.8573827581049917129, :rel-tol(10⁻¹⁵), 'irregular Spherical Conical Function with error check: value';
  is-approx conicalP-mhalf(0, .5), 0.8978491247257322404, :rel-tol(10⁻¹⁵), 'regular Spherical Conical Function';
  lives-ok { ($val, $err) = conicalP-mhalf-e(0, .5) }, 'regular Spherical Conical Function with error check';
  is-approx $val, 0.8978491247257322404, :rel-tol(10⁻¹⁵), 'regular Spherical Conical Function with error check: value';
  is-approx conicalP0(0, .5), 1.0731820071493643751, :rel-tol(10⁻¹⁵), 'P⁰₋₁ ₂₊ᵢₗ(x) Function';
  lives-ok { ($val, $err) = conicalP0-e(0, .5) }, 'P⁰₋₁ ₂₊ᵢₗ(x) Function with error check';
  is-approx $val, 1.0731820071493643751, :rel-tol(10⁻¹⁵), 'P⁰₋₁ ₂₊ᵢₗ(x) Function with error check: value';
  is-approx conicalP1(0, .5), 0.14933621085538265636, :rel-tol(10⁻¹⁵), 'P¹₋₁ ₂₊ᵢₗ(x) Function';
  lives-ok { ($val, $err) = conicalP1-e(0, .5) }, 'P¹₋₁ ₂₊ᵢₗ(x) Function with error check';
  is-approx $val, 0.14933621085538265636, :rel-tol(10⁻¹⁵), 'P¹₋₁ ₂₊ᵢₗ(x) Function with error check: value';
  is-approx conicalP-sph-reg(2, 1, -.5), 1.6406279287008789526, :rel-tol(10⁻¹⁵), 'Regular Spherical Conical Function';
  lives-ok { ($val, $err) = conicalP-sph-reg-e(2, 1, -.5) }, 'Regular Spherical Conical Function with error check';
  is-approx $val, 1.6406279287008789526, :rel-tol(10⁻¹⁵), 'Regular Spherical Conical Function with error check: value';
  is-approx conicalP-cyl-reg(2, 1, -.5), 2.2048510472375258708, :rel-tol(10⁻¹⁵), 'Regular Cylindrical Conical Function';
  lives-ok { ($val, $err) = conicalP-cyl-reg-e(2, 1, -.5) }, 'Regular Cylindrical Conical Function with error check';
  is-approx $val, 2.2048510472375258708, :rel-tol(10⁻¹⁵), 'Regular Cylindrical Conical Function with error check: value';
  is-approx legendre-H3d0(1, 1), 0.7160229153604338713, :rel-tol(10⁻¹⁵), '0 radial eigenfunction of the Laplacian on 3D hyperbolic space';
  lives-ok { ($val, $err) = legendre-H3d0-e(1, 1) }, '0 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $val, 0.7160229153604338713, :rel-tol(10⁻¹⁵), '0 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  is-approx legendre-H3d1(1, 1), 0.3397013994799344639, :rel-tol(10⁻¹⁵), '1 radial eigenfunction of the Laplacian on 3D hyperbolic space';
  lives-ok { ($val, $err) = legendre-H3d1-e(1, 1) }, '1 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $val, 0.3397013994799344639, :rel-tol(10⁻¹⁵), '1 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  is-approx legendre-H3d(5, 1, 1), 0.011498635037491577728, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space';
  lives-ok { ($val, $err) = legendre-H3d-e(5, 1, 1) }, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $val, 0.011498635037491577728, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  lives-ok { @out = legendre-H3d-array(10, 1, 3) }, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space array';
  is-approx @out[0], 0.014086820716211607, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space array: value';
}, 'Legendre functions';

subtest {
  my ($val, $err);
  is-approx gsl-log(1.1), 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(x)';
  lives-ok { ($val, $err) = gsl-log-e(1.1) }, 'log(x) with error check';
  is-approx $val, 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(x) with error check: value';
  is-approx gsl-log-abs(-1.1), 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(|x|)';
  lives-ok { ($val, $err) = gsl-log-abs-e(-1.1) }, 'log(|x|) with error check';
  is-approx $val, 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(|x|) with error check: value';
  my ($lnrval, $lnrerr, $thetaval, $thetaerr);
  lives-ok { ($lnrval, $lnrerr, $thetaval, $thetaerr) = gsl-log-complex-e(1, 1) }, 'log(z) with error check';
  is-approx $lnrval, 0.3465735902799726547, :rel-tol(10⁻¹⁵), 'log(z) with error check: lnr';
  is-approx $thetaval, 0.7853981633974483096, :rel-tol(10⁻¹⁵), 'log(z) with error check: theta';
  is-approx gsl-log1plusx(1e-4), 0.00009999500033330833533, :rel-tol(10⁻¹⁵), 'log(1+x)';
  lives-ok { ($val, $err) = gsl-log1plusx-e(1e-4) }, 'log(1+x) with error check';
  is-approx $val, 0.00009999500033330833533, :rel-tol(10⁻¹⁵), 'log(1+x) with error check: value';
  is-approx gsl-log1plusx-mx(1e-4), -4.999666691664666833e-09, :rel-tol(10⁻¹⁵), 'log(1+x)-x';
  lives-ok { ($val, $err) = gsl-log1plusx-mx-e(1e-4) }, 'log(1+x)-x with error check';
  is-approx $val, -4.999666691664666833e-09, :rel-tol(10⁻¹⁵), 'log(1+x)-x with error check: value';
}, 'logarithms';

subtest {
  my ($val, $err, @out);
  is-approx mathieu-a(2, 1.1), 4.440022293558291, :rel-tol(10⁻¹⁵), 'aₙ(q)';
  lives-ok { ($val, $err) = mathieu-a-e(2, 1.1) }, 'aₙ(q) with error check';
  is-approx $val, 4.440022293558291, :rel-tol(10⁻¹⁵), 'aₙ(q) with error check: value';
  is-approx mathieu-b(2, 1.1e0), 3.8996898851752686, :rel-tol(10⁻¹⁵), 'bₙ(q)';
  lives-ok { ($val, $err) = mathieu-b-e(2, 1.1) }, 'bₙ(q) with error check';
  is-approx $val, 3.8996898851752686, :rel-tol(10⁻¹⁵), 'bₙ(q) with error check: value';
  lives-ok { @out = mathieu-a-array(0, 5, 0) }, 'aₙ(q) array';
  is-deeply @out, [0e0, 1e0, 4e0, 9e0, 16e0, 25e0], 'aₙ(q) array: values';
  lives-ok { @out = mathieu-b-array(0, 5, 0) }, 'bₙ(q) array';
  is-deeply @out, [0e0, 1e0, 4e0, 9e0, 16e0, 25e0], 'bₙ(q) array: values';
  is-approx mathieu-ce(0, 0, 0), 0.7071067811865475, :rel-tol(10⁻¹⁵), 'ceₙ(q,x)';
  lives-ok { ($val, $err) = mathieu-ce-e(0, 0, 0) }, 'ceₙ(q,x) with error check';
  is-approx $val, 0.7071067811865475, :rel-tol(10⁻¹⁵), 'ceₙ(q,x) with error check: value';
  is-approx mathieu-se(15, 0, π/2), -1, :rel-tol(10⁻¹⁵), 'seₙ(q,x)';
  lives-ok { ($val, $err) = mathieu-se-e(15, 0, π/2) }, 'seₙ(q,x) with error check';
  is-approx $val, -1, :rel-tol(10⁻¹⁵), 'seₙ(q,x) with error check: value';
  lives-ok { @out = mathieu-ce-array(0, 5, 0, π/2) }, 'ceₙ(q,x) array';
  is-deeply @out, [0.7071067811865475e0, 6.123233995736766e-17, -1e0, -1.8369701987210297e-16, 1e0, 3.061616997868383e-16], 'ceₙ(q,x) array: values';
  lives-ok { @out = mathieu-se-array(0, 5, 0, π/2) }, 'seₙ(q,x) array';
  is-deeply @out, [0e0, 1e0, 1.2246467991473532e-16, -1e0, -2.4492935982947064e-16, 1e0], 'seₙ(q,x) array: values';
  is-approx mathieu-Mc(1, 0, 1, 0), 0.8447696705150902, :rel-tol(10⁻¹⁵), 'Mcʲₙ(q,x)';
  lives-ok { ($val, $err) = mathieu-Mc-e(1, 0, 1, 0) }, 'Mcʲₙ(q,x) with error check';
  is-approx $val, 0.8447696705150902, :rel-tol(10⁻¹⁵), 'Mcʲₙ(q,x) with error check: value';
  is-approx mathieu-Ms(1, 0, 1, 0), 0, :rel-tol(10⁻¹⁵), 'Msʲₙ(q,x)';
  lives-ok { ($val, $err) = mathieu-Ms-e(1, 0, 1, 0) }, 'Msʲₙ(q,x) with error check';
  is-approx $val, 0, :rel-tol(10⁻¹⁵), 'Msʲₙ(q,x) with error check: value';
  lives-ok { @out = mathieu-Mc-array(1, 0, 5, 1, π/2) }, 'Mcʲₙ(q,x) array';
  is-deeply @out, [-0.3118830825472924e0, -0.4013382117693621e0, 0.12436859192138153e0, 0.4930738160216241e0, 0.47545235504042044e0, 0.2964329279875498e0], 'Mcʲₙ(q,x) array: values';
  lives-ok { @out = mathieu-Ms-array(1, 0, 5, 1, π/2) }, 'Msʲₙ(q,x) array';
  is-deeply @out, [0e0, -0.3397911837218603e0, 0.1452203874466516e0, 0.4932413901187376e0, 0.47541486595587257e0, 0.2964318355087123e0], 'Msʲₙ(q,x) array: values';
}, 'Mathieu functions';

subtest {
  my ($val, $err);
  is-approx pow-int(2, 3), 8, :rel-tol(10⁻¹⁵), 'xⁿ';
  lives-ok { ($val, $err) = pow-int-e(2, 3) }, 'xⁿ with error check';
  is-approx $val, 8, :rel-tol(10⁻¹⁵), 'xⁿ with error check: value';
}, 'Power functions';

subtest {
  my ($val, $err);
  is-approx psi-int(1), -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(n)';
  lives-ok { ($val, $err) = psi-int-e(1) }, 'ψ(n) with error check';
  is-approx $val, -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(n) with error check: value';
  is-approx psi(1), -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(x)';
  lives-ok { ($val, $err) = psi-e(1) }, 'ψ(x) with error check';
  is-approx $val, -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(x) with error check: value';
  is-approx psi1piy(1), 0.09465032062247697727, :rel-tol(10⁻¹⁵), '𝕽[ψ(1+iy)]';
  lives-ok { ($val, $err) = psi1piy-e(1) }, '𝕽[ψ(1+iy)] with error check';
  is-approx $val, 0.09465032062247697727, :rel-tol(10⁻¹⁵), '𝕽[ψ(1+iy)] with error check: value';
  is-approx psi1-int(1), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(n)';
  lives-ok { ($val, $err) = psi1-int-e(1) }, 'ψ’(n) with error check';
  is-approx $val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(n) with error check: value';
  is-approx psi1(1), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(x)';
  lives-ok { ($val, $err) = psi1-e(1) }, 'ψ’(x) with error check';
  is-approx $val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(x) with error check: value';
  is-approx psin(1, 1), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψⁿ(n)';
  lives-ok { ($val, $err) = psin-e(1, 1) }, 'ψⁿ(n) with error check';
  is-approx $val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψⁿ(n) with error check: value';
}, 'Psi functions';

subtest {
  my ($val, $err);
  is-approx synchrotron1(1), 0.651422815355364504, 10⁻¹⁵, 'First synchrotron function';
  lives-ok { ($val, $err) = synchrotron1-e(1) }, 'First synchrotron function with error check';
  is-approx $val, 0.651422815355364504, 10⁻¹⁵, 'First synchrotron function with error check: value';
  is-approx synchrotron2(1), 0.49447506210420666, :rel-tol(10⁻¹⁵), 'Second synchrotron function';
  lives-ok { ($val, $err) = synchrotron2-e(1) }, 'Second synchrotron function with error check';
  is-approx $val, 0.49447506210420666, :rel-tol(10⁻¹⁵), 'Second synchrotron function with error check: value';
}, 'Synchrotron functions';

subtest {
  my ($val, $err);
  is-approx transport2(1), 0.97303256135517012845, 10⁻¹⁵, 'J(2,x)';
  lives-ok { ($val, $err) = transport2-e(1) }, 'J(2,x) with error check';
  is-approx $val, 0.97303256135517012845, 10⁻¹⁵, 'J(2,x) with error check: value';
  is-approx transport3(1), 0.479841006572417499939, 10⁻¹⁵, 'J(3,x)';
  lives-ok { ($val, $err) = transport3-e(1) }, 'J(3,x) with error check';
  is-approx $val, 0.479841006572417499939, 10⁻¹⁵, 'J(3,x) with error check: value';
  is-approx transport4(1), 0.31724404523442648241, 10⁻¹⁵, 'J(4,x)';
  lives-ok { ($val, $err) = transport4-e(1) }, 'J(4,x) with error check';
  is-approx $val, 0.31724404523442648241, 10⁻¹⁵, 'J(4,x) with error check: value';
  is-approx transport5(1), 0.236615879239094789259153, 10⁻¹⁵, 'J(5,x)';
  lives-ok { ($val, $err) = transport5-e(1) }, 'J(5,x) with error check';
  is-approx $val, 0.236615879239094789259153, 10⁻¹⁵, 'J(5,x) with error check: value';
}, 'Transport functions';

subtest {
  my ($val, $err);
  is-approx gsl-sin(1), 0.8414709848078965067, 10⁻¹⁵, 'sin(x)';
  lives-ok { ($val, $err) = gsl-sin-e(1) }, 'sin(x) with error check';
  is-approx $val, 0.8414709848078965067, 10⁻¹⁵, 'sin(x) with error check: value';
  is-approx gsl-cos(1), 0.5403023058681397174, 10⁻¹⁵, 'cos(x)';
  lives-ok { ($val, $err) = gsl-cos-e(1) }, 'cos(x) with error check';
  is-approx $val, 0.5403023058681397174, 10⁻¹⁵, 'cos(x) with error check: value';
  is-approx gsl-hypot(3, 4), 5, 10⁻¹⁵, '√x²+y²';
  lives-ok { ($val, $err) = gsl-hypot-e(3, 4) }, '√x²+y² with error check';
  is-approx $val, 5, 10⁻¹⁵, '√x²+y² with error check: value';
  is-approx gsl-sinc(80.5), 0.0039541600768172754, 10⁻¹⁵, 'sinc(x)';
  lives-ok { ($val, $err) = gsl-sinc-e(80.5) }, 'sinc(x) with error check';
  is-approx $val, 0.0039541600768172754, 10⁻¹⁵, 'sinc(x) with error check: value';
  my ($rval, $rerr, $ival, $ierr);
  lives-ok { ($rval, $rerr, $ival, $ierr) = gsl-complex-sin-e(1, 5) }, 'sin(z) with error check';
  is-approx $rval, 62.44551846769653403, 10⁻¹⁵, 'sin(z) with error check: re';
  is-approx $ival, 40.09216577799840254, 10⁻¹⁵, 'sin(z) with error check: im';
  lives-ok { ($rval, $rerr, $ival, $ierr) = gsl-complex-cos-e(1, 5) }, 'cos(z) with error check';
  is-approx $rval, 40.09580630629882573, :rel-tol(10⁻¹⁵), 'cos(z) with error check: re';
  is-approx $ival, -62.43984868079963017, :rel-tol(10⁻¹⁵), 'cos(z) with error check: im';
  lives-ok { ($rval, $rerr, $ival, $ierr) = gsl-complex-logsin-e(5, 5) }, 'log(sin(z)) with error check';
  is-approx $rval, 4.3068909128079757420, 10⁻¹⁵, 'log(sin(z)) with error check: re';
  is-approx $ival, 2.8540063315538773952, 10⁻¹⁵, 'log(sin(z)) with error check: im';
  is-approx gsl-lnsinh(1), 0.16143936157119563361, 10⁻¹⁵, 'log(sinh(x))';
  lives-ok { ($val, $err) = gsl-lnsinh-e(1) }, 'log(sinh(x)) with error check';
  is-approx $val, 0.16143936157119563361, 10⁻¹⁵, 'log(sinh(x)) with error check: value';
  is-approx gsl-lncosh(1), 0.4337808304830271870, 10⁻¹⁵, 'log(cosh(x))';
  lives-ok { ($val, $err) = gsl-lncosh-e(1) }, 'log(cosh(x)) with error check';
  is-approx $val, 0.4337808304830271870, 10⁻¹⁵, 'log(cosh(x)) with error check: value';
  my ($xval, $xerr, $yval, $yerr);
  lives-ok { ($xval, $xerr, $yval, $yerr) = polar-to-rect(10, π/6) }, 'polar to rect';
  is-approx $xval, (10 * sqrt(3) / 2), :rel-tol(10⁻¹⁵), 'polar to rect: value';
  is-approx $yval, 5, :rel-tol(10⁻¹⁵), 'polar to rect: value';
  dies-ok { ($xval, $xerr, $yval, $yerr) = polar-to-rect(10, 3 * π) }, 'polar to rect dies when theta > π';
  my ($thetaval, $thetaerr);
  lives-ok { ($rval, $rerr, $thetaval, $thetaerr) = rect-to-polar(10, 6) }, 'rect to polar';
  is-approx $rval, 11.6619037896906, :rel-tol(10⁻¹⁵), 'rect to polar: value';
  is-approx $thetaval, 0.5404195002705842, :rel-tol(10⁻¹⁵), 'rect to polar: value';
  is-approx angle-restrict-symm(1e9), 0.5773954235013851694, 10⁻¹⁵, 'θ in [-π,π)';
  lives-ok { $thetaval = angle-restrict-symm-e(1e9) }, 'θ in [-π,π) with error check';
  is-approx $thetaval, 0.5773954235013851694, 10⁻¹⁵, 'θ in [-π,π) with error check: value';
  is-approx angle-restrict-pos(1e9), 0.5773954235013851694, 10⁻¹⁵, 'θ in [-0,2π)';
  lives-ok { $thetaval = angle-restrict-pos-e(1e9) }, 'θ in [-0,2π) with error check';
  is-approx $thetaval, 0.5773954235013851694, 10⁻¹⁵, 'θ in [-0,2π) with error check: value';
  lives-ok { ($val, $err) = gsl-sin-err-e(1, 1e-9) }, 'sin(x±dx) with error check';
  is-approx $val, 0.8414709848078965067, 10⁻¹⁵, 'sin(x±dx) with error check: value';
  lives-ok { ($val, $err) = gsl-cos-err-e(1, 1e-9) }, 'cos(x±dx) with error check';
  is-approx $val, 0.5403023058681397174, 10⁻¹⁵, 'cos(x±dx) with error check: value';
}, 'Trigonometric functions';

subtest {
  my ($val, $err);
  is-approx zeta-int(5), 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)';
  lives-ok { ($val, $err) = zeta-int-e(5) }, 'ζ(n) with error check';
  is-approx $val, 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(n) with error check: value';
  is-approx zeta(5), 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)';
  lives-ok { ($val, $err) = zeta-e(5) }, 'ζ(x) with error check';
  is-approx $val, 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(x) with error check: value';
  is-approx zetam1-int(5), 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)-1';
  lives-ok { ($val, $err) = zetam1-int-e(5) }, 'ζ(n)-1 with error check';
  is-approx $val, 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)-1 with error check: value';
  is-approx zetam1(5), 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)-1';
  lives-ok { ($val, $err) = zetam1-e(5) }, 'ζ(x)-1 with error check';
  is-approx $val, 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)-1 with error check: value';
  is-approx hzeta(5, 1), 1.0369277551433699263, 10⁻¹⁵, 'ζ(s,q)';
  lives-ok { ($val, $err) = hzeta-e(5, 1) }, 'ζ(s,q) with error check';
  is-approx $val, 1.0369277551433699263, 10⁻¹⁵, 'ζ(s,q) with error check: value';
  is-approx eta-int(5), 0.9721197704469093059, 10⁻¹⁵, 'η(n)';
  lives-ok { ($val, $err) = eta-int-e(5) }, 'η(n) with error check';
  is-approx $val, 0.9721197704469093059, 10⁻¹⁵, 'η(n) with error check: value';
  is-approx eta(5), 0.9721197704469093059, 10⁻¹⁵, 'η(x)';
  lives-ok { ($val, $err) = eta-e(5) }, 'η(x) with error check';
  is-approx $val, 0.9721197704469093059, 10⁻¹⁵, 'η(x) with error check: value';
}, 'Zeta functions';

done-testing;
