Question

I am writing some simple Vector and Matrix classes. They look like this:

// Vector with Floats
case class Vector3f(x: Float, y: Float, z: Float) {
  def +(v: Vector3f) = Vector3f(x + v.x, y + v.y, z + v.z)
}

// Vector with Doubles
case class Vector3d(x: Double, y: Double, z: Double) {
  def +(v: Vector3d) = Vector3d(x + v.x, y + v.y, z + v.z)
}

If I go on with further methods and classes like Point3f/d, Vector4f/d, Matrix3f/d, Matrix4f/d ... this is going to be a lot of work. Uff... So I thought generics could possible help here and remove redundancy from my code base. I thought of something like this:

// first I define a generic Vector class
case class Vector3[@specialized(Float, Double) T](x: T, y: T, z: T) {
   def +(v: Vector3[T]) = new Vector3[T](x + v.x, y + v.y, z + v.z)
}

// than I use some type aliases to hide the generic nature
type Vector3f = Vector3[Float]
type Vector3d = Vector3[Double]

The idea is that the scala compiler generates specialized classes for Vector3[Float] and Vector3[Double] similar as a C++ template would do. Unfortunately I have to put some type bound on the type parameter [T] of class Vector3 such that the operator + is defined on T. My question: How can I write Vector3[Float] that it has the same performance characteristics as Vector3f? Context: I would like to use the Vector3f / Vector3d classes in collision detection code ... so performance does matter for me.

Was it helpful?

Solution

Use a context bound of Fractional:

case class Vector3[@specialized(Float, Double) T : Fractional](x: T, y: T, z: T)  { ...

then within the body of the class, get an instance of the arithmetic operators:

  val fractOps = implicitly[Fractional[T]]

lastly import its members into the scope of the class:

  import fractOps._

Thereafter you can write ordinary infix operations on values of type T used within the class. Sadly, you will have to use fractOps.div(a, b) instead of a / b for division.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top