cljs.math/next-after

functionsince v1.11.50Edit
(next-after start direction)

Source docstring:
Returns the adjacent floating point number to start in the direction of
the second argument. If the arguments are equal, the second is returned.
If either arg is #NaN => #NaN
If both arguments are signed zeros => direction
If start is +-Number/MIN_VALUE and direction would cause a smaller magnitude
  => zero with sign matching start
If start is ##Inf or ##-Inf and direction would cause a smaller magnitude
  => Number/MAX_VALUE with same sign as start
If start is equal to +=Number/MAX_VALUE and direction would cause a larger magnitude
  => ##Inf or ##-Inf with sign matching start
See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextAfter-double-double-
Source code @ clojurescript:src/main/cljs/cljs/math.cljs
(defn ^number next-after
  {:added "1.11.10"}
  [start direction]
  ; Branch to descending case first as it is more costly than ascending
  ; case due to start != 0.0f conditional.
  (let [a (js/ArrayBuffer. 8)
        f (js/Float64Array. a)
        i (js/Uint32Array. a)]
    (cond
      (> start direction) (if-not (zero? start)
                            (let [_ (aset f 0 start)
                                  ht (aget i HI)
                                  lt (aget i LO)
                                  ;; ht< != 0 since start != 0.0
                                  ;; So long as the top bit is not set, then whole number is > 0
                                  [hr lr] (if (zero? (bit-and ht INT32-NON-SIGN-BIT))
                                            (add64 ht lt 0xFFFFFFFF 0xFFFFFFFF)
                                            (add64 ht lt 0 1))]
                              (aset i HI hr)
                              (aset i LO lr)
                              (aget f 0))
                            ;; start == 0.0 && direction < 0.0
                            (- js/Number.MIN_VALUE))
      ;; Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
      ;; then bitwise convert start to integer
      (< start direction) (let [_ (aset f 0 (+ start 0.0))
                                ht (aget i HI)
                                lt (aget i LO)
                                [hr lr] (if (zero? (bit-and ht INT32-NON-SIGN-BIT))
                                          (add64 ht lt 0 1)
                                          (add64 ht lt 0xFFFFFFFF 0xFFFFFFFF))]
                            (aset i HI hr)
                            (aset i LO lr)
                            (aget f 0))
      (== start direction) direction
      :default (+ start direction))))