1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
22 functions::FunctionErrors,
23 kernels::{RawRealTrait, RawScalarTrait},
24 validation::StrictFinitePolicy,
25};
26use duplicate::duplicate_item;
27use num::Complex;
28use std::backtrace::Backtrace;
29use thiserror::Error;
30use try_create::ValidationPolicy;
31
32#[duplicate_item(
34 enum_name enum_doc;
35 [CosHInputErrors] ["Errors that can occur during the computation of the hyperbolic cosine.\n\nPrimarily, this enum handles issues related to invalid input arguments,\\nsuch as NaN (Not a Number) or infinity, as determined by the\\nimplemented validation policy (e.g., [`StrictFinitePolicy`]).\n\n# Type Parameters\n\n- `ScalarType`: The numeric type for the computation (e.g., `f64`, `Complex<f64>`),\\n which must implement the [`RawScalarTrait`] trait. The associated type\\n `<RawScalar as RawScalarTrait>::ValidationErrors` is used to convey details of underlying\\n validation failures.\n\n# Variants\n\n- `InvalidArgument`: Signals that the input argument to the hyperbolic cosine\\n function is invalid. This variant wraps the specific error encountered\\n during the validation process, providing more context on the nature of\\n the invalidity."];
36 [SinHInputErrors] ["Errors that can occur during the computation of the hyperbolic sine.\n\nPrimarily, this enum handles issues related to invalid input arguments,\\nsuch as NaN (Not a Number) or infinity, as determined by the\\nimplemented validation policy (e.g., [`StrictFinitePolicy`]).\n\n# Type Parameters\n\n- `ScalarType`: The numeric type for the computation (e.g., `f64`, `Complex<f64>`),\\n which must implement the [`RawScalarTrait`] trait. The associated type\\n `<RawScalar as RawScalarTrait>::ValidationErrors` is used to convey details of underlying\\n validation failures.\n\n# Variants\n\n- `InvalidArgument`: Signals that the input argument to the hyperbolic sine\\n function is invalid. This variant wraps the specific error encountered\\n during the validation process, providing more context on the nature of\\n the invalidity."];
37 [ASinHInputErrors] ["Errors that can occur during the computation of the inverse hyperbolic sine.\n\nPrimarily, this enum handles issues related to invalid input arguments,\\nsuch as NaN (Not a Number) or infinity, as determined by the\\nimplemented validation policy (e.g., [`StrictFinitePolicy`]).\\nNote: `asinh` is defined for all real and complex numbers, so domain errors\\nare not typically raised at this input stage.\n\n# Type Parameters\n\n- `ScalarType`: The numeric type for the computation (e.g., `f64`, `Complex<f64>`),\\n which must implement the [`RawScalarTrait`] trait. The associated type\\n `<RawScalar as RawScalarTrait>::ValidationErrors` is used to convey details of underlying\\n validation failures.\n\n# Variants\n\n- `InvalidArgument`: Signals that the input argument to the inverse hyperbolic sine\\n function is invalid. This variant wraps the specific error encountered\\n during the validation process, providing more context on the nature of\\n the invalidity."];
38)]
39#[derive(Debug, Error)]
40#[doc = enum_doc]
41pub enum enum_name<RawScalar: RawScalarTrait> {
42 #[error("the argument of the function is invalid!")]
48 InvalidArgument {
49 #[source]
51 #[backtrace]
52 source: <RawScalar as RawScalarTrait>::ValidationErrors,
53 },
54}
55
56#[derive(Debug, Error)]
72pub enum TanHRealInputErrors<RawReal: RawRealTrait> {
73 #[error("the argument of the function is invalid!")]
79 InvalidArgument {
80 #[source]
82 #[backtrace]
83 source: <RawReal as RawScalarTrait>::ValidationErrors,
84 },
85}
86
87#[duplicate_item(
88 enum_name enum_doc;
89 [ACosHInputErrors] ["Errors that can occur during the computation of the inverse hyperbolic cosine.\n\nThis enum handles issues related to invalid input arguments, such as NaN or\\ninfinity, as determined by the validation policy (e.g., [`StrictFinitePolicy`]).\\nIt also includes domain errors specific to `acosh`, which is defined for `x >= 1`\\nfor real numbers and for all complex numbers.\n\n# Type Parameters\n\n- `RawScalar`: The numeric type (e.g., `f64`, `Complex<f64>`), implementing [`RawScalarTrait`].\\n `<RawScalar as RawScalarTrait>::ValidationErrors` provides details of validation failures.\n\n# Variants\n\n- `InvalidArgument`: Input is invalid (e.g., NaN, infinity). Wraps `<RawScalar as RawScalarTrait>::ValidationErrors`.\\n- `DomainError`: Input is outside the function's domain (e.g., `x < 1` for real `acosh`)."];
90 [ATanHInputErrors] ["Errors that can occur during the computation of the inverse hyperbolic tangent.\n\nThis enum handles issues related to invalid input arguments, such as NaN or\\ninfinity, as determined by the validation policy (e.g., [`StrictFinitePolicy`]).\\nIt also includes domain errors specific to `atanh`, which is defined for `-1 < x < 1`\\nfor real numbers and for complex numbers `z` where `z != ±1`.\n\n# Type Parameters\n\n- `RawScalar`: The numeric type (e.g., `f64`, `Complex<f64>`), implementing [`RawScalarTrait`].\\n `<RawScalar as RawScalarTrait>::ValidationErrors` provides details of validation failures.\n\n# Variants\n\n- `InvalidArgument`: Input is invalid (e.g., NaN, infinity). Wraps `<RawScalar as RawScalarTrait>::ValidationErrors`.\\n- `DomainError`: Input is outside the function's domain (e.g., `|x| >= 1` for real `atanh`)."];
91)]
92#[derive(Debug, Error)]
93#[doc = enum_doc]
94pub enum enum_name<RawScalar: RawScalarTrait> {
95 #[error("the input argument is outside the domain of the function!")]
100 OutOfDomain {
101 value: RawScalar,
102
103 backtrace: Backtrace,
104 },
105
106 #[error("the argument of the function is invalid!")]
112 InvalidArgument {
113 #[source]
115 #[backtrace]
116 source: <RawScalar as RawScalarTrait>::ValidationErrors,
117 },
118}
119
120#[duplicate_item(
121 enum_name ErrIn enum_doc;
122 [CosHErrors] [CosHInputErrors] ["Errors that can occur when computing the *hyperbolic cosine* of a real or complex number.\n\nIt includes errors for invalid input and output values.\n\n# Type Parameters\n\n- `RawScalar`: A type that implements the [`RawScalarTrait`] trait. This type parameter is used to specify the numeric type for the computation and its associated raw error type `<RawScalar as RawScalarTrait>::ValidationErrors`.\n\n# Variants\n\n- `Input`: Indicates that the input value is invalid. This variant includes the source error that occurred during validation.\n- `Output`: Indicates that the output value is invalid. This variant includes the source error that occurred during validation."];
123 [SinHErrors] [SinHInputErrors] ["Errors that can occur when computing the *hyperbolic sine* of a real or complex number.\n\nIt includes errors for invalid input and output values.\n\n# Type Parameters\n\n- `RawScalar`: A type that implements the [`RawScalarTrait`] trait. This type parameter is used to specify the numeric type for the computation and its associated raw error type `<RawScalar as RawScalarTrait>::ValidationErrors`.\n\n# Variants\n\n- `Input`: Indicates that the input value is invalid. This variant includes the source error that occurred during validation.\n- `Output`: Indicates that the output value is invalid. This variant includes the source error that occurred during validation."];
124 [ASinHErrors] [ASinHInputErrors] ["Errors that can occur when computing the *inverse hyperbolic sine* of a real or complex number.\n\nIt includes errors for invalid input and output values.\n\n# Type Parameters\n\n- `RawScalar`: A type that implements the [`RawScalarTrait`] trait. This type parameter is used to specify the numeric type for the computation and its associated raw error type `<RawScalar as RawScalarTrait>::ValidationErrors`.\n\n# Variants\n\n- `Input`: Indicates that the input value is invalid. This variant includes the source error that occurred during validation.\n- `Output`: Indicates that the output value is invalid. This variant includes the source error that occurred during validation."];
125 [ACosHErrors] [ACosHInputErrors] ["Errors that can occur when computing the *inverse hyperbolic cosine* of a real or complex number.\n\nIt includes errors for invalid input and output values.\n\n# Type Parameters\n\n- `RawScalar`: A type that implements the [`RawScalarTrait`] trait. This type parameter is used to specify the numeric type for the computation and its associated raw error type `<RawScalar as RawScalarTrait>::ValidationErrors`.\n\n# Variants\n\n- `Input`: Indicates that the input value is invalid. This variant includes the source error that occurred during validation.\n- `Output`: Indicates that the output value is invalid. This variant includes the source error that occurred during validation."];
126 [ATanHErrors] [ATanHInputErrors] ["Errors that can occur when computing the *inverse hyperbolic tangent* of a real or complex number.\n\nIt includes errors for invalid input and output values.\n\n# Type Parameters\n\n- `RawScalar`: A type that implements the [`RawScalarTrait`] trait. This type parameter is used to specify the numeric type for the computation and its associated raw error type `<RawScalar as RawScalarTrait>::ValidationErrors`.\n\n# Variants\n\n- `Input`: Indicates that the input value is invalid. This variant includes the source error that occurred during validation.\n- `Output`: Indicates that the output value is invalid. This variant includes the source error that occurred during validation."];
127)]
128#[doc = enum_doc]
129pub type enum_name<RawScalar> =
130 FunctionErrors<ErrIn<RawScalar>, <RawScalar as RawScalarTrait>::ValidationErrors>;
131
132pub type TanHRealErrors<RawReal> =
146 FunctionErrors<TanHRealInputErrors<RawReal>, <RawReal as RawScalarTrait>::ValidationErrors>;
147
148#[derive(Debug, Error)]
161pub enum TanHComplexInputErrors<RawComplex: RawScalarTrait> {
162 #[error("the input argument is outside the domain of the function!")]
163 OutOfDomain {
164 value: RawComplex,
165
166 backtrace: Backtrace,
167 },
168
169 #[error("the argument of the function is invalid!")]
175 InvalidArgument {
176 #[source]
178 #[backtrace]
179 source: <RawComplex as RawScalarTrait>::ValidationErrors,
180 },
181}
182
183pub type TanHComplexErrors<RawComplex> = FunctionErrors<
197 TanHComplexInputErrors<RawComplex>,
198 <RawComplex as RawScalarTrait>::ValidationErrors,
199>;
200#[duplicate_item(
204 T try_func func trait_doc try_func_doc func_doc err_doc;
205 [ACosH] [try_acosh] [acosh] ["Trait for computing the *inverse hyperbolic cosine* of a number.\n\nThis trait defines methods for computing the *inverse hyperbolic cosine* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_acosh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_acosh`: Computes the *inverse hyperbolic cosine* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `acosh`: Computes the *inverse hyperbolic cosine* of `self` and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *inverse hyperbolic cosine* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *inverse hyperbolic cosine* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_acosh` method for safe computations."] ["The error type that is returned by the `try_acosh` method."];
206 [ASinH] [try_asinh] [asinh] ["Trait for computing the *inverse hyperbolic sine* of a number.\n\nThis trait defines methods for computing the *inverse hyperbolic sine* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_asinh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_asinh`: Computes the *inverse hyperbolic sine* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `asinh`: Computes the *inverse hyperbolic sine* of `self` and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *inverse hyperbolic sine* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *inverse hyperbolic sine* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_asinh` method for safe computations."] ["The error type that is returned by the `try_asinh` method."];
207 [ATanH] [try_atanh] [atanh] ["Trait for computing the *inverse hyperbolic tangent* of a number.\n\nThis trait defines methods for computing the *inverse hyperbolic tangent* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_atanh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_atanh`: Computes the *inverse hyperbolic tangent* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `atanh`: Computes the *inverse hyperbolic tangent* of `self` and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *inverse hyperbolic tangent* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *inverse hyperbolic tangent* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_atanh` method for safe computations."] ["The error type that is returned by the `try_atanh` method."];
208 [CosH] [try_cosh] [cosh] ["Trait for computing the *hyperbolic cosine* of a number.\n\nThis trait defines methods for computing the *hyperbolic cosine* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_cosh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_cosh`: Computes the *hyperbolic cosine* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `cosh`: Computes the *hyperbolic cosine* of `self` and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *hyperbolic cosine* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *hyperbolic cosine* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_cosh` method for safe computations."] ["The error type that is returned by the `try_cosh` method."];
209 [SinH] [try_sinh] [sinh] ["Trait for computing the *hyperbolic sine* of a number.\n\nThis trait defines methods for computing the *hyperbolic sine* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_sinh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_sinh`: Computes the *hyperbolic sine* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `sinh`: Computes the *hyperbolic sine* of `self` and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *hyperbolic sine* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *hyperbolic sine* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_sinh` method for safe computations."] ["The error type that is returned by the `try_sinh` method."];
210 [TanH] [try_tanh] [tanh] ["Trait for computing the *hyperbolic tangent* of a number.\n\nThis trait defines methods for computing the *hyperbolic tangent* of a number. It includes both a safe method that returns a [`Result`] and an unsafe method that directly returns the computed value.\n\n# Associated Types\n\n- `Error`: The error type that is returned by the `try_tanh` method. This type must implement the [`std::error::Error`] trait.\n\n# Required Methods\n\n - `try_tanh`: Computes the *hyperbolic tangent* of `self` and returns a [`Result`]. If the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n - `tanh`: Computes the *hyperbolic tangent* of the number and directly returns the computed value. In Debug mode this method may panic if the computation fails."] ["Computes the *hyperbolic tangent* of `self` and returns a [`Result`].\n\nIf the computation is successful, it returns [`Ok`] with the computed value. If an error occurs, it returns [`Err`] with the associated error.\n\n# Errors\n\nThis method returns an error if the computation fails. The error type is defined by the associated [`Error`] type."] ["Computes and returns the *hyperbolic tangent* of `self`.\n\nIn Debug mode this method may panic if the computation fails.\n\n# Panics\n\nIn Debug mode this method may panic if the computation fails. It is recommended to use the `try_tanh` method for safe computations."] ["The error type that is returned by the `try_tanh` method."];
211)]
212#[doc = trait_doc]
213pub trait T: Sized {
214 #[doc = err_doc]
215 type Error: std::error::Error;
216
217 #[doc = try_func_doc]
218 fn try_func(self) -> Result<Self, <Self as T>::Error>;
219
220 #[doc = func_doc]
221 fn func(self) -> Self;
222}
223
224#[duplicate_item (
225 T E ErrIn try_func func scalar_type ;
226 [CosH] [CosHErrors] [CosHInputErrors] [try_cosh] [cosh] [f64] ;
227 [CosH] [CosHErrors] [CosHInputErrors] [try_cosh] [cosh] [Complex::<f64>];
228 [SinH] [SinHErrors] [SinHInputErrors] [try_sinh] [sinh] [f64] ;
229 [SinH] [SinHErrors] [SinHInputErrors] [try_sinh] [sinh] [Complex::<f64>];
230 [TanH] [TanHRealErrors] [TanHRealInputErrors] [try_tanh] [tanh] [f64] ;
231 [ASinH] [ASinHErrors] [ASinHInputErrors] [try_asinh] [asinh] [f64] ;
232 [ASinH] [ASinHErrors] [ASinHInputErrors] [try_asinh] [asinh] [Complex::<f64>];
233)]
234impl T for scalar_type {
235 type Error = E<scalar_type>;
236
237 #[inline(always)]
238 fn try_func(self) -> Result<Self, <Self as T>::Error> {
239 StrictFinitePolicy::<scalar_type, 53>::validate(self)
240 .map_err(|e| ErrIn::InvalidArgument { source: e }.into())
241 .and_then(|v| {
242 StrictFinitePolicy::<scalar_type, 53>::validate(scalar_type::func(v))
243 .map_err(|e| Self::Error::Output { source: e })
244 })
245 }
246
247 #[inline(always)]
248 fn func(self) -> Self {
249 #[cfg(debug_assertions)]
250 {
251 self.try_func().unwrap()
252 }
253 #[cfg(not(debug_assertions))]
254 {
255 scalar_type::func(self)
256 }
257 }
258}
259
260impl ATanH for f64 {
261 type Error = ATanHErrors<f64>;
262
263 #[inline(always)]
264 fn try_atanh(self) -> Result<Self, Self::Error> {
265 StrictFinitePolicy::<f64, 53>::validate(self)
266 .map_err(|e| ATanHInputErrors::InvalidArgument { source: e }.into())
267 .and_then(|v| {
268 if v <= -1. || v >= 1. {
271 Err(ATanHInputErrors::OutOfDomain {
272 value: v,
273 backtrace: Backtrace::force_capture(),
274 }
275 .into())
276 } else {
277 StrictFinitePolicy::<f64, 53>::validate(f64::atanh(v))
278 .map_err(|e| ATanHErrors::Output { source: e })
279 }
280 })
281 }
282
283 #[inline(always)]
284 fn atanh(self) -> Self {
285 #[cfg(debug_assertions)]
286 {
287 self.try_atanh().unwrap()
288 }
289 #[cfg(not(debug_assertions))]
290 {
291 f64::atanh(self)
292 }
293 }
294}
295
296impl ACosH for f64 {
297 type Error = ACosHErrors<f64>;
298
299 #[inline(always)]
300 fn try_acosh(self) -> Result<Self, <Self as ACosH>::Error> {
301 StrictFinitePolicy::<f64, 53>::validate(self)
302 .map_err(|e| ACosHInputErrors::InvalidArgument { source: e }.into())
303 .and_then(|v| {
304 if v < 1.0 {
305 Err(ACosHInputErrors::OutOfDomain {
306 value: v,
307 backtrace: Backtrace::force_capture(),
308 }
309 .into())
310 } else {
311 StrictFinitePolicy::<f64, 53>::validate(f64::acosh(v))
312 .map_err(|e| ACosHErrors::Output { source: e })
313 }
314 })
315 }
316
317 #[inline(always)]
318 fn acosh(self) -> Self {
319 #[cfg(debug_assertions)]
320 {
321 self.try_acosh().unwrap()
322 }
323 #[cfg(not(debug_assertions))]
324 {
325 f64::acosh(self)
326 }
327 }
328}
329
330impl TanH for Complex<f64> {
331 type Error = TanHComplexErrors<Complex<f64>>;
332
333 #[inline(always)]
334 fn try_tanh(self) -> Result<Self, Self::Error> {
335 StrictFinitePolicy::<Self, 53>::validate(self)
336 .map_err(|e| TanHComplexInputErrors::InvalidArgument { source: e }.into())
337 .and_then(|v| {
338 if RawScalarTrait::is_zero(&v.cosh()) {
340 Err(TanHComplexInputErrors::OutOfDomain {
341 value: v,
342 backtrace: Backtrace::force_capture(),
343 }
344 .into())
345 } else {
346 StrictFinitePolicy::<Self, 53>::validate(Complex::<f64>::tanh(v))
347 .map_err(|e| TanHComplexErrors::Output { source: e })
348 }
349 })
350 }
351
352 #[inline(always)]
353 fn tanh(self) -> Self {
354 #[cfg(debug_assertions)]
355 {
356 self.try_tanh().unwrap()
357 }
358 #[cfg(not(debug_assertions))]
359 {
360 Complex::<f64>::tanh(self)
361 }
362 }
363}
364
365impl ATanH for Complex<f64> {
366 type Error = ATanHErrors<Complex<f64>>;
367
368 #[inline(always)]
369 fn try_atanh(self) -> Result<Self, Self::Error> {
370 StrictFinitePolicy::<Self, 53>::validate(self)
371 .map_err(|e| ATanHInputErrors::InvalidArgument { source: e }.into())
372 .and_then(|v| {
373 if v.im == 0. && (v.re <= -1. || v.re >= 1.) {
375 Err(ATanHInputErrors::OutOfDomain {
376 value: v,
377 backtrace: Backtrace::force_capture(),
378 }
379 .into())
380 } else {
381 StrictFinitePolicy::<Self, 53>::validate(Complex::<f64>::atanh(v))
382 .map_err(|e| ATanHErrors::Output { source: e })
383 }
384 })
385 }
386
387 #[inline(always)]
388 fn atanh(self) -> Self {
389 #[cfg(debug_assertions)]
390 {
391 self.try_atanh().unwrap()
392 }
393 #[cfg(not(debug_assertions))]
394 {
395 Complex::<f64>::atanh(self)
396 }
397 }
398}
399
400impl ACosH for Complex<f64> {
401 type Error = ACosHErrors<Complex<f64>>;
402
403 #[inline(always)]
404 fn try_acosh(self) -> Result<Self, <Self as ACosH>::Error> {
405 StrictFinitePolicy::<Complex<f64>, 53>::validate(self)
406 .map_err(|e| ACosHInputErrors::InvalidArgument { source: e }.into())
407 .and_then(|v| {
408 if v.im == 0.0 && v.re < 1.0 {
409 Err(ACosHInputErrors::OutOfDomain {
410 value: v,
411 backtrace: Backtrace::force_capture(),
412 }
413 .into())
414 } else {
415 StrictFinitePolicy::<Complex<f64>, 53>::validate(Complex::<f64>::acosh(v))
416 .map_err(|e| ACosHErrors::Output { source: e })
417 }
418 })
419 }
420
421 #[inline(always)]
422 fn acosh(self) -> Self {
423 #[cfg(debug_assertions)]
424 {
425 self.try_acosh().unwrap()
426 }
427 #[cfg(not(debug_assertions))]
428 {
429 Complex::<f64>::acosh(self)
430 }
431 }
432}
433
434pub trait HyperbolicFunctions: SinH + ASinH + CosH + ACosH + TanH + ATanH {}
476
477#[duplicate_item(
478 T;
479 [f64];
480 [Complex<f64>];
481)]
482impl HyperbolicFunctions for T {}
483#[cfg(test)]
487mod tests {
488 use super::*;
489 #[cfg(feature = "rug")]
492 use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
493
494 #[cfg(feature = "rug")]
495 use try_create::TryNew;
496
497 mod sinh {
498 use super::*;
499
500 mod native64 {
501 use super::*;
502
503 mod real {
504 use super::*;
505
506 #[test]
507 fn test_f64_sinh_valid() {
508 let value = 1.0;
509 let expected_result = 1.1752011936438014;
510 assert_eq!(value.try_sinh().unwrap(), expected_result);
511 assert_eq!(<f64 as SinH>::sinh(value), expected_result);
512 assert_eq!(value.sinh(), expected_result);
513 }
514
515 #[test]
516 fn test_f64_sinh_negative() {
517 let value = -1.0;
518 let expected_result = -1.1752011936438014;
519 assert_eq!(value.try_sinh().unwrap(), expected_result);
520 assert_eq!(value.sinh(), expected_result);
521 }
522
523 #[test]
524 fn test_f64_sinh_zero() {
525 let value = 0.0;
526 assert_eq!(value.try_sinh().unwrap(), 0.0);
527 assert_eq!(value.sinh(), 0.0);
528 }
529
530 #[test]
531 fn test_f64_sinh_nan() {
532 let value = f64::NAN;
533 let result = value.try_sinh();
534 assert!(matches!(result, Err(SinHErrors::Input { .. })));
535 }
536
537 #[test]
538 fn test_f64_sinh_infinity() {
539 let value = f64::INFINITY;
540 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
541 }
542
543 #[test]
544 fn test_f64_sinh_subnormal() {
545 let value = f64::MIN_POSITIVE / 2.0;
546 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
547 }
548 }
549
550 mod complex {
551 use super::*;
552
553 #[test]
554 fn sinh_valid() {
555 let value = Complex::new(1.0, 1.0);
556 let expected_result = Complex::new(0.6349639147847361, 1.2984575814159773);
557 assert_eq!(value.try_sinh().unwrap(), expected_result);
558 assert_eq!(<Complex<f64> as SinH>::sinh(value), expected_result);
559 assert_eq!(value.sinh(), expected_result);
560 }
561
562 #[test]
563 fn sinh_zero() {
564 let value = Complex::new(0.0, 0.0);
565 let expected_result = Complex::new(0.0, 0.0);
566 assert_eq!(value.try_sinh().unwrap(), expected_result);
567 assert_eq!(value.sinh(), expected_result);
568 }
569
570 #[test]
571 fn sinh_nan() {
572 let value = Complex::new(f64::NAN, 0.0);
573 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
574
575 let value = Complex::new(0.0, f64::NAN);
576 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
577 }
578
579 #[test]
580 fn sinh_infinity() {
581 let value = Complex::new(f64::INFINITY, 0.0);
582 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
583
584 let value = Complex::new(0.0, f64::INFINITY);
585 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
586 }
587
588 #[test]
589 fn sinh_subnormal() {
590 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
591 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
592
593 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
594 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input { .. })));
595 }
596 }
597 }
598
599 #[cfg(feature = "rug")]
600 mod rug53 {
601 use super::*;
602 use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
603 use try_create::TryNew;
604
605 mod real {
606 use super::*;
607
608 #[test]
609 fn test_rug_float_sinh_valid() {
610 let value =
611 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
612
613 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
614 53,
615 1.1752011936438014,
616 ))
617 .unwrap();
618 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
619 assert_eq!(value.sinh(), expected_result);
620 }
621
622 #[test]
623 fn test_rug_float_sinh_zero() {
624 let value =
625 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
626
627 let expected_result =
628 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
629 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
630 assert_eq!(value.sinh(), expected_result);
631 }
632 }
633
634 mod complex {
635 use super::*;
636
637 #[test]
638 fn test_complex_rug_float_sinh_valid() {
639 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
640 53,
641 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
642 ))
643 .unwrap();
644
645 let expected_result =
646 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
647 53,
648 (
649 rug::Float::with_val(53, 0.6349639147847361),
650 rug::Float::with_val(53, 1.2984575814159773),
651 ),
652 ))
653 .unwrap();
654 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
655 assert_eq!(value.sinh(), expected_result);
656 }
657
658 #[test]
659 fn test_complex_rug_float_sinh_zero() {
660 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
661 53,
662 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
663 ))
664 .unwrap();
665
666 let expected_result =
667 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
668 53,
669 (rug::Float::with_val(53, 0.), rug::Float::with_val(53, 0.)),
670 ))
671 .unwrap();
672 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
673 assert_eq!(value.sinh(), expected_result);
674 }
675 }
676 }
677 }
678
679 mod cosh {
680 use super::*;
681
682 mod native64 {
683 use super::*;
684
685 mod real {
686 use super::*;
687
688 #[test]
689 fn test_f64_cosh_valid() {
690 let value = 1.0;
691 let expected_result = 1.5430806348152437;
692 assert_eq!(value.try_cosh().unwrap(), expected_result);
693 assert_eq!(<f64 as CosH>::cosh(value), expected_result);
694 assert_eq!(value.cosh(), expected_result);
695 }
696
697 #[test]
698 fn test_f64_cosh_negative() {
699 let value = -1.0;
700 let expected_result = 1.5430806348152437;
701 assert_eq!(value.try_cosh().unwrap(), expected_result);
702 assert_eq!(value.cosh(), expected_result);
703 }
704
705 #[test]
706 fn test_f64_cosh_zero() {
707 let value = 0.0;
708 assert_eq!(value.try_cosh().unwrap(), 1.0);
709 assert_eq!(value.cosh(), 1.0);
710 }
711
712 #[test]
713 fn test_f64_cosh_nan() {
714 let value = f64::NAN;
715 let result = value.try_cosh();
716 assert!(matches!(result, Err(CosHErrors::Input { .. })));
717 }
718
719 #[test]
720 fn test_f64_cosh_infinity() {
721 let value = f64::INFINITY;
722 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
723 }
724
725 #[test]
726 fn test_f64_cosh_subnormal() {
727 let value = f64::MIN_POSITIVE / 2.0;
728 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
729 }
730 }
731
732 mod complex {
733 use super::*;
734
735 #[test]
736 fn cosh_valid() {
737 let value = Complex::new(1.0, 1.0);
738 let expected_result = Complex::new(0.8337300251311491, 0.9888977057628651);
739 assert_eq!(value.try_cosh().unwrap(), expected_result);
740 assert_eq!(<Complex<f64> as CosH>::cosh(value), expected_result);
741 assert_eq!(value.cosh(), expected_result);
742 }
743
744 #[test]
745 fn cosh_zero() {
746 let value = Complex::new(0.0, 0.0);
747 let expected_result = Complex::new(1.0, 0.0);
748 assert_eq!(value.try_cosh().unwrap(), expected_result);
749 assert_eq!(value.cosh(), expected_result);
750 }
751
752 #[test]
753 fn cosh_nan() {
754 let value = Complex::new(f64::NAN, 0.0);
755 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
756
757 let value = Complex::new(0.0, f64::NAN);
758 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
759 }
760
761 #[test]
762 fn cosh_infinity() {
763 let value = Complex::new(f64::INFINITY, 0.0);
764 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
765
766 let value = Complex::new(0.0, f64::INFINITY);
767 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
768 }
769
770 #[test]
771 fn cosh_subnormal() {
772 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
773 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
774
775 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
776 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input { .. })));
777 }
778 }
779 }
780
781 #[cfg(feature = "rug")]
782 mod rug53 {
783 use super::*;
784
785 mod real {
786 use super::*;
787
788 #[test]
789 fn test_rug_float_cosh_valid() {
790 let value =
791 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
792
793 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
794 53,
795 1.5430806348152437,
796 ))
797 .unwrap();
798 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
799 assert_eq!(value.cosh(), expected_result);
800 }
801
802 #[test]
803 fn test_rug_float_cosh_zero() {
804 let value =
805 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
806
807 let expected_result =
808 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
809 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
810 assert_eq!(value.cosh(), expected_result);
811 }
812 }
813
814 mod complex {
815 use super::*;
816
817 #[test]
818 fn test_complex_rug_float_cosh_valid() {
819 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
820 53,
821 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
822 ))
823 .unwrap();
824
825 let expected_result =
826 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
827 53,
828 (
829 rug::Float::with_val(53, 0.833730025131149),
830 rug::Float::with_val(53, 0.9888977057628651),
831 ),
832 ))
833 .unwrap();
834 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
835 assert_eq!(value.cosh(), expected_result);
836 }
837
838 #[test]
839 fn test_complex_rug_float_cosh_zero() {
840 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
841 53,
842 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
843 ))
844 .unwrap();
845
846 let expected_result =
847 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
848 53,
849 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 0.0)),
850 ))
851 .unwrap();
852 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
853 assert_eq!(value.cosh(), expected_result);
854 }
855 }
856 }
857 }
858
859 mod tanh {
860 use super::*;
861
862 mod native64 {
863 use super::*;
864
865 mod real {
866 use super::*;
867
868 #[test]
869 fn test_f64_tanh_valid() {
870 let value = 1.0;
871 let expected_result = 0.7615941559557649;
872 assert_eq!(value.try_tanh().unwrap(), expected_result);
873 assert_eq!(<f64 as TanH>::tanh(value), expected_result);
874 assert_eq!(value.tanh(), expected_result);
875 }
876
877 #[test]
878 fn test_f64_tanh_negative() {
879 let value = -1.0;
880 let expected_result = -0.7615941559557649;
881 assert_eq!(value.try_tanh().unwrap(), expected_result);
882 assert_eq!(value.tanh(), expected_result);
883 }
884
885 #[test]
886 fn test_f64_tanh_zero() {
887 let value = 0.0;
888 assert_eq!(value.try_tanh().unwrap(), 0.0);
889 assert_eq!(value.tanh(), 0.0);
890 }
891
892 #[test]
893 fn test_f64_tanh_nan() {
894 let value = f64::NAN;
895 let result = value.try_tanh();
896 assert!(matches!(result, Err(TanHRealErrors::Input { .. })));
897 }
898
899 #[test]
900 fn test_f64_tanh_infinity() {
901 let value = f64::INFINITY;
902 assert!(matches!(
903 value.try_tanh(),
904 Err(TanHRealErrors::Input { .. })
905 ));
906 }
907
908 #[test]
909 fn test_f64_tanh_subnormal() {
910 let value = f64::MIN_POSITIVE / 2.0;
911 assert!(matches!(
912 value.try_tanh(),
913 Err(TanHRealErrors::Input { .. })
914 ));
915 }
916 }
917
918 mod complex {
919 use super::*;
920
921 #[test]
922 fn tanh_valid() {
923 let value = Complex::new(1.0, 1.0);
924 let expected_result = if cfg!(target_arch = "x86_64") {
925 Complex::new(1.0839233273386948, 0.27175258531951174)
926 } else if cfg!(target_arch = "aarch64") {
927 Complex::new(1.0839233273386946, 0.27175258531951174)
928 } else {
929 todo!("Unknown target architecture");
930 };
931
932 assert_eq!(value.try_tanh().unwrap(), expected_result);
933 assert_eq!(<Complex<f64> as TanH>::tanh(value), expected_result);
934 assert_eq!(value.tanh(), expected_result);
935 }
936
937 #[test]
938 fn tanh_zero() {
939 let value = Complex::new(0.0, 0.0);
940 let expected_result = Complex::new(0.0, 0.0);
941 assert_eq!(value.try_tanh().unwrap(), expected_result);
942 assert_eq!(value.tanh(), expected_result);
943 }
944
945 #[test]
946 fn tanh_nan() {
947 let value = Complex::new(f64::NAN, 0.0);
948 assert!(matches!(
949 value.try_tanh(),
950 Err(TanHComplexErrors::Input { .. })
951 ));
952
953 let value = Complex::new(0.0, f64::NAN);
954 assert!(matches!(
955 value.try_tanh(),
956 Err(TanHComplexErrors::Input { .. })
957 ));
958 }
959
960 #[test]
961 fn tanh_infinity() {
962 let value = Complex::new(f64::INFINITY, 0.0);
963 assert!(matches!(
964 value.try_tanh(),
965 Err(TanHComplexErrors::Input { .. })
966 ));
967
968 let value = Complex::new(0.0, f64::INFINITY);
969 assert!(matches!(
970 value.try_tanh(),
971 Err(TanHComplexErrors::Input { .. })
972 ));
973 }
974
975 #[test]
976 fn tanh_subnormal() {
977 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
978 assert!(matches!(
979 value.try_tanh(),
980 Err(TanHComplexErrors::Input { .. })
981 ));
982
983 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
984 assert!(matches!(
985 value.try_tanh(),
986 Err(TanHComplexErrors::Input { .. })
987 ));
988 }
989 }
990 }
991
992 #[cfg(feature = "rug")]
993 mod rug53 {
994 use super::*;
995
996 mod real {
997 use super::*;
998
999 #[test]
1000 fn test_rug_float_tanh_valid() {
1001 let value =
1002 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1003
1004 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1005 53,
1006 0.7615941559557649,
1007 ))
1008 .unwrap();
1009 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1010 assert_eq!(value.tanh(), expected_result);
1011 }
1012
1013 #[test]
1014 fn test_rug_float_tanh_zero() {
1015 let value =
1016 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1017
1018 let expected_result =
1019 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1020 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1021 assert_eq!(value.tanh(), expected_result);
1022 }
1023 }
1024
1025 mod complex {
1026 use super::*;
1027
1028 #[test]
1029 fn test_complex_rug_float_tanh_valid() {
1030 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1031 53,
1032 (rug::Float::with_val(53, 0.5), rug::Float::with_val(53, 0.5)),
1033 ))
1034 .unwrap();
1035
1036 let expected_result =
1037 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1038 53,
1039 (
1040 rug::Float::with_val(53, 5.640831412674985e-1),
1041 rug::Float::with_val(53, 4.0389645531602575e-1),
1042 ),
1043 ))
1044 .unwrap();
1045 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1046 assert_eq!(value.tanh(), expected_result);
1047 }
1048
1049 #[test]
1050 fn test_complex_rug_float_tanh_zero() {
1051 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1052 53,
1053 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1054 ))
1055 .unwrap();
1056
1057 let expected_result =
1058 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1059 53,
1060 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1061 ))
1062 .unwrap();
1063 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1064 assert_eq!(value.tanh(), expected_result);
1065 }
1066 }
1067 }
1068 }
1069
1070 mod asinh {
1071 use super::*;
1072
1073 mod native64 {
1074 use super::*;
1075
1076 mod real {
1077 use super::*;
1078
1079 #[test]
1080 fn test_f64_asinh_valid() {
1081 let value = 1.0;
1082 let expected_result = 0.881373587019543;
1083 assert_eq!(value.try_asinh().unwrap(), expected_result);
1084 assert_eq!(<f64 as ASinH>::asinh(value), expected_result);
1085 assert_eq!(value.asinh(), expected_result);
1086 }
1087
1088 #[test]
1089 fn test_f64_asinh_negative() {
1090 let value = -1.0;
1091 let expected_result = -0.881373587019543;
1092 assert_eq!(value.try_asinh().unwrap(), expected_result);
1093 assert_eq!(value.asinh(), expected_result);
1094 }
1095
1096 #[test]
1097 fn test_f64_asinh_zero() {
1098 let value = 0.0;
1099 assert_eq!(value.try_asinh().unwrap(), 0.0);
1100 assert_eq!(value.asinh(), 0.0);
1101 }
1102
1103 #[test]
1104 fn test_f64_asinh_nan() {
1105 let value = f64::NAN;
1106 let result = value.try_asinh();
1107 assert!(matches!(result, Err(ASinHErrors::Input { .. })));
1108 }
1109
1110 #[test]
1111 fn test_f64_asinh_infinity() {
1112 let value = f64::INFINITY;
1113 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1114 }
1115
1116 #[test]
1117 fn test_f64_asinh_subnormal() {
1118 let value = f64::MIN_POSITIVE / 2.0;
1119 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1120 }
1121 }
1122
1123 mod complex {
1124 use super::*;
1125
1126 #[test]
1127 fn asinh_valid() {
1128 let value = Complex::new(1.0, 1.0);
1129 let expected_result = Complex::new(1.0612750619050357, 0.6662394324925153);
1130 assert_eq!(value.try_asinh().unwrap(), expected_result);
1131 assert_eq!(<Complex<f64> as ASinH>::asinh(value), expected_result);
1132 assert_eq!(value.asinh(), expected_result);
1133 }
1134
1135 #[test]
1136 fn asinh_zero() {
1137 let value = Complex::new(0.0, 0.0);
1138 let expected_result = Complex::new(0.0, 0.0);
1139 assert_eq!(value.try_asinh().unwrap(), expected_result);
1140 assert_eq!(value.asinh(), expected_result);
1141 }
1142
1143 #[test]
1144 fn asinh_nan() {
1145 let value = Complex::new(f64::NAN, 0.0);
1146 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1147
1148 let value = Complex::new(0.0, f64::NAN);
1149 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1150 }
1151
1152 #[test]
1153 fn asinh_infinity() {
1154 let value = Complex::new(f64::INFINITY, 0.0);
1155 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1156
1157 let value = Complex::new(0.0, f64::INFINITY);
1158 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1159 }
1160
1161 #[test]
1162 fn asinh_subnormal() {
1163 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1164 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1165
1166 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1167 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input { .. })));
1168 }
1169 }
1170 }
1171
1172 #[cfg(feature = "rug")]
1173 mod rug53 {
1174 use super::*;
1175
1176 mod real {
1177 use super::*;
1178
1179 #[test]
1180 fn test_rug_float_asinh_valid() {
1181 let value =
1182 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1183
1184 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1185 53,
1186 0.881373587019543,
1187 ))
1188 .unwrap();
1189 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1190 assert_eq!(value.asinh(), expected_result);
1191 }
1192
1193 #[test]
1194 fn test_rug_float_asinh_zero() {
1195 let value =
1196 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1197
1198 let expected_result =
1199 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1200 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1201 assert_eq!(value.asinh(), expected_result);
1202 }
1203 }
1204
1205 mod complex {
1206 use super::*;
1207
1208 #[test]
1209 fn test_complex_rug_float_asinh_valid() {
1210 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1211 53,
1212 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
1213 ))
1214 .unwrap();
1215
1216 let expected_result =
1217 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1218 53,
1219 (
1220 rug::Float::with_val(53, 1.0612750619050357),
1221 rug::Float::with_val(53, 0.6662394324925153),
1222 ),
1223 ))
1224 .unwrap();
1225 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1226 assert_eq!(value.asinh(), expected_result);
1227 }
1228
1229 #[test]
1230 fn test_complex_rug_float_asinh_zero() {
1231 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1232 53,
1233 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1234 ))
1235 .unwrap();
1236
1237 let expected_result =
1238 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1239 53,
1240 (rug::Float::with_val(53, 0.), rug::Float::with_val(53, 0.)),
1241 ))
1242 .unwrap();
1243 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1244 assert_eq!(value.asinh(), expected_result);
1245 }
1246 }
1247 }
1248 }
1249
1250 mod acosh {
1251 use super::*;
1252
1253 mod native64 {
1254 use super::*;
1255
1256 mod real {
1257 use super::*;
1258
1259 #[test]
1260 fn test_f64_acosh_valid() {
1261 let value = 1.5;
1262 let expected_result = 0.9624236501192069;
1263 assert_eq!(value.try_acosh().unwrap(), expected_result);
1264 assert_eq!(<f64 as ACosH>::acosh(value), expected_result);
1265 assert_eq!(value.acosh(), expected_result);
1266 }
1267
1268 #[test]
1269 fn test_f64_acosh_out_of_domain() {
1270 let value = 0.9;
1271 let err = value.try_acosh().unwrap_err();
1272 assert!(matches!(
1273 err,
1274 ACosHErrors::Input {
1275 source: ACosHInputErrors::OutOfDomain { value: 0.9, .. }
1276 }
1277 ));
1278 }
1279
1280 #[test]
1281 fn test_f64_acosh_one() {
1282 let value = 1.0;
1283 let expected_result = 0.0;
1284 assert_eq!(value.try_acosh().unwrap(), expected_result);
1285 assert_eq!(value.acosh(), expected_result);
1286 }
1287
1288 #[test]
1289 fn test_f64_acosh_nan() {
1290 let value = f64::NAN;
1291 let result = value.try_acosh();
1292 assert!(matches!(result, Err(ACosHErrors::Input { .. })));
1293 }
1294
1295 #[test]
1296 fn test_f64_acosh_infinity() {
1297 let value = f64::INFINITY;
1298 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1299 }
1300
1301 #[test]
1302 fn test_f64_acosh_subnormal() {
1303 let value = f64::MIN_POSITIVE / 2.0;
1304 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1305 }
1306 }
1307
1308 mod complex {
1309 use super::*;
1310
1311 #[test]
1312 fn acosh_valid() {
1313 let value = Complex::new(1.5, 1.5);
1314 let expected_result = if cfg!(target_arch = "x86_64") {
1315 Complex::new(1.44973434958536, 0.840395108841671)
1316 } else if cfg!(target_arch = "aarch64") {
1317 Complex::new(1.4497343495853596, 0.8403951088416711)
1318 } else {
1319 todo!("Unknown target architecture");
1320 };
1321
1322 assert_eq!(value.try_acosh().unwrap(), expected_result);
1323 assert_eq!(<Complex<f64> as ACosH>::acosh(value), expected_result);
1324 assert_eq!(value.acosh(), expected_result);
1325 }
1326
1327 #[test]
1328 fn acosh_out_of_domain() {
1329 let v = Complex::new(-1.1, 0.);
1330 let err = v.try_acosh().unwrap_err();
1331 assert!(matches!(
1332 err,
1333 ACosHErrors::Input {
1334 source: ACosHInputErrors::OutOfDomain { .. }
1335 }
1336 ));
1337 }
1338
1339 #[test]
1340 fn acosh_one() {
1341 let value = Complex::new(1.0, 0.0);
1342 let expected_result = Complex::new(0.0, 0.0);
1343 assert_eq!(value.try_acosh().unwrap(), expected_result);
1344 assert_eq!(value.acosh(), expected_result);
1345 }
1346
1347 #[test]
1348 fn acosh_nan() {
1349 let value = Complex::new(f64::NAN, 0.0);
1350 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1351
1352 let value = Complex::new(0.0, f64::NAN);
1353 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1354 }
1355
1356 #[test]
1357 fn acosh_infinity() {
1358 let value = Complex::new(f64::INFINITY, 0.0);
1359 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1360
1361 let value = Complex::new(0.0, f64::INFINITY);
1362 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1363 }
1364
1365 #[test]
1366 fn acosh_subnormal() {
1367 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1368 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1369
1370 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1371 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input { .. })));
1372 }
1373 }
1374 }
1375
1376 #[cfg(feature = "rug")]
1377 mod rug53 {
1378 use super::*;
1379
1380 mod real {
1381 use super::*;
1382
1383 #[test]
1384 fn test_rug_float_acosh_valid() {
1385 let value =
1386 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.5)).unwrap();
1387
1388 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1389 53,
1390 0.9624236501192069,
1391 ))
1392 .unwrap();
1393 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1394 assert_eq!(value.acosh(), expected_result);
1395 }
1396
1397 #[test]
1398 fn test_rug_float_acosh_one() {
1399 let value =
1400 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1401
1402 let expected_result =
1403 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1404 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1405 assert_eq!(value.acosh(), expected_result);
1406 }
1407 }
1408
1409 mod complex {
1410 use super::*;
1411
1412 #[test]
1413 fn test_complex_rug_float_acosh_valid() {
1414 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1415 53,
1416 (rug::Float::with_val(53, 1.5), rug::Float::with_val(53, 1.5)),
1417 ))
1418 .unwrap();
1419
1420 let expected_result =
1421 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1422 53,
1423 (
1424 rug::Float::with_val(53, 1.4497343495853598),
1425 rug::Float::with_val(53, 8.403951088416711e-1),
1426 ),
1427 ))
1428 .unwrap();
1429 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1430 assert_eq!(value.acosh(), expected_result);
1431 }
1432
1433 #[test]
1434 fn test_complex_rug_float_acosh_one() {
1435 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1436 53,
1437 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 0.0)),
1438 ))
1439 .unwrap();
1440
1441 let expected_result =
1442 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1443 53,
1444 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1445 ))
1446 .unwrap();
1447 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1448 assert_eq!(value.acosh(), expected_result);
1449 }
1450 }
1451 }
1452 }
1453
1454 mod atanh {
1455 use super::*;
1456
1457 mod native64 {
1458 use super::*;
1459
1460 mod real {
1461 use super::*;
1462
1463 #[test]
1464 fn test_f64_atanh_valid() {
1465 let value = 0.5;
1466 let expected_result = if cfg!(target_arch = "x86_64") {
1467 0.5493061443340548
1468 } else if cfg!(target_arch = "aarch64") {
1469 0.5493061443340549
1470 } else {
1471 todo!("Unknown target architecture");
1472 };
1473
1474 assert_eq!(value.try_atanh().unwrap(), expected_result);
1475 assert_eq!(<f64 as ATanH>::atanh(value), expected_result);
1476 assert_eq!(value.atanh(), expected_result);
1477 }
1478
1479 #[test]
1480 fn test_f64_atanh_negative() {
1481 let value = -0.5;
1482 let expected_result = -0.5493061443340548;
1483 assert_eq!(value.try_atanh().unwrap(), expected_result);
1484 assert_eq!(value.atanh(), expected_result);
1485 }
1486
1487 #[test]
1488 fn test_f64_atanh_out_of_domain() {
1489 let value = 1.0;
1490 let err = value.try_atanh().unwrap_err();
1491 assert!(matches!(
1492 err,
1493 ATanHErrors::Input {
1494 source: ATanHInputErrors::OutOfDomain { value: 1., .. }
1495 }
1496 ));
1497 }
1498
1499 #[test]
1500 fn test_f64_atanh_zero() {
1501 let value = 0.0;
1502 assert_eq!(value.try_atanh().unwrap(), 0.0);
1503 assert_eq!(value.atanh(), 0.0);
1504 }
1505
1506 #[test]
1507 fn test_f64_atanh_nan() {
1508 let value = f64::NAN;
1509 let result = value.try_atanh();
1510 assert!(matches!(result, Err(ATanHErrors::Input { .. })));
1511 }
1512
1513 #[test]
1514 fn test_f64_atanh_infinity() {
1515 let value = f64::INFINITY;
1516 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1517 }
1518
1519 #[test]
1520 fn test_f64_atanh_subnormal() {
1521 let value = f64::MIN_POSITIVE / 2.0;
1522 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1523 }
1524 }
1525
1526 mod complex {
1527 use super::*;
1528
1529 #[test]
1530 fn atanh_valid() {
1531 let value = Complex::new(0.5, 0.5);
1532 let expected_result = Complex::new(0.4023594781085251, 0.5535743588970452);
1533 assert_eq!(value.try_atanh().unwrap(), expected_result);
1534 assert_eq!(<Complex<f64> as ATanH>::atanh(value), expected_result);
1535 assert_eq!(value.atanh(), expected_result);
1536 }
1537
1538 #[test]
1539 fn atanh_out_of_domain() {
1540 let v = Complex::new(-1., 0.);
1541 let err = v.try_atanh().unwrap_err();
1542 assert!(matches!(
1543 err,
1544 ATanHErrors::Input {
1545 source: ATanHInputErrors::OutOfDomain { .. }
1546 }
1547 ));
1548 }
1549
1550 #[test]
1551 fn atanh_zero() {
1552 let value = Complex::new(0.0, 0.0);
1553 let expected_result = Complex::new(0.0, 0.0);
1554 assert_eq!(value.try_atanh().unwrap(), expected_result);
1555 assert_eq!(value.atanh(), expected_result);
1556 }
1557
1558 #[test]
1559 fn atanh_nan() {
1560 let value = Complex::new(f64::NAN, 0.0);
1561 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1562
1563 let value = Complex::new(0.0, f64::NAN);
1564 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1565 }
1566
1567 #[test]
1568 fn atanh_infinity() {
1569 let value = Complex::new(f64::INFINITY, 0.0);
1570 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1571
1572 let value = Complex::new(0.0, f64::INFINITY);
1573 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1574 }
1575
1576 #[test]
1577 fn atanh_subnormal() {
1578 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1579 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1580
1581 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1582 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input { .. })));
1583 }
1584 }
1585 }
1586
1587 #[cfg(feature = "rug")]
1588 mod rug53 {
1589 use super::*;
1590
1591 mod real {
1592 use super::*;
1593
1594 #[test]
1595 fn test_rug_float_atanh_valid() {
1596 let value =
1597 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.5)).unwrap();
1598
1599 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1600 53,
1601 0.5493061443340549,
1602 ))
1603 .unwrap();
1604 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1605 assert_eq!(value.atanh(), expected_result);
1606 }
1607
1608 #[test]
1609 fn test_rug_float_atanh_zero() {
1610 let value =
1611 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1612
1613 let expected_result =
1614 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1615 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1616 assert_eq!(value.atanh(), expected_result);
1617 }
1618 }
1619
1620 mod complex {
1621 use super::*;
1622
1623 #[test]
1624 fn test_complex_rug_float_atanh_valid() {
1625 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1626 53,
1627 (rug::Float::with_val(53, 0.5), rug::Float::with_val(53, 0.5)),
1628 ))
1629 .unwrap();
1630
1631 let expected_result =
1632 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1633 53,
1634 (
1635 rug::Float::with_val(53, 0.40235947810852507),
1636 rug::Float::with_val(53, 0.5535743588970452),
1637 ),
1638 ))
1639 .unwrap();
1640 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1641 assert_eq!(value.atanh(), expected_result);
1642 }
1643
1644 #[test]
1645 fn test_complex_rug_float_atanh_zero() {
1646 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1647 53,
1648 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1649 ))
1650 .unwrap();
1651
1652 let expected_result =
1653 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1654 53,
1655 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1656 ))
1657 .unwrap();
1658 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1659 assert_eq!(value.atanh(), expected_result);
1660 }
1661 }
1662 }
1663 }
1664}
1665