use slatec_sys::{FortranInteger, special as raw};
use super::{SpecialFunctionError, runtime};
const LOG_INTEGRAL_MIN_F64: f64 = 2.061_153_622_438_558e-9;
const LOG_INTEGRAL_MAX_F64: f64 = 4.851_651_954_097_903e8;
const LOG_INTEGRAL_MIN_F32: f32 = 2.061_153_7e-9;
const LOG_INTEGRAL_MAX_F32: f32 = 4.851_652e8;
fn logarithmic_integral_input(function: &'static str, x: f64) -> Result<(), SpecialFunctionError> {
if x.is_finite() && x >= LOG_INTEGRAL_MIN_F64 && x <= LOG_INTEGRAL_MAX_F64 && x != 1.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument: "x",
value: x,
})
}
}
#[cfg(feature = "special-f32")]
fn logarithmic_integral_input_f32(
function: &'static str,
x: f32,
) -> Result<(), SpecialFunctionError> {
if x.is_finite() && x >= LOG_INTEGRAL_MIN_F32 && x <= LOG_INTEGRAL_MAX_F32 && x != 1.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument: "x",
value: f64::from(x),
})
}
}
fn finite(
function: &'static str,
argument: &'static str,
value: f64,
) -> Result<(), SpecialFunctionError> {
runtime::finite(function, argument, value)
}
#[cfg(feature = "special-f32")]
fn finite_f32(
function: &'static str,
argument: &'static str,
value: f32,
) -> Result<(), SpecialFunctionError> {
runtime::finite_f32(function, argument, value)
}
fn nonnegative(
function: &'static str,
argument: &'static str,
value: f64,
) -> Result<(), SpecialFunctionError> {
if value.is_finite() && value >= 0.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument,
value,
})
}
}
fn positive(
function: &'static str,
argument: &'static str,
value: f64,
) -> Result<(), SpecialFunctionError> {
if value.is_finite() && value > 0.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument,
value,
})
}
}
#[cfg(feature = "special-f32")]
fn nonnegative_f32(
function: &'static str,
argument: &'static str,
value: f32,
) -> Result<(), SpecialFunctionError> {
if value.is_finite() && value >= 0.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument,
value: f64::from(value),
})
}
}
#[cfg(feature = "special-f32")]
fn positive_f32(
function: &'static str,
argument: &'static str,
value: f32,
) -> Result<(), SpecialFunctionError> {
if value.is_finite() && value > 0.0 {
Ok(())
} else {
Err(SpecialFunctionError::Domain {
function,
argument,
value: f64::from(value),
})
}
}
fn status(function: &'static str, ier: FortranInteger) -> Result<(), SpecialFunctionError> {
if ier == 0 {
Ok(())
} else {
Err(SpecialFunctionError::NativeStatus {
function,
status: ier,
})
}
}
pub fn logarithmic_integral(x: f64) -> Result<f64, SpecialFunctionError> {
logarithmic_integral_input("logarithmic_integral", x)?;
let _runtime = runtime::lock_fnlib();
let mut x = x;
Ok(unsafe { raw::dli(&mut x) })
}
pub fn spence_integral(x: f64) -> Result<f64, SpecialFunctionError> {
finite("spence_integral", "x", x)?;
let _runtime = runtime::lock_fnlib();
let mut x = x;
Ok(unsafe { raw::dspenc(&mut x) })
}
pub fn carlson_rc(x: f64, y: f64) -> Result<f64, SpecialFunctionError> {
nonnegative("carlson_rc", "x", x)?;
positive("carlson_rc", "y", y)?;
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut ier) = (x, y, 0);
let value = unsafe { raw::drc(&mut x, &mut y, &mut ier) };
status("carlson_rc", ier)?;
Ok(value)
}
pub fn carlson_rf(x: f64, y: f64, z: f64) -> Result<f64, SpecialFunctionError> {
nonnegative("carlson_rf", "x", x)?;
nonnegative("carlson_rf", "y", y)?;
nonnegative("carlson_rf", "z", z)?;
if x + y == 0.0 || x + z == 0.0 || y + z == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rf",
argument: "x, y, z",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut ier) = (x, y, z, 0);
let value = unsafe { raw::drf(&mut x, &mut y, &mut z, &mut ier) };
status("carlson_rf", ier)?;
Ok(value)
}
pub fn carlson_rd(x: f64, y: f64, z: f64) -> Result<f64, SpecialFunctionError> {
nonnegative("carlson_rd", "x", x)?;
nonnegative("carlson_rd", "y", y)?;
positive("carlson_rd", "z", z)?;
if x + y == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rd",
argument: "x, y",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut ier) = (x, y, z, 0);
let value = unsafe { raw::drd(&mut x, &mut y, &mut z, &mut ier) };
status("carlson_rd", ier)?;
Ok(value)
}
pub fn carlson_rj(x: f64, y: f64, z: f64, p: f64) -> Result<f64, SpecialFunctionError> {
nonnegative("carlson_rj", "x", x)?;
nonnegative("carlson_rj", "y", y)?;
nonnegative("carlson_rj", "z", z)?;
positive("carlson_rj", "p", p)?;
if x + y == 0.0 || x + z == 0.0 || y + z == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rj",
argument: "x, y, z",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut p, mut ier) = (x, y, z, p, 0);
let value = unsafe { raw::drj(&mut x, &mut y, &mut z, &mut p, &mut ier) };
status("carlson_rj", ier)?;
Ok(value)
}
#[cfg(feature = "special-f32")]
pub fn logarithmic_integral_f32(x: f32) -> Result<f32, SpecialFunctionError> {
logarithmic_integral_input_f32("logarithmic_integral_f32", x)?;
let _runtime = runtime::lock_fnlib();
let mut x = x;
Ok(unsafe { raw::ali(&mut x) })
}
#[cfg(feature = "special-f32")]
pub fn spence_integral_f32(x: f32) -> Result<f32, SpecialFunctionError> {
finite_f32("spence_integral_f32", "x", x)?;
let _runtime = runtime::lock_fnlib();
let mut x = x;
Ok(unsafe { raw::spenc(&mut x) })
}
#[cfg(feature = "special-f32")]
pub fn carlson_rc_f32(x: f32, y: f32) -> Result<f32, SpecialFunctionError> {
nonnegative_f32("carlson_rc_f32", "x", x)?;
positive_f32("carlson_rc_f32", "y", y)?;
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut ier) = (x, y, 0);
let value = unsafe { raw::rc(&mut x, &mut y, &mut ier) };
status("carlson_rc_f32", ier)?;
Ok(value)
}
#[cfg(feature = "special-f32")]
pub fn carlson_rf_f32(x: f32, y: f32, z: f32) -> Result<f32, SpecialFunctionError> {
nonnegative_f32("carlson_rf_f32", "x", x)?;
nonnegative_f32("carlson_rf_f32", "y", y)?;
nonnegative_f32("carlson_rf_f32", "z", z)?;
if x + y == 0.0 || x + z == 0.0 || y + z == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rf_f32",
argument: "x, y, z",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut ier) = (x, y, z, 0);
let value = unsafe { raw::rf(&mut x, &mut y, &mut z, &mut ier) };
status("carlson_rf_f32", ier)?;
Ok(value)
}
#[cfg(feature = "special-f32")]
pub fn carlson_rd_f32(x: f32, y: f32, z: f32) -> Result<f32, SpecialFunctionError> {
nonnegative_f32("carlson_rd_f32", "x", x)?;
nonnegative_f32("carlson_rd_f32", "y", y)?;
positive_f32("carlson_rd_f32", "z", z)?;
if x + y == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rd_f32",
argument: "x, y",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut ier) = (x, y, z, 0);
let value = unsafe { raw::rd(&mut x, &mut y, &mut z, &mut ier) };
status("carlson_rd_f32", ier)?;
Ok(value)
}
#[cfg(feature = "special-f32")]
pub fn carlson_rj_f32(x: f32, y: f32, z: f32, p: f32) -> Result<f32, SpecialFunctionError> {
nonnegative_f32("carlson_rj_f32", "x", x)?;
nonnegative_f32("carlson_rj_f32", "y", y)?;
nonnegative_f32("carlson_rj_f32", "z", z)?;
positive_f32("carlson_rj_f32", "p", p)?;
if x + y == 0.0 || x + z == 0.0 || y + z == 0.0 {
return Err(SpecialFunctionError::Domain {
function: "carlson_rj_f32",
argument: "x, y, z",
value: 0.0,
});
}
let _runtime = runtime::lock_fnlib();
let _xerror = crate::runtime::permit_recoverable_native_statuses();
let (mut x, mut y, mut z, mut p, mut ier) = (x, y, z, p, 0);
let value = unsafe { raw::rj(&mut x, &mut y, &mut z, &mut p, &mut ier) };
status("carlson_rj_f32", ier)?;
Ok(value)
}