pub struct Octonion<F>where
F: RealField,{
pub s: F,
pub e1: F,
pub e2: F,
pub e3: F,
pub e4: F,
pub e5: F,
pub e6: F,
pub e7: F,
}Expand description
Represents an octonion number with a scalar part and seven imaginary parts.
An octonion is an 8-dimensional hypercomplex number, extending quaternions.
It consists of a scalar component s and seven imaginary components e1 through e7.
§Type Parameters
F- The floating-point type used for the components of the octonion (e.g.,f32,f64).
§Fields
s- The scalar (real) part of the octonion.e1- The coefficient of the first imaginary unit.e2- The coefficient of the second imaginary unit.e3- The coefficient of the third imaginary unit.e4- The coefficient of the fourth imaginary unit.e5- The coefficient of the fifth imaginary unit.e6- The coefficient of the sixth imaginary unit.e7- The coefficient of the seventh imaginary unit.
§Derives
Copy: Allows instances ofOctonionto be copied by bitwise copy.Clone: Implements cloning behavior forOctonion.Default: Provides a default (zero) value forOctonion.
Fields§
§s: F§e1: F§e2: F§e3: F§e4: F§e5: F§e6: F§e7: FImplementations§
Source§impl<F> Octonion<F>where
F: RealField,
impl<F> Octonion<F>where
F: RealField,
Sourcepub fn norm(&self) -> F
pub fn norm(&self) -> F
Computes the norm (magnitude) of the octonion.
The norm is the square root of the sum of the squares of all its components,
which is sqrt(norm_sqr()).
§Returns
The scalar value F representing the norm.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert_eq!(o.norm(), 5.0); // sqrt(3*3 + 4*4) = sqrt(9 + 16) = sqrt(25) = 5Sourcepub fn normalize(&self) -> Self
pub fn normalize(&self) -> Self
Returns a normalized version of the octonion (a unit octonion).
A unit octonion has a norm of 1. If the current octonion’s norm is zero,
the original octonion is returned to avoid division by zero, meaning
normalize() on a zero octonion returns a zero octonion.
§Returns
A new Octonion with a norm of 1, or self if its norm is zero.
§Examples
use deep_causality_num::{Octonion, Octonion64, Zero};
let o = Octonion64::new(3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let unit_o = o.normalize();
assert!((unit_o.norm() - 1.0).abs() < 1e-9);
assert_eq!(unit_o.s, 0.6000000000000001); // 3/5
assert_eq!(unit_o.e1, 0.8); // 4/5
let zero_o = Octonion::<f64>::zero();
assert_eq!(zero_o.normalize(), zero_o);Sourcepub fn dot(&self, other: &Self) -> F
pub fn dot(&self, other: &Self) -> F
Computes the dot product of self with another octonion other.
The dot product is the sum of the products of corresponding components:
s*other.s + e₁*other.e₁ + e₂*other.e₂ + ... + e₇*other.e₇.
§Arguments
other- A reference to anotherOctonionwith which to compute the dot product.
§Returns
The scalar value F representing the dot product.
§Examples
use deep_causality_num::Octonion;
let o1 = Octonion::new(1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let o2 = Octonion::new(3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert_eq!(o1.dot(&o2), 1.0 * 3.0 + 2.0 * 4.0); // 3 + 8 = 11Source§impl<F> Octonion<F>where
F: RealField,
impl<F> Octonion<F>where
F: RealField,
Sourcepub fn new(s: F, e1: F, e2: F, e3: F, e4: F, e5: F, e6: F, e7: F) -> Self
pub fn new(s: F, e1: F, e2: F, e3: F, e4: F, e5: F, e6: F, e7: F) -> Self
Creates a new Octonion from its eight scalar components.
§Arguments
s- The scalar (real) part.e1- The coefficient of the first imaginary unit.e2- The coefficient of the second imaginary unit.e3- The coefficient of the third imaginary unit.e4- The coefficient of the fourth imaginary unit.e5- The coefficient of the fifth imaginary unit.e6- The coefficient of the sixth imaginary unit.e7- The coefficient of the seventh imaginary unit.
§Returns
A new Octonion instance.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
assert_eq!(o.s, 1.0);
assert_eq!(o.e7, 8.0);Sourcepub fn from_real(re: F) -> Self
pub fn from_real(re: F) -> Self
Creates a new Octonion from a single real (scalar) value.
The real value populates the scalar part (s) of the octonion, and all
imaginary parts (e1 through e7) are set to zero.
§Arguments
re- The real scalar value.
§Returns
A new Octonion instance representing a real number.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::Zero;
let o = Octonion::from_real(5.0);
assert_eq!(o.s, 5.0);
assert!(o.e1.is_zero());
assert!(o.e7.is_zero());Sourcepub fn identity() -> Self
pub fn identity() -> Self
Returns the identity octonion (1 + 0e₁ + … + 0e₇).
The identity octonion has a scalar part of 1 and all imaginary parts are 0. When multiplied by any other octonion, it returns the other octonion.
§Returns
The identity Octonion instance.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::{One, Zero};
let identity: Octonion<f64> = Octonion::identity();
assert_eq!(identity.s, 1.0);
assert!(identity.e1.is_zero());
assert!(identity.e7.is_zero());
// The identity is also accessible via the One trait
assert_eq!(identity, Octonion::one());Trait Implementations§
Source§impl<F: RealField> Add for Octonion<F>
Implements the addition operator (+) for two Octonion numbers.
impl<F: RealField> Add for Octonion<F>
Implements the addition operator (+) for two Octonion numbers.
Octonion addition is performed component-wise:
(s₁ + v₁) + (s₂ + v₂) = (s₁ + s₂) + (v₁ + v₂)
§Arguments
self- The left-hand sideOctonion.rhs- The right-hand sideOctonion.
§Returns
A new Octonion representing the sum of self and rhs.
§Examples
use deep_causality_num::Octonion;
let o1 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let o2 = Octonion::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
let sum = o1 + o2;
assert_eq!(sum.s, 10.0);
assert_eq!(sum.e1, 12.0);
// ... and so on for other componentsSource§impl<F: RealField> AddAssign for Octonion<F>
Implements the addition assignment operator (+=) for two Octonion numbers.
impl<F: RealField> AddAssign for Octonion<F>
Implements the addition assignment operator (+=) for two Octonion numbers.
Each component of self is added to the corresponding component of other.
self = self + other
§Arguments
self- The left-hand sideOctonionto be modified.other- The right-hand sideOctonionto add.
§Examples
use deep_causality_num::Octonion;
let mut o1 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let o2 = Octonion::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
o1 += o2;
assert_eq!(o1.s, 10.0);
assert_eq!(o1.e1, 12.0);Source§fn add_assign(&mut self, other: Self)
fn add_assign(&mut self, other: Self)
+= operation. Read moreSource§impl<T, U> AsPrimitive<U> for Octonion<T>
impl<T, U> AsPrimitive<U> for Octonion<T>
Source§fn as_(self) -> U
fn as_(self) -> U
Converts the octonion to a primitive type U by casting its scalar part.
This method is part of the AsPrimitive trait, allowing the octonion’s
scalar component to be cast to various primitive numerical types.
§Type Parameters
U- The target primitive type.
§Returns
The scalar part of the octonion, cast to type U.
§Examples
use deep_causality_num::{Octonion, AsPrimitive};
let o = Octonion::new(10.5f64, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
let val_f32: f32 = o.as_();
assert_eq!(val_f32, 10.5f32);
let val_i32: i32 = o.as_();
assert_eq!(val_i32, 10i32);Source§impl<F: RealField + ConstOne + ConstZero> ConstOne for Octonion<F>
Implements the ConstOne trait for Octonion.
impl<F: RealField + ConstOne + ConstZero> ConstOne for Octonion<F>
Implements the ConstOne trait for Octonion.
Provides a compile-time constant for the identity octonion.
Source§impl<F: RealField + ConstZero> ConstZero for Octonion<F>
Implements the ConstZero trait for Octonion.
impl<F: RealField + ConstZero> ConstZero for Octonion<F>
Implements the ConstZero trait for Octonion.
Provides a compile-time constant for the zero octonion.
Source§impl<F: RealField + Debug> Debug for Octonion<F>
Implements the Debug trait for Octonion.
impl<F: RealField + Debug> Debug for Octonion<F>
Implements the Debug trait for Octonion.
This allows Octonion instances to be formatted using the {:?} debug formatter.
It provides a detailed, structured representation of all eight components of the octonion.
§Arguments
self- TheOctonioninstance to format.f- The formatter to write to.
§Returns
A std::fmt::Result indicating success or failure of the formatting operation.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
// This will print:
// Octonion {
// s: 1.0,
// e1: 2.0,
// e2: 3.0,
// e3: 4.0,
// e4: 5.0,
// e5: 6.0,
// e6: 7.0,
// e7: 8.0,
// }
println!("{:?}", o);Source§impl<F: RealField + Display> Display for Octonion<F>
Implements the Display trait for Octonion.
impl<F: RealField + Display> Display for Octonion<F>
Implements the Display trait for Octonion.
This allows Octonion instances to be formatted using the {} display formatter.
It provides a human-readable algebraic representation of the octonion,
e.g., 1 + 2e₁ + 3e₂ + ....
If all components are zero, it displays “0”.
§Arguments
self- TheOctonioninstance to format.f- The formatter to write to.
§Returns
A std::fmt::Result indicating success or failure of the formatting operation.
§Examples
use deep_causality_num::Octonion;
let o1 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
println!("{}", o1); // Example output: 1 + 2e₁ + 3e₂ + 4e₃ + 5e₄ + 6e₅ + 7e₆ + 8e₇
let o2 = Octonion::new(0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
println!("{}", o2); // Example output: -1e₁
let o3 = Octonion::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
println!("{}", o3); // Output: 0Source§impl<F: RealField> Div<F> for Octonion<F>
Implements scalar division for an Octonion by a scalar of type F.
impl<F: RealField> Div<F> for Octonion<F>
Implements scalar division for an Octonion by a scalar of type F.
Each component of the octonion is divided by the scalar value.
o / scalar = (s / scalar, e₁ / scalar, ..., e₇ / scalar)
§Arguments
self- TheOctonionto be divided.scalar- The scalar value of typeF.
§Returns
A new Octonion representing the quotient of self divided by scalar.
If scalar is zero, the result will have infinite or NaN components.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0);
let scalar = 2.0;
let quot = o / scalar;
assert_eq!(quot.s, 1.0);
assert_eq!(quot.e1, 2.0);
// ... and so on for other componentsSource§impl<F: RealField> Div for Octonion<F>
Implements the division operator (/) for two Octonion numbers.
impl<F: RealField> Div for Octonion<F>
Implements the division operator (/) for two Octonion numbers.
Octonion division is defined as multiplication by the inverse of the divisor:
self / other = self * other.inverse().
Due to the non-associativity of octonions, there are distinct left and right
division operations. This implementation performs right division (equivalent to
self * other⁻¹).
§Arguments
self- The dividendOctonion.other- The divisorOctonion.
§Returns
A new Octonion representing the quotient of self divided by other.
If other is a zero octonion, the result will have NaN components.
§Notes
The clippy::suspicious_arithmetic_impl lint is allowed here because the
implementation delegates to Mul and inverse(), which correctly handles
the complex nature of octonion division.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::{One, Zero};
let o1 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let o_one = Octonion::one(); // Identity octonion (1 + 0e1 + ...)
let result = o1 / o_one;
assert_eq!(result, o1);
// Division of imaginary units
let e1 = Octonion::new(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e2 = Octonion::new(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e3 = Octonion::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0);
let neg_e3 = -e3;
assert_eq!(e1 / e2, neg_e3);Source§impl<F: RealField> DivAssign<F> for Octonion<F>
Implements scalar division assignment (/=) for an Octonion by a scalar of type F.
impl<F: RealField> DivAssign<F> for Octonion<F>
Implements scalar division assignment (/=) for an Octonion by a scalar of type F.
Each component of self is divided by the scalar value.
self = self / scalar
§Arguments
self- TheOctonionto be modified.scalar- The scalar value of typeF.
§Examples
use deep_causality_num::Octonion;
let mut o = Octonion::new(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0);
let scalar = 2.0;
o /= scalar;
assert_eq!(o.s, 1.0);
assert_eq!(o.e1, 2.0);Source§fn div_assign(&mut self, scalar: F)
fn div_assign(&mut self, scalar: F)
/= operation. Read moreSource§impl<F: RealField> DivAssign for Octonion<F>
Implements the division assignment operator (/=) for an Octonion and another Octonion.
impl<F: RealField> DivAssign for Octonion<F>
Implements the division assignment operator (/=) for an Octonion and another Octonion.
self = self / other (right division)
§Arguments
self- The left-hand sideOctonionto be modified.other- The right-hand sideOctonionto divide by.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::{One, Zero};
let mut o = Octonion::one(); // 1
let e1 = Octonion::new(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let neg_e1 = -e1;
o /= e1; // o becomes 1 / e1 = -e1
assert_eq!(o, neg_e1);Source§fn div_assign(&mut self, other: Self)
fn div_assign(&mut self, other: Self)
/= operation. Read moreSource§impl<T: RealField> DivisionAlgebra<T> for Octonion<T>
Implements the DivisionAlgebra trait for Octonion.
impl<T: RealField> DivisionAlgebra<T> for Octonion<T>
Implements the DivisionAlgebra trait for Octonion.
Octonions form a non-associative division algebra over the real numbers.
This trait provides methods for conjugate, norm_sqr, and inverse,
which are fundamental to division algebras.
Source§fn conjugate(&self) -> Self
fn conjugate(&self) -> Self
Computes the conjugate of the octonion.
The conjugate of an octonion s + e₁i + ... + e₇p is s - e₁i - ... - e₇p.
The scalar part remains unchanged, while all imaginary parts are negated.
§Returns
A new octonion representing the conjugate of self.
§Examples
use deep_causality_num::{Octonion, DivisionAlgebra};
let o = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let conj_o = o.conjugate();
assert_eq!(conj_o.s, 1.0);
assert_eq!(conj_o.e1, -2.0);
assert_eq!(conj_o.e7, -8.0);Source§fn norm_sqr(&self) -> T
fn norm_sqr(&self) -> T
Computes the square of the norm (magnitude) of the octonion.
The norm squared is calculated as the sum of the squares of all its components:
s² + e₁² + e₂² + e₃² + e₄² + e₅² + e₆² + e₇².
§Returns
The scalar value F representing the squared norm.
§Examples
use deep_causality_num::{Octonion, DivisionAlgebra};
let o = Octonion::new(1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert_eq!(o.norm_sqr(), 5.0); // 1*1 + 2*2 = 5Source§fn inverse(&self) -> Self
fn inverse(&self) -> Self
Computes the inverse of the octonion.
The inverse o⁻¹ of an octonion o is defined as conjugate(o) / norm_sqr(o).
§Returns
A new Octonion representing the inverse of self. If norm_sqr() is zero,
an octonion with NaN components is returned to indicate an undefined inverse.
§Examples
use deep_causality_num::{One, Octonion, Zero, DivisionAlgebra};
let o = Octonion::new(1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // 1 + e1
let inverse_o = o.inverse();
// (1 + e1) * (0.5 - 0.5e1) = 0.5 - 0.5e1 + 0.5e1 - 0.5e1*e1 = 0.5 + 0.5 = 1
let expected_inverse = Octonion::new(0.5, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
// Use approximate equality due to floating point arithmetic
assert!((inverse_o.s - expected_inverse.s) < 1e-9);
assert!((inverse_o.e1 - expected_inverse.e1) < 1e-9);
let zero_o = Octonion::<f64>::zero();
let inv_zero = zero_o.inverse();
assert!(inv_zero.s.is_nan());Source§impl<T: RealField + FromPrimitive> FromPrimitive for Octonion<T>
Implements the FromPrimitive trait for Octonion.
impl<T: RealField + FromPrimitive> FromPrimitive for Octonion<T>
Implements the FromPrimitive trait for Octonion.
This allows conversion from various primitive integer and floating-point types
into an Octonion. The converted value populates the scalar part (s)
of the octonion, with all imaginary parts set to zero.
Each from_* method attempts to convert the given primitive value into
the underlying real field type T and then constructs an Octonion from it.
Source§fn from_isize(n: isize) -> Option<Self>
fn from_isize(n: isize) -> Option<Self>
Converts an isize value into an Octonion.
The isize value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theisizevalue to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_isize(10);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 10.0);Source§fn from_i8(n: i8) -> Option<Self>
fn from_i8(n: i8) -> Option<Self>
Converts an i8 value into an Octonion.
The i8 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thei8value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_i8(5);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 5.0);Source§fn from_i16(n: i16) -> Option<Self>
fn from_i16(n: i16) -> Option<Self>
Converts an i16 value into an Octonion.
The i16 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thei16value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_i16(100);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 100.0);Source§fn from_i32(n: i32) -> Option<Self>
fn from_i32(n: i32) -> Option<Self>
Converts an i32 value into an Octonion.
The i32 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thei32value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_i32(1000);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 1000.0);Source§fn from_i64(n: i64) -> Option<Self>
fn from_i64(n: i64) -> Option<Self>
Converts an i64 value into an Octonion.
The i64 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thei64value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_i64(100_000);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 100_000.0);Source§fn from_i128(n: i128) -> Option<Self>
fn from_i128(n: i128) -> Option<Self>
Converts an i128 value into an Octonion.
The i128 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thei128value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_i128(1_000_000_000_000);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 1_000_000_000_000.0);Source§fn from_usize(n: usize) -> Option<Self>
fn from_usize(n: usize) -> Option<Self>
Converts a usize value into an Octonion.
The usize value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theusizevalue to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_usize(123);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 123.0);Source§fn from_u8(n: u8) -> Option<Self>
fn from_u8(n: u8) -> Option<Self>
Converts a u8 value into an Octonion.
The u8 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theu8value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_u8(255);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 255.0);Source§fn from_u16(n: u16) -> Option<Self>
fn from_u16(n: u16) -> Option<Self>
Converts a u16 value into an Octonion.
The u16 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theu16value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_u16(65535);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 65535.0);Source§fn from_u32(n: u32) -> Option<Self>
fn from_u32(n: u32) -> Option<Self>
Converts a u32 value into an Octonion.
The u32 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theu32value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_u32(4_000_000_000);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 4_000_000_000.0);Source§fn from_u64(n: u64) -> Option<Self>
fn from_u64(n: u64) -> Option<Self>
Converts a u64 value into an Octonion.
The u64 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theu64value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_u64(u64::MAX);
assert!(o.is_some());
assert_eq!(o.unwrap().s, u64::MAX as f64);Source§fn from_u128(n: u128) -> Option<Self>
fn from_u128(n: u128) -> Option<Self>
Converts a u128 value into an Octonion.
The u128 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Theu128value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_u128(u128::MAX);
assert!(o.is_some());
// Note: f64 can't represent all u128 values precisely.
assert_eq!(o.unwrap().s, u128::MAX as f64);Source§fn from_f32(n: f32) -> Option<Self>
fn from_f32(n: f32) -> Option<Self>
Converts an f32 value into an Octonion.
The f32 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thef32value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f64>> = Octonion::from_f32(3.14f32);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 3.14f32 as f64);Source§fn from_f64(n: f64) -> Option<Self>
fn from_f64(n: f64) -> Option<Self>
Converts an f64 value into an Octonion.
The f64 value is used for the scalar part of the octonion, and all
imaginary parts are set to zero.
§Arguments
n- Thef64value to convert.
§Returns
An Option<Self> which is Some(Octonion) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, FromPrimitive};
let o: Option<Octonion<f32>> = Octonion::from_f64(2.718f64);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 2.718f32);Source§impl<F: RealField> Mul<F> for Octonion<F>
Implements scalar multiplication for an Octonion by a scalar of type F.
impl<F: RealField> Mul<F> for Octonion<F>
Implements scalar multiplication for an Octonion by a scalar of type F.
Each component of the octonion is multiplied by the scalar value.
o * scalar = (s * scalar, e₁ * scalar, ..., e₇ * scalar)
§Arguments
self- TheOctonionto be multiplied.scalar- The scalar value of typeF.
§Returns
A new Octonion representing the product of self and scalar.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let scalar = 2.0;
let prod = o * scalar;
assert_eq!(prod.s, 2.0);
assert_eq!(prod.e1, 4.0);
// ... and so on for other componentsSource§impl<F: RealField> Mul for Octonion<F>
Implements the multiplication operator (*) for two Octonion numbers.
impl<F: RealField> Mul for Octonion<F>
Implements the multiplication operator (*) for two Octonion numbers.
Octonion multiplication is non-commutative and non-associative, following the rules of the Cayley-Dickson construction. The product is calculated based on the Fano plane relationships between the imaginary units.
The formula for the product of two octonions (s₁, e₁, e₂, e₃, e₄, e₅, e₆, e₇)
and (s₂, f₁, f₂, f₃, f₄, f₅, f₆, f₇) is complex and involves all components.
§Arguments
self- The left-hand sideOctonion.rhs- The right-hand sideOctonion.
§Returns
A new Octonion representing the product of self and rhs.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::Zero;
let e1 = Octonion::new(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e2 = Octonion::new(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e3 = Octonion::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0);
// Example of non-commutative multiplication
assert_eq!(e1 * e2, e3);
assert_eq!(e2 * e1, -e3);
// Example of an imaginary unit squared
let neg_one = Octonion::new(-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert_eq!(e1 * e1, neg_one);Source§impl<F: RealField> MulAssign<F> for Octonion<F>
Implements scalar multiplication assignment (*=) for an Octonion by a scalar of type F.
impl<F: RealField> MulAssign<F> for Octonion<F>
Implements scalar multiplication assignment (*=) for an Octonion by a scalar of type F.
Each component of self is multiplied by the scalar value.
self = self * scalar
§Arguments
self- TheOctonionto be modified.scalar- The scalar value of typeF.
§Examples
use deep_causality_num::Octonion;
let mut o = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let scalar = 2.0;
o *= scalar;
assert_eq!(o.s, 2.0);
assert_eq!(o.e1, 4.0);Source§fn mul_assign(&mut self, scalar: F)
fn mul_assign(&mut self, scalar: F)
*= operation. Read moreSource§impl<F: RealField> MulAssign for Octonion<F>
Implements the multiplication assignment operator (*=) for an Octonion and another Octonion.
impl<F: RealField> MulAssign for Octonion<F>
Implements the multiplication assignment operator (*=) for an Octonion and another Octonion.
self = self * other
§Arguments
self- The left-hand sideOctonionto be modified.other- The right-hand sideOctonionto multiply by.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::Zero;
let mut o = Octonion::new(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // 1
let e1 = Octonion::new(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
o *= e1; // o becomes e1
assert_eq!(o, e1);Source§fn mul_assign(&mut self, other: Self)
fn mul_assign(&mut self, other: Self)
*= operation. Read moreSource§impl<F: RealField> Neg for Octonion<F>
Implements the unary negation operator (-) for Octonion numbers.
impl<F: RealField> Neg for Octonion<F>
Implements the unary negation operator (-) for Octonion numbers.
Negation is performed component-wise:
-(s + e₁i + ... + e₇p) = -s - e₁i - ... - e₇p
§Arguments
self- TheOctonionto negate.
§Returns
A new Octonion with all its components negated.
§Examples
use deep_causality_num::Octonion;
let o = Octonion::new(1.0, -2.0, 3.0, -4.0, 5.0, -6.0, 7.0, -8.0);
let neg_o = -o;
assert_eq!(neg_o.s, -1.0);
assert_eq!(neg_o.e1, 2.0);
assert_eq!(neg_o.e2, -3.0);
// ... and so on for other componentsSource§impl<T: RealField + NumCast> NumCast for Octonion<T>
impl<T: RealField + NumCast> NumCast for Octonion<T>
Source§fn from<N: ToPrimitive>(n: N) -> Option<Self>
fn from<N: ToPrimitive>(n: N) -> Option<Self>
Converts a number n into an Octonion<T>.
This method is part of the NumCast trait. It attempts to convert any
type N that implements ToPrimitive into an Octonion<T>.
The conversion is applied only to the scalar part (s) of the octonion,
with all imaginary parts set to zero.
§Type Parameters
N- The numeric type to convert from.
§Arguments
n- The value to convert.
§Returns
An Option<Self> which is Some(Octonion<T>) if the conversion is
successful and None otherwise.
§Examples
use deep_causality_num::{Octonion, NumCast};
let o: Option<Octonion<f64>> = <Octonion<_> as NumCast>::from(10);
assert!(o.is_some());
assert_eq!(o.unwrap().s, 10.0);
let o_float: Option<Octonion<f32>> = <Octonion<_> as NumCast>::from(3.14f64);
assert!(o_float.is_some());
assert_eq!(o_float.unwrap().s, 3.14f32);Source§impl<F: RealField> One for Octonion<F>
Implements the One trait for Octonion.
impl<F: RealField> One for Octonion<F>
Implements the One trait for Octonion.
Source§fn is_one(&self) -> bool
fn is_one(&self) -> bool
Checks if the octonion is the multiplicative identity (one).
An octonion is considered one if its scalar part is 1 and all imaginary parts are 0.
§Returns
true if the octonion is the multiplicative identity, false otherwise.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::{One, Zero};
let o1 = Octonion::<f64>::one();
assert!(o1.is_one());
let o2 = Octonion::new(1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert!(!o2.is_one());
let o3 = Octonion::<f64>::zero();
assert!(!o3.is_one());Source§impl<F> PartialOrd for Octonion<F>where
F: RealField + PartialOrd,
impl<F> PartialOrd for Octonion<F>where
F: RealField + PartialOrd,
Source§impl<F: RealField> Product for Octonion<F>
Implements the Product trait for Octonion, allowing an iterator of octonions to be multiplied.
impl<F: RealField> Product for Octonion<F>
Implements the Product trait for Octonion, allowing an iterator of octonions to be multiplied.
The product is performed by iteratively multiplying each octonion in the iterator. Due to non-associativity, the order of multiplication matters. This implementation performs sequential left-to-right multiplication.
§Arguments
iter- An iterator that yieldsOctonion<F>values.
§Returns
A single Octonion representing the product of all octonions in the iterator.
If the iterator is empty, it returns the identity octonion (1).
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::One;
let o_one = Octonion::one();
let e1 = Octonion::new(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e2 = Octonion::new(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let e3 = Octonion::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0);
let octonions = vec![o_one, e1, e2];
let product: Octonion<f64> = octonions.into_iter().product();
assert_eq!(product, e3); // (1 * e1) * e2 = e1 * e2 = e3
let empty_vec: Vec<Octonion<f64>> = Vec::new();
let empty_product: Octonion<f64> = empty_vec.into_iter().product();
assert_eq!(empty_product, Octonion::one());Source§impl<T: RealField> Rotation<T> for Octonion<T>
impl<T: RealField> Rotation<T> for Octonion<T>
Source§fn rotate_x(&self, angle: T) -> Self
fn rotate_x(&self, angle: T) -> Self
Rotates the Octonion around the $e_1$ axis. $R = \cos(\theta/2) + e_1 \sin(\theta/2)$
Source§fn rotate_y(&self, angle: T) -> Self
fn rotate_y(&self, angle: T) -> Self
Rotates the Octonion around the $e_2$ axis. $R = \cos(\theta/2) + e_2 \sin(\theta/2)$
Source§fn rotate_z(&self, angle: T) -> Self
fn rotate_z(&self, angle: T) -> Self
Rotates the Octonion around the $e_3$ axis. $R = \cos(\theta/2) + e_3 \sin(\theta/2)$
Source§fn global_phase(&self, _angle: T) -> Self
fn global_phase(&self, _angle: T) -> Self
Global Phase Shift.
Octonions are a Real algebra. They do not have a central imaginary unit $i$ that commutes with everything (unlike Complex numbers). Therefore, a “Global Phase” $e^{i\phi}$ is not well-defined in standard Octonion arithmetic without picking a specific preferred axis (which effectively becomes a rotation).
To maintain mathematical strictness, this is an Identity operation.
Source§impl<F: RealField> Sub for Octonion<F>
Implements the subtraction operator (-) for two Octonion numbers.
impl<F: RealField> Sub for Octonion<F>
Implements the subtraction operator (-) for two Octonion numbers.
Octonion subtraction is performed component-wise:
(s₁ + v₁) - (s₂ + v₂) = (s₁ - s₂) + (v₁ - v₂)
§Arguments
self- The left-hand sideOctonion.rhs- The right-hand sideOctonion.
§Returns
A new Octonion representing the difference between self and rhs.
§Examples
use deep_causality_num::Octonion;
let o1 = Octonion::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
let o2 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
let diff = o1 - o2;
assert_eq!(diff.s, 8.0);
assert_eq!(diff.e1, 8.0);
// ... and so on for other componentsSource§impl<F: RealField> SubAssign for Octonion<F>
Implements the subtraction assignment operator (-=) for two Octonion numbers.
impl<F: RealField> SubAssign for Octonion<F>
Implements the subtraction assignment operator (-=) for two Octonion numbers.
Each component of other is subtracted from the corresponding component of self.
self = self - other
§Arguments
self- The left-hand sideOctonionto be modified.other- The right-hand sideOctonionto subtract.
§Examples
use deep_causality_num::Octonion;
let mut o1 = Octonion::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
let o2 = Octonion::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
o1 -= o2;
assert_eq!(o1.s, 8.0);
assert_eq!(o1.e1, 8.0);Source§fn sub_assign(&mut self, other: Self)
fn sub_assign(&mut self, other: Self)
-= operation. Read moreSource§impl<F: RealField> Sum for Octonion<F>
Implements the Sum trait for Octonion, allowing an iterator of octonions to be summed.
impl<F: RealField> Sum for Octonion<F>
Implements the Sum trait for Octonion, allowing an iterator of octonions to be summed.
The sum is performed by iteratively adding each octonion in the iterator.
§Arguments
iter- An iterator that yieldsOctonion<F>values.
§Returns
A single Octonion representing the sum of all octonions in the iterator.
If the iterator is empty, it returns the zero octonion.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::Zero;
let o1 = Octonion::new(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
let o2 = Octonion::new(2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0);
let o3 = Octonion::new(3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0);
let octonions = vec![o1, o2, o3];
let sum: Octonion<f64> = octonions.into_iter().sum();
assert_eq!(sum.s, 6.0);
assert_eq!(sum.e1, 6.0);
let empty_vec: Vec<Octonion<f64>> = Vec::new();
let empty_sum: Octonion<f64> = empty_vec.into_iter().sum();
assert_eq!(empty_sum, Octonion::zero());Source§impl<F: RealField + ToPrimitive> ToPrimitive for Octonion<F>
Implements the ToPrimitive trait for Octonion.
impl<F: RealField + ToPrimitive> ToPrimitive for Octonion<F>
Implements the ToPrimitive trait for Octonion.
This allows conversion from an Octonion into various primitive integer
and floating-point types. The conversion is performed only on the scalar part (s)
of the octonion.
Each to_* method attempts to convert the octonion’s scalar part into
the target primitive type.
Source§fn to_isize(&self) -> Option<isize>
fn to_isize(&self) -> Option<isize>
Converts the scalar part of the Octonion to an isize.
§Returns
An Option<isize> which is Some(isize) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(10.5f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<isize> = o.to_isize();
assert_eq!(val, Some(10));Source§fn to_i8(&self) -> Option<i8>
fn to_i8(&self) -> Option<i8>
Converts the scalar part of the Octonion to an i8.
§Returns
An Option<i8> which is Some(i8) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(5.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<i8> = o.to_i8();
assert_eq!(val, Some(5));Source§fn to_i16(&self) -> Option<i16>
fn to_i16(&self) -> Option<i16>
Converts the scalar part of the Octonion to an i16.
§Returns
An Option<i16> which is Some(i16) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(100.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<i16> = o.to_i16();
assert_eq!(val, Some(100));Source§fn to_i32(&self) -> Option<i32>
fn to_i32(&self) -> Option<i32>
Converts the scalar part of the Octonion to an i32.
§Returns
An Option<i32> which is Some(i32) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(1000.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<i32> = o.to_i32();
assert_eq!(val, Some(1000));Source§fn to_i64(&self) -> Option<i64>
fn to_i64(&self) -> Option<i64>
Converts the scalar part of the Octonion to an i64.
§Returns
An Option<i64> which is Some(i64) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(100_000.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<i64> = o.to_i64();
assert_eq!(val, Some(100_000));Source§fn to_i128(&self) -> Option<i128>
fn to_i128(&self) -> Option<i128>
Converts the scalar part of the Octonion to an i128.
§Returns
An Option<i128> which is Some(i128) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(1_000_000_000_000_000.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<i128> = o.to_i128();
assert_eq!(val, Some(1_000_000_000_000_000));Source§fn to_usize(&self) -> Option<usize>
fn to_usize(&self) -> Option<usize>
Converts the scalar part of the Octonion to a usize.
§Returns
An Option<usize> which is Some(usize) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(123.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<usize> = o.to_usize();
assert_eq!(val, Some(123));Source§fn to_u8(&self) -> Option<u8>
fn to_u8(&self) -> Option<u8>
Converts the scalar part of the Octonion to a u8.
§Returns
An Option<u8> which is Some(u8) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(255.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<u8> = o.to_u8();
assert_eq!(val, Some(255));Source§fn to_u16(&self) -> Option<u16>
fn to_u16(&self) -> Option<u16>
Converts the scalar part of the Octonion to a u16.
§Returns
An Option<u16> which is Some(u16) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(65535.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<u16> = o.to_u16();
assert_eq!(val, Some(65535));Source§fn to_u32(&self) -> Option<u32>
fn to_u32(&self) -> Option<u32>
Converts the scalar part of the Octonion to a u32.
§Returns
An Option<u32> which is Some(u32) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(4_000_000_000.0f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<u32> = o.to_u32();
assert_eq!(val, Some(4_000_000_000));Source§fn to_u64(&self) -> Option<u64>
fn to_u64(&self) -> Option<u64>
Converts the scalar part of the Octonion to a u64.
§Returns
An Option<u64> which is Some(u64) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(u64::MAX as f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<u64> = o.to_u64();
assert_eq!(val, Some(u64::MAX));Source§fn to_u128(&self) -> Option<u128>
fn to_u128(&self) -> Option<u128>
Converts the scalar part of the Octonion to a u128.
§Returns
An Option<u128> which is Some(u128) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(u128::MAX as f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<u128> = o.to_u128();
// Note: f64 can't represent all u128 values precisely.
assert_eq!(val, Some(u128::MAX));Source§fn to_f32(&self) -> Option<f32>
fn to_f32(&self) -> Option<f32>
Converts the scalar part of the Octonion to an f32.
§Returns
An Option<f32> which is Some(f32) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(3.1415926535f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<f32> = o.to_f32();
assert_eq!(val, Some(3.1415927f32));Source§fn to_f64(&self) -> Option<f64>
fn to_f64(&self) -> Option<f64>
Converts the scalar part of the Octonion to an f64.
§Returns
An Option<f64> which is Some(f64) if the conversion is successful,
and None otherwise.
§Examples
use deep_causality_num::{Octonion, ToPrimitive};
let o = Octonion::new(2.718281828f64, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
let val: Option<f64> = o.to_f64();
assert_eq!(val, Some(2.718281828f64));Source§impl<F: RealField> Zero for Octonion<F>
Implements the Zero trait for Octonion.
impl<F: RealField> Zero for Octonion<F>
Implements the Zero trait for Octonion.
Source§fn is_zero(&self) -> bool
fn is_zero(&self) -> bool
Checks if the octonion is the additive identity (zero).
An octonion is considered zero if all its components are zero.
§Returns
true if all components are zero, false otherwise.
§Examples
use deep_causality_num::Octonion;
use deep_causality_num::Zero;
let o1 = Octonion::<f64>::zero();
assert!(o1.is_zero());
let o2 = Octonion::new(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
assert!(!o2.is_zero());impl<T: RealField> AbelianGroup for Octonion<T>
Implements the AbelianGroup trait for Octonion.
This signifies that Octonions form an abelian (commutative) group under addition.
Addition is component-wise, ensuring commutativity and associativity.
impl<F> Copy for Octonion<F>
impl<T: RealField> Distributive for Octonion<T>
Implements the Distributive marker trait for Octonion.
This signifies that multiplication of Octonions distributes over addition,
i.e., a * (b + c) = (a * b) + (a * c). This property holds for octonions.