### ----------------------------------------------------
### -- Math::Libgsl::Function
### -- Licenses: Artistic-2.0
### -- Authors: Fernando Santagata
### -- File: t/02-function.rakutest
### ----------------------------------------------------
### -- Chunk 1 of 5
#!/usr/bin/env raku

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, 