Skip to content

Instantly share code, notes, and snippets.

@milibopp
Created December 16, 2014 13:03
Show Gist options
  • Save milibopp/5ab39051f0b09620f824 to your computer and use it in GitHub Desktop.
Save milibopp/5ab39051f0b09620f824 to your computer and use it in GitHub Desktop.
Compare Vector3 implementations
struct Addition;
struct Multiplication;
trait Group<Op> {
fn group_op(&self, rhs: &Self) -> Self;
fn unital() -> Self;
fn inverse(&self) -> Self;
}
trait AddGroup<AddOp>: Group<AddOp> {}
trait Field<AddOp, MulOp>: AddGroup<AddOp> + Group<MulOp> {}
impl Group<Addition> for f64 {
fn group_op(&self, rhs: &f64) -> f64 { *self + *rhs }
fn unital() -> f64 { 0.0f64 }
fn inverse(&self) -> f64 { -*self }
}
impl Group<Multiplication> for f64 {
fn group_op(&self, rhs: &f64) -> f64 { *self * *rhs }
fn unital() -> f64 { 1.0f64 }
fn inverse(&self) -> f64 { 1.0f64 / *self }
}
impl AddGroup<Addition> for f64 {}
impl Field<Addition, Multiplication> for f64 {}
trait VectorSpace<F: Field<AddOp, MulOp>, AddOp, MulOp>: Group<AddOp> {
fn scalar_mul(&self, a: &F) -> Self;
}
#[deriving(Show)]
struct Vector3<F> {
pub x: F,
pub y: F,
pub z: F,
}
impl<F: Group<Op>, Op> Group<Op> for Vector3<F> {
fn group_op(&self, rhs: &Vector3<F>) -> Vector3<F> {
Vector3 {
x: self.x.group_op(&rhs.x),
y: self.y.group_op(&rhs.y),
z: self.z.group_op(&rhs.z),
}
}
fn unital() -> Vector3<F> {
Vector3 {
x: Group::unital(),
y: Group::unital(),
z: Group::unital(),
}
}
fn inverse(&self) -> Vector3<F> {
Vector3 {
x: self.x.inverse(),
y: self.y.inverse(),
z: self.z.inverse(),
}
}
}
impl<F: Field<AddOp, MulOp>, AddOp, MulOp> VectorSpace<F, AddOp, MulOp> for Vector3<F> {
fn scalar_mul(&self, a: &F) -> Vector3<F> {
Vector3 {
x: Group::<MulOp>::group_op(&self.x, a),
y: Group::<MulOp>::group_op(&self.y, a),
z: Group::<MulOp>::group_op(&self.z, a),
}
}
}
fn group_fn<G: Group<Op>, Op>(a: &G, b: &G) -> G {
a.group_op(b).group_op(b)
}
fn main() {
// Let's create a vector
let v = Vector3 { x: 1.0f64, y: 2.0, z: -3.0 };
// Adding vectors is the group operation
println!("{}", Group::<Addition>::group_op(&v, &v));
// Multiplying vectors component-wise is one, too
println!("{}", Group::<Multiplication>::group_op(&v, &v));
// Multiply by a scalar
println!("{}", v.scalar_mul(&3.0));
// Apply a group function to a vector
println!("{}", group_fn::<_, Addition>(&v, &v));
// Treat a field as a group
println!("{}", group_fn::<_, Addition>(&2.0f64, &3.0f64));
println!("{}", group_fn::<_, Multiplication>(&2.0f64, &3.0f64));
}
trait Group {
fn group_op(&self, rhs: &Self) -> Self;
fn unital() -> Self;
fn inverse(&self) -> Self;
}
trait Field {
fn add_op(&self, rhs: &Self) -> Self;
fn add_unital() -> Self;
fn add_inverse(&self) -> Self;
fn mul_op(&self, rhs: &Self) -> Self;
fn mul_unital() -> Self;
fn mul_inverse(&self) -> Self;
}
impl Field for f64 {
fn add_op(&self, rhs: &f64) -> f64 { *self + *rhs }
fn add_unital() -> f64 { 0.0f64 }
fn add_inverse(&self) -> f64 { -*self }
fn mul_op(&self, rhs: &f64) -> f64 { *self * *rhs }
fn mul_unital() -> f64 { 1.0f64 }
fn mul_inverse(&self) -> f64 { 1.0f64 / *self }
}
struct FieldAddGroup<F: Field>(F);
impl<F> Group for FieldAddGroup<F>
where F: Field + Copy
{
fn group_op(&self, rhs: &FieldAddGroup<F>) -> FieldAddGroup<F> {
let FieldAddGroup(ref lhs) = *self;
let FieldAddGroup(ref rhs) = *rhs;
FieldAddGroup(lhs.add_op(rhs))
}
fn unital() -> FieldAddGroup<F> {
FieldAddGroup(Field::add_unital())
}
fn inverse(&self) -> FieldAddGroup<F> {
let FieldAddGroup(ref x) = *self;
FieldAddGroup(x.add_inverse())
}
}
impl<F: Field> Deref<F> for FieldAddGroup<F> {
fn deref(&self) -> &F {
let FieldAddGroup(ref inner) = *self;
inner
}
}
struct FieldMulGroup<F: Field>(F);
impl<F> Group for FieldMulGroup<F>
where F: Field + Copy
{
fn group_op(&self, rhs: &FieldMulGroup<F>) -> FieldMulGroup<F> {
let FieldMulGroup(ref lhs) = *self;
let FieldMulGroup(ref rhs) = *rhs;
FieldMulGroup(lhs.mul_op(rhs))
}
fn unital() -> FieldMulGroup<F> {
FieldMulGroup(Field::mul_unital())
}
fn inverse(&self) -> FieldMulGroup<F> {
let FieldMulGroup(ref x) = *self;
FieldMulGroup(x.mul_inverse())
}
}
impl<F: Field> Deref<F> for FieldMulGroup<F> {
fn deref(&self) -> &F {
let FieldMulGroup(ref inner) = *self;
inner
}
}
trait VectorSpace<F: Field>: Group {
fn scalar_mul(&self, a: &F) -> Self;
}
#[deriving(Show)]
struct Vector3<F> {
pub x: F,
pub y: F,
pub z: F,
}
impl<F: Field> Group for Vector3<F> {
fn group_op(&self, rhs: &Vector3<F>) -> Vector3<F> {
Vector3 {
x: self.x.add_op(&rhs.x),
y: self.y.add_op(&rhs.y),
z: self.z.add_op(&rhs.z),
}
}
fn unital() -> Vector3<F> {
Vector3 {
x: Field::add_unital(),
y: Field::add_unital(),
z: Field::add_unital(),
}
}
fn inverse(&self) -> Vector3<F> {
Vector3 {
x: self.x.add_inverse(),
y: self.y.add_inverse(),
z: self.z.add_inverse(),
}
}
}
impl<F: Field> VectorSpace<F> for Vector3<F> {
fn scalar_mul(&self, a: &F) -> Vector3<F> {
Vector3 {
x: self.x.mul_op(a),
y: self.y.mul_op(a),
z: self.z.mul_op(a),
}
}
}
fn group_fn<G: Group>(a: &G, b: &G) -> G {
a.group_op(b).group_op(b)
}
fn main() {
// Let's create a vector
let v = Vector3 { x: 1.0f64, y: 2.0, z: -3.0 };
// Adding vectors is the group operation
println!("{}", v.group_op(&v));
// Multiply by a scalar
println!("{}", v.scalar_mul(&3.0));
// Apply a group function to a vector
println!("{}", group_fn(&v, &v));
// Treat a field as a group
println!("{}", *group_fn(&FieldAddGroup(2.0f64), &FieldAddGroup(3.0)));
println!("{}", *group_fn(&FieldMulGroup(2.0f64), &FieldMulGroup(3.0)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment