Skip to content

Instantly share code, notes, and snippets.

@zesterer
Created July 16, 2018 08:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zesterer/98b9710dc1062a3890805fb4382decef to your computer and use it in GitHub Desktop.
Save zesterer/98b9710dc1062a3890805fb4382decef to your computer and use it in GitHub Desktop.
A few tests for coord
#![allow(unused_imports)]
#![allow(dead_code)]
extern crate core;
use core::ops::{
Add, Sub, Mul, Div,
AddAssign, SubAssign, MulAssign, DivAssign,
};
use core::fmt;
// CORE TRAITS
trait VecItem: Copy + Clone {}
trait VecN { type Item: VecItem; }
impl<T: VecItem> VecN for Vec3<T> { type Item = T; }
// UNARY TO VECTOR OPERATORS
trait UnToVec<R: VecN>: VecN {
fn map<F: Fn(Self::Item) -> R::Item>(&self, f: F) -> R;
}
// UNARY TO SCALAR OPERATORS
trait UnToScal<R>: VecN {
fn fold<F: Fn(Self::Item, R) -> R>(&self, a: R, f: F) -> R;
fn fold_back<F: Fn(Self::Item, R) -> R>(&self, a: R, f: F) -> R;
fn apply_to<F: Fn(Self::Item, &mut R)>(&self, a: &mut R, f: F);
}
// BINARY TO VECTOR OPERATORS
trait BinToVec<O: VecN, R: VecN>: VecN {
fn map_with<F: Fn(Self::Item, O::Item) -> R::Item>(&self, o: O, f: F) -> R;
}
// BINARY TO SCALAR OPERATORS
trait BinToScal<O: VecN, R>: VecN {
}
// CONVERSION TRAITS
trait ConvFrom<T> { fn conv_from(a: T) -> Self; }
trait ConvTo<T> { fn to(self) -> T; }
impl<T, U> ConvTo<U> for T
where U: ConvFrom<T>
{
fn to(self) -> U {
U::conv_from(self)
}
}
// Binary operations
impl<T: VecItem + Add<Output=T>> Add for Vec3<T> {
type Output = Vec3<T>;
fn add(self, o: Self) -> Self::Output {
self.map_with(o, |a, b| a + b)
}
}
// ITEM IMPLEMENTATIONS
impl VecItem for u8 {}
impl VecItem for u16 {}
impl VecItem for u32 {}
impl VecItem for u64 {}
impl VecItem for i8 {}
impl VecItem for i16 {}
impl VecItem for i32 {}
impl VecItem for i64 {}
impl VecItem for f32 {}
impl VecItem for f64 {}
impl VecItem for bool {}
impl VecItem for &'static str {}
macro_rules! impl_primitive_conv_from {
($from:ty, $to:ty) => {
impl ConvFrom<$from> for $to {
fn conv_from(a: $from) -> Self { a as Self }
}
}
}
impl_primitive_conv_from!(i8 , f32);
impl_primitive_conv_from!(i16, f32);
impl_primitive_conv_from!(i32, f32);
impl_primitive_conv_from!(i64, f32);
impl_primitive_conv_from!(f32, f32);
impl_primitive_conv_from!(f64, f32);
impl_primitive_conv_from!(i8 , f64);
impl_primitive_conv_from!(i16, f64);
impl_primitive_conv_from!(i32, f64);
impl_primitive_conv_from!(i64, f64);
impl_primitive_conv_from!(f32, f64);
impl_primitive_conv_from!(f64, f64);
impl_primitive_conv_from!(u8 , i64);
impl_primitive_conv_from!(u16, i64);
impl_primitive_conv_from!(u32, i64);
impl_primitive_conv_from!(i8 , i64);
impl_primitive_conv_from!(i16, i64);
impl_primitive_conv_from!(i32, i64);
impl_primitive_conv_from!(i64, i64);
impl_primitive_conv_from!(u8 , u64);
impl_primitive_conv_from!(u16, u64);
impl_primitive_conv_from!(u32, u64);
impl_primitive_conv_from!(u64, u64);
impl_primitive_conv_from!(u8 , i32);
impl_primitive_conv_from!(u16, i32);
impl_primitive_conv_from!(i8 , i32);
impl_primitive_conv_from!(i16, i32);
impl_primitive_conv_from!(i32, i32);
impl_primitive_conv_from!(u8 , u32);
impl_primitive_conv_from!(u16, u32);
impl_primitive_conv_from!(u32, u32);
impl_primitive_conv_from!(u8 , i16);
impl_primitive_conv_from!(i8 , i16);
impl_primitive_conv_from!(i16, i16);
impl_primitive_conv_from!(u8 , u16);
impl_primitive_conv_from!(u16, u16);
impl_primitive_conv_from!(i8 , i8);
impl_primitive_conv_from!(u8 , u8);
// VEC3
#[derive(Copy, Clone)]
struct Vec3<T: VecItem> {
x: T,
y: T,
z: T,
}
impl<T: VecItem> Vec3<T> {
fn new(x: T, y: T, z: T) -> Vec3<T> {
Vec3 { x, y, z }
}
}
impl<T: VecItem, U: VecItem> ConvFrom<Vec3<U>> for Vec3<T>
where T: ConvFrom<U>
{
fn conv_from(a: Vec3<U>) -> Self {
a.map(|e| T::conv_from(e))
}
}
// Unary to vector
impl<T: VecItem, R: VecItem> UnToVec<Vec3<R>> for Vec3<T> {
fn map<F: Fn(Self::Item) -> R>(&self, f: F) -> Vec3<R> {
Vec3 {
x: f(self.x),
y: f(self.y),
z: f(self.z),
}
}
}
// Unary to scalar
impl<T: VecItem, R> UnToScal<R> for Vec3<T> {
fn fold<F: Fn(Self::Item, R) -> R>(&self, a: R, f: F) -> R {
let a = f(self.x, a);
let a = f(self.y, a);
f(self.z, a)
}
fn fold_back<F: Fn(Self::Item, R) -> R>(&self, a: R, f: F) -> R {
let a = f(self.z, a);
let a = f(self.y, a);
f(self.x, a)
}
fn apply_to<F: Fn(Self::Item, &mut R)>(&self, a: &mut R, f: F) {
f(self.x, a);
f(self.y, a);
f(self.z, a);
}
}
// Binary to vector
impl<T: VecItem, O: VecItem, R: VecItem> BinToVec<Vec3<O>, Vec3<R>> for Vec3<T> {
fn map_with<F: Fn(Self::Item, O) -> R>(&self, o: Vec3<O>, f: F) -> Vec3<R> {
Vec3 {
x: f(self.x, o.x),
y: f(self.y, o.y),
z: f(self.z, o.z),
}
}
}
// Binary to scalar
impl<T: VecItem, O: VecItem, R> BinToScal<Vec3<O>, R> for Vec3<T> {
}
// Debug
impl<T: VecItem + fmt::Debug> fmt::Debug for Vec3<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(x: {:?}, y: {:?}, z: {:?})", self.x, self.y, self.z)
}
}
// Display
impl<T: VecItem + fmt::Display> fmt::Display for Vec3<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {}, {})", self.x, self.y, self.z)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let _v0 = Vec3::new(0, 0, 0);
let _v1: Vec3<f32> = _v0.to();
let _v2 = _v1.map(|e| e * 2.0);
fn test_pass<V: ConvTo<Vec3<f32>>>(_v: V) {
// Nothing yet
}
test_pass(_v0);
test_pass(_v1);
let _v0 = Vec3::new("x", "y", "z");
let _v0 = Vec3::new(true, false, false);
let _v1 = Vec3::new(3.0, 7.0, 3.0);
let _v2 = _v0.map_with(_v1, |a, b| if a { b > 5.0 } else { true });
let _t = Vec3::new(5, 7, 12).fold(0, |e, a| a + e);
println!("{:?}", Vec3::new(1.5, 2.5, 3.5));
println!("{}", Vec3::new(4.5, 5.5, 6.5));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment