#!/usr/bin/env perl6

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

subtest {
  is-approx gsl_sf_airy_Ai(0e0, GSL_PREC_DOUBLE), 0.355028053887817, :rel-tol(10⁻¹⁵), 'Ai';
  my gsl_sf_result $res .= new;
  ok gsl_sf_airy_Ai_e(0e0, GSL_PREC_DOUBLE, $res) == 0, 'Ai with error check';
  is-approx $res.val, 0.355028053887817, :rel-tol(10⁻¹⁵), 'Ai: value';
  ok $res.err < 10⁻¹⁶, 'Ai: error';
  is-approx gsl_sf_airy_Bi(0e0, GSL_PREC_DOUBLE), 0.614926627446001, :rel-tol(10⁻¹⁵), 'Bi';
  ok gsl_sf_airy_Bi_e(0e0, GSL_PREC_DOUBLE, $res) == 0, 'Bi with error check';
  is-approx $res.val, 0.614926627446001, :rel-tol(10⁻¹⁵), 'Bi: value';
  ok $res.err < 10⁻¹⁵, 'Bi: error';
  is-approx gsl_sf_airy_Ai_scaled(10e0, GSL_PREC_DOUBLE), 0.158123666854346, :rel-tol(10⁻¹⁵), 'Ai scaled';
  ok gsl_sf_airy_Ai_scaled_e(10e0, GSL_PREC_DOUBLE, $res) == 0, 'Ai scaled with error check';
  is-approx $res.val, 0.158123666854346, :rel-tol(10⁻¹⁵), 'Ai scaled: value';
  is-approx gsl_sf_airy_Bi_scaled(10e0, GSL_PREC_DOUBLE), 0.318340105336734, :rel-tol(10⁻¹⁴), 'Bi scaled';
  ok gsl_sf_airy_Bi_scaled_e(10e0, GSL_PREC_DOUBLE, $res) == 0, 'Bi scaled with error check';
  is-approx $res.val, 0.318340105336734, :rel-tol(10⁻¹⁴), 'Bi scaled: value';
  is-approx gsl_sf_airy_Ai_deriv(0e0, GSL_PREC_DOUBLE), -0.258819403792807, :rel-tol(10⁻¹⁵), 'Ai deriv';
  ok gsl_sf_airy_Ai_deriv_e(0e0, GSL_PREC_DOUBLE, $res) == 0, 'Ai deriv with error check';
  is-approx $res.val, -0.258819403792807, :rel-tol(10⁻¹⁵), 'Ai deriv: value';
  is-approx gsl_sf_airy_Bi_deriv(0e0, GSL_PREC_DOUBLE), 0.448288357353826, :rel-tol(10⁻¹⁵), 'Bi deriv';
  ok gsl_sf_airy_Bi_deriv_e(0e0, GSL_PREC_DOUBLE, $res) == 0, 'Bi deriv with error check';
  is-approx $res.val, 0.448288357353826, :rel-tol(10⁻¹⁵), 'Bi deriv: value';
  is-approx gsl_sf_airy_Ai_deriv_scaled(10e0, GSL_PREC_DOUBLE), -0.503909360711311, :rel-tol(10⁻¹⁵), 'Ai deriv scaled';
  ok gsl_sf_airy_Ai_deriv_scaled_e(10e0, GSL_PREC_DOUBLE, $res) == 0, 'Ai deriv scaled with error check';
  is-approx $res.val, -0.503909360711311, :rel-tol(10⁻¹⁵), 'Ai deriv scaled: value';
  is-approx gsl_sf_airy_Bi_deriv_scaled(10e0, GSL_PREC_DOUBLE), 0.998555942673837, :rel-tol(10⁻¹⁵), 'Bi deriv scaled';
  ok gsl_sf_airy_Bi_deriv_scaled_e(10e0, GSL_PREC_DOUBLE, $res) == 0, 'Bi deriv scaled with error check';
  is-approx $res.val, 0.998555942673837, :rel-tol(10⁻¹⁵), 'Bi deriv scaled: value';
  is-approx gsl_sf_airy_zero_Ai(1), -2.338107410459767, :rel-tol(10⁻¹⁵), 'zero of Ai';
  ok gsl_sf_airy_zero_Ai_e(1, $res) == 0, 'zero of Ai with error check';
  is-approx $res.val, -2.338107410459767, :rel-tol(10⁻¹⁵), 'zero of Ai: value';
  ok gsl_sf_airy_zero_Bi(1).round(10⁻¹⁴) == -1.17371322270913, 'zero of Bi';
  ok gsl_sf_airy_zero_Bi_e(1, $res) == 0, 'zero of Bi with error check';
  ok $res.val.round(10⁻¹⁴) == -1.17371322270913, 'zero of Bi: value';
  ok gsl_sf_airy_zero_Ai_deriv(1).round(10⁻¹⁴) == -1.01879297164747, 'zero of Ai deriv';
  ok gsl_sf_airy_zero_Ai_deriv_e(1, $res) == 0, 'zero of Ai deriv with error check';
  ok $res.val.round(10⁻¹⁴) == -1.01879297164747, 'zero of Ai deriv: value';
  ok gsl_sf_airy_zero_Bi_deriv(1).round(10⁻¹⁴) == -2.29443968261412, 'zero of Bi deriv';
  ok gsl_sf_airy_zero_Bi_deriv_e(1, $res) == 0, 'zero of Bi deriv with error check';
  ok $res.val.round(10⁻¹⁴) == -2.29443968261412, 'zero of Bi deriv: value';
}, 'raw - Airy functions';

