1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
24 core::{
25 errors::ErrorsValidationRawReal,
26 traits::{raw::RawScalarValidate, validation::sealed::NativeReal},
27 },
28 functions::FunctionErrors,
29 kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait},
30};
31use duplicate::duplicate_item;
32use num::Complex;
33use num_traits::Float;
34use std::backtrace::Backtrace;
35use thiserror::Error;
36
37#[cfg(debug_assertions)]
38use crate::{Constants, core::errors::capture_backtrace};
39
40#[duplicate_item(
42 enum_name enum_doc;
43 [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 RawScalarValidate>::ValidationError` 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."];
44 [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 RawScalarValidate>::ValidationError` 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."];
45 [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 RawScalarValidate>::ValidationError` 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."];
46)]
47#[derive(Debug, Error)]
48#[doc = enum_doc]
49pub enum enum_name<RawScalar: RawScalarTrait> {
50 #[error("the argument of the function is invalid!")]
56 InvalidArgument {
57 #[source]
59 #[backtrace]
60 source: <RawScalar as RawScalarValidate>::ValidationError,
61 },
62}
63
64#[derive(Debug, Error)]
80pub enum TanHRealInputErrors<RawReal: RawRealTrait> {
81 #[error("the argument of the function is invalid!")]
87 InvalidArgument {
88 #[source]
90 #[backtrace]
91 source: <RawReal as RawScalarValidate>::ValidationError,
92 },
93}
94
95#[duplicate_item(
96 enum_name enum_doc;
97 [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 RawScalarValidate>::ValidationError` provides details of validation failures.\n\n# Variants\n\n- `InvalidArgument`: Input is invalid (e.g., NaN, infinity). Wraps `<RawScalar as RawScalarValidate>::ValidationError`.\\n- `DomainError`: Input is outside the function's domain (e.g., `x < 1` for real `acosh`)."];
98 [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 RawScalarValidate>::ValidationError` provides details of validation failures.\n\n# Variants\n\n- `InvalidArgument`: Input is invalid (e.g., NaN, infinity). Wraps `<RawScalar as RawScalarValidate>::ValidationError`.\\n- `DomainError`: Input is outside the function's domain (e.g., `|x| >= 1` for real `atanh`)."];
99)]
100#[derive(Debug, Error)]
101#[doc = enum_doc]
102pub enum enum_name<RawScalar: RawScalarTrait> {
103 #[error("the input argument is outside the domain of the function!")]
108 OutOfDomain {
109 value: RawScalar,
111
112 backtrace: Backtrace,
114 },
115
116 #[error("the argument of the function is invalid!")]
122 InvalidArgument {
123 #[source]
125 #[backtrace]
126 source: <RawScalar as RawScalarValidate>::ValidationError,
127 },
128}
129
130#[duplicate_item(
131 enum_name ErrIn enum_doc;
132 [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 RawScalarValidate>::ValidationError`.\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."];
133 [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 RawScalarValidate>::ValidationError`.\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."];
134 [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 RawScalarValidate>::ValidationError`.\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."];
135 [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 RawScalarValidate>::ValidationError`.\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."];
136 [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 RawScalarValidate>::ValidationError`.\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."];
137)]
138#[doc = enum_doc]
139pub type enum_name<RawScalar> =
140 FunctionErrors<ErrIn<RawScalar>, <RawScalar as RawScalarValidate>::ValidationError>;
141
142pub type TanHRealErrors<RawReal> =
156 FunctionErrors<TanHRealInputErrors<RawReal>, <RawReal as RawScalarValidate>::ValidationError>;
157
158#[derive(Debug, Error)]
171pub enum TanHComplexInputErrors<RawComplex: RawComplexTrait> {
172 #[error("the input argument is outside the domain of the function!")]
177 OutOfDomain {
178 value: RawComplex,
180
181 backtrace: Backtrace,
183 },
184
185 #[error("the argument of the function is invalid!")]
191 InvalidArgument {
192 #[source]
194 #[backtrace]
195 source: <RawComplex as RawScalarValidate>::ValidationError,
196 },
197}
198
199pub type TanHComplexErrors<RawComplex> = FunctionErrors<
213 TanHComplexInputErrors<RawComplex>,
214 <RawComplex as RawScalarValidate>::ValidationError,
215>;
216#[duplicate_item(
220 T try_func func trait_doc try_func_doc func_doc err_doc;
221 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
222 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
223 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
224 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
225 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
226 [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. Provides both a fallible method that returns a [`Result`] and a panicking method that directly returns the computed value or panics on invalid input.\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."];
227)]
228#[doc = trait_doc]
229pub trait T: Sized {
230 #[doc = err_doc]
231 type Error: std::error::Error;
232
233 #[doc = try_func_doc]
234 #[must_use = "this `Result` may contain an error that should be handled"]
235 fn try_func(self) -> Result<Self, <Self as T>::Error>;
236
237 #[doc = func_doc]
238 fn func(self) -> Self;
239}
240
241#[duplicate_item(
242 my_trait E ErrIn try_func func scalar_type ;
243 [CosH] [CosHErrors] [CosHInputErrors] [try_cosh] [cosh] [T] ;
244 [CosH] [CosHErrors] [CosHInputErrors] [try_cosh] [cosh] [Complex::<T>];
245 [SinH] [SinHErrors] [SinHInputErrors] [try_sinh] [sinh] [T] ;
246 [SinH] [SinHErrors] [SinHInputErrors] [try_sinh] [sinh] [Complex::<T>];
247 [TanH] [TanHRealErrors] [TanHRealInputErrors] [try_tanh] [tanh] [T] ;
248 [ASinH] [ASinHErrors] [ASinHInputErrors] [try_asinh] [asinh] [T] ;
249 [ASinH] [ASinHErrors] [ASinHInputErrors] [try_asinh] [asinh] [Complex::<T>];
250)]
251impl<T> my_trait for scalar_type
252where
253 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
254{
255 type Error = E<scalar_type>;
256
257 #[inline(always)]
258 fn try_func(self) -> Result<Self, <Self as my_trait>::Error> {
259 #[cfg(debug_assertions)]
260 {
261 self.validate_raw_scalar()
262 .map_err(|e| ErrIn::InvalidArgument { source: e }.into())
263 .and_then(|v| {
264 scalar_type::func(v)
265 .validate_raw_scalar()
266 .map_err(|e| Self::Error::Output { source: e })
267 })
268 }
269 #[cfg(not(debug_assertions))]
270 {
271 Ok(scalar_type::func(self))
272 }
273 }
274
275 #[inline(always)]
276 fn func(self) -> Self {
277 #[cfg(debug_assertions)]
278 {
279 self.try_func().unwrap()
280 }
281 #[cfg(not(debug_assertions))]
282 {
283 scalar_type::func(self)
284 }
285 }
286}
287
288impl<T> ATanH for T
289where
290 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
291{
292 type Error = ATanHErrors<T>;
293
294 #[inline(always)]
295 fn try_atanh(self) -> Result<Self, Self::Error> {
296 #[cfg(debug_assertions)]
297 {
298 self.validate_raw_scalar()
299 .map_err(|e| ATanHInputErrors::InvalidArgument { source: e }.into())
300 .and_then(|v| {
301 if v <= T::negative_one() || v >= T::one() {
304 Err(ATanHInputErrors::OutOfDomain {
305 value: v,
306 backtrace: capture_backtrace(),
307 }
308 .into())
309 } else {
310 <T as Float>::atanh(v)
311 .validate_raw_scalar()
312 .map_err(|e| ATanHErrors::Output { source: e })
313 }
314 })
315 }
316 #[cfg(not(debug_assertions))]
317 {
318 Ok(<T as Float>::atanh(self))
319 }
320 }
321
322 #[inline(always)]
323 fn atanh(self) -> Self {
324 #[cfg(debug_assertions)]
325 {
326 self.try_atanh().unwrap()
327 }
328 #[cfg(not(debug_assertions))]
329 {
330 <T as Float>::atanh(self)
331 }
332 }
333}
334
335impl<T> ACosH for T
336where
337 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
338{
339 type Error = ACosHErrors<T>;
340
341 #[inline(always)]
342 fn try_acosh(self) -> Result<Self, <Self as ACosH>::Error> {
343 #[cfg(debug_assertions)]
344 {
345 self.validate_raw_scalar()
346 .map_err(|e| ACosHInputErrors::InvalidArgument { source: e }.into())
347 .and_then(|v| {
348 if v < T::one() {
349 Err(ACosHInputErrors::OutOfDomain {
350 value: v,
351 backtrace: capture_backtrace(),
352 }
353 .into())
354 } else {
355 <T as Float>::acosh(v)
356 .validate_raw_scalar()
357 .map_err(|e| ACosHErrors::Output { source: e })
358 }
359 })
360 }
361 #[cfg(not(debug_assertions))]
362 {
363 Ok(<T as Float>::acosh(self))
364 }
365 }
366
367 #[inline(always)]
368 fn acosh(self) -> Self {
369 #[cfg(debug_assertions)]
370 {
371 self.try_acosh().unwrap()
372 }
373 #[cfg(not(debug_assertions))]
374 {
375 <T as Float>::acosh(self)
376 }
377 }
378}
379
380impl<T> TanH for Complex<T>
381where
382 Self: RawComplexTrait<RawReal = T>,
383 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
384{
385 type Error = TanHComplexErrors<Complex<T>>;
386
387 #[inline(always)]
388 fn try_tanh(self) -> Result<Self, Self::Error> {
389 #[cfg(debug_assertions)]
390 {
391 self.validate_raw_scalar()
392 .map_err(|e| TanHComplexInputErrors::InvalidArgument { source: e }.into())
393 .and_then(|v| {
394 if RawScalarTrait::is_zero(&v.cosh()) {
396 Err(TanHComplexInputErrors::OutOfDomain {
397 value: v,
398 backtrace: capture_backtrace(),
399 }
400 .into())
401 } else {
402 Complex::<T>::tanh(v)
403 .validate_raw_scalar()
404 .map_err(|e| TanHComplexErrors::Output { source: e })
405 }
406 })
407 }
408 #[cfg(not(debug_assertions))]
409 {
410 Ok(Complex::<T>::tanh(self))
411 }
412 }
413
414 #[inline(always)]
415 fn tanh(self) -> Self {
416 #[cfg(debug_assertions)]
417 {
418 self.try_tanh().unwrap()
419 }
420 #[cfg(not(debug_assertions))]
421 {
422 Complex::<T>::tanh(self)
423 }
424 }
425}
426
427impl<T> ATanH for Complex<T>
428where
429 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
430{
431 type Error = ATanHErrors<Complex<T>>;
432
433 #[inline(always)]
434 fn try_atanh(self) -> Result<Self, Self::Error> {
435 #[cfg(debug_assertions)]
436 {
437 self.validate_raw_scalar()
438 .map_err(|e| ATanHInputErrors::InvalidArgument { source: e }.into())
439 .and_then(|v| {
440 if v.im == T::zero() && (v.re <= T::negative_one() || v.re >= T::one()) {
442 Err(ATanHInputErrors::OutOfDomain {
443 value: v,
444 backtrace: capture_backtrace(),
445 }
446 .into())
447 } else {
448 Complex::<T>::atanh(v)
449 .validate_raw_scalar()
450 .map_err(|e| ATanHErrors::Output { source: e })
451 }
452 })
453 }
454 #[cfg(not(debug_assertions))]
455 {
456 Ok(Complex::<T>::atanh(self))
457 }
458 }
459
460 #[inline(always)]
461 fn atanh(self) -> Self {
462 #[cfg(debug_assertions)]
463 {
464 self.try_atanh().unwrap()
465 }
466 #[cfg(not(debug_assertions))]
467 {
468 Complex::<T>::atanh(self)
469 }
470 }
471}
472
473impl<T> ACosH for Complex<T>
474where
475 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
476{
477 type Error = ACosHErrors<Complex<T>>;
478
479 #[inline(always)]
480 fn try_acosh(self) -> Result<Self, <Self as ACosH>::Error> {
481 #[cfg(debug_assertions)]
482 {
483 self.validate_raw_scalar()
484 .map_err(|e| ACosHInputErrors::InvalidArgument { source: e }.into())
485 .and_then(|v| {
486 if v.im == T::zero() && v.re < T::one() {
487 Err(ACosHInputErrors::OutOfDomain {
488 value: v,
489 backtrace: capture_backtrace(),
490 }
491 .into())
492 } else {
493 Complex::<T>::acosh(v)
494 .validate_raw_scalar()
495 .map_err(|e| ACosHErrors::Output { source: e })
496 }
497 })
498 }
499 #[cfg(not(debug_assertions))]
500 {
501 Ok(Complex::<T>::acosh(self))
502 }
503 }
504
505 #[inline(always)]
506 fn acosh(self) -> Self {
507 #[cfg(debug_assertions)]
508 {
509 self.try_acosh().unwrap()
510 }
511 #[cfg(not(debug_assertions))]
512 {
513 Complex::<T>::acosh(self)
514 }
515 }
516}
517
518pub trait HyperbolicFunctions: SinH + ASinH + CosH + ACosH + TanH + ATanH {}
560
561impl<T> HyperbolicFunctions for T where T: SinH + ASinH + CosH + ACosH + TanH + ATanH {}
562#[cfg(test)]
566mod tests {
567 use super::*;
568 use approx::assert_ulps_eq;
569
570 #[cfg(feature = "rug")]
571 use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
572
573 #[cfg(feature = "rug")]
574 use try_create::TryNew;
575
576 mod sinh {
577 use super::*;
578
579 mod native {
580 use super::*;
581
582 mod real {
583 use super::*;
584
585 #[test]
586 fn test_f64_sinh_valid() {
587 let value = 1.0;
588 let expected_result = 1.1752011936438014;
589 assert_eq!(value.try_sinh().unwrap(), expected_result);
590 assert_eq!(<f64 as Float>::sinh(value), expected_result);
591 assert_eq!(value.sinh(), expected_result);
592 }
593
594 #[test]
595 fn test_f64_sinh_negative() {
596 let value = -1.0;
597 let expected_result = -1.1752011936438014;
598 assert_eq!(value.try_sinh().unwrap(), expected_result);
599 assert_eq!(<f64 as Float>::sinh(value), expected_result);
600 assert_eq!(SinH::sinh(value), expected_result);
601 }
602
603 #[test]
604 fn test_f64_sinh_zero() {
605 let value = 0.0;
606 assert_eq!(value.try_sinh().unwrap(), 0.0);
607 assert_eq!(ASinH::asinh(value), 0.0);
608 }
609
610 #[test]
611 #[cfg(debug_assertions)]
612 fn test_f64_sinh_nan() {
613 let value = f64::NAN;
614 let result = value.try_sinh();
615 assert!(matches!(result, Err(SinHErrors::Input(..))));
616 }
617
618 #[test]
619 #[cfg(debug_assertions)]
620 fn test_f64_sinh_infinity() {
621 let value = f64::INFINITY;
622 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
623 }
624
625 #[test]
626 #[cfg(debug_assertions)]
627 fn test_f64_sinh_subnormal() {
628 let value = f64::MIN_POSITIVE / 2.0;
629 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
630 }
631 }
632
633 mod complex {
634 use super::*;
635
636 #[test]
637 fn sinh_valid() {
638 let value = Complex::new(1.0, 1.0);
639 let expected_result = Complex::new(0.6349639147847361, 1.2984575814159773);
640 assert_eq!(value.try_sinh().unwrap(), expected_result);
641 assert_eq!(<Complex<f64> as SinH>::sinh(value), expected_result);
642 assert_eq!(value.sinh(), expected_result);
643 }
644
645 #[test]
646 fn sinh_zero() {
647 let value = Complex::new(0.0, 0.0);
648 let expected_result = Complex::new(0.0, 0.0);
649 assert_eq!(value.try_sinh().unwrap(), expected_result);
650 assert_eq!(value.sinh(), expected_result);
651 }
652
653 #[test]
654 #[cfg(debug_assertions)]
655 fn sinh_nan() {
656 let value = Complex::new(f64::NAN, 0.0);
657 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
658
659 let value = Complex::new(0.0, f64::NAN);
660 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
661 }
662
663 #[test]
664 #[cfg(debug_assertions)]
665 fn sinh_infinity() {
666 let value = Complex::new(f64::INFINITY, 0.0);
667 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
668
669 let value = Complex::new(0.0, f64::INFINITY);
670 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
671 }
672
673 #[test]
674 #[cfg(debug_assertions)]
675 fn sinh_subnormal() {
676 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
677 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
678
679 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
680 assert!(matches!(value.try_sinh(), Err(SinHErrors::Input(..))));
681 }
682 }
683 }
684
685 #[cfg(feature = "rug")]
686 mod rug53 {
687 use super::*;
688 use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
689 use try_create::TryNew;
690
691 mod real {
692 use super::*;
693
694 #[test]
695 fn test_rug_float_sinh_valid() {
696 let value =
697 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
698
699 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
700 53,
701 1.1752011936438014,
702 ))
703 .unwrap();
704 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
705 assert_eq!(value.sinh(), expected_result);
706 }
707
708 #[test]
709 fn test_rug_float_sinh_zero() {
710 let value =
711 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
712
713 let expected_result =
714 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
715 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
716 assert_eq!(value.sinh(), expected_result);
717 }
718 }
719
720 mod complex {
721 use super::*;
722
723 #[test]
724 fn test_complex_rug_float_sinh_valid() {
725 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
726 53,
727 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
728 ))
729 .unwrap();
730
731 let expected_result =
732 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
733 53,
734 (
735 rug::Float::with_val(53, 0.6349639147847361),
736 rug::Float::with_val(53, 1.2984575814159773),
737 ),
738 ))
739 .unwrap();
740 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
741 assert_eq!(value.sinh(), expected_result);
742 }
743
744 #[test]
745 fn test_complex_rug_float_sinh_zero() {
746 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
747 53,
748 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
749 ))
750 .unwrap();
751
752 let expected_result =
753 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
754 53,
755 (rug::Float::with_val(53, 0.), rug::Float::with_val(53, 0.)),
756 ))
757 .unwrap();
758 assert_eq!(value.clone().try_sinh().unwrap(), expected_result);
759 assert_eq!(value.sinh(), expected_result);
760 }
761 }
762 }
763 }
764
765 mod cosh {
766 use super::*;
767
768 mod native {
769 use super::*;
770
771 mod real {
772 use super::*;
773
774 #[test]
775 fn test_f64_cosh_valid() {
776 let value = 1.0;
777 let expected_result = 1.5430806348152437;
778 assert_eq!(value.try_cosh().unwrap(), expected_result);
779 assert_eq!(<f64 as CosH>::cosh(value), expected_result);
780 assert_eq!(CosH::cosh(value), expected_result);
781 }
782
783 #[test]
784 fn test_f64_cosh_negative() {
785 let value = -1.0;
786 let expected_result = 1.5430806348152437;
787 assert_eq!(value.try_cosh().unwrap(), expected_result);
788 assert_eq!(<f64 as CosH>::cosh(value), expected_result);
789 assert_eq!(CosH::cosh(value), expected_result);
790 }
791
792 #[test]
793 fn test_f64_cosh_zero() {
794 let value = 0.0;
795 assert_eq!(value.try_cosh().unwrap(), 1.0);
796 assert_eq!(<f64 as CosH>::cosh(value), 1.0);
797 assert_eq!(CosH::cosh(value), 1.0);
798 }
799
800 #[test]
801 #[cfg(debug_assertions)]
802 fn test_f64_cosh_nan() {
803 let value = f64::NAN;
804 let result = value.try_cosh();
805 assert!(matches!(result, Err(CosHErrors::Input(..))));
806 }
807
808 #[test]
809 #[cfg(debug_assertions)]
810 fn test_f64_cosh_infinity() {
811 let value = f64::INFINITY;
812 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
813 }
814
815 #[test]
816 #[cfg(debug_assertions)]
817 fn test_f64_cosh_subnormal() {
818 let value = f64::MIN_POSITIVE / 2.0;
819 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
820 }
821 }
822
823 mod complex {
824 use super::*;
825
826 #[test]
827 fn cosh_valid() {
828 let value = Complex::new(1.0, 1.0);
829 let expected_result = Complex::new(0.8337300251311491, 0.9888977057628651);
830 assert_eq!(value.try_cosh().unwrap(), expected_result);
831 assert_eq!(<Complex<f64> as CosH>::cosh(value), expected_result);
832 assert_eq!(value.cosh(), expected_result);
833 }
834
835 #[test]
836 fn cosh_zero() {
837 let value = Complex::new(0.0, 0.0);
838 let expected_result = Complex::new(1.0, 0.0);
839 assert_eq!(value.try_cosh().unwrap(), expected_result);
840 assert_eq!(value.cosh(), expected_result);
841 }
842
843 #[test]
844 #[cfg(debug_assertions)]
845 fn cosh_nan() {
846 let value = Complex::new(f64::NAN, 0.0);
847 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
848
849 let value = Complex::new(0.0, f64::NAN);
850 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
851 }
852
853 #[test]
854 #[cfg(debug_assertions)]
855 fn cosh_infinity() {
856 let value = Complex::new(f64::INFINITY, 0.0);
857 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
858
859 let value = Complex::new(0.0, f64::INFINITY);
860 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
861 }
862
863 #[test]
864 #[cfg(debug_assertions)]
865 fn cosh_subnormal() {
866 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
867 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
868
869 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
870 assert!(matches!(value.try_cosh(), Err(CosHErrors::Input(..))));
871 }
872 }
873 }
874
875 #[cfg(feature = "rug")]
876 mod rug53 {
877 use super::*;
878
879 mod real {
880 use super::*;
881
882 #[test]
883 fn test_rug_float_cosh_valid() {
884 let value =
885 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
886
887 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
888 53,
889 1.5430806348152437,
890 ))
891 .unwrap();
892 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
893 assert_eq!(value.cosh(), expected_result);
894 }
895
896 #[test]
897 fn test_rug_float_cosh_zero() {
898 let value =
899 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
900
901 let expected_result =
902 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
903 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
904 assert_eq!(value.cosh(), expected_result);
905 }
906 }
907
908 mod complex {
909 use super::*;
910
911 #[test]
912 fn test_complex_rug_float_cosh_valid() {
913 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
914 53,
915 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
916 ))
917 .unwrap();
918
919 let expected_result =
920 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
921 53,
922 (
923 rug::Float::with_val(53, 0.833730025131149),
924 rug::Float::with_val(53, 0.9888977057628651),
925 ),
926 ))
927 .unwrap();
928 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
929 assert_eq!(value.cosh(), expected_result);
930 }
931
932 #[test]
933 fn test_complex_rug_float_cosh_zero() {
934 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
935 53,
936 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
937 ))
938 .unwrap();
939
940 let expected_result =
941 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
942 53,
943 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 0.0)),
944 ))
945 .unwrap();
946 assert_eq!(value.clone().try_cosh().unwrap(), expected_result);
947 assert_eq!(value.cosh(), expected_result);
948 }
949 }
950 }
951 }
952
953 mod tanh {
954 use super::*;
955
956 mod native {
957 use super::*;
958
959 mod real {
960 use super::*;
961
962 #[test]
963 fn test_f64_tanh_valid() {
964 let value = 1.0;
965 let expected_result = 0.7615941559557649;
966 assert_eq!(value.try_tanh().unwrap(), expected_result);
967 assert_eq!(<f64 as TanH>::tanh(value), expected_result);
968 assert_eq!(value.tanh(), expected_result);
969 }
970
971 #[test]
972 fn test_f64_tanh_negative() {
973 let value = -1.0;
974 let expected_result = -0.7615941559557649;
975 assert_eq!(value.try_tanh().unwrap(), expected_result);
976 assert_eq!(<f64 as Float>::tanh(value), expected_result);
977 assert_eq!(TanH::tanh(value), expected_result);
978 }
979
980 #[test]
981 fn test_f64_tanh_zero() {
982 let value = 0.0;
983 let expected_result = 0.0;
984 assert_eq!(value.try_tanh().unwrap(), expected_result);
985 assert_eq!(<f64 as Float>::tanh(value), expected_result);
986 assert_eq!(TanH::tanh(value), expected_result);
987 }
988
989 #[test]
990 #[cfg(debug_assertions)]
991 fn test_f64_tanh_nan() {
992 let value = f64::NAN;
993 let result = value.try_tanh();
994 assert!(matches!(result, Err(TanHRealErrors::Input(..))));
995 }
996
997 #[test]
998 #[cfg(debug_assertions)]
999 fn test_f64_tanh_infinity() {
1000 let value = f64::INFINITY;
1001 assert!(matches!(value.try_tanh(), Err(TanHRealErrors::Input(..))));
1002 }
1003
1004 #[test]
1005 #[cfg(debug_assertions)]
1006 fn test_f64_tanh_subnormal() {
1007 let value = f64::MIN_POSITIVE / 2.0;
1008 assert!(matches!(value.try_tanh(), Err(TanHRealErrors::Input(..))));
1009 }
1010 }
1011
1012 mod complex {
1013 use super::*;
1014
1015 #[test]
1016 fn tanh_valid() {
1017 let value = Complex::new(1.0, 1.0);
1018 let expected_result = if cfg!(target_arch = "x86_64") {
1019 Complex::new(1.0839233273386948, 0.27175258531951174)
1020 } else if cfg!(target_arch = "aarch64") {
1021 Complex::new(1.0839233273386946, 0.27175258531951174)
1022 } else {
1023 todo!("Architecture not-tested");
1024 };
1025
1026 assert_eq!(value.try_tanh().unwrap(), expected_result);
1027 assert_eq!(<Complex<f64> as TanH>::tanh(value), expected_result);
1028 assert_eq!(value.tanh(), expected_result);
1029 }
1030
1031 #[test]
1032 fn tanh_zero() {
1033 let value = Complex::new(0.0, 0.0);
1034 let expected_result = Complex::new(0.0, 0.0);
1035 assert_eq!(value.try_tanh().unwrap(), expected_result);
1036 assert_eq!(value.tanh(), expected_result);
1037 }
1038
1039 #[test]
1040 #[cfg(debug_assertions)]
1041 fn tanh_nan() {
1042 let value = Complex::new(f64::NAN, 0.0);
1043 assert!(matches!(
1044 value.try_tanh(),
1045 Err(TanHComplexErrors::Input(..))
1046 ));
1047
1048 let value = Complex::new(0.0, f64::NAN);
1049 assert!(matches!(
1050 value.try_tanh(),
1051 Err(TanHComplexErrors::Input(..))
1052 ));
1053 }
1054
1055 #[test]
1056 #[cfg(debug_assertions)]
1057 fn tanh_infinity() {
1058 let value = Complex::new(f64::INFINITY, 0.0);
1059 assert!(matches!(
1060 value.try_tanh(),
1061 Err(TanHComplexErrors::Input(..))
1062 ));
1063
1064 let value = Complex::new(0.0, f64::INFINITY);
1065 assert!(matches!(
1066 value.try_tanh(),
1067 Err(TanHComplexErrors::Input(..))
1068 ));
1069 }
1070
1071 #[test]
1072 #[cfg(debug_assertions)]
1073 fn tanh_subnormal() {
1074 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1075 assert!(matches!(
1076 value.try_tanh(),
1077 Err(TanHComplexErrors::Input(..))
1078 ));
1079
1080 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1081 assert!(matches!(
1082 value.try_tanh(),
1083 Err(TanHComplexErrors::Input(..))
1084 ));
1085 }
1086 }
1087 }
1088
1089 #[cfg(feature = "rug")]
1090 mod rug53 {
1091 use super::*;
1092
1093 mod real {
1094 use super::*;
1095
1096 #[test]
1097 fn test_rug_float_tanh_valid() {
1098 let value =
1099 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1100
1101 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1102 53,
1103 0.7615941559557649,
1104 ))
1105 .unwrap();
1106 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1107 assert_eq!(value.tanh(), expected_result);
1108 }
1109
1110 #[test]
1111 fn test_rug_float_tanh_zero() {
1112 let value =
1113 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1114
1115 let expected_result =
1116 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1117 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1118 assert_eq!(value.tanh(), expected_result);
1119 }
1120 }
1121
1122 mod complex {
1123 use super::*;
1124
1125 #[test]
1126 fn test_complex_rug_float_tanh_valid() {
1127 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1128 53,
1129 (rug::Float::with_val(53, 0.5), rug::Float::with_val(53, 0.5)),
1130 ))
1131 .unwrap();
1132
1133 let expected_result =
1134 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1135 53,
1136 (
1137 rug::Float::with_val(53, 5.640831412674985e-1),
1138 rug::Float::with_val(53, 4.0389645531602575e-1),
1139 ),
1140 ))
1141 .unwrap();
1142 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1143 assert_eq!(value.tanh(), expected_result);
1144 }
1145
1146 #[test]
1147 fn test_complex_rug_float_tanh_zero() {
1148 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1149 53,
1150 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1151 ))
1152 .unwrap();
1153
1154 let expected_result =
1155 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1156 53,
1157 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1158 ))
1159 .unwrap();
1160 assert_eq!(value.clone().try_tanh().unwrap(), expected_result);
1161 assert_eq!(value.tanh(), expected_result);
1162 }
1163 }
1164 }
1165 }
1166
1167 mod asinh {
1168 use super::*;
1169
1170 mod native {
1171 use super::*;
1172
1173 mod real {
1174 use super::*;
1175
1176 #[test]
1177 fn test_f64_asinh_valid() {
1178 let value = 1.0;
1179 let expected_result = 0.881373587019543;
1180 assert_eq!(value.try_asinh().unwrap(), expected_result);
1181 assert_eq!(<f64 as ASinH>::asinh(value), expected_result);
1182 assert_eq!(value.asinh(), expected_result);
1183 }
1184
1185 #[test]
1186 fn test_f64_asinh_negative() {
1187 let value = -1.0;
1188 let expected_result = -0.881373587019543;
1189 assert_eq!(value.try_asinh().unwrap(), expected_result);
1190 assert_eq!(<f64 as Float>::asinh(value), expected_result);
1191 assert_eq!(ASinH::asinh(value), expected_result);
1192 }
1193
1194 #[test]
1195 fn test_f64_asinh_zero() {
1196 let value = 0.0;
1197 assert_eq!(value.try_asinh().unwrap(), 0.0);
1198 assert_eq!(<f64 as Float>::asinh(value), 0.0);
1199 assert_eq!(ASinH::asinh(value), 0.0);
1200 }
1201
1202 #[test]
1203 #[cfg(debug_assertions)]
1204 fn test_f64_asinh_nan() {
1205 let value = f64::NAN;
1206 let result = value.try_asinh();
1207 assert!(matches!(result, Err(ASinHErrors::Input(..))));
1208 }
1209
1210 #[test]
1211 #[cfg(debug_assertions)]
1212 fn test_f64_asinh_infinity() {
1213 let value = f64::INFINITY;
1214 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1215 }
1216
1217 #[test]
1218 #[cfg(debug_assertions)]
1219 fn test_f64_asinh_subnormal() {
1220 let value = f64::MIN_POSITIVE / 2.0;
1221 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1222 }
1223 }
1224
1225 mod complex {
1226 use super::*;
1227
1228 #[test]
1229 fn asinh_valid() {
1230 let value = Complex::new(1.0, 1.0);
1231 let expected_result = Complex::new(1.0612750619050357, 0.6662394324925153);
1232 assert_eq!(value.try_asinh().unwrap(), expected_result);
1233 assert_eq!(<Complex<f64> as ASinH>::asinh(value), expected_result);
1234 assert_eq!(value.asinh(), expected_result);
1235 }
1236
1237 #[test]
1238 fn asinh_zero() {
1239 let value = Complex::new(0.0, 0.0);
1240 let expected_result = Complex::new(0.0, 0.0);
1241 assert_eq!(value.try_asinh().unwrap(), expected_result);
1242 assert_eq!(value.asinh(), expected_result);
1243 }
1244
1245 #[test]
1246 #[cfg(debug_assertions)]
1247 fn asinh_nan() {
1248 let value = Complex::new(f64::NAN, 0.0);
1249 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1250
1251 let value = Complex::new(0.0, f64::NAN);
1252 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1253 }
1254
1255 #[test]
1256 #[cfg(debug_assertions)]
1257 fn asinh_infinity() {
1258 let value = Complex::new(f64::INFINITY, 0.0);
1259 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1260
1261 let value = Complex::new(0.0, f64::INFINITY);
1262 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1263 }
1264
1265 #[test]
1266 #[cfg(debug_assertions)]
1267 fn asinh_subnormal() {
1268 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1269 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1270
1271 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1272 assert!(matches!(value.try_asinh(), Err(ASinHErrors::Input(..))));
1273 }
1274 }
1275 }
1276
1277 #[cfg(feature = "rug")]
1278 mod rug53 {
1279 use super::*;
1280
1281 mod real {
1282 use super::*;
1283
1284 #[test]
1285 fn test_rug_float_asinh_valid() {
1286 let value =
1287 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1288
1289 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1290 53,
1291 0.881373587019543,
1292 ))
1293 .unwrap();
1294 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1295 assert_eq!(value.asinh(), expected_result);
1296 }
1297
1298 #[test]
1299 fn test_rug_float_asinh_zero() {
1300 let value =
1301 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1302
1303 let expected_result =
1304 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1305 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1306 assert_eq!(value.asinh(), expected_result);
1307 }
1308 }
1309
1310 mod complex {
1311 use super::*;
1312
1313 #[test]
1314 fn test_complex_rug_float_asinh_valid() {
1315 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1316 53,
1317 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 1.0)),
1318 ))
1319 .unwrap();
1320
1321 let expected_result =
1322 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1323 53,
1324 (
1325 rug::Float::with_val(53, 1.0612750619050357),
1326 rug::Float::with_val(53, 0.6662394324925153),
1327 ),
1328 ))
1329 .unwrap();
1330 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1331 assert_eq!(value.asinh(), expected_result);
1332 }
1333
1334 #[test]
1335 fn test_complex_rug_float_asinh_zero() {
1336 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1337 53,
1338 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1339 ))
1340 .unwrap();
1341
1342 let expected_result =
1343 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1344 53,
1345 (rug::Float::with_val(53, 0.), rug::Float::with_val(53, 0.)),
1346 ))
1347 .unwrap();
1348 assert_eq!(value.clone().try_asinh().unwrap(), expected_result);
1349 assert_eq!(value.asinh(), expected_result);
1350 }
1351 }
1352 }
1353 }
1354
1355 mod acosh {
1356 use super::*;
1357
1358 mod native {
1359 use super::*;
1360
1361 mod real {
1362 use super::*;
1363
1364 #[test]
1365 fn test_f64_acosh_valid() {
1366 let value = 1.5;
1367 let expected_result = 0.9624236501192069;
1368 assert_eq!(value.try_acosh().unwrap(), expected_result);
1369 assert_eq!(<f64 as ACosH>::acosh(value), expected_result);
1370 assert_eq!(value.acosh(), expected_result);
1371 }
1372
1373 #[test]
1374 #[cfg(debug_assertions)]
1375 fn test_f64_acosh_out_of_domain() {
1376 let value = 0.9;
1377 let err = value.try_acosh().unwrap_err();
1378 assert!(matches!(
1379 err,
1380 ACosHErrors::Input(ACosHInputErrors::OutOfDomain { value: 0.9, .. })
1381 ));
1382 }
1383
1384 #[test]
1385 fn test_f64_acosh_one() {
1386 let value = 1.0;
1387 let expected_result = 0.0;
1388 assert_eq!(value.try_acosh().unwrap(), expected_result);
1389 assert_eq!(<f64 as ACosH>::acosh(value), expected_result);
1390 }
1391
1392 #[test]
1393 #[cfg(debug_assertions)]
1394 fn test_f64_acosh_nan() {
1395 let value = f64::NAN;
1396 let result = value.try_acosh();
1397 assert!(matches!(result, Err(ACosHErrors::Input(..))));
1398 }
1399
1400 #[test]
1401 #[cfg(debug_assertions)]
1402 fn test_f64_acosh_infinity() {
1403 let value = f64::INFINITY;
1404 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1405 }
1406
1407 #[test]
1408 #[cfg(debug_assertions)]
1409 fn test_f64_acosh_subnormal() {
1410 let value = f64::MIN_POSITIVE / 2.0;
1411 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1412 }
1413 }
1414
1415 mod complex {
1416 use super::*;
1417
1418 #[test]
1419 fn acosh_valid() {
1420 let value = Complex::new(1.5, 1.5);
1421 let expected_result = if cfg!(target_arch = "x86_64") {
1422 Complex::new(1.44973434958536, 0.840395108841671)
1423 } else if cfg!(target_arch = "aarch64") {
1424 Complex::new(1.4497343495853596, 0.8403951088416711)
1425 } else {
1426 todo!("Architecture not-tested");
1427 };
1428
1429 assert_eq!(value.try_acosh().unwrap(), expected_result);
1430 assert_eq!(<Complex<f64> as ACosH>::acosh(value), expected_result);
1431 assert_eq!(value.acosh(), expected_result);
1432 }
1433
1434 #[test]
1435 #[cfg(debug_assertions)]
1436 fn acosh_out_of_domain() {
1437 let v = Complex::new(-1.1, 0.);
1438 let err = v.try_acosh().unwrap_err();
1439 assert!(matches!(
1440 err,
1441 ACosHErrors::Input(ACosHInputErrors::OutOfDomain { .. })
1442 ));
1443 }
1444
1445 #[test]
1446 fn acosh_one() {
1447 let value = Complex::new(1.0, 0.0);
1448 let expected_result = Complex::new(0.0, 0.0);
1449 assert_eq!(value.try_acosh().unwrap(), expected_result);
1450 assert_eq!(value.acosh(), expected_result);
1451 }
1452
1453 #[test]
1454 #[cfg(debug_assertions)]
1455 fn acosh_nan() {
1456 let value = Complex::new(f64::NAN, 0.0);
1457 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1458
1459 let value = Complex::new(0.0, f64::NAN);
1460 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1461 }
1462
1463 #[test]
1464 #[cfg(debug_assertions)]
1465 fn acosh_infinity() {
1466 let value = Complex::new(f64::INFINITY, 0.0);
1467 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1468
1469 let value = Complex::new(0.0, f64::INFINITY);
1470 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1471 }
1472
1473 #[test]
1474 #[cfg(debug_assertions)]
1475 fn acosh_subnormal() {
1476 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1477 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1478
1479 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1480 assert!(matches!(value.try_acosh(), Err(ACosHErrors::Input(..))));
1481 }
1482 }
1483 }
1484
1485 #[cfg(feature = "rug")]
1486 mod rug53 {
1487 use super::*;
1488
1489 mod real {
1490 use super::*;
1491
1492 #[test]
1493 fn test_rug_float_acosh_valid() {
1494 let value =
1495 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.5)).unwrap();
1496
1497 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1498 53,
1499 0.9624236501192069,
1500 ))
1501 .unwrap();
1502 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1503 assert_eq!(value.acosh(), expected_result);
1504 }
1505
1506 #[test]
1507 fn test_rug_float_acosh_one() {
1508 let value =
1509 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 1.0)).unwrap();
1510
1511 let expected_result =
1512 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1513 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1514 assert_eq!(value.acosh(), expected_result);
1515 }
1516 }
1517
1518 mod complex {
1519 use super::*;
1520
1521 #[test]
1522 fn test_complex_rug_float_acosh_valid() {
1523 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1524 53,
1525 (rug::Float::with_val(53, 1.5), rug::Float::with_val(53, 1.5)),
1526 ))
1527 .unwrap();
1528
1529 let expected_result =
1530 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1531 53,
1532 (
1533 rug::Float::with_val(53, 1.4497343495853598),
1534 rug::Float::with_val(53, 8.403951088416711e-1),
1535 ),
1536 ))
1537 .unwrap();
1538 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1539 assert_eq!(value.acosh(), expected_result);
1540 }
1541
1542 #[test]
1543 fn test_complex_rug_float_acosh_one() {
1544 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1545 53,
1546 (rug::Float::with_val(53, 1.0), rug::Float::with_val(53, 0.0)),
1547 ))
1548 .unwrap();
1549
1550 let expected_result =
1551 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1552 53,
1553 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1554 ))
1555 .unwrap();
1556 assert_eq!(value.clone().try_acosh().unwrap(), expected_result);
1557 assert_eq!(value.acosh(), expected_result);
1558 }
1559 }
1560 }
1561 }
1562
1563 mod atanh {
1564 use super::*;
1565
1566 mod native {
1567 use super::*;
1568
1569 mod real {
1570 use super::*;
1571
1572 #[test]
1573 fn test_f64_atanh_valid() {
1574 let value = 0.5;
1575 let expected_result = 0.5493061443340548;
1576
1577 assert_ulps_eq!(value.try_atanh().unwrap(), expected_result);
1578 assert_ulps_eq!(<f64 as ATanH>::atanh(value), expected_result);
1579 assert_ulps_eq!(value.atanh(), expected_result);
1580 }
1581
1582 #[test]
1583 fn test_f64_atanh_negative() {
1584 let value = -0.5;
1585 let expected_result = -0.5493061443340548;
1586 assert_eq!(value.try_atanh().unwrap(), expected_result);
1587 assert_eq!(ATanH::atanh(value), expected_result);
1588 }
1589
1590 #[test]
1591 #[cfg(debug_assertions)]
1592 fn test_f64_atanh_out_of_domain() {
1593 let value = 1.0;
1594 let err = value.try_atanh().unwrap_err();
1595 assert!(matches!(
1596 err,
1597 ATanHErrors::Input(ATanHInputErrors::OutOfDomain { value: 1., .. })
1598 ));
1599 }
1600
1601 #[test]
1602 fn test_f64_atanh_zero() {
1603 let value = 0.0;
1604 assert_eq!(value.try_atanh().unwrap(), 0.0);
1605 assert_eq!(ATanH::atanh(value), 0.0);
1606 }
1607
1608 #[test]
1609 #[cfg(debug_assertions)]
1610 fn test_f64_atanh_nan() {
1611 let value = f64::NAN;
1612 let result = value.try_atanh();
1613 assert!(matches!(result, Err(ATanHErrors::Input(..))));
1614 }
1615
1616 #[test]
1617 #[cfg(debug_assertions)]
1618 fn test_f64_atanh_infinity() {
1619 let value = f64::INFINITY;
1620 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1621 }
1622
1623 #[test]
1624 #[cfg(debug_assertions)]
1625 fn test_f64_atanh_subnormal() {
1626 let value = f64::MIN_POSITIVE / 2.0;
1627 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1628 }
1629 }
1630
1631 mod complex {
1632 use super::*;
1633
1634 #[test]
1635 fn atanh_valid() {
1636 let value = Complex::new(0.5, 0.5);
1637 let expected_result = Complex::new(0.4023594781085251, 0.5535743588970452);
1638 assert_eq!(value.try_atanh().unwrap(), expected_result);
1639 assert_eq!(<Complex<f64> as ATanH>::atanh(value), expected_result);
1640 assert_eq!(value.atanh(), expected_result);
1641 }
1642
1643 #[test]
1644 #[cfg(debug_assertions)]
1645 fn atanh_out_of_domain() {
1646 let v = Complex::new(-1., 0.);
1647 let err = v.try_atanh().unwrap_err();
1648 assert!(matches!(
1649 err,
1650 ATanHErrors::Input(ATanHInputErrors::OutOfDomain { .. })
1651 ));
1652 }
1653
1654 #[test]
1655 fn atanh_zero() {
1656 let value = Complex::new(0.0, 0.0);
1657 let expected_result = Complex::new(0.0, 0.0);
1658 assert_eq!(value.try_atanh().unwrap(), expected_result);
1659 assert_eq!(value.atanh(), expected_result);
1660 }
1661
1662 #[test]
1663 #[cfg(debug_assertions)]
1664 fn atanh_nan() {
1665 let value = Complex::new(f64::NAN, 0.0);
1666 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1667
1668 let value = Complex::new(0.0, f64::NAN);
1669 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1670 }
1671
1672 #[test]
1673 #[cfg(debug_assertions)]
1674 fn atanh_infinity() {
1675 let value = Complex::new(f64::INFINITY, 0.0);
1676 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1677
1678 let value = Complex::new(0.0, f64::INFINITY);
1679 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1680 }
1681
1682 #[test]
1683 #[cfg(debug_assertions)]
1684 fn atanh_subnormal() {
1685 let value = Complex::new(f64::MIN_POSITIVE / 2.0, 0.0);
1686 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1687
1688 let value = Complex::new(0.0, f64::MIN_POSITIVE / 2.0);
1689 assert!(matches!(value.try_atanh(), Err(ATanHErrors::Input(..))));
1690 }
1691 }
1692 }
1693
1694 #[cfg(feature = "rug")]
1695 mod rug53 {
1696 use super::*;
1697
1698 mod real {
1699 use super::*;
1700
1701 #[test]
1702 fn test_rug_float_atanh_valid() {
1703 let value =
1704 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.5)).unwrap();
1705
1706 let expected_result = RealRugStrictFinite::<53>::try_new(rug::Float::with_val(
1707 53,
1708 0.5493061443340549,
1709 ))
1710 .unwrap();
1711 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1712 assert_eq!(value.atanh(), expected_result);
1713 }
1714
1715 #[test]
1716 fn test_rug_float_atanh_zero() {
1717 let value =
1718 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1719
1720 let expected_result =
1721 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
1722 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1723 assert_eq!(value.atanh(), expected_result);
1724 }
1725 }
1726
1727 mod complex {
1728 use super::*;
1729
1730 #[test]
1731 fn test_complex_rug_float_atanh_valid() {
1732 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1733 53,
1734 (rug::Float::with_val(53, 0.5), rug::Float::with_val(53, 0.5)),
1735 ))
1736 .unwrap();
1737
1738 let expected_result =
1739 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1740 53,
1741 (
1742 rug::Float::with_val(53, 0.40235947810852507),
1743 rug::Float::with_val(53, 0.5535743588970452),
1744 ),
1745 ))
1746 .unwrap();
1747 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1748 assert_eq!(value.atanh(), expected_result);
1749 }
1750
1751 #[test]
1752 fn test_complex_rug_float_atanh_zero() {
1753 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1754 53,
1755 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1756 ))
1757 .unwrap();
1758
1759 let expected_result =
1760 ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
1761 53,
1762 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
1763 ))
1764 .unwrap();
1765 assert_eq!(value.clone().try_atanh().unwrap(), expected_result);
1766 assert_eq!(value.atanh(), expected_result);
1767 }
1768 }
1769 }
1770 }
1771}
1772