====== std.mathx — genaue Elementarfunktionen ====== exp, log, sin, cos, tan und atan mit ordentlicher Argumentreduktion — dazu die Genauigkeitsvarianten ''expm1''/''log1p'', die hyperbolischen Funktionen und den Zugriff auf die Exponentenebene. → [[lyx_-_programmiersprache:units:mathematik|Mathematik-Units]] · [[lyx_-_programmiersprache:units:feq|std.feq]] · [[lyx_-_programmiersprache:units:math|std.math]] · [[lyx_-_programmiersprache:units:complex|std.complex]] import std.mathx; Schicht 1, hängt an [[lyx_-_programmiersprache:units:feq|std.feq]], ''std.math'' und ''std.alloc''. 29 Funktionen. Alle Beispiele mit ''lyxc 1.0.21A'' übersetzt und ausgeführt. ---- ===== Warum es diese Unit gibt ===== ''ExpF64'' und ''LogF64'' aus ''std.math'' tragen rund **1e−7** relativen Fehler — die halbe Genauigkeit, die ''f64'' hergibt. Alles, was darauf aufbaut, erbt das: ''PowF64'' (ist ''exp∘log''), Gamma, sämtliche Verteilungen, Entropien. Der Unterschied lässt sich nicht mit ''PrintF64'' zeigen — sechs Nachkommastellen verdecken ihn. Über die Bitmuster ist er eindeutig: unit main; import std.io; import std.string; import std.math; import std.feq; import std.mathx; fn ZB(t: pchar, v: f64): void { Print(t); PrintLn(IntToStr(FeqBits(v))); } fn main(): int64 { ZB("Bits MxLog(1000) : ", MxLog(1000.0)); ZB("Bits LogF64(1000) : ", LogF64(1000.0)); ZB("Bits MxExp(10) : ", MxExp(10.0)); ZB("Bits ExpF64(10) : ", ExpF64(10.0)); return 0; } Bits MxLog(1000) : 4619463459452485536 Bits LogF64(1000) : 4619463459373954948 Bits MxExp(10) : 4671783802770883936 Bits ExpF64(10) : 4671783802770877367 ^ Funktion ^ Abstand zum exakten Wert ^ | ''MxLog(1000)'' | **0 ULP** — bitgenau | | ''LogF64(1000)'' | 78 530 588 ULP | | ''MxExp(10)'' | **0 ULP** — bitgenau | | ''ExpF64(10)'' | 6 569 ULP | Die ''Mx''-Fassungen treffen das Bitmuster der Referenzrechnung **exakt**. Bei ''LogF64'' liegen dazwischen über 78 Millionen darstellbare Zahlen. > **Wo das zählt und wo nicht.** Für eine Anzeige mit zwei Nachkommastellen ist 1e−7 belanglos. Sobald ein Ergebnis aber **weiterverrechnet** wird — Produkte vieler Logarithmen, Iterationen, Differenzen fast gleicher Werte —, wächst der Fehler mit. Eine Verteilungsfunktion, die intern zwanzig Mal ''exp'' aufruft, hat am Ende keine sieben Stellen mehr. ---- ===== Argumentreduktion ===== ''MxSin'' und ''MxCos'' zerlegen π/2 in **sechs 21-Bit-Stücke**. Das klingt umständlich, ist aber der Grund, warum sie bei großen Argumenten noch etwas Sinnvolles liefern: bei ''sin(1e16)'' entscheidet die Genauigkeit der π/2-Darstellung darüber, welcher Punkt der Periode überhaupt getroffen wird. > **''SinF64'' aus ''std.math'' rechnet bei großen Argumenten falsch** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1537|#1537]]) — ''sin(1e16)'' ergibt dort 0,909 statt 0,780; bei 1e12 stimmen noch etwa vier Stellen. Zusätzlich ist die **installierte** Standardbibliothek veralteter als das Repository ([[https://github.com/SEOLizer/LyX-Compiler/issues/1578|#1578]]) und liefert für ''SinF64(−6,282895)'' den Wert ''−11,89'' — außerhalb des Wertebereichs. > > ''MxSin''/''MxCos'' umgehen beides und sind zugleich **unabhängig davon, welche Fassung der Standardbibliothek installiert ist**. ''MxSinCos(x, sinAddr, cosAddr)'' rechnet beide auf einmal und spart die zweite Reduktion — bei Drehfaktoren und Koordinatentransformationen die günstigere Form. ---- ===== ''atan2'' — der zweite Reparaturfall ===== > **''Atan2F64'' achtet seit [[https://github.com/SEOLizer/LyX-Compiler/issues/1577|#1577]] auf das Vorzeichen der Null** — die Fallreihenfolge folgt C99 F.10.1.4, ''atan2(-0.0, -1.0)'' ergibt ''-π''. Was bleibt, ist die Genauigkeit von etwa zehn Stellen; dafür gibt es ''MxAtan2''. Das Vorzeichen der Null ist kein Spitzfindigkeit: bei komplexen Verzweigungsschnitten und bei Winkeln nahe π entscheidet es darüber, ob das Ergebnis ''+π'' oder ''−π'' lautet. ---- ===== Genauigkeitsvarianten ===== var x: f64 := 0.000000001; MxExpm1(x) // exp(x) - 1, ohne Auslöschung MxLog1p(x) // log(1 + x), ohne Auslöschung Bei kleinem ''x'' ist ''exp(x)'' fast genau 1. Die Differenz ''exp(x) − 1'' löscht dann die führenden Stellen aus — von 16 Stellen bleiben bei ''x = 1e−9'' noch etwa sieben. ''MxExpm1'' rechnet die Differenz **direkt** und behält alle Stellen. Das ist der Normalfall in der Zinsrechnung (kleine Zinssätze über kurze Zeiträume) und in der Wahrscheinlichkeitsrechnung (Wahrscheinlichkeiten nahe 0 oder 1). ---- ===== Funktionsübersicht ===== ^ Gruppe ^ Funktionen ^ | Exponential und Logarithmus | ''MxExp'' · ''MxLog'' · ''MxLog2'' · ''MxLog10'' · ''MxExp2'' · ''MxExp10'' · ''MxPow'' | | Genauigkeitsvarianten | ''MxExpm1'' · ''MxLog1p'' | | Winkelfunktionen | ''MxSin'' · ''MxCos'' · ''MxTan'' · ''MxSinCos'' · ''MxAtan'' · ''MxAtan2'' | | Hyperbolisch | ''MxSinh'' · ''MxCosh'' · ''MxTanh'' · ''MxAsinh'' · ''MxAcosh'' · ''MxAtanh'' | | Wurzeln und Reste | ''MxCbrt'' · ''MxFmod'' · ''MxRemainder'' | | Exponentenebene | ''MxLdexp'' · ''MxFrexp'' · ''MxScalbn'' · ''MxCopySign'' · ''MxModf'' | > **''MxFmod'' und ''MxRemainder'' sind nicht dasselbe.** Für ''7,5'' und ''2'' liefert ''MxFmod'' den Wert ''1,5'' — den Rest mit dem Vorzeichen des Dividenden, wie ''%'' bei Ganzzahlen. ''MxRemainder'' liefert ''−0,5'': den Rest zum **nächstgelegenen** Vielfachen, also stets betragsmäßig höchstens die Hälfte des Divisors. Für Winkelnormalisierung ist ''MxRemainder'' die richtige Wahl, für „wie viel bleibt übrig" ''MxFmod''. Die Exponentenfunktionen arbeiten auf der Bitdarstellung: ''MxLdexp(x, n)'' multipliziert mit ''2ⁿ'' ohne zu rechnen, ''MxFrexp'' zerlegt in Mantisse und Exponent, ''MxModf'' in Vor- und Nachkommateil. ---- ===== Offener Punkt ===== > **Nicht alles im Bestand nutzt die genauen Fassungen.** ''QuatExp'', ''ProbLogGamma'' und die Verteilungen in [[lyx_-_programmiersprache:units:prob|std.prob]] rufen weiterhin ''ExpF64''/''LogF64'' auf und erben deren 1e−7. Ebenso rechnen ''fft'', ''tensor'', ''autodiff'', ''prob'' und ''quat'' die Winkelfunktionen über ''SinF64''/''CosF64'' — sie sind damit davon abhängig, welche Fassung der Standardbibliothek eingebunden ist. Eine Umstellung auf ''MxSinCos'' ist vorgeschlagen, aber nicht entschieden. ---- Letzte Aktualisierung: 2026-08-16 · alle Beispiele mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die Genauigkeit über Bitmuster gegen eine unabhängige Referenzrechnung gemessen, nicht über die Textausgabe.