Last active
August 26, 2018 01:04
-
-
Save zesterer/63a321489dc45fc300c7e3fc6d2ba4aa to your computer and use it in GitHub Desktop.
Typed noise implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ops::{Add, Mul}; | |
use std::marker::PhantomData; | |
// Generic NoiseFn type | |
trait NoiseFn: Copy + Clone { | |
type Inp: Copy + Clone; | |
type Out: Copy + Clone; | |
fn get(&self, i: Self::Inp) -> Self::Out; | |
} | |
// Impl macros | |
macro_rules! impl_combiner_op { | |
($op_trait:tt, $op_ty:tt, $op_fn:ident, $this:tt) => { | |
impl< | |
Inp: Copy + Clone, | |
Out: Copy + Clone + $op_trait, | |
A: NoiseFn<Inp=Inp, Out=Out>, | |
B: NoiseFn<Inp=Inp, Out=Out>, | |
O: NoiseFn<Inp=Inp, Out=Out>, | |
> $op_trait<O> for $this<Inp, Out, A, B> where Self: NoiseFn { | |
type Output = $op_ty<Inp, Out, Self, O>; | |
fn $op_fn(self, o: O) -> Self::Output { | |
Self::Output { a: self, b: o, _p: PhantomData } | |
} | |
} | |
} | |
} | |
macro_rules! impl_modifier_op { | |
($op_trait:tt, $op_ty:tt, $op_fn:ident, $this:tt) => { | |
impl< | |
Inp: Copy + Clone, | |
Out: Copy + Clone + $op_trait, | |
F: NoiseFn<Inp=Inp, Out=Out>, | |
O: NoiseFn<Inp=Inp, Out=Out>, | |
> $op_trait<O> for $this<Inp, Out, F> where Self: NoiseFn { | |
type Output = $op_ty<Inp, Out, Self, O>; | |
fn $op_fn(self, o: O) -> Self::Output { | |
Self::Output { a: self, b: o, _p: PhantomData } | |
} | |
} | |
} | |
} | |
macro_rules! impl_generator_op { | |
($op_trait:tt, $op_ty:tt, $op_fn:ident, $this:tt) => { | |
impl< | |
Inp: Copy + Clone, | |
Out: Copy + Clone + $op_trait, | |
O: NoiseFn<Inp=Inp, Out=Out>, | |
> $op_trait<O> for $this<Inp, Out> where Self: NoiseFn { | |
type Output = $op_ty<Inp, Out, Self, O>; | |
fn $op_fn(self, o: O) -> Self::Output { | |
Self::Output { a: self, b: o, _p: PhantomData } | |
} | |
} | |
} | |
} | |
// AddFn | |
#[derive(Copy, Clone)] | |
struct AddFn<Inp: Copy + Clone, Out: Copy + Clone, A: NoiseFn, B: NoiseFn> { | |
a: A, | |
b: B, | |
_p: PhantomData<(Inp, Out)>, | |
} | |
impl< | |
Inp: Copy + Clone, | |
Out: Copy + Clone + Add, | |
A: NoiseFn<Inp=Inp, Out=Out>, | |
B: NoiseFn<Inp=Inp, Out=Out>, | |
> NoiseFn for AddFn<Inp, Out, A, B> | |
where <Out as Add>::Output: Copy | |
{ | |
type Inp = Inp; | |
type Out = <Out as Add>::Output; | |
fn get(&self, i: Inp) -> <Out as Add>::Output { | |
self.a.get(i) + self.b.get(i) | |
} | |
} | |
impl_combiner_op!(Add, AddFn, add, AddFn); | |
// SquareFn | |
#[derive(Copy, Clone)] | |
struct SquareFn<Inp: Copy + Clone, Out: Copy + Clone, F: NoiseFn> { | |
f: F, | |
_p: PhantomData<(Inp, Out)>, | |
} | |
impl<Inp: Copy + Clone, Out: Copy + Clone, F: NoiseFn> SquareFn<Inp, Out, F> { | |
fn new(f: F) -> Self { Self { f, _p: PhantomData } } | |
} | |
impl< | |
Inp: Copy + Clone, | |
Out: Copy + Clone + Mul, | |
F: NoiseFn<Inp=Inp, Out=Out>, | |
> NoiseFn for SquareFn<Inp, Out, F> | |
where <Out as Mul>::Output: Copy | |
{ | |
type Inp = Inp; | |
type Out = <Out as Mul>::Output; | |
fn get(&self, i: Inp) -> <Out as Mul>::Output { | |
self.f.get(i) * self.f.get(i) | |
} | |
} | |
impl_modifier_op!(Add, AddFn, add, SquareFn); | |
// ConstFn | |
#[derive(Copy, Clone)] | |
struct ConstFn<Inp: Copy + Clone, Out: Copy + Clone> { | |
v: Out, | |
_p: PhantomData<Inp>, | |
} | |
impl<Inp: Copy + Clone, Out: Copy + Clone> ConstFn<Inp, Out> { | |
fn new(v: Out) -> Self { Self { v, _p: PhantomData } } | |
} | |
impl<Inp: Copy + Clone, Out: Copy + Clone> NoiseFn for ConstFn<Inp, Out> { | |
type Inp = Inp; | |
type Out = Out; | |
fn get(&self, _i: Inp) -> Out { | |
self.v | |
} | |
} | |
impl_generator_op!(Add, AddFn, add, ConstFn); | |
// Example | |
fn main() { | |
let func = ConstFn::new(5) + SquareFn::new(ConstFn::new(2) + ConstFn::new(3)); | |
println!("Hello, world! Result = {}", func.get(2)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TODO:
Clean up implementation of
NoiseFn
traitUse
Into<T>
forNoiseFn::get
andMyNoise::new
arguments