Scala专门化用于原始类型的数值运算
发布时间:2020-12-16 21:30:39 所属栏目:安全 来源:网络整理
导读:我写了一个简单的数学函数: def clamp(num: Double,min: Double,max: Double) = if (num min) min else if (num max) max else num 这很简单,直到我需要与Long类型相同的功能.我用类型参数和专业化来概括它: import Ordering.Implicits._def clamp[@specia
我写了一个简单的数学函数:
def clamp(num: Double,min: Double,max: Double) = if (num < min) min else if (num > max) max else num 这很简单,直到我需要与Long类型相同的功能.我用类型参数和专业化来概括它: 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 它工作,但我发现字节码在引擎盖下进行了大量的装箱和拆箱: 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; } 有没有更好的方法来进行无拳击的广义算术运算? 解决方法
spire project绝对是寻找高性能数值抽象的最佳选择.它的所有类型类都专门用于常见类型,如long,double,float,int.
这是使用spire类型类的方法: import spire.algebra._ import spire.implicits._ def clamp[@specialized T:Order](a: T,min: T,max: T) = if(a < min) min else if(a > max) max else a 这里是专门的字节码(长版本),使用:scala REPL中的javap提取: public long clamp$mJc$sp(long,long,spire.algebra.Order<java.lang.Object>); descriptor: (JJJLspire/algebra/Order;)J flags: ACC_PUBLIC Code: stack=5,locals=8,args_size=5 0: aload 7 2: lload_1 3: lload_3 4: invokeinterface #96,5 // InterfaceMethod spire/algebra/Order.lt$mcJ$sp:(JJ)Z 9: ifeq 16 12: lload_3 13: goto 35 16: aload 7 18: lload_1 19: lload 5 21: invokeinterface #99,5 // InterfaceMethod spire/algebra/Order.gt$mcJ$sp:(JJ)Z 26: ifeq 34 29: lload 5 31: goto 35 34: lload_1 35: lreturn 正如你所看到的,它正在调用spire.algebra.Order的gt方法的长专用版本,所以没有涉及到拳击. 您还可以注意到,从运算符(<和>)到类型类方法调用的转换不会出现在代码中.这背后的机制非常精细.请参阅Erik Osheim的这篇blog post,他是尖顶的主要作者之一. 但最重要的是,即使代码是通用的,结果也非常快. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |