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