I wrote a function that does simple math:
def clamp(num: Double, min: Double, max: Double) = if (num < min) min else if (num > max) max else num
It is very simple until I needed the same function with a long type. I generalized it with type parameter and specialization:
import Ordering.Implicits._ def clamp[@specialized N: Ordering](num: N, min: N, max: N) = if (num < min) min else if (num > max) max else num
This works, but I found that the bytecode does a lot of boxing and unpacking under the hood:
public boolean clamp$mZc$sp(boolean num, boolean min, boolean max, Ordering<Object> evidence$1) { return Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToBoolean(num), evidence$1).$greater(BoxesRunTime.boxToBoolean(max)) ? max : Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToBoolean(num), evidence$1).$less(BoxesRunTime.boxToBoolean(min)) ? min : num; } public byte clamp$mBc$sp(byte num, byte min, byte max, Ordering<Object> evidence$1) { return Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToByte(num), evidence$1).$greater(BoxesRunTime.boxToByte(max)) ? max : Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToByte(num), evidence$1).$less(BoxesRunTime.boxToByte(min)) ? min : num; } public char clamp$mCc$sp(char num, char min, char max, Ordering<Object> evidence$1) { return Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToCharacter(num), evidence$1).$greater(BoxesRunTime.boxToCharacter(max)) ? max : Ordering.Implicits..MODULE$.infixOrderingOps(BoxesRunTime.boxToCharacter(num), evidence$1).$less(BoxesRunTime.boxToCharacter(min)) ? min : num; }
Is there a better way to do general arithmetic without boxing?
source share