Vraag Drijvende wijs Modulo-operatie


Ik probeer de afstandsbeperking voor trigonometrie uit te voeren. Maar in plaats daarvan denk ik dat het misschien beter is om gewoon een modulo pi / 2-bewerking uit te voeren op inkomende gegevens. Ik vroeg me af welke algoritmen bestaan ​​en zijn efficiënt voor deze bewerking voor 32-bits IEEE 754 drijvende komma?

Ik moet dit implementeren tijdens de assembly, dus fmod, division, multiplication, etc. zijn niet beschikbaar voor mij met slechts één instructie. Mijn processor gebruikt 16-bits woorden en ik heb 32-bits drijvende-komma optellen, aftrekken, vermenigvuldigen, delen, vierkantswortel, cosinus en sinus geïmplementeerd. Ik heb alleen een afstandsvermindering (modulus) nodig om waarden in te voeren voor cosinus en sinus.


16
2018-02-29 19:38


oorsprong


antwoorden:


Ik denk dat standaardbibliotheek fmod() zal in de meeste gevallen de beste keuze zijn. Hier is een link tot een bespreking van verschillende eenvoudige algoritmen.

Op mijn machine, fmod() maakt gebruik van geoptimaliseerde inline-assemblagecode (/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

Dus het gebruikt eigenlijk een speciale CPU-instructie (fprem) voor de berekening.


14
2018-02-29 20:01



Misschien mis ik hier het punt, maar heb je iets tegen gewoon gebruiken FMOD?

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

13
2018-02-29 20:01



Het gewenste algoritme om een ​​zwevend punt te beperken value tussen 0 en enige modulus n:

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

bijvoorbeeld 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


8
2018-06-22 20:31