num_absurd/
lib.rs

1use std::ops::{Add, Sub, Mul, Div, Neg};
2use std::fmt::{Display, Debug, Formatter, Result as FmtResult};
3use num_complex::Complex;
4use num_traits::{Zero, One, Float};
5
6/// Macro for creating complex numbers with real and imaginary parts
7///
8/// # Examples
9///
10/// ```rust
11/// # use num_absurd::co;
12/// let c1 = co!(1.0, 2.0);    // 1 + 2i
13/// let c2 = co!(3.0);         // 3 + 0i (real number)
14/// ```
15#[macro_export]
16macro_rules! co {
17    ($re:expr, $im:expr) => {
18        Complex::new($re, $im)
19    };
20    ($re:expr) => {
21        Complex::new($re, <_ as num_traits::Zero>::zero())
22    };
23}
24
25/// Macro for creating absurd numbers with complex and absurd parts
26///
27/// # Examples
28///
29/// ```rust
30/// # use num_absurd::{ab, co};
31/// let a1 = ab!(co!(1.0, 0.0), co!(2.0, 0.0));  // 1 + 2z
32/// let a2 = ab!(co!(0.0, 1.0), co!(1.0, 0.0));  // i + z
33/// let a3 = ab_real!(1.0, 2.0);                  // 1 + 2z (shorthand for reals)
34/// ```
35#[macro_export]
36macro_rules! ab {
37    // Match when both arguments are complex numbers (contain co! or Complex::new)
38    ($co:expr, $ab:expr) => {
39        Absurd::new($co, $ab)
40    };
41}
42
43/// Macro for creating absurd numbers from real number components
44///
45/// # Examples
46///
47/// ```rust
48/// # use num_absurd::ab_real;
49/// let a = ab_real!(1.0, 2.0);  // 1 + 2z (both parts are real)
50/// ```
51#[macro_export]
52macro_rules! ab_real {
53    ($co_re:expr, $ab_re:expr) => {
54        Absurd::new(co!($co_re), co!($ab_re))
55    };
56}
57
58/// An Absurd Number representing `a + bz` where `a, b` are complex numbers
59/// and `z = 1/0` is the absurd unit.
60///
61/// # Type Parameters
62///
63/// * `T` - The underlying numeric type (must implement `Float + Clone + Debug`)
64///
65/// # Mathematical Foundation
66///
67/// Absurd numbers extend complex numbers by introducing the absurd unit `z = 1/0`.
68/// This allows division by zero to be defined consistently within the algebraic structure.
69///
70/// ## Representation
71///
72/// An absurd number has the form: `(a + bi) + (c + di)z`
73/// where:
74/// - `a, b, c, d ∈ ℝ` (real numbers)
75/// - `i` is the imaginary unit (`i² = -1`)
76/// - `z` is the absurd unit (`z = 1/0`)
77///
78/// # Examples
79///
80/// ```rust
81/// use num_absurd::*;
82///
83/// // Create absurd numbers
84/// let a1: Absurd<f64> = ab!(co!(1.0, 2.0), co!(3.0, 0.0));  // (1+2i) + 3z
85/// let a2: Absurd<f32> = ab!(2.0, 1.0);                       // 2 + z
86///
87/// // Arithmetic operations
88/// let sum = a1 + a1;
89/// let difference = a1 - a2;
90/// ```
91#[derive(Debug, Clone, PartialEq)]
92pub struct Absurd<T>
93where
94    T: Float + Clone + Debug,
95{
96    /// The complex part (coefficient of 1)
97    pub complex: Complex<T>,
98    /// The absurd part (coefficient of z)
99    pub absurd: Complex<T>,
100}
101
102impl<T> Absurd<T>
103where
104    T: Float + Clone + Debug,
105{
106    /// Create a new absurd number from complex and absurd parts
107    ///
108    /// # Arguments
109    ///
110    /// * `complex` - The complex coefficient (coefficient of 1)
111    /// * `absurd` - The absurd coefficient (coefficient of z)
112    ///
113    /// # Examples
114    ///
115    /// ```rust
116    /// use num_absurd::*;
117    ///
118    /// let a = Absurd::new(co!(1.0, 2.0), co!(3.0, 0.0));  // (1+2i) + 3z
119    /// ```
120    pub fn new(complex: Complex<T>, absurd: Complex<T>) -> Self {
121        Self { complex, absurd }
122    }
123
124    /// Create an absurd number from real parts only
125    ///
126    /// # Arguments
127    ///
128    /// * `complex_re` - Real part of complex coefficient
129    /// * `absurd_re` - Real part of absurd coefficient
130    ///
131    /// # Examples
132    ///
133    /// ```rust
134    /// use num_absurd::*;
135    ///
136    /// let a = Absurd::from_reals(1.0, 2.0);  // 1 + 2z
137    /// // Or use the macro: ab_real!(1.0, 2.0)
138    /// ```
139    pub fn from_reals(complex_re: T, absurd_re: T) -> Self {
140        Self {
141            complex: Complex::new(complex_re, T::zero()),
142            absurd: Complex::new(absurd_re, T::zero()),
143        }
144    }
145
146    /// Create a pure complex absurd number (absurd part is zero)
147    ///
148    /// # Arguments
149    ///
150    /// * `complex` - The complex number
151    ///
152    /// # Examples
153    ///
154    /// ```rust
155    /// use num_absurd::*;
156    ///
157    /// let a = Absurd::from_complex(co!(1.0, 2.0));  // (1+2i) + 0z
158    /// ```
159    pub fn from_complex(complex: Complex<T>) -> Self {
160        Self {
161            complex,
162            absurd: Complex::zero(),
163        }
164    }
165
166    /// Create a pure absurd number (complex part is zero)
167    ///
168    /// # Arguments
169    ///
170    /// * `absurd` - The absurd coefficient
171    ///
172    /// # Examples
173    ///
174    /// ```rust
175    /// use num_absurd::*;
176    ///
177    /// let a = Absurd::from_absurd(co!(1.0, 2.0));  // 0 + (1+2i)z
178    /// ```
179    pub fn from_absurd(absurd: Complex<T>) -> Self {
180        Self {
181            complex: Complex::zero(),
182            absurd,
183        }
184    }
185
186    /// Get the absurd unit `z = 1/0`
187    ///
188    /// # Examples
189    ///
190    /// ```rust
191    /// use num_absurd::*;
192    ///
193    /// let z: Absurd<f64> = Absurd::z();  // 0 + 1z
194    /// ```
195    pub fn z() -> Self {
196        Self {
197            complex: Complex::zero(),
198            absurd: Complex::one(),
199        }
200    }
201
202    /// Check if this is a pure complex number (absurd part is zero)
203    ///
204    /// # Examples
205    ///
206    /// ```rust
207    /// use num_absurd::*;
208    ///
209    /// let a1 = ab!(co!(1.0, 2.0), co!(0.0, 0.0));
210    /// let a2 = ab!(co!(1.0, 2.0), co!(1.0, 0.0));
211    ///
212    /// assert!(a1.is_complex());
213    /// assert!(!a2.is_complex());
214    /// ```
215    pub fn is_complex(&self) -> bool {
216        self.absurd.is_zero()
217    }
218
219    /// Check if this is a pure absurd number (complex part is zero)
220    ///
221    /// # Examples
222    ///
223    /// ```rust
224    /// use num_absurd::*;
225    ///
226    /// let a1 = ab!(co!(0.0, 0.0), co!(1.0, 2.0));
227    /// let a2 = ab!(co!(1.0, 0.0), co!(1.0, 2.0));
228    ///
229    /// assert!(a1.is_pure_absurd());
230    /// assert!(!a2.is_pure_absurd());
231    /// ```
232    pub fn is_pure_absurd(&self) -> bool {
233        self.complex.is_zero()
234    }
235
236    /// Attempt to convert to a complex number if absurd part is zero
237    ///
238    /// # Returns
239    ///
240    /// `Some(complex)` if absurd part is zero, `None` otherwise
241    ///
242    /// # Examples
243    ///
244    /// ```rust
245    /// use num_absurd::*;
246    ///
247    /// let a1 = ab!(co!(1.0, 2.0), co!(0.0, 0.0));
248    /// let a2 = ab!(co!(1.0, 2.0), co!(1.0, 0.0));
249    ///
250    /// assert!(a1.to_complex().is_some());
251    /// assert!(a2.to_complex().is_none());
252    /// ```
253    pub fn to_complex(&self) -> Option<Complex<T>> {
254        if self.is_complex() {
255            Some(self.complex)
256        } else {
257            None
258        }
259    }
260
261    /// Multiply by the absurd unit (equivalent to dividing by zero)
262    ///
263    /// For any absurd number `a + bz`, multiplying by `z` gives:
264    /// `(a + bz) * z = az + b`
265    ///
266    /// This effectively "shifts" the complex part to the absurd part
267    /// and reduces the absurd part by one power of z.
268    ///
269    /// # Examples
270    ///
271    /// ```rust
272    /// use num_absurd::*;
273    ///
274    /// let a = ab!(co!(1.0, 2.0), co!(3.0, 0.0));  // (1+2i) + 3z
275    /// let result = a.multiply_by_z();              // (1+2i)z + 3
276    /// ```
277    pub fn multiply_by_z(&self) -> Self {
278        Self {
279            complex: self.absurd,
280            absurd: self.complex,
281        }
282    }
283
284    /// Divide by zero (equivalent to multiplying by the absurd unit)
285    ///
286    /// This is an alias for `multiply_by_z()` that makes the operation
287    /// more explicit in terms of division by zero.
288    ///
289    /// # Examples
290    ///
291    /// ```rust
292    /// use num_absurd::*;
293    ///
294    /// let a = ab!(co!(2.0, 0.0), co!(0.0, 0.0));  // 2 + 0z
295    /// let result = a.divide_by_zero();             // 0 + 2z (which is 2z)
296    /// ```
297    pub fn divide_by_zero(&self) -> Self {
298        self.multiply_by_z()
299    }
300
301    /// Get the complex conjugate of the absurd number
302    ///
303    /// For an absurd number `(a + bi) + (c + di)z`, the complex conjugate is:
304    /// `(a - bi) + (c - di)z`
305    ///
306    /// # Examples
307    ///
308    /// ```rust
309    /// use num_absurd::*;
310    ///
311    /// let a = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
312    /// let conj = a.complex_conjugate();
313    /// // conj = (1-2i) + (3-4i)z
314    /// ```
315    pub fn complex_conjugate(&self) -> Self {
316        Self {
317            complex: self.complex.conj(),
318            absurd: self.absurd.conj(),
319        }
320    }
321
322    /// Get the absurd conjugate of the absurd number
323    ///
324    /// For an absurd number `a + bz`, the absurd conjugate is: `a - bz`
325    ///
326    /// # Examples
327    ///
328    /// ```rust
329    /// use num_absurd::*;
330    ///
331    /// let a = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
332    /// let conj = a.absurd_conjugate();
333    /// // conj = (1+2i) - (3+4i)z
334    /// ```
335    pub fn absurd_conjugate(&self) -> Self {
336        Self {
337            complex: self.complex,
338            absurd: -self.absurd,
339        }
340    }
341
342    /// Calculate the norm squared of the absurd number
343    ///
344    /// For `a + bz`, this returns `|a|² + |b|²`
345    ///
346    /// # Examples
347    ///
348    /// ```rust
349    /// use num_absurd::*;
350    ///
351    /// let a = ab!(co!(3.0, 4.0), co!(1.0, 2.0));
352    /// let norm_sq = a.norm_squared();
353    /// // |3+4i|² + |1+2i|² = 25 + 5 = 30
354    /// ```
355    pub fn norm_squared(&self) -> T {
356        self.complex.norm_sqr() + self.absurd.norm_sqr()
357    }
358
359    /// Calculate the norm of the absurd number
360    ///
361    /// For `a + bz`, this returns `√(|a|² + |b|²)`
362    ///
363    /// # Examples
364    ///
365    /// ```rust
366    /// use num_absurd::*;
367    ///
368    /// let a = ab!(co!(3.0, 4.0), co!(0.0, 0.0));
369    /// let norm = a.norm();
370    /// // √(|3+4i|²) = √25 = 5
371    /// ```
372    pub fn norm(&self) -> T {
373        self.norm_squared().sqrt()
374    }
375}
376
377// Implement Zero trait
378impl<T> Zero for Absurd<T>
379where
380    T: Float + Clone + Debug,
381{
382    fn zero() -> Self {
383        Self {
384            complex: Complex::zero(),
385            absurd: Complex::zero(),
386        }
387    }
388
389    fn is_zero(&self) -> bool {
390        self.complex.is_zero() && self.absurd.is_zero()
391    }
392}
393
394// Implement One trait
395impl<T> One for Absurd<T>
396where
397    T: Float + Clone + Debug,
398{
399    fn one() -> Self {
400        Self {
401            complex: Complex::one(),
402            absurd: Complex::zero(),
403        }
404    }
405}
406
407// Addition: (a₁ + b₁z) + (a₂ + b₂z) = (a₁ + a₂) + (b₁ + b₂)z
408impl<T> Add for Absurd<T>
409where
410    T: Float + Clone + Debug,
411{
412    type Output = Self;
413
414    fn add(self, rhs: Self) -> Self::Output {
415        Self {
416            complex: self.complex + rhs.complex,
417            absurd: self.absurd + rhs.absurd,
418        }
419    }
420}
421
422// Subtraction: (a₁ + b₁z) - (a₂ + b₂z) = (a₁ - a₂) + (b₁ - b₂)z
423impl<T> Sub for Absurd<T>
424where
425    T: Float + Clone + Debug,
426{
427    type Output = Self;
428
429    fn sub(self, rhs: Self) -> Self::Output {
430        Self {
431            complex: self.complex - rhs.complex,
432            absurd: self.absurd - rhs.absurd,
433        }
434    }
435}
436
437// Negation: -(a + bz) = -a + (-b)z
438impl<T> Neg for Absurd<T>
439where
440    T: Float + Clone + Debug,
441{
442    type Output = Self;
443
444    fn neg(self) -> Self::Output {
445        Self {
446            complex: -self.complex,
447            absurd: -self.absurd,
448        }
449    }
450}
451
452// Multiplication: (a₁ + b₁z)(a₂ + b₂z) = a₁a₂ + (a₁b₂ + a₂b₁)z + b₁b₂z²
453// Since z² behavior follows polynomial ring rules, we need special handling
454impl<T> Mul for Absurd<T>
455where
456    T: Float + Clone + Debug,
457{
458    type Output = Self;
459
460    fn mul(self, rhs: Self) -> Self::Output {
461        // For now, implement basic multiplication
462        // More complex z² handling can be added later
463        let complex_part = self.complex * rhs.complex;
464        let absurd_part = self.complex * rhs.absurd + self.absurd * rhs.complex;
465        
466        Self {
467            complex: complex_part,
468            absurd: absurd_part,
469        }
470    }
471}
472
473// Scalar multiplication
474impl<T> Mul<T> for Absurd<T>
475where
476    T: Float + Clone + Debug,
477{
478    type Output = Self;
479
480    fn mul(self, rhs: T) -> Self::Output {
481        Self {
482            complex: self.complex * rhs,
483            absurd: self.absurd * rhs,
484        }
485    }
486}
487
488// Division implementation
489impl<T> Div for Absurd<T>
490where
491    T: Float + Clone + Debug,
492{
493    type Output = Self;
494
495    fn div(self, rhs: Self) -> Self::Output {
496        if rhs.is_zero() {
497            // Division by zero: multiply by z
498            self.multiply_by_z()
499        } else {
500            // Standard division for non-zero denominators
501            // This is a simplified implementation
502            let norm_sq = rhs.norm_squared();
503            let conj = rhs.complex_conjugate();
504            let numerator = self * conj;
505            
506            Self {
507                complex: numerator.complex / norm_sq,
508                absurd: numerator.absurd / norm_sq,
509            }
510        }
511    }
512}
513
514// Display implementation
515impl<T> Display for Absurd<T>
516where
517    T: Float + Clone + Debug + Display,
518{
519    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
520        let complex_zero = Complex::zero();
521        let absurd_zero = Complex::zero();
522
523        if self.complex == complex_zero && self.absurd == absurd_zero {
524            write!(f, "0")
525        } else if self.absurd == absurd_zero {
526            write!(f, "{}", self.complex)
527        } else if self.complex == complex_zero {
528            if self.absurd == Complex::one() {
529                write!(f, "z")
530            } else {
531                write!(f, "{}z", self.absurd)
532            }
533        } else {
534            if self.absurd == Complex::one() {
535                write!(f, "{} + z", self.complex)
536            } else {
537                write!(f, "{} + {}z", self.complex, self.absurd)
538            }
539        }
540    }
541}
542
543// Convenient type aliases
544/// 32-bit floating point absurd number
545pub type Absurd32 = Absurd<f32>;
546
547/// 64-bit floating point absurd number  
548pub type Absurd64 = Absurd<f64>;
549
550#[cfg(test)]
551mod tests {
552    use super::*;
553
554    #[test]
555    fn test_basic_creation() {
556        let a1 = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
557        assert_eq!(a1.complex, co!(1.0, 2.0));
558        assert_eq!(a1.absurd, co!(3.0, 4.0));
559    }
560
561    #[test]
562    fn test_addition() {
563        let a1 = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
564        let a2 = ab!(co!(5.0, 6.0), co!(7.0, 8.0));
565        let result = a1 + a2;
566        
567        assert_eq!(result.complex, co!(6.0, 8.0));
568        assert_eq!(result.absurd, co!(10.0, 12.0));
569    }
570
571    #[test]
572    fn test_multiplication() {
573        let a1 = ab!(co!(1.0, 0.0), co!(0.0, 0.0));  // 1
574        let a2 = ab!(co!(2.0, 0.0), co!(0.0, 0.0));  // 2
575        let result = a1 * a2;
576        
577        assert_eq!(result.complex, co!(2.0, 0.0));
578        assert_eq!(result.absurd, co!(0.0, 0.0));
579    }
580
581    #[test]
582    fn test_division_by_zero() {
583        let a = ab!(co!(2.0, 0.0), co!(0.0, 0.0));  // 2
584        let zero = Absurd::<f64>::zero();
585        let result = a / zero;
586        
587        // 2 / 0 should equal 2z
588        assert_eq!(result.complex, co!(0.0, 0.0));
589        assert_eq!(result.absurd, co!(2.0, 0.0));
590    }
591
592    #[test]
593    fn test_absurd_unit() {
594        let z = Absurd::<f64>::z();
595        assert_eq!(z.complex, co!(0.0, 0.0));
596        assert_eq!(z.absurd, co!(1.0, 0.0));
597    }
598
599    #[test]
600    fn test_multiply_by_z() {
601        let a = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
602        let result = a.multiply_by_z();
603        
604        // (1+2i) + (3+4i)z → (3+4i) + (1+2i)z
605        assert_eq!(result.complex, co!(3.0, 4.0));
606        assert_eq!(result.absurd, co!(1.0, 2.0));
607    }
608
609    #[test]
610    fn test_conjugates() {
611        let a = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
612        
613        let complex_conj = a.complex_conjugate();
614        assert_eq!(complex_conj.complex, co!(1.0, -2.0));
615        assert_eq!(complex_conj.absurd, co!(3.0, -4.0));
616        
617        let absurd_conj = a.absurd_conjugate();
618        assert_eq!(absurd_conj.complex, co!(1.0, 2.0));
619        assert_eq!(absurd_conj.absurd, co!(-3.0, -4.0));
620    }
621
622    #[test]
623    fn test_norm() {
624        let a = ab!(co!(3.0, 4.0), co!(0.0, 0.0));  // 3+4i
625        let norm = a.norm();
626        assert!((norm - 5.0).abs() < 1e-10);
627    }
628
629    #[test]
630    fn test_macros() {
631        let c = co!(1.0, 2.0);
632        assert_eq!(c, Complex::new(1.0, 2.0));
633        
634        let c_real = co!(3.0);
635        assert_eq!(c_real, Complex::new(3.0, 0.0));
636        
637        let a = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
638        assert_eq!(a.complex, co!(1.0, 2.0));
639        assert_eq!(a.absurd, co!(3.0, 4.0));
640        
641        let a_simple = ab_real!(1.0, 2.0);
642        assert_eq!(a_simple.complex, co!(1.0, 0.0));
643        assert_eq!(a_simple.absurd, co!(2.0, 0.0));
644    }
645
646    #[test]
647    fn test_is_predicates() {
648        let complex_only = ab!(co!(1.0, 2.0), co!(0.0, 0.0));
649        let absurd_only = ab!(co!(0.0, 0.0), co!(1.0, 2.0));
650        let mixed = ab!(co!(1.0, 2.0), co!(3.0, 4.0));
651        
652        assert!(complex_only.is_complex());
653        assert!(!complex_only.is_pure_absurd());
654        
655        assert!(!absurd_only.is_complex());
656        assert!(absurd_only.is_pure_absurd());
657        
658        assert!(!mixed.is_complex());
659        assert!(!mixed.is_pure_absurd());
660    }
661}