#![deny(rustdoc::broken_intra_doc_links)]
use crate::{
functions::FunctionErrors,
kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait},
validation::{StrictFinitePolicy, capture_backtrace},
};
use duplicate::duplicate_item;
use num::Complex;
use std::backtrace::Backtrace;
use thiserror::Error;
use try_create::ValidationPolicy;
const DOC_FUNC_NAME_TRAIT: &str = "\
Trait for computing the MATH_OP_DESC of a number.
Provides both a fallible method that returns a [`Result`] and a panicking method \
that directly returns the computed value or panics on invalid input.
# Domain
DOMAIN_DESC
# Associated Types
- `Error`: The error type returned by [`try_func_name`](Self::try_func_name).
# Required Methods
- [`try_func_name`](Self::try_func_name): Computes the MATH_OP_DESC and returns a [`Result`]
- [`func_name`](Self::func_name): Computes the MATH_OP_DESC or panics on error";
const DOC_TRY_FUNC_NAME: &str = "\
Computes the MATH_OP_DESC of `self` and returns a [`Result`].
# Errors
Returns an error if:
- Input validation fails (NaN, infinity, subnormal)
- Input is outside the function's domain
- Result validation fails";
const DOC_FUNC_NAME: &str = "\
Computes the MATH_OP_DESC of `self` and directly returns the computed value.
This is a **panicking method** (not `unsafe`) that panics on invalid input. \
For error handling, use [`try_func_name`](Self::try_func_name).
# Panics
Panics if input is invalid or outside the function's domain.";
#[derive(Debug, Error)]
pub enum FUNC_NAMERealInputErrors<RawReal: RawRealTrait> {
#[error("the argument is invalid")]
InvalidArgument {
#[source]
source: <RawReal as RawScalarTrait>::ValidationErrors,
},
}
pub type FUNC_NAMERealErrors<RawReal> = FunctionErrors<
FUNC_NAMERealInputErrors<RawReal>,
<RawReal as RawScalarTrait>::ValidationErrors,
>;
#[derive(Debug, Error)]
pub enum FUNC_NAMEComplexInputErrors<RawComplex: RawComplexTrait> {
#[error("the argument is invalid")]
InvalidArgument {
#[source]
source: <RawComplex as RawScalarTrait>::ValidationErrors,
},
}
pub type FUNC_NAMEComplexErrors<RawComplex> = FunctionErrors<
FUNC_NAMEComplexInputErrors<RawComplex>,
<RawComplex as RawScalarTrait>::ValidationErrors,
>;
#[doc = DOC_FUNC_NAME_TRAIT]
pub trait FUNC_NAME: Sized {
type Error: std::error::Error;
#[doc = DOC_TRY_FUNC_NAME]
fn try_func_name(self) -> Result<Self, Self::Error>;
#[doc = DOC_FUNC_NAME]
fn func_name(self) -> Self;
}
impl FUNC_NAME for f64 {
type Error = FUNC_NAMERealErrors<Self>;
#[inline(always)]
fn try_func_name(self) -> Result<Self, Self::Error> {
StrictFinitePolicy::<Self, 53>::validate(self)
.map_err(|e| FUNC_NAMERealInputErrors::InvalidArgument { source: e })?;
let result = self.func_name();
StrictFinitePolicy::<Self, 53>::validate(result)
.map_err(|e| FunctionErrors::Output { source: e })?;
Ok(result)
}
#[inline(always)]
fn func_name(self) -> Self {
#[cfg(debug_assertions)]
{
self.try_func_name().unwrap()
}
#[cfg(not(debug_assertions))]
{
f64::func_name(self)
}
}
}
impl FUNC_NAME for Complex<f64> {
type Error = FUNC_NAMEComplexErrors<Self>;
#[inline(always)]
fn try_func_name(self) -> Result<Self, Self::Error> {
StrictFinitePolicy::<Self, 53>::validate(self)
.map_err(|e| FUNC_NAMEComplexInputErrors::InvalidArgument { source: e })?;
let result = self.func_name();
StrictFinitePolicy::<Self, 53>::validate(result)
.map_err(|e| FunctionErrors::Output { source: e })?;
Ok(result)
}
#[inline(always)]
fn func_name(self) -> Self {
#[cfg(debug_assertions)]
{
self.try_func_name().unwrap()
}
#[cfg(not(debug_assertions))]
{
Complex::func_name(&self)
}
}
}
#[duplicate_item(
kernel_type;
[Native64StrictFinite];
[Native64StrictFiniteInDebug];
// Add rug kernels when #[cfg(feature = "rug")]:
// #[cfg(feature = "rug")]
// [RugStrictFinite];
// #[cfg(feature = "rug")]
// [RugStrictFiniteInDebug];
)]
impl FUNC_NAME for crate::RealValidated<kernel_type> {
type Error = FUNC_NAMERealErrors<kernel_type::RawReal>;
fn try_func_name(self) -> Result<Self, Self::Error> {
let result = self.value.try_func_name()?;
Ok(Self::new(result))
}
fn func_name(self) -> Self {
self.try_func_name().unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::RealNative64StrictFinite;
#[test]
fn test_func_name_valid_input() {
let x = RealNative64StrictFinite::from_f64();
let result = x.try_func_name().unwrap();
}
#[test]
fn test_func_name_domain_error() {
let x = RealNative64StrictFinite::from_f64();
assert!(x.try_func_name().is_err());
}
#[test]
#[should_panic(expected = "domain")]
fn test_func_name_panic() {
let x = RealNative64StrictFinite::from_f64();
x.func_name(); }
#[cfg(feature = "rug")]
#[test]
fn test_func_name_rug() {
}
}