subtest {
  ok gsl_sf_bessel_J0(0e0) == 1, 'J0';
  my gsl_sf_result $res .= new;
  ok gsl_sf_bessel_J0_e(2.0e0, $res) == 0, 'J0 with error check';
  is-approx $res.val, 0.223890779141236, :rel-tol(10⁻¹⁴), 'J0 with error check: value';
  ok gsl_sf_bessel_J1(0e0) == 0, 'J1';
  ok gsl_sf_bessel_J1_e(2.0e0, $res) == 0, 'J1 with error check';
  is-approx $res.val, 0.576724807756873, :rel-tol(10⁻¹⁵), 'J1 with error check: value';
  ok gsl_sf_bessel_Jn(2, 0e0) == 0, 'Jn';
  ok gsl_sf_bessel_Jn_e(4, 0.1e0, $res) == 0, 'Jn with error check';
  is-approx $res.val, 2.602864854568404e-07, :rel-tol(10⁻¹⁵), 'Jn with error check: value';
  my $result = CArray[num64].allocate: 3;
  ok gsl_sf_bessel_Jn_array(0, 2, 0e0, $result) == 0, 'Jn array returns ok';
  is-deeply $result.list, (1e0, 0e0, 0e0), 'Jn array results';
  is-approx gsl_sf_bessel_Y0(0.1e0), -1.534238651350367, :rel-tol(10⁻¹⁵), 'Y0';
  ok gsl_sf_bessel_Y0_e(0.1e0, $res) == 0, 'Y0 with error check';
  is-approx $res.val, -1.534238651350367, :rel-tol(10⁻¹⁵), 'Y0 with error check: value';
  is-approx gsl_sf_bessel_Y1(0.1e0), -6.458951094702026, :rel-tol(10⁻¹⁵), 'Y1';
  ok gsl_sf_bessel_Y1_e(0.1e0, $res) == 0, 'Y1 with error check';
  is-approx $res.val, -6.458951094702026, :rel-tol(10⁻¹⁵), 'Y1 with error check: value';
  ok gsl_sf_bessel_Yn(4, 0.1e0) == -305832.2979335312, 'Yn';
  ok gsl_sf_bessel_Yn_e(4, 0.1e0, $res) == 0, 'Yn with error check';
  ok $res.val == -305832.2979335312, 'Yn with error check: value';
  ok gsl_sf_bessel_Yn_array(0, 2, 0.1e0, $result) == 0, 'Yn array returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (-1.534238651350367, -6.458951094702026, -127.644783242690176), 'Yn array results';
  is-approx gsl_sf_bessel_I0(.1e0), 1.002501562934096, :rel-tol(10⁻¹⁵), 'I0';
  ok gsl_sf_bessel_I0_e(.1e0, $res) == 0, 'I0 with error check';
  is-approx $res.val, 1.002501562934096, :rel-tol(10⁻¹⁵), 'I0 with error check: value';
  is-approx gsl_sf_bessel_I1(0.1e0), 0.050062526047092694, :rel-tol(10⁻¹⁵), 'I1';
  ok gsl_sf_bessel_I1_e(0.1e0, $res) == 0, 'I1 with error check';
  is-approx $res.val, 0.050062526047092694, :rel-tol(10⁻¹⁵), 'I1 with error check: value';
  is-approx gsl_sf_bessel_In(-4, 0.1e0), 2.6054690212996574e-07, :rel-tol(10⁻¹⁵), 'In';
  ok gsl_sf_bessel_In_e(-4, 0.1e0, $res) == 0, 'In with error check';
  is-approx $res.val, 2.6054690212996574e-07, :rel-tol(10⁻¹⁵), 'In with error check: value';
  ok gsl_sf_bessel_In_array(0, 2, 0.1e0, $result) == 0, 'In array returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (1.002501562934096, 0.050062526047093, 0.001251041992242), 'In array results';
  ok gsl_sf_bessel_I0_scaled(.1e0) == 0.9071009257823011, 'I0 scaled';
  ok gsl_sf_bessel_I0_scaled_e(.1e0, $res) == 0, 'I0 scaled with error check';
  ok $res.val == 0.9071009257823011, 'I0 scaled with error check: value';
  ok gsl_sf_bessel_I1_scaled(0.1e0) == 0.045298446808809324, 'I1 scaled';
  ok gsl_sf_bessel_I1_scaled_e(0.1e0, $res) == 0, 'I1 scaled with error check';
  ok $res.val == 0.045298446808809324, 'I1 scaled with error check: value';
  ok gsl_sf_bessel_In_scaled(-4, 0.1e0) == 2.3575258620054605e-07, 'In scaled';
  ok gsl_sf_bessel_In_scaled_e(-4, 0.1e0, $res) == 0, 'In scaled with error check';
  ok $res.val == 2.3575258620054605e-07, 'In scaled with error check: value';
  ok gsl_sf_bessel_In_scaled_array(0, 2, 0.1e0, $result) == 0, 'In scaled array returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (0.907100925782301, 0.045298446808809, 0.001131989606115), 'In scaled array results';
  is-approx gsl_sf_bessel_K0(.1e0), 2.427069024702017, :rel-tol(10⁻¹⁵), 'K0';
  ok gsl_sf_bessel_K0_e(.1e0, $res) == 0, 'K0 with error check';
  ok $res.val == 2.427069024702017, 'K0 with error check: value';
  is-approx gsl_sf_bessel_K1(.1e0), 9.853844780870606, :rel-tol(10⁻¹⁵), 'K1';
  ok gsl_sf_bessel_K1_e(.1e0, $res) == 0, 'K1 with error check';
  ok $res.val == 9.853844780870606, 'K1 with error check: value';
  is-approx gsl_sf_bessel_Kn(0, .1e0), 2.427069024702017, :rel-tol(10⁻¹⁵), 'Kn';
  ok gsl_sf_bessel_Kn_e(0, .1e0, $res) == 0, 'Kn with error check';
  ok $res.val == 2.427069024702017, 'Kn with error check: value';
  ok gsl_sf_bessel_Kn_array(0, 2, .1e0, $result) == 0, 'Kn array returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (2.427069024702017, 9.853844780870606, 199.503964642114144), 'Kn array results';
  is-approx gsl_sf_bessel_K0_scaled(.1e0), 2.682326102262895, :rel-tol(10⁻¹⁵), 'K0 scaled';
  ok gsl_sf_bessel_K0_scaled_e(.1e0, $res) == 0, 'K0 scaled with error check';
  ok $res.val == 2.682326102262895, 'K0 scaled with error check: value';
  is-approx gsl_sf_bessel_K1_scaled(.1e0), 10.890182683049698, :rel-tol(10⁻¹⁵), 'K1 scaled';
  ok gsl_sf_bessel_K1_scaled_e(.1e0, $res) == 0, 'K1 scaled with error check';
  ok $res.val == 10.890182683049698, 'K1 scaled with error check: value';
  is-approx gsl_sf_bessel_Kn_scaled(5, 2e0), 69.68655087607676, :rel-tol(10⁻¹⁵), 'Kn scaled';
  ok gsl_sf_bessel_Kn_scaled_e(5, 2e0, $res) == 0, 'Kn scaled with error check';
  is-approx $res.val, 69.68655087607676, :rel-tol(10⁻¹⁵), 'Kn scaled with error check: value';
  is-approx gsl_sf_bessel_Kn_scaled_array(5, 8, 2e0, $result), 0, :rel-tol(10⁻¹⁵), 'Kn scaled array';
  is-deeply $result.list».round(10⁻¹⁵), (69.68655087607676, 364.658500356566016, 2257.63755301547264), 'Kn scaled array results';
  is-approx gsl_sf_bessel_j0(1e0), 0.841470984807897, :rel-tol(10⁻¹⁵), 'j0';
  ok gsl_sf_bessel_j0_e(1e0, $res) == 0, 'j0 with error check';
  is-approx $res.val, 0.841470984807897, :rel-tol(10⁻¹⁵), 'j0 with error check: value';
  is-approx gsl_sf_bessel_j1(1e0), 0.301168678939757, :rel-tol(10⁻¹⁵), 'j1';
  ok gsl_sf_bessel_j1_e(1e0, $res) == 0, 'j1 with error check';
  is-approx $res.val, 0.301168678939757, :rel-tol(10⁻¹⁵), 'j1 with error check: value';
  is-approx gsl_sf_bessel_j2(1e0), 0.06203505201137386, :rel-tol(10⁻¹⁵), 'j2';
  ok gsl_sf_bessel_j2_e(1e0, $res) == 0, 'j2 with error check';
  is-approx $res.val, 0.06203505201137386, :rel-tol(10⁻¹⁵), 'j2 with error check: value';
  is-approx gsl_sf_bessel_jl(0, 0e0), 1, :rel-tol(10⁻¹⁵), 'jl';
  ok gsl_sf_bessel_jl_e(0, 0e0, $res) == 0, 'jl with error check';
  is-approx $res.val, 1, :rel-tol(10⁻¹⁵), 'jl with error check: value';
  ok gsl_sf_bessel_jl_array(2, 0e0, $result) == 0, 'jl array returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (1.0, 0.0, 0.0), 'jl array scaled results';
  ok gsl_sf_bessel_jl_array(2, 0e0, $result) == 0, 'jl array steed returns ok';
  is-deeply $result.list».round(10⁻¹⁵), (1.0, 0.0, 0.0), 'jl array steed scaled results';
  is-approx gsl_sf_bessel_y0(1e0), -0.54030230586814, :rel-tol(10⁻¹⁵), 'y0';
  ok gsl_sf_bessel_y0_e(1e0, $res) == 0, 'y0 with error check';
  is-approx $res.val, -0.54030230586814, :rel-tol(10⁻¹⁵), 'y0 with error check: value';
  is-approx gsl_sf_bessel_y1(1e0), -1.381773290676036, :rel-tol(10⁻¹⁵), 'y1';
  ok gsl_sf_bessel_y1_e(1e0, $res) == 0, 'y1 with error check';
  is-approx $res.val, -1.381773290676036, :rel-tol(10⁻¹⁵), 'y1 with error check: value';
  is-approx gsl_sf_bessel_y2(1e0), -3.605017566159968, :rel-tol(10⁻¹⁵), 'y2';
  ok gsl_sf_bessel_y2_e(1e0, $res) == 0, 'y2 with error check';
  is-approx $res.val, -3.605017566159968, :rel-tol(10⁻¹⁵), 'y2 with error check: value';
  is-approx gsl_sf_bessel_yl(0, 1e0), -0.54030230586814, :rel-tol(10⁻¹⁵), 'yl';
  ok gsl_sf_bessel_yl_e(0, 1e0, $res) == 0, 'yl with error check';
  is-approx $res.val, -0.54030230586814, :rel-tol(10⁻¹⁵), 'yl with error check: value';
  ok gsl_sf_bessel_yl_array(0, 1e0, $result) == 0, 'yl array';
  is-deeply $result.list».round(10⁻¹⁵), (-0.54030230586814, .0, .0), 'yl array results';
  ok gsl_sf_bessel_i0_scaled(0e0) == 1, 'i0 scaled';
  ok gsl_sf_bessel_i0_scaled_e(0e0, $res) == 0, 'i0 scaled with error check';
  ok $res.val == 1, 'i0 scaled with error check: value';
  ok gsl_sf_bessel_i1_scaled(0e0) == .0, 'i1 scaled';
  ok gsl_sf_bessel_i1_scaled_e(0e0, $res) == 0, 'i1 scaled with error check';
  ok $res.val == .0, 'i1 scaled with error check: value';
  ok gsl_sf_bessel_i2_scaled(0e0) == .0, 'i2 scaled';
  ok gsl_sf_bessel_i2_scaled_e(0e0, $res) == 0, 'i2 scaled with error check';
  ok $res.val == .0, 'i2 scaled with error check: value';
  ok gsl_sf_bessel_il_scaled(0, 0e0) == 1e0, 'il scaled';
  ok gsl_sf_bessel_il_scaled_e(0, 0e0, $res) == 0, 'il scaled with error check';
  ok $res.val == 1e0, 'il scaled with error check: value';
  ok gsl_sf_bessel_il_scaled_array(3, 0e0, $result) == 0, 'il scaled array';
  is-deeply $result.list, (1e0, 0e0, 0e0), 'il scaled array results';
  is-approx gsl_sf_bessel_k0_scaled(2e0), 0.785398163397448, :rel-tol(10⁻¹⁵), 'k0 scaled';
  ok gsl_sf_bessel_k0_scaled_e(2e0, $res) == 0, 'k0 scaled with error check';
  is-approx $res.val, 0.785398163397448, :rel-tol(10⁻¹⁵), 'k0 scaled with error check: value';
  is-approx gsl_sf_bessel_k1_scaled(2e0), 1.178097245096172, :rel-tol(10⁻¹⁵), 'k1 scaled';
  ok gsl_sf_bessel_k1_scaled_e(2e0, $res) == 0, 'k1 scaled with error check';
  is-approx $res.val, 1.178097245096172, :rel-tol(10⁻¹⁵), 'k1 scaled with error check: value';
  is-approx gsl_sf_bessel_k2_scaled(2e0), 2.552544031041707, :rel-tol(10⁻¹⁵), 'k2 scaled';
  ok gsl_sf_bessel_k2_scaled_e(2e0, $res) == 0, 'k2 scaled with error check';
  is-approx $res.val, 2.552544031041707, :rel-tol(10⁻¹⁵), 'k2 scaled with error check: value';
  is-approx gsl_sf_bessel_kl_scaled(5, 2e0), 138.107358294920048, :rel-tol(10⁻¹⁵), 'kl scaled';
  ok gsl_sf_bessel_kl_scaled_e(5, 2e0, $res) == 0, 'kl scaled with error check';
  is-approx $res.val, 138.107358294920048, :rel-tol(10⁻¹⁵), 'kl scaled with error check: value';
  is-approx gsl_sf_bessel_kl_scaled_array(2, 2e0, $result), 0, :rel-tol(10⁻¹⁵), 'kl scaled array';
  is-deeply $result.list».round(10⁻¹⁵), (0.785398163397448, 1.178097245096172, 2.552544031041707), 'kl scaled array results';
  is-approx gsl_sf_bessel_Jnu(.75e0, 1e0), 0.558652493204891, :rel-tol(10⁻¹⁵), 'Jnu';
  ok gsl_sf_bessel_Jnu_e(.75e0, 1e0, $res) == 0, 'Jnu with error check';
  is-approx $res.val, 0.558652493204891, :rel-tol(10⁻¹⁵), 'Jnu with error check: value';
  my CArray[num64] $v .= new: .1e0, .2e0 … 10e0;
  ok gsl_sf_bessel_sequence_Jnu_e(2e0, GSL_MODE_DEFAULT, 100, $v) == 0, 'Jnu sequence with error check';
  is-approx $v[0], 0.0012489586587999192, :rel-tol(10⁻¹⁵), 'Jnu sequence with error check: value [0]';
  is-approx $v[20], 0.37462362515054953, :rel-tol(10⁻¹⁵), 'Jnu sequence with error check: value [20]';
  is-approx gsl_sf_bessel_Ynu(.0001e0, 1e0), 0.08813676933044477, :rel-tol(10⁻¹⁵), 'Ynu';
  ok gsl_sf_bessel_Ynu_e(.0001e0, 1e0, $res) == 0, 'Ynu with error check';
  is-approx $res.val, 0.08813676933044477, :rel-tol(10⁻¹⁵), 'Ynu with error check: value';
  is-approx gsl_sf_bessel_Inu(1e0, 1e0), 0.565159103992485, :rel-tol(10⁻¹⁵), 'Inu';
  ok gsl_sf_bessel_Inu_e(1e0, 1e0, $res) == 0, 'Inu with error check';
  is-approx $res.val, 0.565159103992485, :rel-tol(10⁻¹⁵), 'Inu with error check: value';
  is-approx gsl_sf_bessel_Inu_scaled(1e0, 1e0), 0.20791041534970847, :rel-tol(10⁻¹⁵), 'Inu scaled';
  ok gsl_sf_bessel_Inu_scaled_e(1e0, 1e0, $res) == 0, 'Inu scaled with error check';
  is-approx $res.val, 0.20791041534970847, :rel-tol(10⁻¹⁵), 'Inu scaled with error check: value';
  is-approx gsl_sf_bessel_Knu(1e0, 1e0), 0.601907230197235, :rel-tol(10⁻¹⁵), 'Knu';
  ok gsl_sf_bessel_Knu_e(1e0, 1e0, $res) == 0, 'Knu with error check';
  is-approx $res.val, 0.601907230197235, :rel-tol(10⁻¹⁵), 'Knu with error check: value';
  is-approx gsl_sf_bessel_lnKnu(1e0, 1e0), -0.507651948210752, :rel-tol(10⁻¹⁵), 'lnKnu';
  ok gsl_sf_bessel_lnKnu_e(1e0, 1e0, $res) == 0, 'lnKnu with error check';
  is-approx $res.val, -0.507651948210752, :rel-tol(10⁻¹⁵), 'lnKnu with error check: value';
  is-approx gsl_sf_bessel_Knu_scaled(1e0, 1e0), 1.636153486263258, :rel-tol(10⁻¹⁵), 'Knu scaled';
  ok gsl_sf_bessel_Knu_scaled_e(1e0, 1e0, $res) == 0, 'Knu scaled with error check';
  is-approx $res.val, 1.636153486263258, :rel-tol(10⁻¹⁵), 'Knu scaled with error check: value';
  is-approx gsl_sf_bessel_zero_J0(1), 2.404825557695771, :rel-tol(10⁻¹⁵), 'zero of J0';
  ok gsl_sf_bessel_zero_J0_e(1, $res) == 0, 'zero of J0 with error check';
  is-approx $res.val, 2.404825557695771, :rel-tol(10⁻¹⁵), 'zero of J0 with error check: value';
  is-approx gsl_sf_bessel_zero_J1(1), 3.831705970207503, :rel-tol(10⁻¹⁵), 'zero of J1';
  ok gsl_sf_bessel_zero_J1_e(1, $res) == 0, 'zero of J1 with error check';
  is-approx $res.val, 3.831705970207503, :rel-tol(10⁻¹⁵), 'zero of J1 with error check: value';
  is-approx gsl_sf_bessel_zero_Jnu(0e0, 1), 2.404825557695775, :rel-tol(10⁻¹⁵), 'zero of Jnu';
  ok gsl_sf_bessel_zero_Jnu_e(0e0, 1, $res) == 0, 'zero of Jnu with error check';
  is-approx $res.val, 2.404825557695775, :rel-tol(10⁻¹⁵), 'zero of Jnu with error check: value';
}, 'raw - Bessel functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_clausen(π/20), 0.447888244813355, :rel-tol(10⁻¹⁵), 'Clausen';
  ok gsl_sf_clausen_e(π/20, $res) == 0, 'Clausen with error check';
  is-approx $res.val, 0.447888244813355, :rel-tol(10⁻¹⁵), 'Clausen with error check: value';
}, 'raw - Clausen functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_hydrogenicR_1(3e0, 2e0), 0.025759948256148472, :rel-tol(10⁻¹⁵), 'hydrogenic R 1';
  ok gsl_sf_hydrogenicR_1_e(3e0, 2e0, $res) == 0, 'hydrogenic R 1 with error check';
  is-approx $res.val, 0.025759948256148472, :rel-tol(10⁻¹⁵), 'hydrogenic R 1 with error check: value';
  is-approx gsl_sf_hydrogenicR(4, 1, 3e0, 0e0), 0e0, :rel-tol(10⁻¹⁵), 'hydrogenic R';
  ok gsl_sf_hydrogenicR_e(4, 1, 3e0, 0e0, $res) == 0, 'hydrogenic R with error check';
  is-approx $res.val, 0e0, :rel-tol(10⁻¹⁵), 'hydrogenic R with error check: value';

  my num64 ($exp_F, $exp_G);
  my num64 $eta   = 1e0;
  my num64 $x     = 5e0;
  my num64 $L_F   = 0e0;
  my int32 $k     = 0;
  my gsl_sf_result $F  .= new;
  my gsl_sf_result $Fp .= new;
  my gsl_sf_result $G  .= new;
  my gsl_sf_result $Gp .= new;
  ok gsl_sf_coulomb_wave_FG_e($eta, $x, $L_F, $k, $F, $Fp, $G, $Gp, $exp_F, $exp_G) == 0, 'F and G + derivatives';
  is-approx $F.val, 0.684937412005944, :rel-tol(10⁻¹⁵), 'F: value';
  is-approx $Fp.val, -0.723642386255606, :rel-tol(10⁻¹⁵), 'F derivative: value';
  is-approx $G.val, -0.8984143590920198, :rel-tol(10⁻¹⁵), 'G: value';
  is-approx $Gp.val, -0.510804758519035, :rel-tol(10⁻¹⁵), 'G derivative: value';

  my num64 $L_min = 1e0;
  my int32 $kmax  = 3;
  my CArray[num64] $fc_array .= new: 0e0, 0e0, 0e0, 0e0;
  my num64 $F_exponent = 0e0;
  ok gsl_sf_coulomb_wave_F_array($L_min, $kmax, $eta, $x, $fc_array, $F_exponent) == 0, 'F array';
  is-deeply $fc_array.list».round(10⁻¹⁵), (1.092881104936675, 1.186370500609351, 0.904222651420796, 0.526623050054267), 'F array results';
  ok $F_exponent == 0, 'F array overflow exponent';

  $F_exponent = 0e0;
  my num64 $G_exponent = 0e0;
  $fc_array[^4] = 0e0, 0e0, 0e0, 0e0;
  my CArray[num64] $gc_array .= new: 0e0, 0e0, 0e0, 0e0;
  ok gsl_sf_coulomb_wave_FG_array($L_min, $kmax, $eta, $x, $fc_array, $gc_array, $F_exponent, $G_exponent) == 0, 'FG array';
  is-deeply $fc_array.list».round(10⁻¹⁵), (1.092881104936676, 1.186370500609353, 0.904222651420797, 0.526623050054267), 'FG array results: F';
  is-deeply $gc_array.list».round(10⁻¹⁵), (-0.401136354144034, 0.382961011797984, 1.091535333071877, 1.708616969572756), 'FG array results: G';
  ok $F_exponent == 0, 'F array overflow exponent';
  ok $G_exponent == 0, 'G array overflow exponent';

  $fc_array[^4] = 0e0, 0e0, 0e0, 0e0;
  $gc_array[^4] = 0e0, 0e0, 0e0, 0e0;
  $F_exponent = 0e0;
  $G_exponent = 0e0;
  my CArray[num64] $fcp_array .= new: 0e0, 0e0, 0e0, 0e0;
  my CArray[num64] $gcp_array .= new: 0e0, 0e0, 0e0, 0e0;
  ok gsl_sf_coulomb_wave_FGp_array($L_min, $kmax, $eta, $x, $fc_array, $fcp_array, $gc_array, $gcp_array, $F_exponent, $G_exponent) == 0, 'FG array + derivatives';
  is-deeply $fc_array.list».round(10⁻¹⁵), (1.092881104936676, 1.186370500609353, 0.904222651420797, 0.526623050054267), 'FG array results: F';
  is-deeply $gc_array.list».round(10⁻¹⁵), (-0.401136354144034, 0.382961011797984, 1.091535333071877, 1.708616969572756), 'FG array results: G';
  is-deeply $fcp_array.list».round(10⁻¹⁵), (-0.342809548488476, 0.154144770433327, 0.406603168927167, 0.37909717266402), 'FG array results: F derivative';
  is-deeply $gcp_array.list».round(10⁻¹⁵), (-0.789186146285826, -0.79314898867443, -0.615089960092336, -0.668918949964118), 'FG array results: G derivative';
  ok $F_exponent == 0, 'F array overflow exponent';
  ok $G_exponent == 0, 'G array overflow exponent';

  $fc_array[^4] = 0e0, 0e0, 0e0, 0e0;
  $F_exponent = 0e0;
  ok gsl_sf_coulomb_wave_sphF_array($L_min, $kmax, $eta, $x, $fc_array, $F_exponent) == 0, 'F/x array';
  is-deeply $fc_array.list».round(10⁻¹⁵), (0.218576220987335, 0.23727410012187, 0.180844530284159, 0.105324610010853), 'F/x array results';
  ok $F_exponent == 0, 'F/x array overflow exponent';

  my num64 $L = 2e0;
  my gsl_sf_result $result .= new;
  ok gsl_sf_coulomb_CL_e($L, $eta, $result) == 0, 'Normalization Constant';
  is-approx $result.val, 0.011428736368066569, :rel-tol(10⁻¹⁵), 'Normalization Constant: value';

  my CArray[num64] $cl .= new: 0e0, 0e0, 0e0, 0e0;
  ok gsl_sf_coulomb_CL_array($L_min, $kmax, $eta, $cl) == 0, 'Normalization Constant array';
  is-deeply $cl.list».round(10⁻¹⁵), (0.051110862831842, 0.011428736368067, 0.001720992271461, 0.000197106469892), 'Normalization Constant array: values';
}, 'raw - Coulomb functions';

