Gre*_*Ros 5 generics f# numbers bit-manipulation inline
我在F#中编写了一个提供一些按位操作的库¹,我想确保尽可能多的函数是inline使用静态类型参数进行绑定(这允许我编写一个函数并将其用于int16,int32也许甚至bignum只有很少的开销).这条路线肯定无法在某些时候起作用.所述库提供的一些功能有些复杂.
¹注意:我知道通过公共接口公开内联let绑定的问题.
但是,我想把它延伸到最远的程度.现在,我正在尝试以这种形式编写人口计数算法,我正面临一个问题.我不确定如何对掩码进行编码,例如0x3333...,这些算法中出现的掩码.我可以使用一些额外的技巧来绕过移位常数和类似的东西.
有没有我可以使用的技巧,无论是通过F#的类型推断和静态类型参数,还是通过bit-twiddling,以我想要的方式编写算法?有没有什么办法可以在静态泛型函数中编码这些常量?
一个更模糊的问题:我是否可以依赖一些特定的东西来充分利用静态类型参数,尤其是在数值的背景下?例如,我大量使用GenericOne和GenericZero.还有更多这样的事情,我可能错过了吗?
首先,您可以使用数字文字来避免丑陋地使用GenericOne和GenericZero.这是一个简短的例子:
module NumericLiteralG = begin
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline FromInt32 (n:int) =
let one : ^a = FromOne()
let zero : ^a = FromZero()
let n_incr = if n > 0 then 1 else -1
let g_incr = if n > 0 then one else (zero - one)
let rec loop i g =
if i = n then g
else loop (i + n_incr) (g + g_incr)
loop 0 zero
end
// Usage
let inline ten() = 10G
ten() + 1
ten() + 2L
Run Code Online (Sandbox Code Playgroud)
其次,F#似乎不支持通用的六进制数字文字.一个技巧是使用双反引号,以便您有指示性名称:
let inline shift x =
let ``0x33333333G`` = 858993459G
((x >>> 2) &&& ``0x33333333G``) + (x &&& ``0x33333333G``)
// Usage
shift 20
shift 20L
shift 20uy
Run Code Online (Sandbox Code Playgroud)
有关数字文字的SO有一些很好的问题.如果你走这条路,我会提供一些参考: