function | since v1.11.50 | Edit |
(copy-sign magnitude sign)
Returns a double with the magnitude of the first argument and the sign of the second. See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#copySign-double-double-
(defn ^number copy-sign
{:added "1.11.10"}
[magnitude sign]
;; 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 bytes
b (js/Uint8Array. a)
;; find the offset of the byte that holds the sign bit
sbyte (if little-endian? 7 0)]
;; the first double holds the magnitude, the second holds the sign value
(aset d 0 magnitude)
(aset d 1 sign)
;; read the sign bit from the sign value
(let [sign-sbyte (bit-and 0x80 (aget b (+ 8 sbyte)))
;; read all the bits that aren't the sign bit in the same byte of the magnitude
mag-sbyte (bit-and 0x7F (aget b sbyte))]
;; combine the sign bit from the sign value and the non-sign-bits from the magnitude value
;; write it back into the byte in the magnitude
(aset b sbyte (bit-or sign-sbyte mag-sbyte))
;; retrieve the full magnitude value with the updated byte
(aget d 0))))