Improves usability by providing accessor methods, index traits and conversion traits implementations.
This commit is contained in:
parent
a01bf5e03c
commit
9e3f6959b5
3 changed files with 269 additions and 135 deletions
|
|
@ -25,7 +25,7 @@ fn emit_expression<W: std::io::Write>(collector: &mut W, expression: &Expression
|
|||
}
|
||||
ExpressionContent::InvokeClassMethod(class, _, _) => {
|
||||
if *method_name == "Constructor" {
|
||||
collector.write_fmt(format_args!("{} {{ ", class.class_name))?;
|
||||
collector.write_fmt(format_args!("{} {{ groups: {}Groups {{ ", class.class_name, class.class_name))?;
|
||||
} else {
|
||||
collector.write_fmt(format_args!("{}::", class.class_name))?;
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ fn emit_expression<W: std::io::Write>(collector: &mut W, expression: &Expression
|
|||
emit_expression(collector, &argument)?;
|
||||
}
|
||||
if *method_name == "Constructor" {
|
||||
collector.write_all(b" }")?;
|
||||
collector.write_all(b" } }")?;
|
||||
} else {
|
||||
collector.write_all(b")")?;
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ fn emit_expression<W: std::io::Write>(collector: &mut W, expression: &Expression
|
|||
}
|
||||
ExpressionContent::Access(inner_expression, array_index) => {
|
||||
emit_expression(collector, &inner_expression)?;
|
||||
collector.write_fmt(format_args!(".g{}", array_index))?;
|
||||
collector.write_fmt(format_args!(".group{}()", array_index))?;
|
||||
}
|
||||
ExpressionContent::Swizzle(inner_expression, indices) => {
|
||||
if expression.size == 1 {
|
||||
|
|
@ -99,7 +99,7 @@ fn emit_expression<W: std::io::Write>(collector: &mut W, expression: &Expression
|
|||
collector.write_all(b", ")?;
|
||||
}
|
||||
emit_expression(collector, &inner_expression)?;
|
||||
collector.write_fmt(format_args!(".g{}", array_index))?;
|
||||
collector.write_fmt(format_args!(".group{}()", array_index))?;
|
||||
if inner_expression.size > 1 {
|
||||
collector.write_fmt(format_args!("[{}]", *component_index))?;
|
||||
}
|
||||
|
|
@ -193,8 +193,11 @@ pub fn emit_code<W: std::io::Write>(collector: &mut W, ast_node: &AstNode, inden
|
|||
.write_all(b"use crate::{simd::*, *};\nuse std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};\n\n")?;
|
||||
}
|
||||
AstNode::ClassDefinition { class } => {
|
||||
collector.write_fmt(format_args!("#[derive(Clone, Copy, Debug)]\npub struct {} {{\n", class.class_name))?;
|
||||
for (i, group) in class.grouped_basis.iter().enumerate() {
|
||||
let element_count = class.grouped_basis.iter().fold(0, |a, b| a + b.len());
|
||||
let mut simd_widths = Vec::new();
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("#[derive(Clone, Copy)]\nstruct {}Groups {{\n", class.class_name))?;
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"/// ")?;
|
||||
for (i, element) in group.iter().enumerate() {
|
||||
|
|
@ -205,13 +208,216 @@ pub fn emit_code<W: std::io::Write>(collector: &mut W, ast_node: &AstNode, inden
|
|||
}
|
||||
collector.write_all(b"\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("pub g{}: ", i))?;
|
||||
if group.len() == 1 {
|
||||
collector.write_all(b"f32,\n")?;
|
||||
collector.write_fmt(format_args!("g{}: ", j))?;
|
||||
simd_widths.push(if group.len() == 1 {
|
||||
collector.write_all(b"f32")?;
|
||||
1
|
||||
} else {
|
||||
collector.write_fmt(format_args!("Simd32x{},\n", group.len()))?;
|
||||
collector.write_fmt(format_args!("Simd32x{}", group.len()))?;
|
||||
4
|
||||
});
|
||||
collector.write_all(b",\n")?;
|
||||
}
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("#[derive(Clone, Copy)]\npub union {} {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("groups: {}Groups,\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"/// ")?;
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
for (i, element) in group.iter().enumerate() {
|
||||
if j > 0 || i > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("{}", element))?;
|
||||
}
|
||||
for _ in group.len()..simd_widths[j] {
|
||||
collector.write_all(b", 0")?;
|
||||
}
|
||||
}
|
||||
collector.write_all(b"\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("elements: [f32; {}],\n", simd_widths.iter().fold(0, |a, b| a + b)))?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("impl {} {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"pub const fn new(")?;
|
||||
for i in 0..element_count {
|
||||
if i > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("element{}: f32", i))?;
|
||||
}
|
||||
collector.write_all(b") -> Self {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_all(b"Self { elements: [")?;
|
||||
let mut element_index = 0;
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
for _ in 0..group.len() {
|
||||
if element_index > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("element{}", element_index))?;
|
||||
element_index += 1;
|
||||
}
|
||||
for _ in group.len()..simd_widths[j] {
|
||||
collector.write_all(b", 0.0")?;
|
||||
}
|
||||
}
|
||||
collector.write_all(b"] }\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"#[inline(always)]\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("pub fn group{}(&self) -> ", j))?;
|
||||
if group.len() == 1 {
|
||||
collector.write_all(b"f32")?;
|
||||
} else {
|
||||
collector.write_fmt(format_args!("Simd32x{}", group.len()))?;
|
||||
}
|
||||
collector.write_all(b" {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_fmt(format_args!("unsafe {{ self.groups.g{} }}\n", j))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"#[inline(always)]\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("pub fn group{}_mut(&mut self) -> &mut ", j))?;
|
||||
if group.len() == 1 {
|
||||
collector.write_all(b"f32")?;
|
||||
} else {
|
||||
collector.write_fmt(format_args!("Simd32x{}", group.len()))?;
|
||||
}
|
||||
collector.write_all(b" {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_fmt(format_args!("unsafe {{ &mut self.groups.g{} }}\n", j))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
}
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!(
|
||||
"const {}_INDEX_REMAP: [usize; {}] = [",
|
||||
class.class_name.to_uppercase(),
|
||||
element_count
|
||||
))?;
|
||||
let mut element_index = 0;
|
||||
let mut index_remap = Vec::new();
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
for _ in 0..group.len() {
|
||||
if element_index > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("{}", element_index))?;
|
||||
index_remap.push(element_index);
|
||||
element_index += 1;
|
||||
}
|
||||
element_index += simd_widths[j].saturating_sub(group.len());
|
||||
}
|
||||
collector.write_all(b"];\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("impl std::ops::Index<usize> for {} {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"type Output = f32;\n\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"fn index(&self, index: usize) -> &Self::Output {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_fmt(format_args!(
|
||||
"unsafe {{ &self.elements[{}_INDEX_REMAP[index]] }}\n",
|
||||
class.class_name.to_uppercase()
|
||||
))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("impl std::ops::IndexMut<usize> for {} {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"fn index_mut(&mut self, index: usize) -> &mut Self::Output {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_fmt(format_args!(
|
||||
"unsafe {{ &mut self.elements[{}_INDEX_REMAP[index]] }}\n",
|
||||
class.class_name.to_uppercase()
|
||||
))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!(
|
||||
"impl std::convert::From<{}> for [f32; {}] {{\n",
|
||||
class.class_name, element_count
|
||||
))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("fn from(vector: {}) -> Self {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_all(b"unsafe { [")?;
|
||||
for i in 0..element_count {
|
||||
if i > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("vector.elements[{}]", index_remap[i]))?;
|
||||
}
|
||||
collector.write_all(b"] }\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!(
|
||||
"impl std::convert::From<[f32; {}]> for {} {{\n",
|
||||
element_count, class.class_name
|
||||
))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_fmt(format_args!("fn from(array: [f32; {}]) -> Self {{\n", element_count))?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_all(b"Self { elements: [")?;
|
||||
let mut element_index = 0;
|
||||
for (j, group) in class.grouped_basis.iter().enumerate() {
|
||||
for _ in 0..group.len() {
|
||||
if element_index > 0 {
|
||||
collector.write_all(b", ")?;
|
||||
}
|
||||
collector.write_fmt(format_args!("array[{}]", element_index))?;
|
||||
element_index += 1;
|
||||
}
|
||||
for _ in group.len()..simd_widths[j] {
|
||||
collector.write_all(b", 0.0")?;
|
||||
}
|
||||
}
|
||||
collector.write_all(b"] }\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_fmt(format_args!("impl std::fmt::Debug for {} {{\n", class.class_name))?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {\n")?;
|
||||
emit_indentation(collector, indentation + 2)?;
|
||||
collector.write_all(b"formatter\n")?;
|
||||
emit_indentation(collector, indentation + 3)?;
|
||||
collector.write_fmt(format_args!(".debug_struct(\"{}\")\n", class.class_name))?;
|
||||
let mut element_index = 0;
|
||||
for group in class.grouped_basis.iter() {
|
||||
for element in group.iter() {
|
||||
emit_indentation(collector, indentation + 3)?;
|
||||
collector.write_fmt(format_args!(".field(\"{}\", &self[{}])\n", element, element_index))?;
|
||||
element_index += 1;
|
||||
}
|
||||
}
|
||||
emit_indentation(collector, indentation + 3)?;
|
||||
collector.write_all(b".finish()\n")?;
|
||||
emit_indentation(collector, indentation + 1)?;
|
||||
collector.write_all(b"}\n")?;
|
||||
emit_indentation(collector, indentation)?;
|
||||
collector.write_all(b"}\n\n")?;
|
||||
}
|
||||
AstNode::ReturnStatement { expression } => {
|
||||
|
|
|
|||
144
src/lib.rs
144
src/lib.rs
|
|
@ -12,42 +12,30 @@ pub mod hpga3d;
|
|||
pub mod simd;
|
||||
|
||||
impl epga1d::Scalar {
|
||||
pub const fn new(real: f32) -> Self {
|
||||
Self { g0: real }
|
||||
}
|
||||
|
||||
pub fn real(self) -> f32 {
|
||||
self.g0
|
||||
self[0]
|
||||
}
|
||||
|
||||
pub fn sqrt(self) -> epga1d::ComplexNumber {
|
||||
if self.g0 < 0.0 {
|
||||
epga1d::ComplexNumber::new(0.0, (-self.g0).sqrt())
|
||||
if self[0] < 0.0 {
|
||||
epga1d::ComplexNumber::from([0.0, (-self[0]).sqrt()])
|
||||
} else {
|
||||
epga1d::ComplexNumber::new(self.g0.sqrt(), 0.0)
|
||||
epga1d::ComplexNumber::from([self[0].sqrt(), 0.0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl epga1d::ComplexNumber {
|
||||
pub const fn new(real: f32, imaginary: f32) -> Self {
|
||||
Self {
|
||||
g0: simd::Simd32x2 {
|
||||
f32x2: [real, imaginary],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn real(self) -> f32 {
|
||||
self.g0[0]
|
||||
self[0]
|
||||
}
|
||||
|
||||
pub fn imaginary(self) -> f32 {
|
||||
self.g0[1]
|
||||
self[1]
|
||||
}
|
||||
|
||||
pub fn from_polar(magnitude: f32, argument: f32) -> Self {
|
||||
Self::new(magnitude * argument.cos(), magnitude * argument.sin())
|
||||
Self::from([magnitude * argument.cos(), magnitude * argument.sin()])
|
||||
}
|
||||
|
||||
pub fn arg(self) -> f32 {
|
||||
|
|
@ -59,7 +47,7 @@ impl Exp for epga1d::ComplexNumber {
|
|||
type Output = Self;
|
||||
|
||||
fn exp(self) -> Self {
|
||||
Self::from_polar(self.g0[0].exp(), self.g0[1])
|
||||
Self::from_polar(self[0].exp(), self[1])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +55,7 @@ impl Ln for epga1d::ComplexNumber {
|
|||
type Output = Self;
|
||||
|
||||
fn ln(self) -> Self {
|
||||
Self::new(self.magnitude().g0.ln(), self.arg())
|
||||
Self::from([self.magnitude()[0].ln(), self.arg()])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +63,7 @@ impl Powf for epga1d::ComplexNumber {
|
|||
type Output = Self;
|
||||
|
||||
fn powf(self, exponent: f32) -> Self {
|
||||
Self::from_polar(self.magnitude().g0.powf(exponent), self.arg() * exponent)
|
||||
Self::from_polar(self.magnitude()[0].powf(exponent), self.arg() * exponent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,11 +71,7 @@ impl Exp for ppga2d::IdealPoint {
|
|||
type Output = ppga2d::Translator;
|
||||
|
||||
fn exp(self) -> ppga2d::Translator {
|
||||
ppga2d::Translator {
|
||||
g0: simd::Simd32x3 {
|
||||
f32x3: [1.0, self.g0[0], self.g0[1]],
|
||||
},
|
||||
}
|
||||
ppga2d::Translator::from([1.0, self[0], self[1]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +80,7 @@ impl Ln for ppga2d::Translator {
|
|||
|
||||
fn ln(self) -> ppga2d::IdealPoint {
|
||||
let result: ppga2d::IdealPoint = self.into();
|
||||
result / ppga2d::Scalar { g0: self.g0[0] }
|
||||
result / ppga2d::Scalar::from([self[0]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +88,7 @@ impl Powf for ppga2d::Translator {
|
|||
type Output = Self;
|
||||
|
||||
fn powf(self, exponent: f32) -> Self {
|
||||
(ppga2d::Scalar { g0: exponent } * self.ln()).exp()
|
||||
(ppga2d::Scalar::from([exponent]) * self.ln()).exp()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,23 +96,15 @@ impl Exp for ppga2d::Point {
|
|||
type Output = ppga2d::Motor;
|
||||
|
||||
fn exp(self) -> ppga2d::Motor {
|
||||
let det = self.g0[0] * self.g0[0];
|
||||
let det = self[0] * self[0];
|
||||
if det <= 0.0 {
|
||||
return ppga2d::Motor {
|
||||
g0: simd::Simd32x4 {
|
||||
f32x4: [1.0, 0.0, self.g0[1], self.g0[2]],
|
||||
},
|
||||
};
|
||||
return ppga2d::Motor::from([1.0, 0.0, self[1], self[2]]);
|
||||
}
|
||||
let a = det.sqrt();
|
||||
let c = a.cos();
|
||||
let s = a.sin() / a;
|
||||
let g0 = simd::Simd32x3::from(s) * self.g0;
|
||||
ppga2d::Motor {
|
||||
g0: simd::Simd32x4 {
|
||||
f32x4: [c, g0[0], g0[1], g0[2]],
|
||||
},
|
||||
}
|
||||
let g0 = simd::Simd32x3::from(s) * self.group0();
|
||||
ppga2d::Motor::from([c, g0[0], g0[1], g0[2]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,22 +112,14 @@ impl Ln for ppga2d::Motor {
|
|||
type Output = ppga2d::Point;
|
||||
|
||||
fn ln(self) -> ppga2d::Point {
|
||||
let det = 1.0 - self.g0[0] * self.g0[0];
|
||||
let det = 1.0 - self[0] * self[0];
|
||||
if det <= 0.0 {
|
||||
return ppga2d::Point {
|
||||
g0: simd::Simd32x3 {
|
||||
f32x3: [0.0, self.g0[2], self.g0[3]],
|
||||
},
|
||||
};
|
||||
return ppga2d::Point::from([0.0, self[2], self[3]]);
|
||||
}
|
||||
let a = 1.0 / det;
|
||||
let b = self.g0[0].acos() * a.sqrt();
|
||||
let g0 = simd::Simd32x4::from(b) * self.g0;
|
||||
return ppga2d::Point {
|
||||
g0: simd::Simd32x3 {
|
||||
f32x3: [g0[1], g0[2], g0[3]],
|
||||
},
|
||||
};
|
||||
let b = self[0].acos() * a.sqrt();
|
||||
let g0 = simd::Simd32x4::from(b) * self.group0();
|
||||
return ppga2d::Point::from([g0[1], g0[2], g0[3]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +127,7 @@ impl Powf for ppga2d::Motor {
|
|||
type Output = Self;
|
||||
|
||||
fn powf(self, exponent: f32) -> Self {
|
||||
(ppga2d::Scalar { g0: exponent } * self.ln()).exp()
|
||||
(ppga2d::Scalar::from([exponent]) * self.ln()).exp()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -167,11 +135,7 @@ impl Exp for ppga3d::IdealPoint {
|
|||
type Output = ppga3d::Translator;
|
||||
|
||||
fn exp(self) -> ppga3d::Translator {
|
||||
ppga3d::Translator {
|
||||
g0: simd::Simd32x4 {
|
||||
f32x4: [1.0, self.g0[0], self.g0[1], self.g0[2]],
|
||||
},
|
||||
}
|
||||
ppga3d::Translator::from([1.0, self[0], self[1], self[2]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +144,7 @@ impl Ln for ppga3d::Translator {
|
|||
|
||||
fn ln(self) -> ppga3d::IdealPoint {
|
||||
let result: ppga3d::IdealPoint = self.into();
|
||||
result / ppga3d::Scalar { g0: self.g0[0] }
|
||||
result / ppga3d::Scalar::from([self[0]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +152,7 @@ impl Powf for ppga3d::Translator {
|
|||
type Output = Self;
|
||||
|
||||
fn powf(self, exponent: f32) -> Self {
|
||||
(ppga3d::Scalar { g0: exponent } * self.ln()).exp()
|
||||
(ppga3d::Scalar::from([exponent]) * self.ln()).exp()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,32 +160,18 @@ impl Exp for ppga3d::Line {
|
|||
type Output = ppga3d::Motor;
|
||||
|
||||
fn exp(self) -> ppga3d::Motor {
|
||||
let det = self.g1[0] * self.g1[0] + self.g1[1] * self.g1[1] + self.g1[2] * self.g1[2];
|
||||
let det = self[3] * self[3] + self[4] * self[4] + self[5] * self[5];
|
||||
if det <= 0.0 {
|
||||
return ppga3d::Motor {
|
||||
g0: simd::Simd32x4 {
|
||||
f32x4: [1.0, 0.0, 0.0, 0.0],
|
||||
},
|
||||
g1: simd::Simd32x4 {
|
||||
f32x4: [0.0, self.g0[0], self.g0[1], self.g0[2]],
|
||||
},
|
||||
};
|
||||
return ppga3d::Motor::from([1.0, 0.0, 0.0, 0.0, 0.0, self[0], self[1], self[2]]);
|
||||
}
|
||||
let a = det.sqrt();
|
||||
let c = a.cos();
|
||||
let s = a.sin() / a;
|
||||
let m = self.g0[0] * self.g1[0] + self.g0[1] * self.g1[1] + self.g0[2] * self.g1[2];
|
||||
let m = self[0] * self[3] + self[1] * self[4] + self[2] * self[5];
|
||||
let t = m / det * (c - s);
|
||||
let g0 = simd::Simd32x3::from(s) * self.g1;
|
||||
let g1 = simd::Simd32x3::from(s) * self.g0 + simd::Simd32x3::from(t) * self.g1;
|
||||
ppga3d::Motor {
|
||||
g0: simd::Simd32x4 {
|
||||
f32x4: [c, g0[0], g0[1], g0[2]],
|
||||
},
|
||||
g1: simd::Simd32x4 {
|
||||
f32x4: [s * m, g1[0], g1[1], g1[2]],
|
||||
},
|
||||
}
|
||||
let g0 = simd::Simd32x3::from(s) * self.group1();
|
||||
let g1 = simd::Simd32x3::from(s) * self.group0() + simd::Simd32x3::from(t) * self.group1();
|
||||
ppga3d::Motor::from([c, g0[0], g0[1], g0[2], s * m, g1[0], g1[1], g1[2]])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,30 +179,16 @@ impl Ln for ppga3d::Motor {
|
|||
type Output = ppga3d::Line;
|
||||
|
||||
fn ln(self) -> ppga3d::Line {
|
||||
let det = 1.0 - self.g0[0] * self.g0[0];
|
||||
let det = 1.0 - self[0] * self[0];
|
||||
if det <= 0.0 {
|
||||
return ppga3d::Line {
|
||||
g0: simd::Simd32x3 {
|
||||
f32x3: [self.g1[1], self.g1[2], self.g1[3]],
|
||||
},
|
||||
g1: simd::Simd32x3 {
|
||||
f32x3: [0.0, 0.0, 0.0],
|
||||
},
|
||||
};
|
||||
return ppga3d::Line::from([self[5], self[6], self[7], 0.0, 0.0, 0.0]);
|
||||
}
|
||||
let a = 1.0 / det;
|
||||
let b = self.g0[0].acos() * a.sqrt();
|
||||
let c = a * self.g1[0] * (1.0 - self.g0[0] * b);
|
||||
let g0 = simd::Simd32x4::from(b) * self.g1 + simd::Simd32x4::from(c) * self.g0;
|
||||
let g1 = simd::Simd32x4::from(b) * self.g0;
|
||||
return ppga3d::Line {
|
||||
g0: simd::Simd32x3 {
|
||||
f32x3: [g0[1], g0[2], g0[3]],
|
||||
},
|
||||
g1: simd::Simd32x3 {
|
||||
f32x3: [g1[1], g1[2], g1[3]],
|
||||
},
|
||||
};
|
||||
let b = self[0].acos() * a.sqrt();
|
||||
let c = a * self[4] * (1.0 - self[0] * b);
|
||||
let g0 = simd::Simd32x4::from(b) * self.group1() + simd::Simd32x4::from(c) * self.group0();
|
||||
let g1 = simd::Simd32x4::from(b) * self.group0();
|
||||
return ppga3d::Line::from([g0[1], g0[2], g0[3], g1[1], g1[2], g1[3]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +196,7 @@ impl Powf for ppga3d::Motor {
|
|||
type Output = Self;
|
||||
|
||||
fn powf(self, exponent: f32) -> Self {
|
||||
(ppga3d::Scalar { g0: exponent } * self.ln()).exp()
|
||||
(ppga3d::Scalar::from([exponent]) * self.ln()).exp()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
34
src/simd.rs
34
src/simd.rs
|
|
@ -1,5 +1,3 @@
|
|||
use std::ops::{Index, IndexMut};
|
||||
|
||||
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
|
||||
pub use std::arch::aarch64::*;
|
||||
#[cfg(all(target_arch = "arm", target_feature = "neon"))]
|
||||
|
|
@ -136,7 +134,7 @@ macro_rules! swizzle {
|
|||
};
|
||||
}
|
||||
|
||||
impl Index<usize> for Simd32x4 {
|
||||
impl std::ops::Index<usize> for Simd32x4 {
|
||||
type Output = f32;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
|
|
@ -144,7 +142,7 @@ impl Index<usize> for Simd32x4 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Simd32x3 {
|
||||
impl std::ops::Index<usize> for Simd32x3 {
|
||||
type Output = f32;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
|
|
@ -152,7 +150,7 @@ impl Index<usize> for Simd32x3 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Simd32x2 {
|
||||
impl std::ops::Index<usize> for Simd32x2 {
|
||||
type Output = f32;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
|
|
@ -160,19 +158,19 @@ impl Index<usize> for Simd32x2 {
|
|||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Simd32x4 {
|
||||
impl std::ops::IndexMut<usize> for Simd32x4 {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
unsafe { &mut self.f32x4[index] }
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Simd32x3 {
|
||||
impl std::ops::IndexMut<usize> for Simd32x3 {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
unsafe { &mut self.f32x3[index] }
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Simd32x2 {
|
||||
impl std::ops::IndexMut<usize> for Simd32x2 {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
unsafe { &mut self.f32x2[index] }
|
||||
}
|
||||
|
|
@ -241,11 +239,8 @@ impl std::convert::From<f32> for Simd32x2 {
|
|||
impl std::fmt::Debug for Simd32x4 {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter
|
||||
.debug_tuple("Vec4")
|
||||
.field(&self[0])
|
||||
.field(&self[1])
|
||||
.field(&self[2])
|
||||
.field(&self[3])
|
||||
.debug_list()
|
||||
.entries([self[0], self[1], self[2], self[3]].iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -253,10 +248,8 @@ impl std::fmt::Debug for Simd32x4 {
|
|||
impl std::fmt::Debug for Simd32x3 {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter
|
||||
.debug_tuple("Vec3")
|
||||
.field(&self[0])
|
||||
.field(&self[1])
|
||||
.field(&self[2])
|
||||
.debug_list()
|
||||
.entries([self[0], self[1], self[2]].iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -264,9 +257,8 @@ impl std::fmt::Debug for Simd32x3 {
|
|||
impl std::fmt::Debug for Simd32x2 {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter
|
||||
.debug_tuple("Vec2")
|
||||
.field(&self[0])
|
||||
.field(&self[1])
|
||||
.debug_list()
|
||||
.entries([self[0], self[1]].iter())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -419,4 +411,4 @@ impl std::ops::Mul<Simd32x2> for Simd32x2 {
|
|||
] },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue