Credo che quello che cercava sia un modo più efficiente di approssimare 1.0/x invece di una definizione tecnica di approssimazione che afferma che si potrebbe usare 1 come risposta molto impercisa. Credo anche che questo lo soddisfi.
__inline__ double __attribute__((const)) reciprocal(unsigned long long x) {
//The type is unsigned long long, but you are restricted to a max value of 2^32-1, not
// 2^64-1 like the unsigned long long is capable of storing
union {
double dbl;
unsigned long long ull;
} u = {.dbl=(x*=x)}; // x*x = pow(x, 2)
u.ull = (0xbfcdd6a18f6a6f52ULL - u.ull) >> (unsigned char)1;
// pow(pow(x,2), -0.5) = pow(x, -1) = 1.0/x
// This is done via the 'fast' inverse square root trick
return u.dbl;
}
__inline__ double __attribute__((const)) reciprocal(double x) {
union {
double dbl;
unsigned long long ull;
} u;
u.dbl = x;
u.ull = (0xbfcdd6a18f6a6f52ULL - u.ull) >> (unsigned char)1;
// pow(x, -0.5)
u.dbl *= u.dbl; // pow(pow(x,-0.5), 2) = pow(x, -1) = 1.0/x
return u.dbl;
}
__inline__ float __attribute__((const)) reciprocal(float x) {
union {
float dbl;
unsigned uint;
} u;
u.dbl = x;
u.uint = (0xbe6eb3beU - u.uint) >> (unsigned char)1;
// pow(x, -0.5)
u.dbl *= u.dbl; // pow(pow(x,-0.5), 2) = pow(x, -1) = 1.0/x
return u.dbl;
}
Hmm ....... io feritore se la CPU produce sapeva si potrebbe ottenere il reciproco con un solo moltiplicare , sottrazione e spostamento di bit quando hanno progettato la CPU .... hmm .........
Per quanto riguarda i bench-marking, l'hardware x istruzioni in combinazione con le istruzioni hardware sottrazione sono altrettanto velocemente come hardware 1.0/x istruzioni su moderni computer al giorno (i miei punti di riferimento erano su un i7 di Intel, ma vorrei assumere risultati simili per altri processori). Tuttavia, se questo algoritmo fosse implementato nell'hardware come una nuova istruzione di assemblaggio, allora l'aumento della velocità sarebbe probabilmente abbastanza buono da rendere questa istruzione abbastanza pratica.
Infine, questa implementazione si basa sul meraviglioso "fast" inverse square root algorithm.
Questo dipende in gran parte dalla piattaforma hardware su cui stai lavorando. Inoltre, dipende anche da quanto precisione sei disposto a perdere. Ovviamente, 'float recip (float x) {return 1; } 'è molto veloce, ma non molto preciso ... –
[I reciproci a precisione singola vengono eseguiti in 5 cicli sui processori più recenti. Una moltiplicazione in virgola mobile è anche di 5 cicli.] (Http://www.agner.org/optimize/instruction_tables.pdf) Quindi dubito seriamente che otterrai qualcosa di più veloce di qualcosa come '(float) 1/(float) x'. – Mysticial
Per i principianti, qual è la tua piattaforma e il tuo compilatore? E che tipo di dati stai operando? –