subtest {
  my gsl_sf_result $res .= new;
  ok gsl_sf_coupling_3j(0, 1, 1, 0,  1, -1) == sqrt(½), '3-j';
  ok gsl_sf_coupling_3j_e(0, 1, 1, 0,  1, -1, $res) == 0, '3-j with error check';
  ok $res.val == sqrt(½), '3-j with error check: value';
  ok gsl_sf_coupling_6j(2, 2, 4, 2,  2, 2) == 1e0/6e0, '6-j';
  ok gsl_sf_coupling_6j_e(2, 2, 4, 2,  2, 2, $res) == 0, '6-j with error check';
  ok $res.val == 1e0/6e0, '6-j with error check: value';
  is-approx gsl_sf_coupling_9j(4, 2,  4, 3, 3, 2, 1, 1, 2), (-sqrt(⅙)/10e0), :rel-tol(10⁻¹⁵), '9-j';
  ok gsl_sf_coupling_9j_e(4, 2,  4, 3, 3, 2, 1, 1, 2, $res) == 0, '9-j with error check';
  is-approx $res.val, (-sqrt(⅙)/10e0), :rel-tol(10⁻¹⁵), '9-j with error check: value';
}, 'raw - Coupling coefficients';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_dawson(0.5e0), 0.424436383502022, :rel-tol(10⁻¹⁵), 'Dawson';
  ok gsl_sf_dawson_e(0.5e0, $res) == 0, 'Dawson with error check';
  is-approx $res.val, 0.424436383502022, :rel-tol(10⁻¹⁵), 'Dawson with error check: value';
}, 'raw - Dawson function';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_debye_1(0.1e0), 0.975277750004723, :rel-tol(10⁻¹⁵), 'Debye 1';
  ok gsl_sf_debye_1_e(0.1e0, $res) == 0, 'Debye 1 with error check';
  is-approx $res.val, 0.975277750004723, :rel-tol(10⁻¹⁵), 'Debye 1 with error check: value';
  is-approx gsl_sf_debye_2(0.1e0), 0.967083287045303, :rel-tol(10⁻¹⁵), 'Debye 2';
  ok gsl_sf_debye_2_e(0.1e0, $res) == 0, 'Debye 2 with error check';
  is-approx $res.val, 0.967083287045303, :rel-tol(10⁻¹⁵), 'Debye 2 with error check: value';
  is-approx gsl_sf_debye_3(0.1e0), 0.962999940487211, :rel-tol(10⁻¹⁵), 'Debye 3';
  ok gsl_sf_debye_3_e(0.1e0, $res) == 0, 'Debye 3 with error check';
  is-approx $res.val, 0.962999940487211, :rel-tol(10⁻¹⁵), 'Debye 3 with error check: value';
  is-approx gsl_sf_debye_4(0.1e0), 0.960555486124336, :rel-tol(10⁻¹⁵), 'Debye 4';
  ok gsl_sf_debye_4_e(0.1e0, $res) == 0, 'Debye 4 with error check';
  is-approx $res.val, 0.960555486124336, :rel-tol(10⁻¹⁵), 'Debye 4 with error check: value';
  is-approx gsl_sf_debye_5(0.1e0), 0.958928494283106, :rel-tol(10⁻¹⁵), 'Debye 5';
  ok gsl_sf_debye_5_e(0.1e0, $res) == 0, 'Debye 5 with error check';
  is-approx $res.val, 0.958928494283106, :rel-tol(10⁻¹⁵), 'Debye 5 with error check: value';
  is-approx gsl_sf_debye_6(0.1e0), 0.957767773826055, :rel-tol(10⁻¹⁵), 'Debye 6';
  ok gsl_sf_debye_6_e(0.1e0, $res) == 0, 'Debye 6 with error check';
  is-approx $res.val, 0.957767773826055, :rel-tol(10⁻¹⁵), 'Debye 6 with error check: value';
}, 'raw - Debye functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_dilog(0.1e0), 0.10261779109939113, :rel-tol(10⁻¹⁵), 'real dilogarithm';
  ok gsl_sf_dilog_e(0.1e0, $res) == 0, 'real dilogarithm with error check';
  is-approx $res.val, 0.10261779109939113, :rel-tol(10⁻¹⁵), 'real dilogarithm with error check: value';
  my gsl_sf_result $res_re .= new;
  my gsl_sf_result $res_im .= new;
  ok gsl_sf_complex_dilog_xy_e(0e0, -.5e0, $res_re, $res_im) == 0, 'complex dilogarithm';
  is-approx $res_re.val, -0.058975074421566, :rel-tol(10⁻¹⁵), 'complex dilogarithm: re';
  is-approx $res_im.val, -0.487222358294522, :rel-tol(10⁻¹⁵), 'complex dilogarithm: img';
  ok gsl_sf_complex_dilog_e(0.98e0, π/2, $res_re, $res_im) == 0, 'complex dilogarithm polar coord';
  is-approx $res_re.val, -0.198716383777859, :rel-tol(10⁻¹⁵), 'complex dilogarithm polar coord: re';
  is-approx $res_im.val, 0.900200458829818, :rel-tol(10⁻¹⁵), 'complex dilogarithm polar coord: img';
  ok gsl_sf_complex_spence_xy_e(-0.5e0, 0e0, $res_re, $res_im) == 0, 'Spence dilogarithm';
  is-approx $res_re.val, 2.374395270272480, :rel-tol(10⁻¹⁵), 'Spence dilogarithm: re';
  is-approx $res_im.val, -1.273806204919600, :rel-tol(10⁻¹⁵), 'Spence dilogarithm: img';
}, 'raw - Dilogarithms';

