2012-10-22 6 views
5

Sto scrivendo una libreria¹ in F # che fornisce alcune operazioni bit a bit, e voglio assicurarmi quante più funzioni possibili sono inline lasciare binding con parametri di tipo statico (ciò consente io per scrivere una funzione e usarla per int16, int32 e forse anche bignum con poco overhead). A un certo punto questa rotta non funzionerà sicuramente. Alcune delle funzionalità fornite da detta libreria sono alquanto complicate.Utilizzo dei parametri di tipo statico di F # e costanti numeriche di codifica

¹Nota: sono a conoscenza dei problemi relativi all'esposizione di binding inline tramite un'interfaccia pubblica.

Tuttavia, voglio estendere questo nella misura massima possibile. In questo momento, sto cercando di scrivere l'algoritmo population count in questo modulo e sto affrontando un problema. Non sono sicuro di come codificare le maschere, ad es. 0x3333..., che compaiono in questi algoritmi. Posso aggirare le costanti del turno e simili usando alcuni trucchi extra.

C'è qualche trucco che posso usare, sia tramite l'inferenza di tipo F # e parametri di tipo statico, o tramite bit-twiddling, per scrivere l'algoritmo nel modo che voglio? Esiste un modo per codificare questi tipi di costanti nella funzione statica generica?

Una domanda più vaga: ci sono alcune cose specifiche su cui posso fare affidamento per utilizzare i parametri di tipo statico al loro massimo, specialmente nel contesto dei numeri? Ad esempio, utilizzo intensamente lo GenericOne e lo GenericZero. Ci sono più cose come questa, che potrei aver perso?

+2

quanto riguarda le risorse, un trucco utile è quello di definire i numeri generici in modo da poter scrivere cioè '42G '(vedi http://stackoverflow.com/questions/4732672/how-to-write-a-function-for-generic-umbers). Ho anche scritto un articolo con alcune informazioni in più, ma penso che probabilmente non troverai molte novità lì (vedi http://tomasp.net/blog/fsharp-generic-numeric.aspx). –

+0

Usando il letterale numerico generico, puoi scrivere ie 'lasciare inline shift a = (a &&& 8G) <<< 2', ma suppongo che non sia la risposta alla tua domanda (perché potresti farlo con 'GenericOne') . Quindi, hai qualche esempio specifico più complesso in cui l'approccio diretto non funziona per te? –

+3

'0x33 ...' è ''signedtype'.MaxValue/5 * 2 + 1', ti aiuta? – harold

risposta

5

Innanzitutto, è possibile utilizzare numeric literals per evitare usi sgradevoli di GenericOne e GenericZero. Ecco un breve esempio:

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 

In secondo luogo, F # non sembra supportare generici hexa letterali numerici. Un trucco è quello di utilizzare doppi apici inversi in modo da avere i nomi indicativi:

let inline shift x = 
    let ``0x33333333G`` = 858993459G 
    ((x >>> 2) &&& ``0x33333333G``) + (x &&& ``0x33333333G``) 

// Usage 
shift 20 
shift 20L 
shift 20uy 

ci sono alcune belle domande sul SO circa letterali numerici. Io do alcuni riferimenti in caso di seguire questa strada:

+0

È interessante. Leggerò letterali numerici come questi, e analizzerò anche le domande SO che hai menzionato. Vorrei tuttavia sottolineare che, in generale, non vi è alcun problema con i letterali numerici esadecimali in F #.Forse c'è un problema con te usare i letterali 'G' ... – GregRos

+0

Sì, perché' 0x33333333I' non funziona (il che ha senso), non mi aspetto che '0x33333333G' funzioni. – pad

+0

Grazie :) Questa risposta mi ha aiutato molto. Inoltre, vorrei sottolineare che l'algoritmo per 'FromInt' non è molto efficiente. [Qui] (https://snipt.net/GregRos/-1040/) è un'implementazione migliore, sebbene funzioni solo per numeri interi. – GregRos

Problemi correlati