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}