subtest {
  my gsl_sf_result $res .= new;
  ok gsl_sf_multiply(-3e0, 2e0) == -6e0, 'multiplication';
  ok gsl_sf_multiply_e(-3e0, 2e0, $res) == 0, 'multiplication with error check';
  ok $res.val == -6e0, 'multiplication with error check: value';
  ok gsl_sf_multiply_err_e(-3e0, .001e0, 2e0, .001e0, $res) == 0, 'multiplication with abs errors';
  ok $res.val == -6, 'multiplication with abs errors: value';
  is-approx $res.err, 0.005000000000002665, :rel-tol(10⁻¹⁵), 'multiplication with abs errors: error';
}, 'raw - multiplication with error propagation';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_ellint_Kcomp(.99e0, GSL_MODE_DEFAULT), 3.356600523361192, :rel-tol(10⁻¹⁵), 'Legendre K';
  ok gsl_sf_ellint_Kcomp_e(.99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre K with error check';
  is-approx $res.val, 3.356600523361192, :rel-tol(10⁻¹⁵), 'Legendre K with error check: value';
  is-approx gsl_sf_ellint_Ecomp(.99e0, GSL_MODE_DEFAULT), 1.028475809028804, :rel-tol(10⁻¹⁵), 'Legendre E';
  ok gsl_sf_ellint_Ecomp_e(.99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre E with error check';
  is-approx $res.val, 1.028475809028804, :rel-tol(10⁻¹⁵), 'Legendre E with error check: value';
  is-approx gsl_sf_ellint_Pcomp(.99e0, .1e0, GSL_MODE_DEFAULT), 3.137926123518364, :rel-tol(10⁻¹⁵), 'Legendre P';
  ok gsl_sf_ellint_Pcomp_e(.99e0, .1e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre P with error check';
  is-approx $res.val, 3.137926123518364, :rel-tol(10⁻¹⁵), 'Legendre P with error check: value';
  is-approx gsl_sf_ellint_Dcomp(.99e0, GSL_MODE_DEFAULT), 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre D';
  ok gsl_sf_ellint_Dcomp_e(.99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre D with error check';
  is-approx $res.val, 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre D with error check: value';
  is-approx gsl_sf_ellint_F(π/3, .99e0, GSL_MODE_DEFAULT), 1.306533339273877, :rel-tol(10⁻¹⁵), 'Legendre incomplete F';
  ok gsl_sf_ellint_F_e(π/3, .99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete F with error check';
  is-approx $res.val, 1.306533339273877, :rel-tol(10⁻¹⁵), 'Legendre incomplete F with error check: value';
  is-approx gsl_sf_ellint_E(π/3, .99e0, GSL_MODE_DEFAULT), 0.870481922037794, :rel-tol(10⁻¹⁵), 'Legendre incomplete E';
  ok gsl_sf_ellint_E_e(π/3, .99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete E with error check';
  is-approx $res.val, 0.870481922037794, :rel-tol(10⁻¹⁵), 'Legendre incomplete E with error check: value';
  is-approx gsl_sf_ellint_P(π/3, .99e0, .5e0, GSL_MODE_DEFAULT), 1.12887265987641, :rel-tol(10⁻¹⁵), 'Legendre incomplete P';
  ok gsl_sf_ellint_P_e(π/3, .99e0, .5e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete P with error check';
  is-approx $res.val, 1.12887265987641, :rel-tol(10⁻¹⁵), 'Legendre incomplete P with error check: value';
  is-approx gsl_sf_ellint_D(π/2, .99e0, GSL_MODE_DEFAULT), 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre incomplete D';
  ok gsl_sf_ellint_D_e(π/2, .99e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete D with error check';
  is-approx $res.val, 2.375395076351788, :rel-tol(10⁻¹⁵), 'Legendre incomplete D with error check: value';
  is-approx gsl_sf_ellint_RC(1e0, 2e0, GSL_MODE_DEFAULT), 0.785398163397448, :rel-tol(10⁻¹⁵), 'Legendre incomplete RC';
  ok gsl_sf_ellint_RC_e(1e0, 2e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete RC with error check';
  is-approx $res.val, 0.785398163397448, :rel-tol(10⁻¹⁵), 'Legendre incomplete RC with error check: value';
  is-approx gsl_sf_ellint_RD(1e0, 2e0, 3e0, GSL_MODE_DEFAULT), 0.29046028102899063, :rel-tol(10⁻¹⁵), 'Legendre incomplete RD';
  ok gsl_sf_ellint_RD_e(1e0, 2e0, 3e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete RD with error check';
  is-approx $res.val, 0.29046028102899063, :rel-tol(10⁻¹⁵), 'Legendre incomplete RD with error check: value';
  is-approx gsl_sf_ellint_RF(1e0, 2e0, 3e0, GSL_MODE_DEFAULT), 0.726945935468908, :rel-tol(10⁻¹⁵), 'Legendre incomplete RF';
  ok gsl_sf_ellint_RF_e(1e0, 2e0, 3e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete RF with error check';
  is-approx $res.val, 0.726945935468908, :rel-tol(10⁻¹⁵), 'Legendre incomplete RF with error check: value';
  is-approx gsl_sf_ellint_RJ(2e0, 3e0, 4e0, 5e0, GSL_MODE_DEFAULT), 0.1429757966715675, :rel-tol(10⁻¹⁵), 'Legendre incomplete RJ';
  ok gsl_sf_ellint_RJ_e(2e0, 3e0, 4e0, 5e0, GSL_MODE_DEFAULT, $res) == 0, 'Legendre incomplete RJ with error check';
  is-approx $res.val, 0.1429757966715675, :rel-tol(10⁻¹⁵), 'Legendre incomplete RJ with error check: value';
}, 'raw - elliptic integrals';

subtest {
  my num64 $sn;
  my num64 $cn;
  my num64 $dn;
  ok gsl_sf_elljac_e(.5e0, .5e0, $sn, $cn, $dn) == 0, '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';
}, 'raw - elliptic functions';

subtest {
  my gsl_sf_result $res .= new;
  ok gsl_sf_erf(-10e0) == -1, 'erf';
  ok gsl_sf_erf_e(-10e0, $res) == 0, 'erf with error check';
  ok $res.val == -1, 'erf with error check: value';
  ok gsl_sf_erfc(-10e0) == 2, 'erfc';
  ok gsl_sf_erfc_e(-10e0, $res) == 0, 'erfc with error check';
  ok $res.val == 2, 'erfc with error check: value';
  is-approx gsl_sf_log_erfc(-.1e0), 0.1065764005865225, :rel-tol(10⁻¹⁵), 'log erfc';
  ok gsl_sf_log_erfc_e(-.1e0, $res) == 0, 'log erfc with error check';
  is-approx $res.val, 0.1065764005865225, :rel-tol(10⁻¹⁵), 'log erfc with error check: value';
  is-approx gsl_sf_erf_Z(1e0), 0.24197072451914334, :rel-tol(10⁻¹⁵), 'erf Z';
  ok gsl_sf_erf_Z_e(1e0, $res) == 0, 'erf Z with error check';
  is-approx $res.val, 0.24197072451914334, :rel-tol(10⁻¹⁵), 'erf Z with error check: value';
  is-approx gsl_sf_erf_Q(1e0), 0.158655253931457, :rel-tol(10⁻¹⁵), 'erf Q';
  ok gsl_sf_erf_Q_e(1e0, $res) == 0, 'erf Q with error check';
  is-approx $res.val, 0.158655253931457, :rel-tol(10⁻¹⁵), 'erf Q with error check: value';
  is-approx gsl_sf_hazard(-1e0), 0.2875999709391784, :rel-tol(10⁻¹⁵), 'hazard';
  ok gsl_sf_hazard_e(-1e0, $res) == 0, 'erf Q with error check';
  is-approx $res.val, 0.2875999709391784, :rel-tol(10⁻¹⁵), 'hazard with error check: value';
}, 'raw - error functions';

subtest {
  my gsl_sf_result $res .= new;
  my gsl_sf_result_e10 $rese10 .= new;
  ok gsl_sf_exp(10e0) == exp(10e0), 'exp';
  ok gsl_sf_exp_e(10e0, $res) == 0, 'exp with error check';
  ok $res.val == exp(10e0), 'exp with error check: value';
  ok gsl_sf_exp_e10_e(10e0, $rese10) == 0, 'exp with extended range error check';
  ok $rese10.val == exp(10e0), 'exp with extended range error check: value';
  ok gsl_sf_exp_mult(10e0, -2e0) == -2 * exp(10e0), 'exp mult';
  ok gsl_sf_exp_mult_e(10e0, -2e0, $res) == 0, 'exp mult with error check';
  ok $res.val == -2 * exp(10e0), 'exp mult with error check: value';
  ok gsl_sf_exp_mult_e10_e(10e0, -2e0, $rese10) == 0, 'exp mult with extended range error check';
  ok $rese10.val == -2 * exp(10e0), 'exp mult with extended range error check: value';
  ok gsl_sf_expm1(-10e0) == exp(-10e0) - 1, 'exp(x) - 1';
  ok gsl_sf_expm1_e(-10e0, $res) == 0, 'exp(x) - 1 with error check';
  ok $res.val == exp(-10e0) - 1, 'exp(x) - 1 with error check: value';
  is-approx gsl_sf_exprel(-10e0), 0.09999546000702375, :rel-tol(10⁻¹⁵), '(exp(x) - 1) / x';
  ok gsl_sf_exprel_e(-10e0, $res) == 0, '(exp(x) - 1) / x with error check';
  is-approx $res.val, 0.09999546000702375, :rel-tol(10⁻¹⁵), '(exp(x) - 1) / x with error check: value';
  is-approx gsl_sf_exprel_2(-10e0), 0.18000090799859525, :rel-tol(10⁻¹⁵), '2 * (exp(x) - 1 - x) / x²';
  ok gsl_sf_exprel_2_e(-10e0, $res) == 0, '2 * (exp(x) - 1 - x) / x² with error check';
  is-approx $res.val, 0.18000090799859525, :rel-tol(10⁻¹⁵), '2 * (exp(x) - 1 - x) / x² with error check: value';
  is-approx gsl_sf_exprel_n(3, -10e0), 0.24599972760042138, :rel-tol(10⁻¹⁵), 'N relative exponential';
  ok gsl_sf_exprel_n_e(3, -10e0, $res) == 0, 'N relative exponential with error check';
  is-approx $res.val, 0.24599972760042138, :rel-tol(10⁻¹⁵), 'N relative exponential with error check: value';
  ok gsl_sf_exp_err_e(-10e0, 16e0 * 2.2204460492503131e-16, $res) == 0, 'exp with absolute error';
  ok $res.val == exp(-10), 'exp with absolute error: value';
  ok gsl_sf_exp_err_e10_e(1e0, 16e0 * 2.2204460492503131e-16, $rese10) == 0, 'exp with extended range error check';
  ok $rese10.val == 𝑒, 'exp with extended range error check: value';
  ok gsl_sf_exp_mult_err_e(-10e0, 2e0 * 2.2204460492503131e-16, 2e0, 2e0 * 2.2204460492503131e-16, $res) == 0, 'y * exp(x) with absolute error';
  ok $res.val == 2 * exp(-10), 'y * exp(x) with absolute error: value';
  ok gsl_sf_exp_mult_err_e10_e(-10e0, 2e0 * 2.2204460492503131e-16, 2e0, 2e0 * 2.2204460492503131e-16, $rese10) == 0, 'y * exp(x) with extended range error check';
  ok $rese10.val == 2 * exp(-10), 'y * exp(x) with extended range error check: value';
}, 'raw - exponential functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_expint_E1(1e0), 0.21938393439552029, :rel-tol(10⁻¹⁵), 'E₁(x)';
  ok gsl_sf_expint_E1_e(1e0, $res) == 0, 'E₁(x) with error check';
  is-approx $res.val, 0.21938393439552029, :rel-tol(10⁻¹⁵), 'E₁(x) with error check: value';
  is-approx gsl_sf_expint_E2(1e0), 0.148495506775922, :rel-tol(10⁻¹⁵), 'E₂(x)';
  ok gsl_sf_expint_E2_e(1e0, $res) == 0, 'E₂(x) with error check';
  is-approx $res.val, 0.148495506775922, :rel-tol(10⁻¹⁵), 'E₂(x) with error check: value';
  is-approx gsl_sf_expint_En(1, 1e0), 0.21938393439552029, :rel-tol(10⁻¹⁵), 'Eₙ(x)';
  ok gsl_sf_expint_En_e(1, 1e0, $res) == 0, 'Eₙ(x) with error check';
  is-approx $res.val, 0.21938393439552029, :rel-tol(10⁻¹⁵), 'Eₙ(x) with error check: value';
  is-approx gsl_sf_expint_Ei(1e0), 1.895117816355937, :rel-tol(10⁻¹⁵), 'Eᵢ(x)';
  ok gsl_sf_expint_Ei_e(1e0, $res) == 0, 'Eᵢ(x) with error check';
  is-approx $res.val, 1.895117816355937, :rel-tol(10⁻¹⁵), 'Eᵢ(x) with error check: value';
  is-approx gsl_sf_Shi(.1e0), 0.100055572225057, :rel-tol(10⁻¹⁵), 'Shi(x)';
  ok gsl_sf_Shi_e(.1e0, $res) == 0, 'Shi(x) with error check';
  is-approx $res.val, 0.100055572225057, :rel-tol(10⁻¹⁵), 'Shi(x) with error check: value';
  is-approx gsl_sf_Chi(1e0), 0.837866940980208, :rel-tol(10⁻¹⁵), 'Chi(x)';
  ok gsl_sf_Chi_e(1e0, $res) == 0, 'Chi(x) with error check';
  is-approx $res.val, 0.837866940980208, :rel-tol(10⁻¹⁵), 'Chi(x) with error check: value';
  is-approx gsl_sf_expint_3(1e0), 0.807511182139672, :rel-tol(10⁻¹⁵), 'Ei₃(x)';
  ok gsl_sf_expint_3_e(1e0, $res) == 0, 'Ei₃(x) with error check';
  is-approx $res.val, 0.807511182139672, :rel-tol(10⁻¹⁵), 'Ei₃(x) with error check: value';
  is-approx gsl_sf_Si(1e0), 0.946083070367183, :rel-tol(10⁻¹⁵), 'Si(x)';
  ok gsl_sf_Si_e(1e0, $res) == 0, 'Si(x) with error check';
  is-approx $res.val, 0.946083070367183, :rel-tol(10⁻¹⁵), 'Si(x) with error check: value';
  is-approx gsl_sf_Ci(1e0), 0.337403922900968, :rel-tol(10⁻¹⁵), 'Ci(x)';
  ok gsl_sf_Ci_e(1e0, $res) == 0, 'Ci(x) with error check';
  is-approx $res.val, 0.337403922900968, :rel-tol(10⁻¹⁵), 'Ci(x) with error check: value';
  is-approx gsl_sf_atanint(1e0), 0.915965594177219, :rel-tol(10⁻¹⁵), 'atanint(x)';
  ok gsl_sf_atanint_e(1e0, $res) == 0, 'atanint(x) with error check';
  is-approx $res.val, 0.915965594177219, :rel-tol(10⁻¹⁵), 'atanint(x) with error check: value';
}, 'raw - exponential integrals';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_fermi_dirac_m1(1e0), 0.731058578630005, :rel-tol(10⁻¹⁵), 'F₋₁(x)';
  ok gsl_sf_fermi_dirac_m1_e(1e0, $res) == 0, 'F₋₁(x) with error check';
  is-approx $res.val, 0.731058578630005, :rel-tol(10⁻¹⁵), 'F₋₁(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_0(1e0), 1.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x)';
  ok gsl_sf_fermi_dirac_0_e(1e0, $res) == 0, 'F₀(x) with error check';
  is-approx $res.val, 1.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_1(1e0), 1.806286070444775, :rel-tol(10⁻¹⁵), 'F₁(x)';
  ok gsl_sf_fermi_dirac_1_e(1e0, $res) == 0, 'F₁(x) with error check';
  is-approx $res.val, 1.806286070444775, :rel-tol(10⁻¹⁵), 'F₁(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_2(1e0), 2.164165612812701, :rel-tol(10⁻¹⁵), 'F₂(x)';
  ok gsl_sf_fermi_dirac_2_e(1e0, $res) == 0, 'F₂(x) with error check';
  is-approx $res.val, 2.164165612812701, :rel-tol(10⁻¹⁵), 'F₂(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_int(3, 1e0), 2.39822608224894, :rel-tol(10⁻¹⁵), 'Fⱼ(x)';
  ok gsl_sf_fermi_dirac_int_e(3, 1e0, $res) == 0, 'Fⱼ(x) with error check';
  is-approx $res.val, 2.39822608224894, :rel-tol(10⁻¹⁵), 'Fⱼ(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_mhalf(1e0), 1.027057125474351, :rel-tol(10⁻¹⁵), 'F-1/2(x)';
  ok gsl_sf_fermi_dirac_mhalf_e(1e0, $res) == 0, 'F-1/2(x) with error check';
  is-approx $res.val, 1.027057125474351, :rel-tol(10⁻¹⁵), 'F-1/2(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_half(1e0), 1.575640776151300, :rel-tol(10⁻¹⁵), 'F1/2(x)';
  ok gsl_sf_fermi_dirac_half_e(1e0, $res) == 0, 'F1/2(x) with error check';
  is-approx $res.val, 1.575640776151300, :rel-tol(10⁻¹⁵), 'F1/2(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_3half(1e0), 2.002258148778464, :rel-tol(10⁻¹⁵), 'F3/2(x)';
  ok gsl_sf_fermi_dirac_3half_e(1e0, $res) == 0, 'F3/2(x) with error check';
  is-approx $res.val, 2.002258148778464, :rel-tol(10⁻¹⁵), 'F3/2(x) with error check: value';
  is-approx gsl_sf_fermi_dirac_inc_0(1e0, 2e0), 0.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x,b)';
  ok gsl_sf_fermi_dirac_inc_0_e(1e0, 2e0, $res) == 0, 'F₀(x,b) with error check';
  is-approx $res.val, 0.313261687518223, :rel-tol(10⁻¹⁵), 'F₀(x,b) with error check: value';
}, 'raw - Fermi-Dirac integrals';

subtest {
  my gsl_sf_result $res .= new;
  my gsl_sf_result $resi .= new;
  ok gsl_sf_gamma(9e0) == 40320, 'Γ(x)';
  ok gsl_sf_gamma_e(9e0, $res) == 0, 'Γ(x) with error check';
  ok $res.val == 40320, 'Γ(x) with error check: value';
  is-approx gsl_sf_lngamma(.1e0), 2.252712651734205, :rel-tol(10⁻¹⁵), 'log(|Γ(x)|)';
  ok gsl_sf_lngamma_e(.1e0, $res) == 0, 'log(|Γ(x)|) with error check';
  is-approx $res.val, 2.252712651734205, :rel-tol(10⁻¹⁵), 'log(|Γ(x)|) with error check: value';
  my num64 $sgn;
  ok gsl_sf_lngamma_sgn_e(-.1e0, $res, $sgn) == 0, 'log(|Γ(x)|) with error check and sign';
  is-approx $res.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 gsl_sf_gammastar(9e0), 1.009298426421819, :rel-tol(10⁻¹⁵), 'Γ*(x)';
  ok gsl_sf_gammastar_e(9e0, $res) == 0, 'Γ*(x) with error check';
  is-approx $res.val, 1.009298426421819, :rel-tol(10⁻¹⁵), 'Γ*(x) with error check: value';
  ok gsl_sf_gammainv(3e0) == .5, '1/Γ(x)';
  ok gsl_sf_gammainv_e(3e0, $res) == 0, '1/Γ(x) with error check';
  ok $res.val == .5, '1/Γ(x) with error check: value';
  ok gsl_sf_lngamma_complex_e(5e0, 2e0, $res, $resi) == 0, 'log(Γ(z)) with error check';
  is-approx $res.val, 2.748701756133804, :rel-tol(10⁻¹⁵), 'log(Γ(z)) with error check: value';
  is-approx $resi.val, 3.073843410049702, :rel-tol(10⁻¹⁵), 'log(Γ(z)) with error check: value';
  ok gsl_sf_fact(8) == 40320, 'n!';
  ok gsl_sf_fact_e(8, $res) == 0, 'n! with error check';
  ok $res.val == 40320, 'n! with error check: value';
  ok gsl_sf_doublefact(7) == 105, 'n!!';
  ok gsl_sf_doublefact_e(7, $res) == 0, 'n!! with error check';
  ok $res.val == 105, 'n!! with error check: value';
  is-approx gsl_sf_lnfact(7), 8.525161361065414, :rel-tol(10⁻¹⁵), 'log(n!)';
  ok gsl_sf_lnfact_e(7, $res) == 0, 'log(n!) with error check';
  is-approx $res.val, 8.525161361065414, :rel-tol(10⁻¹⁵), 'log(n!) with error check: value';
  is-approx gsl_sf_lndoublefact(7), 4.653960350157524, :rel-tol(10⁻¹⁵), 'log(n!!)';
  ok gsl_sf_lndoublefact_e(7, $res) == 0, 'log(n!!) with error check';
  is-approx $res.val, 4.653960350157524, :rel-tol(10⁻¹⁵), 'log(n!!) with error check: value';
  ok gsl_sf_choose(7, 3) == 35, 'n!/(m!(n-m)!)';
  ok gsl_sf_choose_e(7, 3, $res) == 0, 'n!/(m!(n-m)!) with error check';
  ok $res.val == 35, 'n!/(m!(n-m)!) with error check: value';
  is-approx gsl_sf_lnchoose(7, 3), 3.555348061489414, :rel-tol(10⁻¹⁵), 'log(n!)-log(m!)-log((n-m)!)';
  ok gsl_sf_lnchoose_e(7, 3, $res) == 0, 'log(n!)-log(m!)-log((n-m)!) with error check';
  is-approx $res.val, 3.555348061489414, :rel-tol(10⁻¹⁵), 'log(n!)-log(m!)-log((n-m)!) with error check: value';
  is-approx gsl_sf_taylorcoeff(10, 5e0), 2.691144455467373, :rel-tol(10⁻¹⁵), 'xⁿ/n!';
  ok gsl_sf_taylorcoeff_e(10, 5e0, $res) == 0, 'xⁿ/n! with error check';
  is-approx $res.val, 2.691144455467373, :rel-tol(10⁻¹⁵), 'xⁿ/n! with error check: value';
  ok gsl_sf_poch(5e0, 0e0) == 1, '(a)ₓ';
  ok gsl_sf_poch_e(5e0, 0e0, $res) == 0, '(a)ₓ with error check';
  ok $res.val == 1, '(a)ₓ with error check: value';
  ok gsl_sf_lnpoch(5e0, 0e0) == 0, 'log((a)ₓ)';
  ok gsl_sf_lnpoch_e(5e0, 0e0, $res) == 0, 'log((a)ₓ) with error check';
  ok $res.val == 0, 'log((a)ₓ) with error check: value';
  ok gsl_sf_lnpoch_sgn_e(5e0, 0e0, $res, $sgn) == 0, 'log((a)ₓ) with error check and sign';
  ok $res.val == 0, 'log((a)ₓ) with error check and sign: value';
  ok $sgn == 1, 'log((a)ₓ) with error check and sign: sign';
  is-approx gsl_sf_pochrel(5e0, 0e0), 1.506117668431801, :rel-tol(10⁻¹⁵), '((a)ₓ-1)/x';
  ok gsl_sf_pochrel_e(5e0, 0e0, $res) == 0, '((a)ₓ-1)/x with error check';
  is-approx $res.val, 1.506117668431801, :rel-tol(10⁻¹⁵), '((a)ₓ-1)/x with error check: value';
  is-approx gsl_sf_gamma_inc(1e0, 1e0), 0.367879441171442, :rel-tol(10⁻¹⁵), 'Γ(a,x)';
  ok gsl_sf_gamma_inc_e(1e0, 1e0, $res) == 0, 'Γ(a,x) with error check';
  is-approx $res.val, 0.367879441171442, :rel-tol(10⁻¹⁵), 'Γ(a,x) with error check: value';
  is-approx gsl_sf_gamma_inc_Q(1e0, 1.01e0), 0.364218979571523, :rel-tol(10⁻¹⁵), 'Q(a,x)';
  ok gsl_sf_gamma_inc_Q_e(1e0, 1.01e0, $res) == 0, 'Q(a,x) with error check';
  is-approx $res.val, 0.364218979571523, :rel-tol(10⁻¹⁵), 'Q(a,x) with error check: value';
  is-approx gsl_sf_gamma_inc_P(100e0, 99e0), 0.473304330399461, :rel-tol(10⁻¹⁵), 'P(a,x)';
  ok gsl_sf_gamma_inc_P_e(100e0, 99e0, $res) == 0, 'P(a,x) with error check';
  is-approx $res.val, 0.473304330399461, :rel-tol(10⁻¹⁵), 'P(a,x) with error check: value';
  ok gsl_sf_beta(1e0, 1e0) == 1, 'B(a,b)';
  ok gsl_sf_beta_e(1e0, 1e0, $res) == 0, 'B(a,b) with error check';
  ok $res.val == 1, 'B(a,b) with error check: value';
  is-approx gsl_sf_lnbeta(1e0, 1.01e0), -0.009950330853168186, :rel-tol(10⁻¹⁵), 'log(B(a,b))';
  ok gsl_sf_lnbeta_e(1e0, 1.01e0, $res) == 0, 'log(B(a,b)) with error check';
  is-approx $res.val, -0.009950330853168186, :rel-tol(10⁻¹⁵), 'log(B(a,b)) with error check: value';
  ok gsl_sf_beta_inc(1e0, 1e0, 1e0) == 1, 'Iₓ(a,b)';
  ok gsl_sf_beta_inc_e(1e0, 1e0, 1e0, $res) == 0, 'Iₓ(a,b) with error check';
  ok $res.val == 1, 'Iₓ(a,b) with error check: value';
}, 'raw - gamma e beta functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_gegenpoly_1(0e0, 1e0), 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=1';
  ok gsl_sf_gegenpoly_1_e(0e0, 1e0, $res) == 0, 'Cₙ(λ)(x) n=1 with error check';
  is-approx $res.val, 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=1 with error check: value';
  is-approx gsl_sf_gegenpoly_2(0e0, 1e0), 1, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=2';
  ok gsl_sf_gegenpoly_2_e(0e0, 1e0, $res) == 0, 'Cₙ(λ)(x) n=2 with error check';
  is-approx $res.val, 1, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=2 with error check: value';
  is-approx gsl_sf_gegenpoly_3(1e0, 1e0), 4, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=3';
  ok gsl_sf_gegenpoly_3_e(1e0, 1e0, $res) == 0, 'Cₙ(λ)(x) n=3 with error check';
  is-approx $res.val, 4, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) n=3 with error check: value';
  is-approx gsl_sf_gegenpoly_n(1, 1e0, 1e0), 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x)';
  ok gsl_sf_gegenpoly_n_e(1, 1e0, 1e0, $res) == 0, 'Cₙ(λ)(x) with error check';
  is-approx $res.val, 2, :rel-tol(10⁻¹⁵), 'Cₙ(λ)(x) with error check: value';
  my CArray[num64] $res_array .= new: 0e0 xx 12;
  ok gsl_sf_gegenpoly_array(11, 5e0, 1e0, $res_array) == 0, 'Cₙ(λ)(x) for n=0,1,2…nmax';
  ok $res_array[1] == 10, 'Cₙ(λ)(x) n=1';
  ok $res_array[10] == 9.23780e+4, 'Cₙ(λ)(x) n=10';
}, 'raw - Gegenbauer functions';

subtest {
  my gsl_sf_result $res .= new;
  my num64 $a;
  my CArray[num64] $res_array .= new: 0e0 xx 11;
  ok gsl_sf_hermite_phys(0, .75e0) == 1, 'Hₙ(x)';
  ok gsl_sf_hermite_phys_e(0, .75e0, $res) == 0, 'Hₙ(x) with error check';
  ok $res.val == 1, 'Hₙ(x) with error check: value';
  ok gsl_sf_hermite_phys_array(0, .75e0, $res_array) == 0, 'Hₙ(x) array';
  ok $res_array[0] == 1, 'Hₙ(x) array: results';
  $res_array[0] = 1e0;
  $res_array[$_] = $res_array[$_-1]/2e0 for 1…10;
  is-approx gsl_sf_hermite_phys_series(10, .75e0, $res_array), 29.591702461242672, :rel-tol(10⁻¹⁵), 'sum(aₙHₙ(x))';
  ok gsl_sf_hermite_phys_series_e(10, .75e0, $res_array, $res) == 0, 'sum(aₙHₙ(x)) with error check';
  is-approx $res.val, 29.591702461242672, :rel-tol(10⁻¹⁵), 'Hₙ(x) with error check: value';
  ok gsl_sf_hermite_prob(0, .75e0) == 1, 'Heₙ(x)';
  ok gsl_sf_hermite_prob_e(0, .75e0, $res) == 0, 'Heₙ(x) with error check';
  ok $res.val == 1, 'Heₙ(x) with error check: value';
  ok gsl_sf_hermite_prob_array(0, .75e0, $res_array) == 0, 'Heₙ(x) array';
  ok $res_array[0] == 1, 'Heₙ(x) array: results';
  is-approx gsl_sf_hermite_prob_series(10, .75e0, $res_array), 2.087602422572672, :rel-tol(10⁻¹⁵), 'sum(aₙHeₙ(x))';
  ok gsl_sf_hermite_prob_series_e(10, .75e0, $res_array, $res) == 0, 'sum(aₙHeₙ(x)) with error check';
  is-approx $res.val, 2.087602422572672, :rel-tol(10⁻¹⁵), 'sum(aₙHeₙ(x)) with error check: value';
  ok gsl_sf_hermite_phys_der(225, 128, .75e0) == 0, 'm-derivative of Hₙ(x)';
  ok gsl_sf_hermite_phys_der_e(225, 128, .75e0, $res) == 0, 'm-derivative of Hₙ(x) with error check';
  ok $res.val == 0, 'm-derivative of Hₙ(x) with error check: value';
  ok gsl_sf_hermite_phys_array_der(0, 10, .75e0, $res_array) == 0, 'm-derivative of Hₙ(x) array';
  ok $res_array[0] == 1, 'm-derivative of Hₙ(x) array [0]';
  is-approx $res_array[10], 38740.4384765625, :rel-tol(10⁻¹⁵), 'm-derivative of Hₙ(x) array [10]';
  ok gsl_sf_hermite_phys_der_array(10, 50, .75e0, $res_array) == 0, 'derivatives of Hₙ(x) array';
  is-approx $res_array[0], -8.26632218305863100726861832e38, :rel-tol(10⁻¹⁵), 'derivatives of Hₙ(x) array [0]';
  is-approx $res_array[1], 2.40954750392844799126151557e40, :rel-tol(10⁻¹⁵), 'derivatives of Hₙ(x) array [1]';
  ok gsl_sf_hermite_prob_der(225, 128, .75e0) == 0, 'm-derivative of probabilistic Heₙ(x)';
  ok gsl_sf_hermite_prob_der_e(225, 128, .75e0, $res) == 0, 'm-derivative of probabilistic Heₙ(x) with error check';
  ok $res.val == 0, 'm-derivative of probabilistic Heₙ(x) with error check: value';
  ok gsl_sf_hermite_prob_array_der(0, 10, .75e0, $res_array) == 0, 'm-derivative of probabilistic Heₙ(x) array';
  is-approx $res_array[10], 823.810509681701660156250, :rel-tol(10⁻¹⁵), 'm-derivative of Heₙ(x) array [10]';
  ok gsl_sf_hermite_prob_der_array(10, 50, .75e0, $res_array) == 0, 'derivatives of probabilistic Heₙ(x) array';
  is-approx $res_array[10], 7.9614368698398116765703194e38, :rel-tol(10⁻¹⁵), 'derivatives of Heₙ(x) array [10]';
  is-approx gsl_sf_hermite_func(0, 1.3e0), 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x)';
  ok gsl_sf_hermite_func_e(0, 1.3e0, $res) == 0, 'ψₙ(x) with error check';
  is-approx $res.val, 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x) with error check: value';
  ok gsl_sf_hermite_func_array(1, 1.3e0, $res_array) == 0, 'ψₙ(x) array';
  is-approx $res_array[0], 0.322651504564963746879400858624, :rel-tol(10⁻¹⁵), 'ψₙ(x) array: value';
  $res_array[0] = 1e0;
  $res_array[$_] = $res_array[$_-1]/2e0 for 1…10;
  is-approx gsl_sf_hermite_func_series(10, .75e0, $res_array), 0.8171775729199896, :rel-tol(10⁻¹⁵), 'sum(aₙψₙ(x))';
  ok gsl_sf_hermite_func_series_e(10, .75e0, $res_array, $res) == 0, 'sum(aₙψₙ(x)) with error check';
  is-approx $res.val, 0.8171775729199896, :rel-tol(10⁻¹⁵), 'sum(aₙψₙ(x)) with error check: value';
  is-approx gsl_sf_hermite_func_der(0, 28, .75e0), 0.235262808086212406493191404, :rel-tol(10⁻¹⁵), 'm-derivative of ψₙ(x)';
  ok gsl_sf_hermite_func_der_e(0, 28,.75e0, $res) == 0, 'm-derivative of ψₙ(x) with error check';
  is-approx $res.val, 0.235262808086212406493191404, :rel-tol(10⁻¹⁵), 'm-derivative of ψₙ(x) with error check: value';
  ok gsl_sf_hermite_phys_zero(17, 1) == 0.531633001342654731349086553718, 's-th zero of Hₙ(x)';
  ok gsl_sf_hermite_phys_zero_e(17, 1, $res) == 0, 's-th zero of Hₙ(x) with error check';
  ok $res.val == 0.531633001342654731349086553718, 's-th zero of Hₙ(x) with error check: value';
  ok gsl_sf_hermite_prob_zero(24, 1) == 0.317370096629452319318170455994, 's-th zero of probabilistic Hₙ(x)';
  ok gsl_sf_hermite_prob_zero_e(24, 1, $res) == 0, 's-th zero of probabilistic Hₙ(x) with error check';
  ok $res.val == 0.317370096629452319318170455994, 's-th zero of probabilistic Hₙ(x) with error check: value';
  ok gsl_sf_hermite_func_zero(24, 1) == 0.22441454747251557, 's-th zero of ψₙ(x)';
  ok gsl_sf_hermite_func_zero_e(24, 1, $res) == 0, 's-th zero of ψₙ(x) with error check';
  ok $res.val == 0.22441454747251557, 's-th zero of ψₙ(x) with error check: value';
}, 'raw - Hermite polynomials and functions';

subtest {
  my gsl_sf_result $res .= new;
  my gsl_sf_result_e10 $rese10 .= new;
  is-approx gsl_sf_hyperg_0F1(1e0, .5e0), 1.5660829297563505373, :rel-tol(10⁻¹⁵), '₀F₁(c,x)';
  ok gsl_sf_hyperg_0F1_e(1e0, .5e0, $res) == 0, '₀F₁(c,x) with error check';
  is-approx $res.val, 1.5660829297563505373, :rel-tol(10⁻¹⁵), '₀F₁(c,x) with error check: value';
  is-approx gsl_sf_hyperg_1F1_int(1, 1, .5e0), 1.6487212707001281468, :rel-tol(10⁻¹⁵), '₁F₁(m,n,x)';
  ok gsl_sf_hyperg_1F1_int_e(1, 1, .5e0, $res) == 0, '₁F₁(m,n,x) with error check';
  is-approx $res.val, 1.6487212707001281468, :rel-tol(10⁻¹⁵), '₁F₁(m,n,x) with error check: value';
  is-approx gsl_sf_hyperg_1F1(1e0, 1.5e0, 1e0), 2.0300784692787049755, :rel-tol(10⁻¹⁵), '₁F₁(a,b,x)';
  ok gsl_sf_hyperg_1F1_e(1e0, 1.5e0, 1e0, $res) == 0, '₁F₁(a,b,x) with error check';
  is-approx $res.val, 2.0300784692787049755, :rel-tol(10⁻¹⁵), '₁F₁(a,b,x) with error check: value';
  is-approx gsl_sf_hyperg_U_int(1, 1, 2e0), 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x)';
  ok gsl_sf_hyperg_U_int_e(1, 1, 2e0, $res) == 0, 'U(m,n,x) with error check';
  is-approx $res.val, 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x) with error check: value';
  ok gsl_sf_hyperg_U_int_e10_e(1, 1, 2e0, $rese10) == 0, 'U(m,n,x) with extended range error check';
  is-approx $rese10.val, 0.3613286168882225847, :rel-tol(10⁻¹⁵), 'U(m,n,x) with extended range error check: value';
  is-approx gsl_sf_hyperg_U(1e0, 1.2e0, 2e0), 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x)';
  ok gsl_sf_hyperg_U_e(1e0, 1.2e0, 2e0, $res) == 0, 'U(a,b,x) with error check';
  is-approx $res.val, 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x) with error check: value';
  ok gsl_sf_hyperg_U_e10_e(1e0, 1.2e0, 2e0, $rese10) == 0, 'U(a,b,x) with extended range error check';
  is-approx $rese10.val, 0.3835044780075602550, :rel-tol(10⁻¹⁵), 'U(a,b,x) with extended range error check: value';
  is-approx gsl_sf_hyperg_2F1(1e0, 1e0, 1e0, .5e0), 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)';
  ok gsl_sf_hyperg_2F1_e(1e0, 1e0, 1e0, .5e0, $res) == 0, '₂F₁(a,b,c,x) with error check';
  is-approx $res.val, 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x) with error check: value';
  is-approx gsl_sf_hyperg_2F1_conj(1e0, 1e0, 1e0, .5e0), 3.352857095662929028, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)';
  ok gsl_sf_hyperg_2F1_conj_e(1e0, 1e0, 1e0, .5e0, $res) == 0, '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x) with error check';
  is-approx $res.val, 3.352857095662929028, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x) with error check: value';
  is-approx gsl_sf_hyperg_2F1_renorm(1e0, 1e0, 1e0, .5e0), 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)/Γ(c)';
  ok gsl_sf_hyperg_2F1_renorm_e(1e0, 1e0, 1e0, .5e0, $res) == 0, '₂F₁(a,b,c,x)/Γ(c) with error check';
  is-approx $res.val, 2, :rel-tol(10⁻¹⁵), '₂F₁(a,b,c,x)/Γ(c) with error check: value';
  is-approx gsl_sf_hyperg_2F1_conj_renorm(9e0, 9e0, -1.5e0, -.99e0), 0.10834020229476124874, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c)';
  ok gsl_sf_hyperg_2F1_conj_renorm_e(9e0, 9e0, -1.5e0, -.99e0, $res) == 0, '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c) with error check';
  is-approx $res.val, 0.10834020229476124874, :rel-tol(10⁻¹⁵), '₂F₁(aᵣ+iaᵢ,aR-iaI,c,x)/Γ(c) with error check: value';
  is-approx gsl_sf_hyperg_2F0(.1e0, .5e0, -.02e0), .99901595171179281891589794, :rel-tol(10⁻¹⁵), '₂F₀(a,b,x)';
  ok gsl_sf_hyperg_2F0_e(.1e0, .5e0, -.02e0, $res) == 0, '₂F₀(a,b,x) with error check';
  is-approx $res.val, .99901595171179281891589794, :rel-tol(10⁻¹⁵), '₂F₀(a,b,x) with error check: value';
}, 'raw - Hypergeometric functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_laguerre_1(1e0, 1e0), 1, :rel-tol(10⁻¹⁵), 'Lʲ₁(x)';
  ok gsl_sf_laguerre_1_e(1e0, 1e0, $res) == 0, 'Lʲ₁(x) with error check';
  is-approx $res.val, 1, :rel-tol(10⁻¹⁵), 'Lʲ₁(x) with error check: value';
  is-approx gsl_sf_laguerre_2(1e0, 1e0), .5, :rel-tol(10⁻¹⁵), 'Lʲ₂(x)';
  ok gsl_sf_laguerre_2_e(1e0, 1e0, $res) == 0, 'Lʲ₂(x) with error check';
  is-approx $res.val, .5, :rel-tol(10⁻¹⁵), 'Lʲ₂(x) with error check: value';
  is-approx gsl_sf_laguerre_3(2e0, 1e0), 2.3333333333333333333, :rel-tol(10⁻¹⁵), 'Lʲ₃(x)';
  ok gsl_sf_laguerre_3_e(2e0, 1e0, $res) == 0, 'Lʲ₃(x) with error check';
  is-approx $res.val, 2.3333333333333333333, :rel-tol(10⁻¹⁵), 'Lʲ₃(x) with error check: value';
  is-approx gsl_sf_laguerre_n(1, .5e0, 1e0), .5, :rel-tol(10⁻¹⁵), 'Lʲₙ(x)';
  ok gsl_sf_laguerre_n_e(1, .5e0, 1e0, $res) == 0, 'Lʲₙ(x) with error check';
  is-approx $res.val, .5, :rel-tol(10⁻¹⁵), 'Lʲₙ(x) with error check: value';
}, 'raw - Laguerre functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_lambert_W0(0e0), 0, :rel-tol(10⁻¹⁵), 'W₀(x)';
  ok gsl_sf_lambert_W0_e(0e0, $res) == 0, 'W₀(x) with error check';
  is-approx $res.val, 0, :rel-tol(10⁻¹⁵), 'W₀(x) with error check: value';
  is-approx gsl_sf_lambert_Wm1(0e0), 0, :rel-tol(10⁻¹⁵), 'W₋₁(x)';
  ok gsl_sf_lambert_Wm1_e(0e0, $res) == 0, 'W₋₁(x) with error check';
  is-approx $res.val, 0, :rel-tol(10⁻¹⁵), 'W₋₁(x) with error check: value';
}, 'raw - Lambert functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_legendre_P1(0.5e0), 0.5, :rel-tol(10⁻¹⁵), 'P₁(x)';
  ok gsl_sf_legendre_P1_e(0.5e0, $res) == 0, 'P₁(x) with error check';
  is-approx $res.val, 0.5, :rel-tol(10⁻¹⁵), 'P₁(x) with error check: value';
  is-approx gsl_sf_legendre_P2(0.5e0), -0.125, :rel-tol(10⁻¹⁵), 'P₂(x)';
  ok gsl_sf_legendre_P2_e(0.5e0, $res) == 0, 'P₂(x) with error check';
  is-approx $res.val, -0.125, :rel-tol(10⁻¹⁵), 'P₂(x) with error check: value';
  is-approx gsl_sf_legendre_P3(0.5e0), -0.4375, :rel-tol(10⁻¹⁵), 'P₃(x)';
  ok gsl_sf_legendre_P3_e(0.5e0, $res) == 0, 'P₃(x) with error check';
  is-approx $res.val, -0.4375, :rel-tol(10⁻¹⁵), 'P₃(x) with error check: value';
  is-approx gsl_sf_legendre_Pl(1, 0.5e0), 0.5, :rel-tol(10⁻¹⁵), 'Pₗ(x)';
  ok gsl_sf_legendre_Pl_e(1, 0.5e0, $res) == 0, 'Pₗ(x) with error check';
  is-approx $res.val, 0.5, :rel-tol(10⁻¹⁵), 'Pₗ(x) with error check: value';
  my CArray[num64] $res_array .= new: 0e0 xx 11;
  ok gsl_sf_legendre_Pl_array(10, 0.5e0, $res_array) == 0, 'Pₗ(x) array';
  is-approx $res_array[0], 1, :rel-tol(10⁻¹⁵), 'Pₗ(x) array [0]: value';
  my CArray[num64] $res_der_array .= new: 0e0 xx 11;
  ok gsl_sf_legendre_Pl_deriv_array(10, 0.5e0, $res_array, $res_der_array) == 0, 'Pₗ(x) and dPₗ(x)/dx array';
  is-approx $res_array[0], 1, :rel-tol(10⁻¹⁵), 'Pₗ(x) and dPₗ(x)/dx array Pₗ(x)[0]: value';
  is-approx $res_der_array[0], 0, :rel-tol(10⁻¹⁵), 'Pₗ(x) and dPₗ(x)/dx array dPₗ(x)/dx[0]: value';
  is-approx gsl_sf_legendre_Q0(0e0), 0, :rel-tol(10⁻¹⁵), 'Q₀(x)';
  ok gsl_sf_legendre_Q0_e(0e0, $res) == 0, 'Q₀(x) with error check';
  is-approx $res.val, 0, :rel-tol(10⁻¹⁵), 'Q₀(x) with error check: value';
  is-approx gsl_sf_legendre_Q1(0e0), -1, :rel-tol(10⁻¹⁵), 'Q₁(x)';
  ok gsl_sf_legendre_Q1_e(0e0, $res) == 0, 'Q₁(x) with error check';
  is-approx $res.val, -1, :rel-tol(10⁻¹⁵), 'Q₁(x) with error check: value';
  is-approx gsl_sf_legendre_Ql(10, .5e0), 0.29165813966586752393, :rel-tol(10⁻¹⁵), 'Qₗ(x)';
  ok gsl_sf_legendre_Ql_e(10, .5e0, $res) == 0, 'Qₗ(x) with error check';
  is-approx $res.val, 0.29165813966586752393, :rel-tol(10⁻¹⁵), 'Qₗ(x) with error check: value';
  ok gsl_sf_legendre_array_n(10) == 88, 'lenght of an array';
  ok gsl_sf_legendre_array_index(3, 3) == 9, 'position in an array';
  ok gsl_sf_legendre_nlm(10) == 66, 'position in an nlm array';
  my CArray[num64] $legarray .= new: 0e0 xx gsl_sf_legendre_array_n(10);
  my CArray[num64] $legderivarray .= new: 0e0 xx gsl_sf_legendre_array_n(10);
  my CArray[num64] $legderiv2array .= new: 0e0 xx gsl_sf_legendre_array_n(10);
  ok gsl_sf_legendre_array(GSL_SF_LEGENDRE_SCHMIDT, 10, .5e0, $legarray) == 0, 'Pₗⁿ(x) array';
  is-approx $legarray[0], 1, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) array: value';
  ok gsl_sf_legendre_array_e(GSL_SF_LEGENDRE_SCHMIDT, 10, .5e0, 1e0, $legarray) == 0, 'Pₗⁿ(x) array with error check';
  is-approx $legarray[gsl_sf_legendre_array_index(3, 3)], 0.513489897661093, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) array with error check: value';
  ok gsl_sf_legendre_deriv_array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, $legarray, $legderivarray) == 0, 'dPₗⁿ(x)/dx array';
  is-approx $legderivarray[gsl_sf_legendre_array_index(1, 0)], 1, :rel-tol(10⁻¹⁵), 'dPₗⁿ(x)/dx array: value';
  ok gsl_sf_legendre_deriv_array_e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, 1e0, $legarray, $legderivarray) == 0, 'dPₗⁿ(x)/dx array with error check';
  is-approx $legderivarray[gsl_sf_legendre_array_index(1, 0)], 1, :rel-tol(10⁻¹⁵), 'dPₗⁿ(x)/dx array with error check: value';
  ok gsl_sf_legendre_deriv_alt_array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, $legarray, $legderivarray) == 0, 'alt dPₗⁿ(x)/dx array';
  is-approx $legderivarray[gsl_sf_legendre_array_index(1, 0)], -0.9886859966642594, :rel-tol(10⁻¹⁵), 'alt dPₗⁿ(x)/dx array: value';
  ok gsl_sf_legendre_deriv_alt_array_e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, 1e0, $legarray, $legderivarray) == 0, 'alt dPₗⁿ(x)/dx array with error check';
  is-approx $legderivarray[gsl_sf_legendre_array_index(1, 0)], -0.9886859966642594, :rel-tol(10⁻¹⁵), 'alt dPₗⁿ(x)/dx array with error check: value';
  ok gsl_sf_legendre_deriv2_array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, $legarray, $legderivarray, $legderiv2array) == 0, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array';
  is-approx $legderiv2array[gsl_sf_legendre_array_index(1, 0)], 0, 10⁻¹⁵, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array: value';
  ok gsl_sf_legendre_deriv2_array_e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, 1e0, $legarray, $legderivarray, $legderiv2array) == 0, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check';
  is-approx $legderiv2array[gsl_sf_legendre_array_index(1, 0)], 0, 10⁻¹⁵, 'dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check: value';
  ok gsl_sf_legendre_deriv2_alt_array(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, $legarray, $legderivarray, $legderiv2array) == 0, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array';
  is-approx $legderiv2array[gsl_sf_legendre_array_index(1, 0)], -.15, 10⁻¹⁵, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array: value';
  ok gsl_sf_legendre_deriv2_alt_array_e(GSL_SF_LEGENDRE_SCHMIDT, 10, .15e0, 1e0, $legarray, $legderivarray, $legderiv2array) == 0, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check';
  is-approx $legderiv2array[gsl_sf_legendre_array_index(1, 0)], -.15, 10⁻¹⁵, 'alt dPₗⁿ(x)/dx and d²Pₗⁿ(x)/dx² array with error check: value';
  is-approx gsl_sf_legendre_Plm(10, 0, -.5e0), -0.18822860717773437500, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x)';
  ok gsl_sf_legendre_Plm_e(10, 0, -.5e0, $res) == 0, 'Pₗⁿ(x) with error check';
  is-approx $res.val, -0.18822860717773437500, :rel-tol(10⁻¹⁵), 'Pₗⁿ(x) with error check: value';
  is-approx gsl_sf_legendre_sphPlm(10, 0, -.5e0), -0.24332702369300135, :rel-tol(10⁻¹⁵), 'spherical harmonics';
  ok gsl_sf_legendre_sphPlm_e(10, 0, -.5e0, $res) == 0, 'spherical harmonics with error check';
  is-approx $res.val, -0.24332702369300135, :rel-tol(10⁻¹⁵), 'spherical harmonics with error check: value';
  is-approx gsl_sf_conicalP_half(0e0, .5e0), 0.8573827581049917129, :rel-tol(10⁻¹⁵), 'irregular Spherical Conical Function';
  ok gsl_sf_conicalP_half_e(0e0, .5e0, $res) == 0, 'irregular Spherical Conical Function with error check';
  is-approx $res.val, 0.8573827581049917129, :rel-tol(10⁻¹⁵), 'irregular Spherical Conical Function with error check: value';
  is-approx gsl_sf_conicalP_mhalf(0e0, .5e0), 0.8978491247257322404, :rel-tol(10⁻¹⁵), 'regular Spherical Conical Function';
  ok gsl_sf_conicalP_mhalf_e(0e0, .5e0, $res) == 0, 'regular Spherical Conical Function with error check';
  is-approx $res.val, 0.8978491247257322404, :rel-tol(10⁻¹⁵), 'regular Spherical Conical Function with error check: value';
  is-approx gsl_sf_conicalP_0(0e0, .5e0), 1.0731820071493643751, :rel-tol(10⁻¹⁵), 'P⁰₋₁ ₂₊ᵢₗ(x) Function';
  ok gsl_sf_conicalP_0_e(0e0, .5e0, $res) == 0, 'P⁰₋₁ ₂₊ᵢₗ(x) Function with error check';
  is-approx $res.val, 1.0731820071493643751, :rel-tol(10⁻¹⁵), 'P⁰₋₁ ₂₊ᵢₗ(x) Function with error check: value';
  is-approx gsl_sf_conicalP_1(0e0, .5e0), 0.14933621085538265636, :rel-tol(10⁻¹⁵), 'P¹₋₁ ₂₊ᵢₗ(x) Function';
  ok gsl_sf_conicalP_1_e(0e0, .5e0, $res) == 0, 'P¹₋₁ ₂₊ᵢₗ(x) Function with error check';
  is-approx $res.val, 0.14933621085538265636, :rel-tol(10⁻¹⁵), 'P¹₋₁ ₂₊ᵢₗ(x) Function with error check: value';
  is-approx gsl_sf_conicalP_sph_reg(2, 1e0, -.5e0), 1.6406279287008789526, :rel-tol(10⁻¹⁵), 'Regular Spherical Conical Function';
  ok gsl_sf_conicalP_sph_reg_e(2, 1e0, -.5e0, $res) == 0, 'Regular Spherical Conical Function with error check';
  is-approx $res.val, 1.6406279287008789526, :rel-tol(10⁻¹⁵), 'Regular Spherical Conical Function with error check: value';
  is-approx gsl_sf_conicalP_cyl_reg(2, 1e0, -.5e0), 2.2048510472375258708, :rel-tol(10⁻¹⁵), 'Regular Cylindrical Conical Function';
  ok gsl_sf_conicalP_cyl_reg_e(2, 1e0, -.5e0, $res) == 0, 'Regular Cylindrical Conical Function with error check';
  is-approx $res.val, 2.2048510472375258708, :rel-tol(10⁻¹⁵), 'Regular Cylindrical Conical Function with error check: value';
  is-approx gsl_sf_legendre_H3d_0(1e0, 1e0), 0.7160229153604338713, :rel-tol(10⁻¹⁵), '0 radial eigenfunction of the Laplacian on 3D hyperbolic space';
  ok gsl_sf_legendre_H3d_0_e(1e0, 1e0, $res) == 0, '0 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $res.val, 0.7160229153604338713, :rel-tol(10⁻¹⁵), '0 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  is-approx gsl_sf_legendre_H3d_1(1e0, 1e0), 0.3397013994799344639, :rel-tol(10⁻¹⁵), '1 radial eigenfunction of the Laplacian on 3D hyperbolic space';
  ok gsl_sf_legendre_H3d_1_e(1e0, 1e0, $res) == 0, '1 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $res.val, 0.3397013994799344639, :rel-tol(10⁻¹⁵), '1 radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  is-approx gsl_sf_legendre_H3d(5, 1e0, 1e0), 0.011498635037491577728, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space';
  ok gsl_sf_legendre_H3d_e(5, 1e0, 1e0, $res) == 0, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space with error check';
  is-approx $res.val, 0.011498635037491577728, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space with error check: value';
  ok gsl_sf_legendre_H3d_array(10, 1e0, 3e0, $res_array) == 0, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space array';
  is-approx $res_array[0], 0.014086820716211607, 10⁻¹⁵, 'l radial eigenfunction of the Laplacian on 3D hyperbolic space array: value';
}, 'raw - Legendre functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_log(1.1e0), 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(x)';
  ok gsl_sf_log_e(1.1e0, $res) == 0, 'log(x) with error check';
  is-approx $res.val, 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(x) with error check: value';
  is-approx gsl_sf_log_abs(-1.1e0), 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(|x|)';
  ok gsl_sf_log_abs_e(-1.1e0, $res) == 0, 'log(|x|) with error check';
  is-approx $res.val, 0.09531017980432486004, :rel-tol(10⁻¹⁵), 'log(|x|) with error check: value';
  my gsl_sf_result $lnr .= new;
  my gsl_sf_result $theta .= new;
  ok gsl_sf_complex_log_e(1e0, 1e0, $lnr, $theta) == 0, 'log(z) with error check';
  is-approx $lnr.val, 0.3465735902799726547, :rel-tol(10⁻¹⁵), 'log(z) with error check: lnr';
  is-approx $theta.val, 0.7853981633974483096, :rel-tol(10⁻¹⁵), 'log(z) with error check: theta';
  is-approx gsl_sf_log_1plusx(1e-4), 0.00009999500033330833533, :rel-tol(10⁻¹⁵), 'log(1+x)';
  ok gsl_sf_log_1plusx_e(1e-4, $res) == 0, 'log(1+x) with error check';
  is-approx $res.val, 0.00009999500033330833533, :rel-tol(10⁻¹⁵), 'log(1+x) with error check: value';
  is-approx gsl_sf_log_1plusx_mx(1e-4), -4.999666691664666833e-09, :rel-tol(10⁻¹⁵), 'log(1+x)-x';
  ok gsl_sf_log_1plusx_mx_e(1e-4, $res) == 0, 'log(1+x)-x with error check';
  is-approx $res.val, -4.999666691664666833e-09, :rel-tol(10⁻¹⁵), 'log(1+x)-x with error check: value';
}, 'raw - logarithms';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_mathieu_a(2, 1.1e0), 4.440022293558291, :rel-tol(10⁻¹⁵), 'aₙ(q)';
  ok gsl_sf_mathieu_a_e(2, 1.1e0, $res) == 0, 'aₙ(q) with error check';
  is-approx $res.val, 4.440022293558291, :rel-tol(10⁻¹⁵), 'aₙ(q) with error check: value';
  is-approx gsl_sf_mathieu_b(2, 1.1e0), 3.8996898851752686, :rel-tol(10⁻¹⁵), 'bₙ(q)';
  ok gsl_sf_mathieu_b_e(2, 1.1e0, $res) == 0, 'bₙ(q) with error check';
  is-approx $res.val, 3.8996898851752686, :rel-tol(10⁻¹⁵), 'bₙ(q) with error check: value';
  my gsl_sf_mathieu_workspace $work;
  lives-ok { $work = gsl_sf_mathieu_alloc(6, 20e0) }, 'allocate workspace';
  my CArray[num64] $res_array .= new: 0e0 xx 6;
  ok gsl_sf_mathieu_a_array(0, 5, 0e0, $work, $res_array) == 0, 'aₙ(q) array';
  is-deeply $res_array.list, (0e0, 1e0, 4e0, 9e0, 16e0, 25e0), 'aₙ(q) array: values';
  ok gsl_sf_mathieu_b_array(0, 5, 0e0, $work, $res_array) == 0, 'bₙ(q) array';
  is-deeply $res_array.list, (0e0, 1e0, 4e0, 9e0, 16e0, 25e0), 'bₙ(q) array: values';
  is-approx gsl_sf_mathieu_ce(0, 0e0, 0e0), 0.7071067811865475, :rel-tol(10⁻¹⁵), 'ceₙ(q,x)';
  ok gsl_sf_mathieu_ce_e(0, 0e0, 0e0, $res) == 0, 'ceₙ(q,x) with error check';
  is-approx $res.val, 0.7071067811865475, :rel-tol(10⁻¹⁵), 'ceₙ(q,x) with error check: value';
  is-approx gsl_sf_mathieu_se(15, 0e0, π/2), -1, :rel-tol(10⁻¹⁵), 'seₙ(q,x)';
  ok gsl_sf_mathieu_se_e(15, 0e0, π/2, $res) == 0, 'seₙ(q,x) with error check';
  is-approx $res.val, -1, :rel-tol(10⁻¹⁵), 'seₙ(q,x) with error check: value';
  ok gsl_sf_mathieu_ce_array(0, 5, 0e0, π/2, $work, $res_array) == 0, 'ceₙ(q,x) array';
  is-deeply $res_array.list, (0.7071067811865475e0, 6.123233995736766e-17, -1e0, -1.8369701987210297e-16, 1e0, 3.061616997868383e-16), 'ceₙ(q,x) array: values';
  ok gsl_sf_mathieu_se_array(0, 5, 0e0, π/2, $work, $res_array) == 0, 'seₙ(q,x) array';
  is-deeply $res_array.list, (0e0, 1e0, 1.2246467991473532e-16, -1e0, -2.4492935982947064e-16, 1e0), 'seₙ(q,x) array: values';
  is-approx gsl_sf_mathieu_Mc(1, 0, 1e0, 0e0), 0.8447696705150902, :rel-tol(10⁻¹⁵), 'Mcʲₙ(q,x)';
  ok gsl_sf_mathieu_Mc_e(1, 0, 1e0, 0e0, $res) == 0, 'Mcʲₙ(q,x) with error check';
  is-approx $res.val, 0.8447696705150902, :rel-tol(10⁻¹⁵), 'Mcʲₙ(q,x) with error check: value';
  is-approx gsl_sf_mathieu_Ms(1, 0, 1e0, 0e0), 0, :rel-tol(10⁻¹⁵), 'Msʲₙ(q,x)';
  ok gsl_sf_mathieu_Ms_e(1, 0, 1e0, 0e0, $res) == 0, 'Msʲₙ(q,x) with error check';
  is-approx $res.val, 0, :rel-tol(10⁻¹⁵), 'Msʲₙ(q,x) with error check: value';
  ok gsl_sf_mathieu_Mc_array(1, 0, 5, 1e0, π/2, $work, $res_array) == 0, 'Mcʲₙ(q,x) array';
  is-deeply $res_array.list, (-0.3118830825472924e0, -0.401338211769362e0, 0.12436859192137752e0, 0.4930738160216151e0, 0.4754523550624284e0, 0.29643292798754495e0), 'Mcʲₙ(q,x) array: values';
  ok gsl_sf_mathieu_Ms_array(1, 0, 5, 1e0, π/2, $work, $res_array) == 0, 'Msʲₙ(q,x) array';
  is-deeply $res_array.list, (0e0, -0.3397911837218603e0, 0.1452203874466516e0, 0.49324139011869106e0, 0.4754148659557405e0, 0.2964318355087169e0), 'Msʲₙ(q,x) array: values';
  lives-ok { gsl_sf_mathieu_free($work) }, 'free workspace';
}, 'raw - Mathieu functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_pow_int(2e0, 3), 8, :rel-tol(10⁻¹⁵), 'xⁿ';
  ok gsl_sf_pow_int_e(2e0, 3, $res) == 0, 'xⁿ with error check';
  is-approx $res.val, 8, :rel-tol(10⁻¹⁵), 'xⁿ with error check: value';
}, 'raw - Power functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_psi_int(1), -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(n)';
  ok gsl_sf_psi_int_e(1, $res) == 0, 'ψ(n) with error check';
  is-approx $res.val, -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(n) with error check: value';
  is-approx gsl_sf_psi(1e0), -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(x)';
  ok gsl_sf_psi_e(1e0, $res) == 0, 'ψ(x) with error check';
  is-approx $res.val, -0.57721566490153286060, :rel-tol(10⁻¹⁵), 'ψ(x) with error check: value';
  is-approx gsl_sf_psi_1piy(1e0), 0.09465032062247697727, :rel-tol(10⁻¹⁵), '𝕽[ψ(1+iy)]';
  ok gsl_sf_psi_1piy_e(1e0, $res) == 0, '𝕽[ψ(1+iy)] with error check';
  is-approx $res.val, 0.09465032062247697727, :rel-tol(10⁻¹⁵), '𝕽[ψ(1+iy)] with error check: value';
  is-approx gsl_sf_psi_1_int(1), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(n)';
  ok gsl_sf_psi_1_int_e(1, $res) == 0, 'ψ’(n) with error check';
  is-approx $res.val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(n) with error check: value';
  is-approx gsl_sf_psi_1(1e0), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(x)';
  ok gsl_sf_psi_1_e(1e0, $res) == 0, 'ψ’(x) with error check';
  is-approx $res.val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψ’(x) with error check: value';
  is-approx gsl_sf_psi_n(1, 1e0), 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψⁿ(n)';
  ok gsl_sf_psi_n_e(1, 1e0, $res) == 0, 'ψⁿ(n) with error check';
  is-approx $res.val, 1.6449340668482264364, :rel-tol(10⁻¹⁵), 'ψⁿ(n) with error check: value';
}, 'raw - Psi functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_synchrotron_1(1e0), 0.651422815355364504, 10⁻¹⁵, 'First synchrotron function';
  ok gsl_sf_synchrotron_1_e(1e0, $res) == 0, 'First synchrotron function with error check';
  is-approx $res.val, 0.651422815355364504, 10⁻¹⁵, 'First synchrotron function with error check: value';
  is-approx gsl_sf_synchrotron_2(1e0), 0.49447506210420666, :rel-tol(10⁻¹⁵), 'Second synchrotron function';
  ok gsl_sf_synchrotron_2_e(1e0, $res) == 0, 'Second synchrotron function with error check';
  is-approx $res.val, 0.49447506210420666, :rel-tol(10⁻¹⁵), 'Second synchrotron function with error check: value';
}, 'raw - Synchrotron functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_transport_2(1e0), 0.97303256135517012845, 10⁻¹⁵, 'J(2,x)';
  ok gsl_sf_transport_2_e(1e0, $res) == 0, 'J(2,x) with error check';
  is-approx $res.val, 0.97303256135517012845, 10⁻¹⁵, 'J(2,x) with error check: value';
  is-approx gsl_sf_transport_3(1e0), 0.479841006572417499939, 10⁻¹⁵, 'J(3,x)';
  ok gsl_sf_transport_3_e(1e0, $res) == 0, 'J(3,x) with error check';
  is-approx $res.val, 0.479841006572417499939, 10⁻¹⁵, 'J(3,x) with error check: value';
  is-approx gsl_sf_transport_4(1e0), 0.31724404523442648241, 10⁻¹⁵, 'J(4,x)';
  ok gsl_sf_transport_4_e(1e0, $res) == 0, 'J(4,x) with error check';
  is-approx $res.val, 0.31724404523442648241, 10⁻¹⁵, 'J(4,x) with error check: value';
  is-approx gsl_sf_transport_5(1e0), 0.236615879239094789259153, 10⁻¹⁵, 'J(5,x)';
  ok gsl_sf_transport_5_e(1e0, $res) == 0, 'J(5,x) with error check';
  is-approx $res.val, 0.236615879239094789259153, 10⁻¹⁵, 'J(5,x) with error check: value';
}, 'raw - Transport functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_sin(1e0), 0.8414709848078965067, 10⁻¹⁵, 'sin(x)';
  ok gsl_sf_sin_e(1e0, $res) == 0, 'sin(x) with error check';
  is-approx $res.val, 0.8414709848078965067, 10⁻¹⁵, 'sin(x) with error check: value';
  is-approx gsl_sf_cos(1e0), 0.5403023058681397174, 10⁻¹⁵, 'cos(x)';
  ok gsl_sf_cos_e(1e0, $res) == 0, 'cos(x) with error check';
  is-approx $res.val, 0.5403023058681397174, 10⁻¹⁵, 'cos(x) with error check: value';
  is-approx gsl_sf_hypot(3e0, 4e0), 5, 10⁻¹⁵, '√x²+y²';
  ok gsl_sf_hypot_e(3e0, 4e0, $res) == 0, '√x²+y² with error check';
  is-approx $res.val, 5, 10⁻¹⁵, '√x²+y² with error check: value';
  is-approx gsl_sf_sinc(80.5e0), 0.0039541600768172754, 10⁻¹⁵, 'sinc(x)';
  ok gsl_sf_sinc_e(80.5e0, $res) == 0, 'sinc(x) with error check';
  is-approx $res.val, 0.0039541600768172754, 10⁻¹⁵, 'sinc(x) with error check: value';
  my gsl_sf_result $zr .= new;
  my gsl_sf_result $zi .= new;
  ok gsl_sf_complex_sin_e(1e0, 5e0, $zr, $zi) == 0, 'sin(z) with error check';
  is-approx $zr.val, 62.44551846769653403, 10⁻¹⁵, 'sin(z) with error check: re';
  is-approx $zi.val, 40.09216577799840254, 10⁻¹⁵, 'sin(z) with error check: im';
  ok gsl_sf_complex_cos_e(1e0, 5e0, $zr, $zi) == 0, 'cos(z) with error check';
  is-approx $zr.val, 40.09580630629882573, :rel-tol(10⁻¹⁵), 'cos(z) with error check: re';
  is-approx $zi.val, -62.43984868079963017, :rel-tol(10⁻¹⁵), 'cos(z) with error check: im';
  ok gsl_sf_complex_logsin_e(5e0, 5e0, $zr, $zi) == 0, 'log(sin(z)) with error check';
  is-approx $zr.val, 4.3068909128079757420, 10⁻¹⁵, 'log(sin(z)) with error check: re';
  is-approx $zi.val, 2.8540063315538773952, 10⁻¹⁵, 'log(sin(z)) with error check: im';
  is-approx gsl_sf_lnsinh(1e0), 0.16143936157119563361, 10⁻¹⁵, 'log(sinh(x))';
  ok gsl_sf_lnsinh_e(1e0, $res) == 0, 'log(sinh(x)) with error check';
  is-approx $res.val, 0.16143936157119563361, 10⁻¹⁵, 'log(sinh(x)) with error check: value';
  is-approx gsl_sf_lncosh(1e0), 0.4337808304830271870, 10⁻¹⁵, 'log(cosh(x))';
  ok gsl_sf_lncosh_e(1e0, $res) == 0, 'log(cosh(x)) with error check';
  is-approx $res.val, 0.4337808304830271870, 10⁻¹⁵, 'log(cosh(x)) with error check: value';
  ok gsl_sf_polar_to_rect(10e0, π/6, $zr, $zi) == 0, 'polar to rect';
  is-approx $zr.val, (10e0 * sqrt(3) / 2e0), :rel-tol(10⁻¹⁵), 'polar to rect: value';
  is-approx $zi.val, 10e0 * .5e0, :rel-tol(10⁻¹⁵), 'polar to rect: value';
  ok gsl_sf_rect_to_polar(10e0, 6e0, $zr, $zi) == 0, 'rect to polar';
  is-approx $zr.val, 11.6619037896906, :rel-tol(10⁻¹⁵), 'rect to polar: value';
  is-approx $zi.val, 0.5404195002705842, :rel-tol(10⁻¹⁵), 'rect to polar: value';
  is-approx gsl_sf_angle_restrict_symm(1e9), 0.5773954235013851694, 10⁻¹⁵, 'θ in [-π,π)';
  my num64 $theta = 1e9;
  ok gsl_sf_angle_restrict_symm_e($theta) == 0, 'θ in [-π,π) with error check';
  is-approx $theta, 0.5773954235013851694, 10⁻¹⁵, 'θ in [-π,π) with error check: value';
  is-approx gsl_sf_angle_restrict_pos(1e9), 0.5773954235013851694, 10⁻¹⁵, 'θ in [-0,2π)';
  $theta = 1e9;
  ok gsl_sf_angle_restrict_pos_e($theta) == 0, 'θ in [-0,2π) with error check';
  is-approx $theta, 0.5773954235013851694, 10⁻¹⁵, 'θ in [-0,2π) with error check: value';
  ok gsl_sf_sin_err_e(1e0, 1e-9, $res) == 0, 'sin(x±dx) with error check';
  is-approx $res.val, 0.8414709848078965067, 10⁻¹⁵, 'sin(x±dx) with error check: value';
  ok gsl_sf_cos_err_e(1e0, 1e-9, $res) == 0, 'cos(x±dx) with error check';
  is-approx $res.val, 0.5403023058681397174, 10⁻¹⁵, 'cos(x±dx) with error check: value';
}, 'raw - Trigonometric functions';

