# Vector calculation in Rust

Hi I am trying to get into Rust by implementing a small library for vector calculations.

I am mainly asking to point out whether I chose a valid approach. I also am interested in comments on the overall details I might have missed or got the wrong way.

So for my Vec3 implementation I basically declared a custom type which is an array of length 3. Afterwards I am simply implementing Traits for this type. For now I only implemented it for f32.

pub type Vec3<T = f32> = [T; 3];

pub trait Vector3<T> {
/// Creates a new Vec3 with its values initialized to [0.0, 0.0, 0.0].
fn new() -> Self;

/// Creates a new Vec3 based on the given x, y and z values.
fn from_values(x: f32, y: f32, z: f32) -> Vec3<T>;

/// Calculates the scalar dot product of two Vec3's.
fn dot(a: Vec3<T>, b: Vec3<T>) -> f32;

/// Performs multiplication between two Vec3.
fn multiply(self, a: Vec3) -> Vec3;

/// Calculates the sum of two Vec3 components.Vec3
fn add(self, a: Vec3) -> Vec3;

/// Scales a Vec3 by a scalar value.
fn scale(self, x: f32) -> Vec3;
}

impl Vector3<f32> for Vec3<f32> {
/// Creates a new Vec3 with its values initialized to [0.0, 0.0, 0.0].
///
/// 
/// use glMatrix_rs::vec3::*;
///
/// let result = Vec3::new();
/// assert_eq!([0.0, 0.0, 0.0], result);
/// 
fn new() -> Vec3<f32> {
[0.0, 0.0, 0.0]
}

/// Creates a new Vec3 based on the given x, y and z values.
///
/// ### Arguments
///
/// * x - The first vector component.
/// * y - The second vector component.
/// * z - The third vector component.
///
/// 
/// use glMatrix_rs::vec3::*;
///
/// let result = Vec3::from_values(0.0, 1.0, 2.0);
/// assert_eq!([0.0, 1.0, 2.0], result);
/// 
fn from_values(x: f32, y: f32, z: f32) -> Vec3 {
[x, y, z]
}

/// Calculates the scalar dot product of two Vec3's.
///
/// ### Arguments
///
/// * a - The first vector for dot calculation.
/// * b - The second  vector for dot calculation.
///
/// 
/// use glMatrix_rs::vec3::*;
/// let a = Vec3::from_values(2.0, 2.0, 2.0);
/// let b = Vec3::from_values(2.0, 2.0, 2.0);
/// assert_eq!(12.0, Vec3::dot(a, b));
/// 
fn dot(a: Vec3, b: Vec3) -> f32 {
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}

/// Performs multiplication between two Vec3.
///
/// ### Arguments
///
/// * a - Vector by which self will be multiplied.
///
/// 
/// use glMatrix_rs::vec3::*;
/// let mut out = Vec3::new();
/// let a = Vec3::from_values(1.0, 2.0, 3.0);
/// let b = Vec3::from_values(2.0, 2.0, 2.0);
/// assert_eq!([2.0, 4.0, 6.0], a.multiply(b));
/// 
fn multiply(self, a: Vec3) -> Vec3 {
[self[0] * a[0], self[1] * a[1], self[2] * a[2]]
}

/// Calculates the sum of two Vec3 components.Vec3
///
/// ### Arguments
///
/// * a - Vector which will be added to self.
///
/// 
/// use glMatrix_rs::vec3::*;
/// let x = Vec3::from_values(1.0, 2.0, 3.0);
/// let a = Vec3::from_values(3.0, 2.0, 1.0);
/// 
fn add(self, a: Vec3) -> Vec3 {
[self[0] + a[0], self[1] + a[1], self[2] + a[2]]
}

/// Scales a Vec3 by a scalar value.
///
/// ### Arguments
///
/// * x - Scalar value by which the vector will be scaled.
///
/// 
/// use glMatrix_rs::vec3::*;
/// let a = Vec3::from_values(1.0, 2.0, 3.0);
/// assert_eq!([2.0, 4.0, 6.0], a.scale(2.0));
/// 
fn scale(self, x: f32) -> Vec3 {
[self[0] * x, self[1] * x, self[2] * x]
}
}


You can clone, build and test it any time from my GitHub repository.

My first recommendation is to use std::ops. Try writing implementations of ops::Add for addition, ops::Mul<Vec3<T>> for cross product, and ops::Mul<T> for scaler-vector multiplication. Not only does implementing these standard traits make your code more interoperable with other Rust code, but it also gives you operator overloading, so you can use + and * on your vectors.

Second, I would question the user of the trait Vector3<f32>. Why do you need a trait? I would just put your operations in the implementation of Vec3<T> itself

impl <T> Vec3<T> {

// ... methods ...

}


Looking forward to seeing your completed code. This will even more interesting once you get generics working.

• Thanks for your answer. I think I need the traits, as my type alias does not create a new type. If I try your approach I get impl requires a base type. Also see this Github issue. – チーズパン May 17 '19 at 16:14
• Oh, I missed that. If you can't have a really struct, that is very limiting. Do you have objections to using a struct with an array member instead of a type alias? – Benjamin Kuykendall May 17 '19 at 16:26