How do I make a class generic for all Numeric Types?

前端 未结 3 1357
南笙
南笙 2020-12-29 04:28

I am trying to create a Vector class that is generic for all numeric types. my original attempt was to write a class for all Types like this:

class Vector3f(         


        
3条回答
  •  借酒劲吻你
    2020-12-29 05:09

    The short answer is: you can't get full performance. Or at least I haven't found anything that gives full performance. (And I have tried for a while in exactly this use case; I gave up and wrote a code generator instead, especially since you can't handle different vector sizes generically either.)

    I'd be delighted to be shown otherwise, but thus far everything I've tried has had a small (30%) to vast (900%) increase in runtime.


    Edit: here's a test showing what I mean.

    object Specs {
      def ptime[T](f: => T): T = {
        val t0 = System.nanoTime
        val ans = f
        printf("Elapsed: %.3f s\n",(System.nanoTime-t0)*1e-9)
        ans
      }
      def lots[T](n: Int, f: => T): T = if (n>1) { f; lots(n-1,f) } else f
    
      sealed abstract class SpecNum[@specialized(Int,Double) T] {
        def plus(a: T, b: T): T
      }
    
      implicit object SpecInt extends SpecNum[Int] {
        def plus(a: Int, b: Int) = a + b
      }
    
      final class Vek[@specialized(Int,Double) T](val x: T, val y: T) {
        def +(v: Vek[T])(implicit ev: SpecNum[T]) = new Vek[T](ev.plus(x,v.x), ev.plus(y,v.y))
      }
    
      final class Uek[@specialized(Int,Double) T](var x: T, var y: T) {
        def +=(u: Uek[T])(implicit ev: SpecNum[T]) = { x = ev.plus(x,u.x); y = ev.plus(y,u.y); this }
      }
    
      final class Veq(val x: Int, val y: Int) {
        def +(v: Veq) = new Veq(x + v.x, y + v.y)
      }
    
      final class Ueq(var x: Int, var y: Int) {
        def +=(u: Ueq) = { x += u.x; y += u.y; this }
      }
    
      def main(args: Array[String]) {
        for (i <- 1 to 6) {
          ptime(lots(1000000,{val v = new Vek[Int](3,5); var u = new Vek[Int](0,0); var i=0; while (i<100) { u = (u+v); i += 1 }; u}))
          ptime(lots(1000000,{val v = new Veq(3,5); var u = new Veq(0,0); var i=0; while (i<100) { u = (u+v); i += 1 }; u}))
          ptime(lots(1000000,{val v = new Uek[Int](3,5); val u = new Uek[Int](0,0); var i=0; while (i<100) { u += v; i += 1 }; u}))
          ptime(lots(1000000,{val v = new Ueq(3,5); val u = new Ueq(0,0); var i=0; while (i<100) { u += v; i += 1 }; u}))
        }
      }
    }
    

    and the output:

    Elapsed: 0.939 s
    Elapsed: 0.535 s
    Elapsed: 0.077 s
    Elapsed: 0.075 s
    Elapsed: 0.947 s
    Elapsed: 0.352 s
    Elapsed: 0.064 s
    Elapsed: 0.063 s
    Elapsed: 0.804 s
    Elapsed: 0.360 s
    Elapsed: 0.064 s
    Elapsed: 0.062 s
    Elapsed: 0.521 s  <- Immutable specialized with custom numeric
    Elapsed: 0.364 s  <- Immutable primitive type
    Elapsed: 0.065 s  <- Mutable specialized with custom numeric
    Elapsed: 0.065 s  <- Mutable primitive type
    ...
    

提交回复
热议问题