I wrote a function doing 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 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
It works, but I found that the bytecode does lots of boxing and unboxing 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 any better way to do generalized arithmetic operations without boxing?