subtest {
  my gsl_sf_result $res .= new;
  is-approx gsl_sf_zeta_int(5), 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)';
  ok gsl_sf_zeta_int_e(5, $res) == 0, 'ζ(n) with error check';
  is-approx $res.val, 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(n) with error check: value';
  is-approx gsl_sf_zeta(5e0), 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)';
  ok gsl_sf_zeta_e(5e0, $res) == 0, 'ζ(x) with error check';
  is-approx $res.val, 1.0369277551433699263313655, 10⁻¹⁵, 'ζ(x) with error check: value';
  is-approx gsl_sf_zetam1_int(5), 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)-1';
  ok gsl_sf_zetam1_int_e(5, $res) == 0, 'ζ(n)-1 with error check';
  is-approx $res.val, 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(n)-1 with error check: value';
  is-approx gsl_sf_zetam1(5e0), 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)-1';
  ok gsl_sf_zetam1_e(5e0, $res) == 0, 'ζ(x)-1 with error check';
  is-approx $res.val, 0.0369277551433699263313655, 10⁻¹⁵, 'ζ(x)-1 with error check: value';
  is-approx gsl_sf_hzeta(5e0, 1e0), 1.0369277551433699263, 10⁻¹⁵, 'ζ(s,q)';
  ok gsl_sf_hzeta_e(5e0, 1e0, $res) == 0, 'ζ(s,q) with error check';
  is-approx $res.val, 1.0369277551433699263, 10⁻¹⁵, 'ζ(s,q) with error check: value';
  is-approx gsl_sf_eta_int(5), 0.9721197704469093059, 10⁻¹⁵, 'η(n)';
  ok gsl_sf_eta_int_e(5, $res) == 0, 'η(n) with error check';
  is-approx $res.val, 0.9721197704469093059, 10⁻¹⁵, 'η(n) with error check: value';
  is-approx gsl_sf_eta(5e0), 0.9721197704469093059, 10⁻¹⁵, 'η(x)';
  ok gsl_sf_eta_e(5e0, $res) == 0, 'η(x) with error check';
  is-approx $res.val, 0.9721197704469093059, 10⁻¹⁵, 'η(x) with error check: value';
}, 'raw - Zeta functions';

done-testing;
