cljs.math/IEEE-remainder

functionsince v1.11.50Edit
(IEEE-remainder dividend divisor)

Source docstring:
Returns the remainder per IEEE 754 such that
 remainder = dividend - divisor * n
where n is the integer closest to the exact value of dividend / divisor.
If two integers are equally close, then n is the even one.
If the remainder is zero, sign will match dividend.
If dividend or divisor is ##NaN, or dividend is ##Inf or ##-Inf, or divisor is zero => ##NaN
If dividend is finite and divisor is infinite => dividend

Method: based on fmod return x-[x/p]chopped*p exactlp.
Ported from: https://github.com/openjdk/jdk/blob/master/src/java.base/share/native/libfdlibm/e_remainder.c
See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#IEEEremainder-double-double-
Source code @ clojurescript:src/main/cljs/cljs/math.cljs
(defn ^number IEEE-remainder
  {:added "1.11.10"}
  [dividend divisor]
  ;; check for exception values
  (cond
    (zero? divisor) ##NaN
    ^boolean (js/isNaN divisor) ##NaN
    ;; check if dividend is ##Inf ##-Inf or ##NaN
    ^boolean (js/isNaN dividend) ##NaN
    (not ^boolean (js/isFinite dividend)) ##NaN
    ;; dividend is finish, check if divisor is infinite
    (not ^boolean (js/isFinite divisor)) dividend

    :default
    ;; create a buffer large enough for 2 doubles
    (let [a (js/ArrayBuffer. 16)
          ;; represent the buffer as a double array
          d (js/Float64Array. a)
          ;; represent the buffer as 32 bit ints
          i (js/Uint32Array. a)]
      (aset d 0 dividend)
      (aset d 1 divisor)
      ;; x gets the dividend high and low ints
      (let [hx (aget i HI)
            lx (aget i LO)
            ;; p gets the divisor high and low ints
            hp (aget i (+ HI 2))
            lp (aget i (+ LO 2))
            ;; sx is the sign bit
            sx (bit-and hx INT32-NON-SIGN-BIT)
            ;; strip the sign bit from hp and hx
            hp (bit-and hp INT32-NON-SIGN-BITS)
            hx (bit-and hx INT32-NON-SIGN-BITS)

            ;;make x < 2p
            dividend (if (<= hp 0x7FDFFFFF) (IEEE-fmod dividend (+ divisor divisor)) dividend)]
        (if (zero? (bit-or (- hx hp) (- lx lp)))
          (* 0.0 dividend)
          ;; convert dividend and divisor to absolute values. 
          (let [dividend (Math/abs dividend)
                divisor (Math/abs divisor)
                ;; reduce dividend within range of the divisor
                dividend (if (< hp 0x00200000)
                           ;; smaller divisor compare 2*dividend to the divisor
                           (if (> (+ dividend dividend) divisor)
                             (let [dividend (- dividend divisor)] ;; reduce the dividend
                               (if (>= (+ dividend dividend) divisor) ;; 2*dividend still larger
                                 (- dividend divisor) ;; reduce again
                                 dividend))
                             dividend)
                           ;; compare dividend to half the divisor
                           (let [divisor-half (* 0.5 divisor)]
                             (if (> dividend divisor-half)
                               (let [dividend (- dividend divisor)] ;; reduce the dividend
                                 (if (>= dividend divisor-half) ;; still larger than half divisor
                                   (- dividend divisor) ;; reduce again
                                   dividend))
                               dividend)))]
            ;; update the buffer with the new dividend value
            (aset d 0 dividend)
            ;; calculate a new hi int for the dividend using the saved sign bit
            (let [hx (bit-xor (aget i HI) sx)]
              ;; set the dividend with this new sign bit
              (aset i HI hx)
              ;; retrieve the updated dividend
              (aget d 0))))))))