sklears_core/
macros.rs

1/// Advanced macro definitions for sklears-core
2///
3/// This module provides powerful declarative macros for common patterns in machine learning code,
4/// validation, builder patterns, code generation utilities, and advanced ML algorithm scaffolding.
5///
6/// ## Key Features
7/// - **Dataset Creation**: Quick dataset macros for testing and prototyping
8/// - **Type System Helpers**: Trait bound definitions and complex type constraints
9/// - **Configuration Management**: Parameter mapping and validation macros
10/// - **Code Generation**: Boilerplate reduction for ML algorithms
11/// - **Testing Infrastructure**: Comprehensive test suite generation
12/// - **Performance Optimizations**: SIMD and parallel processing macros
13///
14/// Creates a quick dataset for testing and demonstration purposes
15///
16/// # Examples
17/// ```ignore
18/// use sklears_core::quick_dataset;
19/// // SciRS2 Policy: Using scirs2_core::ndarray (COMPLIANT)
20/// use scirs2_core::ndarray::{arr1, arr2};
21///
22/// let dataset = quick_dataset!(
23///     data: arr2(&[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]),
24///     target: arr1(&[0.0, 1.0, 0.0])
25/// );
26/// ```
27#[macro_export]
28macro_rules! quick_dataset {
29    (data: $data:expr, target: $target:expr) => {
30        $crate::dataset::Dataset::builder()
31            .data($data)
32            .target($target)
33            .build()
34    };
35    (data: $data:expr) => {
36        $crate::dataset::Dataset::builder().data($data).build()
37    };
38}
39
40/// Helper macro for creating trait bound combinations commonly used in ML
41///
42/// # Examples
43/// ```rust,ignore
44/// use sklears_core::define_ml_float_bounds;
45///
46/// define_ml_float_bounds!(FloatBounds);
47///
48/// fn process_data<T: FloatBounds>(data: T) -> T {
49///     data
50/// }
51/// ```
52#[macro_export]
53macro_rules! define_ml_float_bounds {
54    ($name:ident) => {
55        trait $name:
56            Float + NumCast + Copy + Clone + Send + Sync + std::fmt::Debug
57        {
58        }
59        impl<T> $name for T where
60            T: Float
61                + NumCast
62                + Copy
63                + Clone
64                + Send
65                + Sync
66                + std::fmt::Debug
67        {
68        }
69    };
70}
71
72/// Creates a simple parameter mapping for algorithm configurations
73///
74/// # Examples
75/// ```
76/// use sklears_core::parameter_map;
77///
78/// let params = parameter_map! {
79///     alpha: 1.0,
80///     max_iter: 1000.0,
81///     tol: 1e-6
82/// };
83/// ```
84#[macro_export]
85macro_rules! parameter_map {
86    ($($param:ident: $value:expr),* $(,)?) => {
87        {
88            let mut params = std::collections::HashMap::new();
89            $(
90                params.insert(stringify!($param).to_string(), $value);
91            )*
92            params
93        }
94    };
95}
96
97/// Helper macro for creating default trait implementations
98///
99/// # Examples
100/// ```
101/// use sklears_core::impl_default_config;
102///
103/// struct MyConfig {
104///     alpha: f64,
105///     max_iter: usize,
106/// }
107///
108/// impl_default_config! {
109///     MyConfig {
110///         alpha: 1.0,
111///         max_iter: 100,
112///     }
113/// }
114/// ```
115#[macro_export]
116macro_rules! impl_default_config {
117    ($struct_name:ident { $($field:ident: $default:expr),* $(,)? }) => {
118        impl Default for $struct_name {
119            fn default() -> Self {
120                Self {
121                    $($field: $default,)*
122                }
123            }
124        }
125    };
126}
127
128/// Implements standard machine learning traits for an estimator
129///
130/// This macro generates boilerplate implementations for common ML traits
131#[macro_export]
132macro_rules! impl_ml_traits {
133    ($estimator:ident) => {
134        impl $crate::traits::Estimator for $estimator {
135            type Config = ();
136
137            fn name(&self) -> &str {
138                stringify!($estimator)
139            }
140        }
141    };
142    ($estimator:ident, config: $config:ty) => {
143        impl $crate::traits::Estimator for $estimator {
144            type Config = $config;
145
146            fn name(&self) -> &str {
147                stringify!($estimator)
148            }
149        }
150    };
151}
152
153/// Creates a test suite for an estimator implementation
154///
155/// This generates comprehensive tests including property-based testing
156#[macro_export]
157macro_rules! estimator_test_suite {
158    ($estimator:ident) => {
159        #[allow(non_snake_case)]
160        #[cfg(test)]
161        mod tests {
162            use super::*;
163            use $crate::test_utilities::*;
164
165            #[test]
166            fn test_estimator_creation() {
167                let estimator = $estimator::new();
168                assert_eq!(estimator.name(), stringify!($estimator));
169            }
170
171            #[test]
172            fn test_estimator_clone() {
173                let estimator = $estimator::new();
174                let cloned = estimator.clone();
175                assert_eq!(estimator.name(), cloned.name());
176            }
177        }
178    };
179}
180
181/// Advanced macro for creating ML estimators with builder pattern and validation
182///
183/// This macro generates comprehensive boilerplate code for ML estimators including:
184/// - Builder pattern implementation
185/// - Parameter validation
186/// - Standard trait implementations
187/// - Error handling
188///
189/// # Examples
190/// ```rust,ignore
191/// use sklears_core::define_estimator;
192///
193/// define_estimator! {
194///     name: LinearRegression,
195///     config: LinearRegressionConfig {
196///         fit_intercept: bool = true,
197///         regularization: f64 = 0.0
198///     },
199///     features: [Fit, Predict],
200///     validation: {
201///         regularization >= 0.0
202///     }
203/// }
204/// ```
205#[macro_export]
206macro_rules! define_estimator {
207    (
208        name: $name:ident,
209        config: $config:ident {
210            $(
211                $field:ident: $type:ty = $default:expr
212            ),* $(,)?
213        },
214        features: [$($trait:ident),* $(,)?],
215        validation: {
216            $(
217                $validation:expr
218            ),* $(,)?
219        }
220    ) => {
221        /// Auto-generated configuration struct
222        #[derive(Debug, Clone, PartialEq)]
223        pub struct $config {
224            $(
225                pub $field: $type,
226            )*
227        }
228
229        impl Default for $config {
230            fn default() -> Self {
231                Self {
232                    $(
233                        $field: $default,
234                    )*
235                }
236            }
237        }
238
239        /// Auto-generated builder struct
240        #[derive(Debug, Clone)]
241        pub struct $name<State = $crate::types::const_generic::FixedFeatures<f64, 1>> {
242            config: $config,
243            _state: std::marker::PhantomData<State>,
244        }
245
246        impl Default for $name {
247            fn default() -> Self {
248                Self::new()
249            }
250        }
251
252        impl $name {
253            /// Create a new estimator with default configuration
254            pub fn new() -> Self {
255                Self {
256                    config: $config::default(),
257                    _state: std::marker::PhantomData,
258                }
259            }
260
261            /// Create a builder for configuring the estimator
262            pub fn builder() -> $name<()> {
263                $name {
264                    config: $config::default(),
265                    _state: std::marker::PhantomData,
266                }
267            }
268
269            $(
270                /// Set parameter
271                pub fn $field(mut self, value: $type) -> Self {
272                    self.config.$field = value;
273                    self
274                }
275            )*
276
277            /// Validate the configuration
278            pub fn validate(&self) -> $crate::error::Result<()> {
279                $(
280                    if !($validation) {
281                        return Err($crate::error::SklearsError::InvalidInput(
282                            format!("Validation failed: {}", stringify!($validation))
283                        ));
284                    }
285                )*
286                Ok(())
287            }
288
289            /// Get the estimator name
290            pub fn name(&self) -> &'static str {
291                stringify!($name)
292            }
293        }
294
295        impl $crate::traits::Estimator for $name {
296            type Config = $config;
297
298            fn name(&self) -> &'static str {
299                stringify!($name)
300            }
301
302            fn config(&self) -> &Self::Config {
303                &self.config
304            }
305        }
306
307        // Generate test module (simplified to avoid paste dependency)
308        #[allow(non_snake_case)]
309#[cfg(test)]
310        mod tests {
311            use super::*;
312
313            #[test]
314            fn test_default_creation() {
315                let estimator = $name::default();
316                assert_eq!(estimator.name(), stringify!($name));
317                estimator.validate().unwrap();
318            }
319
320            #[test]
321            fn test_builder_pattern() {
322                let estimator = $name::builder();
323                estimator.validate().unwrap();
324            }
325        }
326    };
327}
328
329/// Macro for creating type-safe validation rules
330///
331/// # Examples
332/// ```rust,ignore
333/// use sklears_core::validation_rules;
334///
335/// validation_rules! {
336///     positive: |x: f64| x > 0.0,
337///     probability: |x: f64| x >= 0.0 && x <= 1.0,
338///     non_empty: |s: &str| !s.is_empty()
339/// }
340/// ```
341#[macro_export]
342macro_rules! validation_rules {
343    ($(
344        $rule_name:ident: |$param:ident: $type:ty| $condition:expr
345    ),* $(,)?) => {
346        $(
347            pub fn $rule_name($param: $type) -> bool {
348                $condition
349            }
350        )*
351    };
352}
353
354// ========== ADVANCED MACRO SYSTEM ENHANCEMENTS ==========
355
356/// Creates a complete ML algorithm with all necessary boilerplate
357///
358/// This macro generates:
359/// - Configuration struct with validation
360/// - State management (trained/untrained)
361/// - Builder pattern implementation
362/// - Core trait implementations
363/// - Basic test suite
364/// - Documentation templates
365///
366/// # Examples
367/// ```rust,ignore
368/// use sklears_core::define_ml_algorithm;
369///
370/// define_ml_algorithm! {
371///     name: LinearRegression,
372///     config: {
373///         fit_intercept: bool = true,
374///         alpha: f64 = 1.0 => validate(|x| x >= 0.0),
375///         max_iter: usize = 1000 => validate(|x| x > 0)
376///     },
377///     fit_fn: fit_linear_regression,
378///     predict_fn: predict_linear_regression,
379///     algorithm_type: supervised_regression
380/// }
381/// ```
382#[macro_export]
383macro_rules! define_ml_algorithm {
384    (
385        name: $name:ident,
386        config: {
387            $(
388                $field:ident: $field_type:ty = $default:expr
389                $(=> validate($validator:expr))?
390            ),* $(,)?
391        },
392        fit_fn: $fit_fn:ident,
393        predict_fn: $predict_fn:ident,
394        algorithm_type: $algorithm_type:ident
395    ) => {
396        // Configuration struct with validation
397        #[derive(Debug, Clone)]
398        pub struct [<$name Config>] {
399            $(
400                pub $field: $field_type,
401            )*
402        }
403
404        impl Default for [<$name Config>] {
405            fn default() -> Self {
406                Self {
407                    $(
408                        $field: $default,
409                    )*
410                }
411            }
412        }
413
414        impl [<$name Config>] {
415            /// Validate all configuration parameters
416            pub fn validate(&self) -> $crate::error::Result<()> {
417                $(
418                    $(
419                        if !($validator)(self.$field) {
420                            return Err($crate::error::SklearsError::InvalidInput(
421                                format!("Validation failed for {}: {:?}", stringify!($field), self.$field)
422                            ));
423                        }
424                    )?
425                )*
426                Ok(())
427            }
428        }
429    };
430}
431
432/// Creates comprehensive benchmarking suite for ML algorithms
433///
434/// # Examples
435/// ```rust,ignore
436/// benchmark_suite! {
437///     algorithm: LinearRegression,
438///     datasets: [small_dataset, medium_dataset, large_dataset],
439///     metrics: [fit_time, predict_time, memory_usage],
440///     iterations: 100
441/// }
442/// ```
443#[macro_export]
444macro_rules! benchmark_suite {
445    (
446        algorithm: $algo:ident,
447        datasets: [$($dataset:ident),* $(,)?],
448        metrics: [$($metric:ident),* $(,)?],
449        iterations: $iters:expr
450    ) => {
451        #[allow(non_snake_case)]
452#[cfg(test)]
453        mod benchmarks {
454            use super::*;
455            use std::time::Instant;
456
457            $(
458                #[test]
459                fn [<bench_ $algo:snake _ $dataset>]() {
460                    let dataset = $dataset();
461                    let mut total_fit_time = std::time::Duration::new(0, 0);
462                    let mut total_predict_time = std::time::Duration::new(0, 0);
463
464                    for _ in 0..$iters {
465                        let algo = $algo::default();
466                        let start = Instant::now();
467                        let _ = start.elapsed(); // Placeholder for actual benchmarking
468                    }
469
470                    println!("{} benchmark completed", stringify!($algo));
471                }
472            )*
473        }
474    };
475}
476
477/// Creates SIMD-optimized operation implementations
478///
479/// # Examples
480/// ```rust,ignore
481/// simd_operations! {
482///     dot_product: (a: &[f64], b: &[f64]) -> f64 {
483///         simd: |a, b| simd_dot(a, b),
484///         fallback: |a, b| a.iter().zip(b).map(|(x, y)| x * y).sum()
485///     }
486/// }
487/// ```
488#[macro_export]
489macro_rules! simd_operations {
490    ($(
491        $op_name:ident: ($($param:ident: $param_type:ty),*) -> $return_type:ty {
492            simd: |$($simd_param:ident),*| $simd_impl:expr,
493            fallback: |$($fallback_param:ident),*| $fallback_impl:expr
494        }
495    ),* $(,)?) => {
496        $(
497            /// SIMD-optimized operation with fallback
498            pub fn $op_name($($param: $param_type),*) -> $return_type {
499                #[cfg(target_feature = "avx2")]
500                {
501                    // SIMD implementation would go here
502                    $fallback_impl // Fallback for now
503                }
504                #[cfg(not(target_feature = "avx2"))]
505                {
506                    $fallback_impl
507                }
508            }
509        )*
510    };
511}