2012-02-29 12 views
16

Sto cercando di implementare l'operazione di riduzione del campo per la trigonometria. Ma invece penso che potrebbe essere meglio eseguire semplicemente un'operazione modulo pi/2 sui dati in entrata. Mi chiedevo quali algoritmi esistono e sono efficienti per questa operazione per IEEE 754 a virgola mobile a 32 bit?Funzionamento modulo Floating Point

Devo implementarlo in assembly, quindi fmod, divisione, moltiplicazione, ecc. Non sono disponibili con un'unica istruzione. Il mio processore usa parole a 16 bit e ho implementato addizione a virgola mobile a 32 bit, sottrazione, moltiplicazione, divisione, radice quadrata, coseno e seno. Ho solo bisogno di ridurre la gamma (modulo) per l'immissione di valori a coseno e seno.

+4

In realtà ci sono un sacco di algoritmi intelligenti per esempio google per "riduzione del range di payne hanek", ma penso che non sia quello che vuoi – hirschhornsalz

+1

Il documento di Ng a cui ti sei collegato in una precedente domanda correlata spiega in realtà il Payne-Hanek algoritmo, che AFAIK è ancora lo stato dell'arte per una riduzione del range accurata. Devi solo adattarlo alla precisione singola. – janneb

+0

@Everyone, cancellare/modificare la risposta in modo che si applichi alla mia domanda effettiva. Sto cercando l'algoritmo all'interno di un modulo a virgola mobile. Devo implementare ciò che fa fmod e minimizzare il numero di divisioni che eseguo. – Veridian

risposta

14

Penso di fmod() libreria standard sarà la scelta migliore nella maggior parte dei casi. Ecco uno link per una discussione di diversi semplici algoritmi.

Sulla mia macchina, fmod() usi codice inline ottimizzato di montaggio (/usr/include/bits/mathinline.h):

#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) 
__inline_mathcodeNP2 (fmod, __x, __y, \ 
    register long double __value;       \ 
    __asm __volatile__         \ 
    ("1: fprem\n\t"       \ 
    "fnstsw %%ax\n\t"        \ 
    "sahf\n\t"         \ 
    "jp 1b"        \ 
    : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");   \ 
    return __value) 
#endif 

Così è in realtà utilizza un'istruzione CPU dedicato (fprem) per il calcolo.

+0

Oh, in realtà sto cercando di implementare ciò che fa fmod. Questo è il problema, sto cercando l'algoritmo del modulo per virgola mobile. – Veridian

+0

La forma più diretta è probabilmente (codice preso da link nel mio post, ma è una specie di definizione del modulo per virgola mobile e quindi il modo ovvio di farlo): template T fmod (T x, T y) { T a = (T) (long long) (x/y); restituisce x - a * y; } –

+0

Sono un po 'preoccupato di arrotondare quel prodotto * y, ma non sono sicuro di come mitigarlo. – zmccord

12

Forse mi manca il punto qui, ma avete qualcosa contro semplicemente usando fmod?

double theta = 10.4; 
const double HALF_PI = 2 * atan(1); 
double result = fmod(theta, HALF_PI); 
+0

Vale quindi un voto positivo. –

+0

Oh, in realtà sto cercando di implementare ciò che fa fmod. Questo è il problema, sto cercando l'algoritmo del modulo per virgola mobile. – Veridian

+2

'fmod' è ok se non ti interessa la precisione con argomenti grandi. – hirschhornsalz

7

L'algoritmo che si desidera, per limitare un punto value mobile compreso tra 0 e alcuni modulo n:

Double fmod(Double value, Double modulus) 
{ 
    return value - Trunc(value/modulus)*modulus; 
} 

ad esempio pi mod e (3,14159265358979 mod 2,718281828459045)

3.14159265358979/2.718281828459045 
    = 1.1557273497909217179 

Trunc(1.1557273497909217179) 
    = 1 

1.1557273497909217179 - 1 
    = 0.1557273497909217179 

0.1557273497909217179 * e 
    = 0.1557273497909217179 * 2.718281828459045 
    = 0.42331082513074800 

pi mod e = 0.42331082513074800

+2

Questo è stato particolarmente utile per me perché - anche se la domanda iniziale è stata posta nel contesto della programmazione C/C++, sono giunto a questa particolare domanda che necessitava di una formula generale per fare questo in un sistema di numeri in virgola fissa in cui lavoro. Sono contento che tu abbia postato questo, perché fmod() non era una soluzione ai miei bisogni, anche se potrebbe essere stato per l'OP. Ci sono molte persone che hanno bisogno di questa particolare formula in altri contesti. –

+0

Questo può essere [molto impreciso per grandi 'value's] (https://stackoverflow.com/questions/9505513/floating-point-modulo-operation/37977740#comment12038890_9505761). Ci sono algoritmi più sofisticati. Ma di solito è abbastanza veloce, quindi è una buona scelta se è numericamente ok per il tuo caso d'uso. –