mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
7e0a09feec
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
181 lines
7.2 KiB
C
181 lines
7.2 KiB
C
/* clang-format off */
|
|
//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements single-precision soft-float division
|
|
// with the IEEE-754 default rounding (to nearest, ties to even).
|
|
//
|
|
// For simplicity, this implementation currently flushes denormals to zero.
|
|
// It should be a fairly straightforward exercise to implement gradual
|
|
// underflow with correct rounding.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
__static_yoink("huge_compiler_rt_license");
|
|
|
|
#define SINGLE_PRECISION
|
|
#include "libc/literal.h"
|
|
#include "third_party/compiler_rt/fp_lib.inc"
|
|
|
|
COMPILER_RT_ABI fp_t
|
|
__divsf3(fp_t a, fp_t b) {
|
|
|
|
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
|
|
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
|
|
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
|
|
|
|
rep_t aSignificand = toRep(a) & significandMask;
|
|
rep_t bSignificand = toRep(b) & significandMask;
|
|
int scale = 0;
|
|
|
|
// Detect if a or b is zero, denormal, infinity, or NaN.
|
|
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
|
|
|
const rep_t aAbs = toRep(a) & absMask;
|
|
const rep_t bAbs = toRep(b) & absMask;
|
|
|
|
// NaN / anything = qNaN
|
|
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
|
// anything / NaN = qNaN
|
|
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
|
|
|
if (aAbs == infRep) {
|
|
// infinity / infinity = NaN
|
|
if (bAbs == infRep) return fromRep(qnanRep);
|
|
// infinity / anything else = +/- infinity
|
|
else return fromRep(aAbs | quotientSign);
|
|
}
|
|
|
|
// anything else / infinity = +/- 0
|
|
if (bAbs == infRep) return fromRep(quotientSign);
|
|
|
|
if (!aAbs) {
|
|
// zero / zero = NaN
|
|
if (!bAbs) return fromRep(qnanRep);
|
|
// zero / anything else = +/- zero
|
|
else return fromRep(quotientSign);
|
|
}
|
|
// anything else / zero = +/- infinity
|
|
if (!bAbs) return fromRep(infRep | quotientSign);
|
|
|
|
// one or both of a or b is denormal, the other (if applicable) is a
|
|
// normal number. Renormalize one or both of a and b, and set scale to
|
|
// include the necessary exponent adjustment.
|
|
if (aAbs < implicitBit) scale += normalize(&aSignificand);
|
|
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
|
|
}
|
|
|
|
// Or in the implicit significand bit. (If we fell through from the
|
|
// denormal path it was already set by normalize( ), but setting it twice
|
|
// won't hurt anything.)
|
|
aSignificand |= implicitBit;
|
|
bSignificand |= implicitBit;
|
|
int quotientExponent = aExponent - bExponent + scale;
|
|
|
|
// Align the significand of b as a Q31 fixed-point number in the range
|
|
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
|
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
|
// is accurate to about 3.5 binary digits.
|
|
uint32_t q31b = bSignificand << 8;
|
|
uint32_t reciprocal = UINT32_C(0x7504f333) - q31b;
|
|
|
|
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
|
//
|
|
// x1 = x0 * (2 - x0 * b)
|
|
//
|
|
// This doubles the number of correct binary digits in the approximation
|
|
// with each iteration, so after three iterations, we have about 28 binary
|
|
// digits of accuracy.
|
|
uint32_t correction;
|
|
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
correction = -((uint64_t)reciprocal * q31b >> 32);
|
|
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
|
|
|
// Exhaustive testing shows that the error in reciprocal after three steps
|
|
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
|
|
// expectations. We bump the reciprocal by a tiny value to force the error
|
|
// to be strictly positive (in the range [0x1.4fdfp-37,0x1.287246p-29], to
|
|
// be specific). This also causes 1/1 to give a sensible approximation
|
|
// instead of zero (due to overflow).
|
|
reciprocal -= 2;
|
|
|
|
// The numerical reciprocal is accurate to within 2^-28, lies in the
|
|
// interval [0x1.000000eep-1, 0x1.fffffffcp-1], and is strictly smaller
|
|
// than the true reciprocal of b. Multiplying a by this reciprocal thus
|
|
// gives a numerical q = a/b in Q24 with the following properties:
|
|
//
|
|
// 1. q < a/b
|
|
// 2. q is in the interval [0x1.000000eep-1, 0x1.fffffffcp0)
|
|
// 3. the error in q is at most 2^-24 + 2^-27 -- the 2^24 term comes
|
|
// from the fact that we truncate the product, and the 2^27 term
|
|
// is the error in the reciprocal of b scaled by the maximum
|
|
// possible value of a. As a consequence of this error bound,
|
|
// either q or nextafter(q) is the correctly rounded
|
|
rep_t quotient = (uint64_t)reciprocal*(aSignificand << 1) >> 32;
|
|
|
|
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
|
// In either case, we are going to compute a residual of the form
|
|
//
|
|
// r = a - q*b
|
|
//
|
|
// We know from the construction of q that r satisfies:
|
|
//
|
|
// 0 <= r < ulp(q)*b
|
|
//
|
|
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
|
|
// already have the correct result. The exact halfway case cannot occur.
|
|
// We also take this time to right shift quotient if it falls in the [1,2)
|
|
// range and adjust the exponent accordingly.
|
|
rep_t residual;
|
|
if (quotient < (implicitBit << 1)) {
|
|
residual = (aSignificand << 24) - quotient * bSignificand;
|
|
quotientExponent--;
|
|
} else {
|
|
quotient >>= 1;
|
|
residual = (aSignificand << 23) - quotient * bSignificand;
|
|
}
|
|
|
|
const int writtenExponent = quotientExponent + exponentBias;
|
|
|
|
if (writtenExponent >= maxExponent) {
|
|
// If we have overflowed the exponent, return infinity.
|
|
return fromRep(infRep | quotientSign);
|
|
}
|
|
|
|
else if (writtenExponent < 1) {
|
|
// Flush denormals to zero. In the future, it would be nice to add
|
|
// code to round them correctly.
|
|
return fromRep(quotientSign);
|
|
}
|
|
|
|
else {
|
|
const bool round = (residual << 1) > bSignificand;
|
|
// Clear the implicit bit
|
|
rep_t absResult = quotient & significandMask;
|
|
// Insert the exponent
|
|
absResult |= (rep_t)writtenExponent << significandBits;
|
|
// Round
|
|
absResult += round;
|
|
// Insert the sign and return
|
|
return fromRep(absResult | quotientSign);
|
|
}
|
|
}
|
|
|
|
#if defined(__ARM_EABI__)
|
|
#if defined(COMPILER_RT_ARMHF_TARGET)
|
|
AEABI_RTABI fp_t __aeabi_fdiv(fp_t a, fp_t b) {
|
|
return __divsf3(a, b);
|
|
}
|
|
#else
|
|
AEABI_RTABI fp_t __aeabi_fdiv(fp_t a, fp_t b) COMPILER_RT_ALIAS(__divsf3);
|
|
#endif
|
|
#endif
|