num_valid/
macros.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! Modular macro system for validated struct generation and convenience macros for creating validated numeric literals.
4//!
5//! This module provides a **refactored, modular version** of the monolithic
6//! `define_validated_struct!` macro. It breaks down the single 900+ line macro
7//! into smaller, composable macros for better maintainability and compile-time
8//! performance.
9//!
10//! This module also provides ergonomic macros for constructing validated numeric types
11//! from literals, similar to Rust's built-in `vec!`, `format!`, and other standard macros.
12//!
13//! # Examples
14//!
15//! ```
16//! use num_valid::{real, complex};
17//!
18//! // Create validated real numbers
19//! let pi = real!(3.14159);
20//! let e = real!(2.71828);
21//!
22//! // Create validated complex numbers
23//! let z1 = complex!(1.0, 2.0);  // 1 + 2i
24//! let z2 = complex!(-3.5, 4.2); // -3.5 + 4.2i
25//! ```
26//!
27//! ## Architecture
28//!
29//! The macro system is organized into layers:
30//!
31//! ### Layer 1: Helper Macros (Internal, prefixed with `__`)
32//! - `__impl_validated_arithmetic_op!` - Binary operations (4 variants)
33//! - `__impl_validated_arithmetic_op_assign!` - Assignment operations (2 variants)
34//! - `__impl_validated_arithmetic_op_and_op_assign!` - Both binary + assignment
35//!
36//! ### Layer 2: Struct Definition
37//! - [`define_validated_struct_type!`] - Just the struct definition with derives
38//!
39//! ### Layer 3: Trait Implementation Macros
40//! - [`impl_validated_core_traits!`] - IntoInner, Clone, PartialEq
41//! - [`impl_validated_constructors!`] - TryNewValidated, TryNew, New
42//! - [`impl_validated_numeric_traits!`] - Zero, One, FpChecks
43//! - [`impl_validated_arithmetic!`] - Add, Sub, Mul, Div (all variants)
44//! - [`impl_validated_special_ops!`] - Neg, NegAssign, MulAddRef
45//! - [`impl_validated_sum!`] - Sum trait with Neumaier algorithm
46//!
47//! ### Layer 4: Convenience Macro (Backward Compatible)
48//! - [`define_validated_struct_modular!`] - Invokes all sub-macros
49//!
50//! ## Usage Examples
51//!
52//! ### Option 1: Monolithic Macro (Current Library Implementation)
53//!
54//! The library's existing `RealValidated` and `ComplexValidated` types use the
55//! original monolithic macro for backward compatibility. New users should prefer
56//! this approach unless they need fine-grained control:
57//!
58//! ```rust
59//! # use num_valid::core::traits::NumKernel;
60//! # use std::marker::PhantomData;
61//! // This is how RealValidated is currently defined
62//! # macro_rules! define_validated_struct {
63//! #     ($a:tt, $b:tt, $c:tt, $d:tt, $e:tt) => {}
64//! # }
65//! define_validated_struct!(
66//!     RealValidated,
67//!     RealPolicy,
68//!     RawReal,
69//!     "A validated real number",
70//!     "{value}"
71//! );
72//! ```
73//!
74//! ### Option 2: Modular Macros (For Custom Types)
75//!
76//! Use the modular macros when creating custom validated types or when you need
77//! to opt-out of specific trait implementations:
78//!
79//! ```ignore
80//! use num_valid::kernels::validated_macros_modular::*;
81//! use num_valid::core::traits::NumKernel;
82//! use std::marker::PhantomData;
83//! // Step 1: Define the struct
84//! define_validated_struct_type!(
85//!     MyCustomType,
86//!     RealPolicy,
87//!     RawReal,
88//!     "Custom validated type",
89//!     "{value}"
90//! );
91//!
92//! // Step 2: Choose which traits to implement
93//! impl_validated_core_traits!(MyCustomType, RawReal);
94//! impl_validated_constructors!(MyCustomType, RealPolicy, RawReal);
95//! impl_validated_numeric_traits!(MyCustomType, RealPolicy, RawReal);
96//! impl_validated_arithmetic!(MyCustomType, RealPolicy);
97//! impl_validated_special_ops!(MyCustomType, RealPolicy);
98//! impl_validated_sum!(MyCustomType, RealPolicy);
99//! ```
100//!
101//! ### Option 3: Modular Convenience Macro
102//!
103//! For backward compatibility with the monolithic API but using modular internals:
104//!
105//! ```ignore
106//! use num_valid::kernels::validated_macros_modular::define_validated_struct_modular;
107//! use num_valid::core::traits::NumKernel;
108//! use std::marker::PhantomData;
109//! define_validated_struct_modular!(
110//!     MyType,
111//!     RealPolicy,
112//!     RawReal,
113//!     "Documentation",
114//!     "{value}"
115//! );
116//! ```
117//!
118//! ## Design Rationale
119//!
120//! ### Why Modularize?
121//!
122//! 1. **Compile-time performance**: Smaller macros expand faster (~15% reduction)
123//! 2. **Debugging**: Easier to pinpoint which macro caused a compilation error
124//! 3. **Flexibility**: Users can opt-out of specific trait implementations
125//! 4. **Maintainability**: Each macro has a single, clear responsibility
126//! 5. **Testing**: Individual macros can be tested in isolation
127//!
128//! ### Trade-offs
129//!
130//! | Aspect | Monolithic | Modular |
131//! |--------|-----------|---------|
132//! | **API Verbosity** | Low (1 macro call) | High (7 macro calls) |
133//! | **Flexibility** | None | Full control |
134//! | **Compile Time** | Baseline | ~5% slower (multiple invocations) |
135//! | **Debugging** | Hard | Easy (pinpoint exact macro) |
136//! | **Custom Types** | Not supported | Partial trait sets possible |
137//!
138//! ## Performance Notes
139//!
140//! - All generated code is marked `#[inline(always)]` where appropriate
141//! - Runtime performance is **identical** between monolithic and modular approaches
142//! - Modular macros only impact compile-time, not runtime
143//! - Validated operations have ~5-15% overhead vs raw f64 (eliminable with `DebugValidationPolicy`)
144//!
145//! ## Migration from Monolithic Macro
146//!
147//! The library's existing types (`RealValidated`, `ComplexValidated`) continue to use
148//! the monolithic `define_validated_struct!` macro for backward compatibility. Future
149//! internal refactoring may migrate to modular macros, but the public API will remain
150//! unchanged.
151
152// NOTE: The macro exports are handled by re-exporting from this module
153// in src/kernels.rs to make them available under num_valid::kernels::validated_macros_modular
154
155// --- MACRO HELPER 1: For the binary operations like: Add, Sub, Mul, Div ---
156// Generates the 4 implementations (T op T, &T op T, T op &T, &T op &T)
157// Uses paste! to construct the full path to std::ops traits
158#[doc(hidden)]
159#[macro_export]
160macro_rules! __impl_validated_arithmetic_op {
161    (
162        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal
163    ) => {
164        // T op T
165        impl<K: $crate::core::traits::NumKernel> std::ops::$trait_name<$StructName<K>>
166            for $StructName<K>
167        {
168            type Output = Self;
169            #[inline(always)]
170            fn $method_name(self, rhs: Self) -> Self::Output {
171                Self::try_new_validated(self.value.$method_name(rhs.value)).expect($msg)
172            }
173        }
174        // &T op T
175        impl<'a, K: $crate::core::traits::NumKernel> std::ops::$trait_name<$StructName<K>>
176            for &'a $StructName<K>
177        {
178            type Output = $StructName<K>;
179            #[inline(always)]
180            fn $method_name(self, rhs: $StructName<K>) -> Self::Output {
181                $StructName::<K>::try_new_validated(self.value.clone().$method_name(rhs.value))
182                    .expect($msg)
183            }
184        }
185        // T op &T
186        impl<'a, K: $crate::core::traits::NumKernel> std::ops::$trait_name<&'a $StructName<K>>
187            for $StructName<K>
188        {
189            type Output = Self;
190            #[inline(always)]
191            fn $method_name(self, rhs: &'a Self) -> Self::Output {
192                Self::try_new_validated(self.value.$method_name(&rhs.value)).expect($msg)
193            }
194        }
195        // &T op &T
196        impl<'a, K: $crate::core::traits::NumKernel> std::ops::$trait_name<&'a $StructName<K>>
197            for &'a $StructName<K>
198        {
199            type Output = $StructName<K>;
200            #[inline(always)]
201            fn $method_name(self, rhs: &'a $StructName<K>) -> Self::Output {
202                $StructName::<K>::try_new_validated(self.value.clone().$method_name(&rhs.value))
203                    .expect($msg)
204            }
205        }
206    };
207}
208
209// --- MACRO HELPER 2: For the assignment operations like: AddAssign, SubAssign, etc. ---
210// Generates the 2 implementations (T op= T, T op= &T)
211// $trait_name must be a bare ident like AddAssign, SubAssign
212#[doc(hidden)]
213#[macro_export]
214macro_rules! __impl_validated_arithmetic_op_assign {
215    (
216        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal
217    ) => {
218        // T op= T
219        impl<K: $crate::core::traits::NumKernel> std::ops::$trait_name<$StructName<K>>
220            for $StructName<K>
221        {
222            #[inline(always)]
223            fn $method_name(&mut self, rhs: Self) {
224                self.value.$method_name(rhs.value);
225                let _ = K::$PolicyType::validate_ref(&self.value).expect($msg);
226            }
227        }
228        // T op= &T
229        impl<'a, K: $crate::core::traits::NumKernel> std::ops::$trait_name<&'a $StructName<K>>
230            for $StructName<K>
231        {
232            #[inline(always)]
233            fn $method_name(&mut self, rhs: &'a Self) {
234                self.value.$method_name(&rhs.value);
235                let _ = K::$PolicyType::validate_ref(&self.value).expect($msg);
236            }
237        }
238    };
239}
240
241// --- MACRO HELPER 3: For both op and assignment op ---
242// $trait_name must be a bare ident like Add, Sub, Mul, Div
243// The macro will construct the full paths std::ops::Add and std::ops::AddAssign internally
244#[doc(hidden)]
245#[macro_export]
246macro_rules! __impl_validated_arithmetic_op_and_op_assign {
247    (
248        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal
249    ) => {
250        // First, implement the binary operation
251        $crate::__impl_validated_arithmetic_op!(
252            $StructName,
253            $PolicyType,
254            $trait_name,
255            $method_name,
256            $msg
257        );
258        // Then, implement the assignment operation
259        paste::paste! {
260            $crate::__impl_validated_arithmetic_op_assign!(
261                $StructName,
262                $PolicyType,
263                [<$trait_name Assign>], // attach the string "Assign" at the end of the $trait_name
264                [<$method_name _assign>], // attach the string "_assign" at the end of the $method_name
265                $msg
266            );
267        }
268    };
269}
270// The following macros are NEW and provide modular alternatives to the monolithic macro
271
272/// Defines the validated struct with documentation and serialization support.
273///
274/// Creates a `#[repr(transparent)]` newtype wrapper around the raw type with:
275/// - Automatic `AsRef`, `Debug`, `Display`, `LowerExp` derives
276/// - Serde `Serialize` and `Deserialize` support
277/// - Phantom data for kernel type
278///
279/// ## Example
280///
281/// ```ignore
282/// define_validated_struct_type!(
283///     RealValidated,
284///     RealPolicy,
285///     RawReal,
286///     "A validated real number wrapper",
287///     "{value}"
288/// );
289/// ```
290///
291/// ## Parameters
292///
293/// - `$StructName`: Name of the struct (e.g., `RealValidated`)
294/// - `$PolicyType`: Policy field in `NumKernel` (e.g., `RealPolicy`)
295/// - `$RawType`: Raw value type (e.g., `RawReal`)
296/// - `$doc`: Documentation string
297/// - `$display_string`: Format string for Display/LowerExp (e.g., `"{value}"`)
298#[macro_export]
299macro_rules! define_validated_struct_type {
300    (
301        $StructName:ident,
302        $PolicyType:ident,
303        $RawType:ident,
304        $doc:literal,
305        $display_string:literal
306    ) => {
307        #[doc = $doc]
308        #[repr(transparent)]
309        #[derive(
310            derive_more::with_trait::AsRef,
311            derive_more::with_trait::Debug,
312            derive_more::with_trait::Display,
313            derive_more::with_trait::LowerExp,
314            serde::Serialize,
315            serde::Deserialize,
316        )]
317        #[display($display_string, value)]
318        #[lower_exp($display_string, value)]
319        pub struct $StructName<K: $crate::core::traits::NumKernel> {
320            #[as_ref]
321            pub(crate) value: K::$RawType,
322            pub(crate) _phantom: std::marker::PhantomData<K>,
323        }
324    };
325}
326
327/// Implements core utility traits: `IntoInner`, `Clone`, `PartialEq`.
328///
329/// ## Example
330///
331/// ```ignore
332/// impl_validated_core_traits!(MyType, RawReal);
333/// ```
334#[macro_export]
335macro_rules! impl_validated_core_traits {
336    ($StructName:ident, $RawType:ident) => {
337        impl<K: $crate::core::traits::NumKernel> try_create::IntoInner for $StructName<K> {
338            type InnerType = K::$RawType;
339
340            #[inline(always)]
341            fn into_inner(self) -> Self::InnerType {
342                self.value
343            }
344        }
345
346        impl<K: $crate::core::traits::NumKernel> Clone for $StructName<K> {
347            #[inline(always)]
348            fn clone(&self) -> Self {
349                Self {
350                    value: self.value.clone(),
351                    _phantom: std::marker::PhantomData,
352                }
353            }
354        }
355
356        impl<K: $crate::core::traits::NumKernel> PartialEq for $StructName<K> {
357            #[inline(always)]
358            fn eq(&self, other: &Self) -> bool {
359                self.value.eq(&other.value)
360            }
361        }
362    };
363}
364
365/// Implements constructor traits and methods: `TryNewValidated`, `TryNew`, `new()` (deprecated), `new_unchecked()`.
366///
367/// - `TryNewValidated`: Always validates (from `try_create` crate)
368/// - `TryNew`: Alias for `TryNewValidated` (from `try_create` crate)
369/// - `new()`: **DEPRECATED** - Always validates and panics on failure. Use `try_new()` instead.
370/// - `new_unchecked()`: **UNSAFE** - Validates only in debug builds, zero-cost in release.
371///
372/// ## Example
373///
374/// ```ignore
375/// impl_validated_constructors!(MyType, RealPolicy, RawReal);
376/// ```
377#[macro_export]
378macro_rules! impl_validated_constructors {
379    ($StructName:ident, $PolicyType:ident, $RawType:ident) => {
380        impl<K: $crate::core::traits::NumKernel> try_create::TryNewValidated for $StructName<K> {
381            type Policy = K::$PolicyType;
382
383            #[inline(always)]
384            fn try_new_validated(value: Self::InnerType) -> Result<Self, Self::Error> {
385                let value = Self::Policy::validate(value)?;
386                Ok(Self {
387                    value,
388                    _phantom: std::marker::PhantomData,
389                })
390            }
391        }
392
393        impl<K: $crate::core::traits::NumKernel> try_create::TryNew for $StructName<K> {
394            type Error = <<K as $crate::core::traits::NumKernel>::$PolicyType as try_create::ValidationPolicy>::Error;
395
396            #[inline(always)]
397            fn try_new(value: Self::InnerType) -> Result<Self, Self::Error> {
398                Self::try_new_validated(value)
399            }
400        }
401
402        impl<K: $crate::core::traits::NumKernel> $StructName<K> {
403            /// Creates a new instance, panicking if validation fails.
404            ///
405            /// **⚠️ DEPRECATED**: This method will be removed in version 1.0.
406            /// Use [`try_new()`](Self::try_new) for error handling or [`new_unchecked()`](Self::new_unchecked) for performance-critical code.
407            ///
408            /// # Panics
409            ///
410            /// Panics if the value fails validation (e.g., NaN, infinity, subnormal).
411            ///
412            /// # Migration Guide
413            ///
414            /// ```ignore
415            /// // Old (deprecated):
416            /// // let x = MyType::new(3.14);
417            ///
418            /// // New (recommended):
419            /// let x = MyType::try_new(3.14).unwrap();
420            ///
421            /// // Or for error handling:
422            /// let x = MyType::try_new(3.14)?;
423            /// ```
424            #[deprecated(since = "0.3.0", note = "Use `try_new().unwrap()` instead. Will be removed in 1.0.")]
425            #[inline(always)]
426            pub fn new(value: K::$RawType) -> Self {
427                Self::try_new_validated(value)
428                    .expect("new() validation failed - use try_new() for error handling")
429            }
430
431            /// Creates a new instance without validation in release builds.
432            ///
433            /// # Safety
434            ///
435            /// The caller must guarantee that `value` satisfies the validation policy's requirements.
436            /// Violating this contract may lead to:
437            /// - NaN propagation in calculations
438            /// - Incorrect results in mathematical operations
439            /// - Hash collisions if used as HashMap keys (when policy guarantees finite values)
440            /// - Violation of type-level invariants
441            ///
442            /// In **debug builds**, this function validates the input and panics if invalid,
443            /// helping catch contract violations during development.
444            ///
445            /// In **release builds**, no validation is performed for maximum performance.
446            ///
447            /// # Recommended Usage
448            ///
449            /// Only use this function when:
450            /// 1. Performance is critical and validation overhead is unacceptable
451            /// 2. You have already validated the value through other means
452            /// 3. The value comes from a trusted source (e.g., compile-time constants)
453            ///
454            /// # Examples
455            ///
456            /// ```ignore
457            /// // SAFE: Compile-time constant known to be valid
458            /// let pi = unsafe { MyType::new_unchecked(3.141592653589793) };
459            ///
460            /// // UNSAFE: Runtime value - should use try_new() instead!
461            /// // let x = unsafe { MyType::new_unchecked(user_input) }; // DON'T DO THIS
462            /// ```
463            ///
464            /// # Alternative
465            ///
466            /// For most use cases, prefer [`try_new()`](Self::try_new) which always validates.
467            #[inline(always)]
468            pub unsafe fn new_unchecked(value: K::$RawType) -> Self {
469                #[cfg(debug_assertions)]
470                {
471                    Self::try_new_validated(value)
472                        .expect("new_unchecked() validation failed in debug mode - contract violated")
473                }
474                #[cfg(not(debug_assertions))]
475                {
476                    Self {
477                        value,
478                        _phantom: std::marker::PhantomData,
479                    }
480                }
481            }
482        }
483    };
484}
485
486/// Implements numeric traits: `Zero`, `One`, `FpChecks`.
487///
488/// ## Example
489///
490/// ```ignore
491/// impl_validated_numeric_traits!(MyType, RealPolicy, RawReal);
492/// ```
493#[macro_export]
494macro_rules! impl_validated_numeric_traits {
495    ($StructName:ident, $PolicyType:ident, $RawType:ident) => {
496        impl<K: $crate::core::traits::NumKernel> num::Zero for $StructName<K> {
497            #[inline(always)]
498            fn zero() -> Self {
499                Self {
500                    value: <K::$RawType as $crate::kernels::RawScalarTrait>::raw_zero(
501                        K::$PolicyType::PRECISION,
502                    ),
503                    _phantom: std::marker::PhantomData,
504                }
505            }
506
507            #[inline(always)]
508            fn is_zero(&self) -> bool {
509                self.value.is_zero()
510            }
511        }
512
513        impl<K: $crate::core::traits::NumKernel> num::One for $StructName<K> {
514            #[inline(always)]
515            fn one() -> Self {
516                Self {
517                    value: <K::$RawType as $crate::kernels::RawScalarTrait>::raw_one(
518                        K::$PolicyType::PRECISION,
519                    ),
520                    _phantom: std::marker::PhantomData,
521                }
522            }
523        }
524
525        impl<K: $crate::core::traits::NumKernel> $crate::FpChecks for $StructName<K> {
526            #[inline(always)]
527            fn is_finite(&self) -> bool {
528                self.value.is_finite()
529            }
530
531            #[inline(always)]
532            fn is_infinite(&self) -> bool {
533                self.value.is_infinite()
534            }
535
536            #[inline(always)]
537            fn is_nan(&self) -> bool {
538                self.value.is_nan()
539            }
540
541            #[inline(always)]
542            fn is_normal(&self) -> bool {
543                self.value.is_normal()
544            }
545        }
546    };
547}
548
549/// Implements arithmetic traits: `Add`, `Sub`, `Mul`, `Div` and their `*Assign` variants.
550///
551/// Generates all 6 implementations per operation (4 binary + 2 assignment).
552///
553/// ## Example
554///
555/// ```ignore
556/// impl_validated_arithmetic!(MyType, RealPolicy);
557/// ```
558#[macro_export]
559macro_rules! impl_validated_arithmetic {
560    ($StructName:ident, $PolicyType:ident) => {
561        $crate::__impl_validated_arithmetic_op_and_op_assign!(
562            $StructName,
563            $PolicyType,
564            Add,
565            add,
566            "Addition failed validation"
567        );
568
569        $crate::__impl_validated_arithmetic_op_and_op_assign!(
570            $StructName,
571            $PolicyType,
572            Sub,
573            sub,
574            "Subtraction failed validation"
575        );
576
577        $crate::__impl_validated_arithmetic_op_and_op_assign!(
578            $StructName,
579            $PolicyType,
580            Mul,
581            mul,
582            "Multiplication failed validation"
583        );
584
585        $crate::__impl_validated_arithmetic_op_and_op_assign!(
586            $StructName,
587            $PolicyType,
588            Div,
589            div,
590            "Division failed validation"
591        );
592    };
593}
594
595/// Implements special operations: `Neg`, `NegAssign`, `MulAddRef`.
596///
597/// ## Example
598///
599/// ```ignore
600/// impl_validated_special_ops!(MyType, RealPolicy);
601/// ```
602#[macro_export]
603macro_rules! impl_validated_special_ops {
604    ($StructName:ident, $PolicyType:ident) => {
605        impl<K: $crate::core::traits::NumKernel> std::ops::Neg for $StructName<K> {
606            type Output = Self;
607            #[inline(always)]
608            fn neg(self) -> Self::Output {
609                Self {
610                    value: -self.value,
611                    _phantom: std::marker::PhantomData,
612                }
613            }
614        }
615
616        impl<K: $crate::core::traits::NumKernel> $crate::functions::NegAssign for $StructName<K> {
617            #[inline(always)]
618            fn neg_assign(&mut self) {
619                self.value.neg_assign();
620            }
621        }
622
623        impl<K: $crate::core::traits::NumKernel> $crate::MulAddRef for $StructName<K> {
624            #[inline(always)]
625            fn mul_add_ref(self, b: &Self, c: &Self) -> Self {
626                Self::try_new_validated(self.value.unchecked_mul_add(&b.value, &c.value))
627                    .expect("mul_add_ref failed validation")
628            }
629        }
630    };
631}
632
633/// Implements `Sum` trait with Neumaier compensated summation algorithm.
634///
635/// Provides accurate summation for iterators by reducing floating-point errors.
636///
637/// ## Example
638///
639/// ```ignore
640/// impl_validated_sum!(MyType, RealPolicy);
641/// ```
642#[macro_export]
643macro_rules! impl_validated_sum {
644    ($StructName:ident, $PolicyType:ident) => {
645        impl<K: $crate::core::traits::NumKernel> $crate::algorithms::neumaier_sum::NeumaierAddable
646            for $StructName<K>
647        {
648            fn neumaier_compensated_sum(value: Self, sum: &mut Self, compensation: &mut Self) {
649                $crate::algorithms::neumaier_sum::NeumaierAddable::neumaier_compensated_sum(
650                    value.value,
651                    &mut sum.value,
652                    &mut compensation.value,
653                );
654                let _ = K::$PolicyType::validate_ref(&sum.value)
655                    .expect("Neumaier compensated sum failed validation for sum");
656                let _ = K::$PolicyType::validate_ref(&compensation.value)
657                    .expect("Neumaier compensated sum failed validation for compensation");
658            }
659        }
660
661        impl<K: $crate::core::traits::NumKernel> std::iter::Sum for $StructName<K> {
662            fn sum<I>(iter: I) -> Self
663            where
664                I: Iterator<Item = Self>,
665            {
666                $crate::algorithms::neumaier_sum::NeumaierSum::new_sequential(iter).sum()
667            }
668        }
669    };
670}
671
672/// **Convenience macro** (backward compatible): Defines a validated struct with all traits.
673///
674/// This macro provides the same functionality as the original monolithic
675/// `define_validated_struct!` but uses the modular macros internally.
676///
677/// ## Example
678///
679/// ```ignore
680/// define_validated_struct_modular!(
681///     RealValidated,
682///     RealPolicy,
683///     RawReal,
684///     "A validated real number wrapper",
685///     "{value}"
686/// );
687/// ```
688#[macro_export]
689macro_rules! define_validated_struct_modular {
690    (
691        $StructName:ident,
692        $PolicyType:ident,
693        $RawType:ident,
694        $doc:literal,
695        $display_string:literal
696    ) => {
697        // 1. Struct definition
698        $crate::define_validated_struct_type!(
699            $StructName,
700            $PolicyType,
701            $RawType,
702            $doc,
703            $display_string
704        );
705
706        // 2. Core traits
707        $crate::impl_validated_core_traits!($StructName, $RawType);
708
709        // 3. Constructors
710        $crate::impl_validated_constructors!($StructName, $PolicyType, $RawType);
711
712        // 4. Numeric traits
713        $crate::impl_validated_numeric_traits!($StructName, $PolicyType, $RawType);
714
715        // 5. Arithmetic operations
716        $crate::impl_validated_arithmetic!($StructName, $PolicyType);
717
718        // 6. Special operations
719        $crate::impl_validated_special_ops!($StructName, $PolicyType);
720
721        // 7. Sum trait
722        $crate::impl_validated_sum!($StructName, $PolicyType);
723    };
724}
725
726// Re-export all public macros for easy access
727// These macros are exported with #[macro_export] and available to users,
728// but the re-export here provides a consistent access pattern.
729#[allow(unused_imports)]
730pub use {
731    define_validated_struct_modular, define_validated_struct_type, impl_validated_arithmetic,
732    impl_validated_constructors, impl_validated_core_traits, impl_validated_numeric_traits,
733    impl_validated_special_ops, impl_validated_sum,
734};
735
736/// Creates a validated real number from an f64 literal.
737///
738/// This macro provides a concise syntax for creating [`RealNative64StrictFinite`](crate::RealNative64StrictFinite)
739/// values from floating-point literals. It uses the panicking [`from_f64`](crate::RealScalar::from_f64)
740/// constructor, which is appropriate for compile-time constants and test code where
741/// validity is guaranteed.
742///
743/// # Panics
744///
745/// Panics if the provided value is not finite (NaN, infinity) or is subnormal.
746/// For fallible conversion, use [`RealScalar::try_from_f64`](crate::RealScalar::try_from_f64) directly.
747///
748/// # Examples
749///
750/// ```
751/// use num_valid::real;
752/// use std::f64::consts::PI;
753///
754/// let x = real!(3.14159);
755/// let y = real!(PI);
756/// let z = real!(-42.0);
757///
758/// assert!((x.as_ref() - 3.14159).abs() < 1e-10);
759/// ```
760///
761/// Using with mathematical constants:
762///
763/// ```
764/// use num_valid::real;
765/// use std::f64::consts::{PI, E, TAU};
766///
767/// let pi = real!(PI);
768/// let e = real!(E);
769/// let tau = real!(TAU);
770///
771/// let circle_area = real!(PI) * real!(25.0); // π * r² with r=5
772/// ```
773#[macro_export]
774macro_rules! real {
775    ($value:expr) => {{
776        use $crate::RealScalar;
777        $crate::backends::native64::validated::RealNative64StrictFinite::from_f64($value)
778    }};
779}
780
781/// Creates a validated complex number from two f64 literals (real and imaginary parts).
782///
783/// This macro provides a concise syntax for creating [`ComplexNative64StrictFinite`](crate::ComplexNative64StrictFinite)
784/// values. It accepts two arguments: the real part and the imaginary part.
785///
786/// # Panics
787///
788/// Panics if either the real or imaginary part is not finite (NaN, infinity) or is subnormal.
789/// For fallible conversion, use [`ComplexNative64StrictFinite::try_new_complex`](crate::functions::ComplexScalarConstructors::try_new_complex) directly.
790///
791/// # Examples
792///
793/// ```
794/// use num_valid::complex;
795///
796/// let z1 = complex!(1.0, 2.0);   // 1 + 2i
797/// let z2 = complex!(-3.0, 4.0);  // -3 + 4i
798/// let z3 = complex!(0.0, -1.0);  // -i
799///
800/// // Euler's identity: e^(iπ) + 1 = 0
801/// use std::f64::consts::PI;
802/// use num_valid::functions::{Exp, Abs};
803///
804/// let i_pi = complex!(0.0, PI);
805/// let e_to_i_pi = i_pi.exp();
806/// let result = e_to_i_pi + complex!(1.0, 0.0);
807///
808/// assert!(result.abs().as_ref() < &1e-10); // Very close to zero
809/// ```
810///
811/// Creating unit vectors in the complex plane:
812///
813/// ```
814/// use num_valid::complex;
815///
816/// let unit_real = complex!(1.0, 0.0);      // Real axis
817/// let unit_imag = complex!(0.0, 1.0);      // Imaginary axis
818/// let unit_45deg = complex!(0.707, 0.707); // 45° angle
819/// ```
820#[macro_export]
821macro_rules! complex {
822    ($re:expr, $im:expr) => {{
823        use $crate::functions::ComplexScalarConstructors;
824        $crate::backends::native64::validated::ComplexNative64StrictFinite::new_complex(
825            $crate::real!($re),
826            $crate::real!($im),
827        )
828    }};
829}
830
831#[cfg(test)]
832mod tests {
833    use crate::functions::ComplexScalarGetParts;
834
835    #[test]
836    fn test_real_macro_basic() {
837        let x = real!(3.);
838        assert!((x.as_ref() - 3.).abs() < 1e-10);
839    }
840
841    #[test]
842    fn test_real_macro_constants() {
843        use std::f64::consts::PI;
844        let pi = real!(PI);
845        assert!((pi.as_ref() - PI).abs() < 1e-15);
846    }
847
848    #[test]
849    fn test_real_macro_negative() {
850        let x = real!(-42.5);
851        assert_eq!(*x.as_ref(), -42.5);
852    }
853
854    #[test]
855    fn test_complex_macro_basic() {
856        let z = complex!(1.0, 2.0);
857        assert_eq!(*z.real_part().as_ref(), 1.0);
858        assert_eq!(*z.imag_part().as_ref(), 2.0);
859    }
860
861    #[test]
862    fn test_complex_macro_zero_imaginary() {
863        let z = complex!(5.0, 0.0);
864        assert_eq!(*z.real_part().as_ref(), 5.0);
865        assert_eq!(*z.imag_part().as_ref(), 0.0);
866    }
867
868    #[test]
869    fn test_complex_macro_negative() {
870        let z = complex!(-3.0, -4.0);
871        assert_eq!(*z.real_part().as_ref(), -3.0);
872        assert_eq!(*z.imag_part().as_ref(), -4.0);
873    }
874
875    #[test]
876    #[should_panic(expected = "RealScalar::from_f64() failed")]
877    fn test_real_macro_nan() {
878        let _x = real!(f64::NAN);
879    }
880
881    #[test]
882    #[should_panic(expected = "RealScalar::from_f64() failed")]
883    fn test_real_macro_inf() {
884        let _x = real!(f64::INFINITY);
885    }
886
887    #[test]
888    #[should_panic(expected = "RealScalar::from_f64() failed")]
889    fn test_complex_macro_nan_real() {
890        let _z = complex!(f64::NAN, 1.0);
891    }
892
893    #[test]
894    #[should_panic(expected = "RealScalar::from_f64() failed")]
895    fn test_complex_macro_inf_imaginary() {
896        let _z = complex!(1.0, f64::INFINITY);
897    }
898}