Hat diese Implementierung jedes undefiniertes Verhalten von frexp?

stimmen
0

Ich habe eine benutzerdefinierte Version von gebaut frexp:

auto frexp(float f) noexcept
{
    static_assert(std::numeric_limits<float>::is_iec559);

    uint32_t u;
    std::memcpy(&u, &f, sizeof(float)); // well defined bit transformation from float to int

    int exp = ((u >> 23) & 0xff) - 126; // extract the 8 bits of the exponent (it has an offset of 126)

    // divide by 2^exp (leaving mantissa intact while placing 0 into the exponent)
    u &= ~(0xff << 23); // zero out the exponent bits
    u |= 126 << 23; // place 126 into exponent bits (representing 0)

    std::memcpy(&f, &u, sizeof(float)); // copy back to f
    return std::make_pair(exp, f);
}

Durch die Überprüfung is_iec559ich dafür sorgen , dass floaterfüllt

die Anforderungen der IEC 559 (IEEE 754) Standard.

Meine Frage ist: Bedeutet das , dass die Bit - Operationen ich tue gut definiert sind und tun , was ich will? Wenn nicht, gibt es eine Möglichkeit , es zu beheben?

Getestet habe ich es für einige zufällige Werte und es scheint korrekt zu sein, zumindest auf 10 Fenster mit msvc kompiliert und auf wandbox . Beachten Sie jedoch, dass (absichtlich) Ich bin nicht den Rand der Bearbeitung von Fällen 0, NaNund inf.

Wenn jemand fragt , warum ich das tue: In Benchmarks fand ich , dass diese Version von frexpbis zu 15 mal schneller als std::frexpunter Windows 10. Ich nicht anderen Plattformen noch nicht getestet haben. Aber ich möchte sicherstellen, dass dies nicht nur funktioniert durch übereinstimmt und kann Bremse in Zukunft.

Veröffentlicht am 09/10/2019 um 17:58
quelle vom benutzer
In anderen Sprachen...                            


1 antworten

stimmen
0

„Heißt das, dass die Bit-Operationen ich tue gut definiert ...“

Der TL; DR ;, durch die strenge Definition von „gut definierte“: keine .

Ihre Annahmen sind wahrscheinlich richtig , aber nicht gut definiert , weil es keine Garantien über die Bit - Breite sind, oder die Umsetzung float. Aus § 3.9.1:

gibt es drei Gleitkomma-Typen: float, double und long double. Die Art bietet Doppel mindestens so viel Präzision wie Schwimmer und der Art lange bietet Doppel mindestens so viel Präzision wie double. Der Satz von Werten vom Typ float ist eine Teilmenge der Menge von Werten vom Typ double; der Satz von Werten des Typs Doppel ist eine Teilmenge der Menge von Werten vom Typ long double. Der Wert Darstellung Gleitkommatypen ist implementierungsdefiniert ist.

Die is_iec559Klausel qualifiziert nur mit:

Wahr, wenn und nur wenn der Typ haftet nach IEC 559 Standard

Wenn eine wörtliche Genie Sie einen schrecklichen Compiler geschrieben und machte float= binary16 , double= binary32 und long double= binary64 und machte is_iec559gilt für alle Typen, wäre es noch mit dem Standard entsprechen.

Heißt das, dass ich Exponent und Mantisse in einer gut definierten Weise extrahieren?

Der TL; DR ;, durch die begrenzte Garantien des C ++ Standard: keine .

Angenommen , Sie verwenden float32_tund is_iec559ist wahr, und logisch aus allen Regeln abgeleitet , dass es nur sein könnte binary32 ohne Falle Darstellungen, und Sie richtig argumentiert , dass memcpyein gut für die Konvertierung zwischen arithmetischen Typen der gleichen Breite definiert ist, und wird nicht strict Aliasing. Selbst mit all diesen Annahmen könnte das Verhalten gut definiert , aber es ist nur wahrscheinlich , und nicht garantiert , dass Sie die Mantisse auf diese Weise extrahieren.

Der IEEE 754 - Standard und 2-Komplement bezüglich Bitkette Kodierungen , und das Verhalten der memcpyunter Verwendung beschrieben Bytes . Während es plausibel ist die Bitfolge zu übernehmen uint32_tund float32_twürde die gleiche Art und Weise (zB gleiche Endian) codiert wird, gibt es keine Garantie im Standard dafür. Wenn die Bit - Strings anders gespeichert und Sie verschieben und die kopierten Integer - Darstellung maskieren die Mantisse zu bekommen, wird die Antwort falsch sein, trotz des memcpyVerhalten gut definiert ist.

Wie in den Kommentaren erwähnt, könnte Endianess ein Thema sein. Weiß das jemand?

Mindestens einige Architekturen haben verschiedene Endian für Gleitkommaregister und Integer - Register verwendet. Das gleiche Link sagt , dass mit Ausnahme von kleinen Embedded - Prozessoren, dies kein Problem ist. Ich vertraue darauf , Wikipedia vollständig für alle Themen und lehnen jede weitere Forschung zu tun.

Beantwortet am 16/12/2019 um 22:55
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more