Skip to content

Instantly share code, notes, and snippets.

@zesterer
Last active August 26, 2018 01:04
Show Gist options
  • Save zesterer/63a321489dc45fc300c7e3fc6d2ba4aa to your computer and use it in GitHub Desktop.
Save zesterer/63a321489dc45fc300c7e3fc6d2ba4aa to your computer and use it in GitHub Desktop.
Typed noise implementation
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));
}
@zesterer
Copy link
Author

TODO:

  • Clean up implementation of NoiseFn trait

  • Use Into<T> for NoiseFn::get and MyNoise::new arguments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment