2 Doubles
dxtr edited this page 2026-10-17 04:43:21 +02:00

Doubles

Every type has a counterpart of doubles: dvec2, dvec3 and dvec4, dmat3, dmat3x2 and dmat4, and dquat, specialised arrays of double floats. Every function has one for them too, named with each type's d: dvec3+, dmat4*, dmat4*dvec4, dmat4-from-dquat, dquat-slerp, and the batches dmat4*-batch and dmat4-transform-points over a double-array. The two precisions are defined from one source, so they cannot drift apart.

(gm:dvec3+ (gm:make-dvec3 :x 1 :y 2 :z 3) (gm:make-dvec3 :x 4 :y 5 :z 6))
;; => #(5.0d0 7.0d0 9.0d0)
(gm:radians 180d0)   ; => 3.141592653589793d0

What doubles are for

Single floats are a metre apart 10,000 km from the origin; doubles there are 2 nanometres apart. A renderer keeps positions in doubles and gives the GPU floats relative to the camera, subtracted in doubles first, as Unreal's translated world space does:

(let ((position (gm:make-dvec3 :x 1d7))               ; 10,000 km out
      (camera (gm:make-dvec3 :x (- 1d7 0.25d0))))     ; a quarter of a metre away
  (gm:vec3-from-dvec3 (gm:dvec3- position camera)))   ; what the GPU gets
;; => #(0.25 0.0 0.0)

Done in single floats, the same subtraction gives #(0.0 0.0 0.0).

Components

A dvec3's components, dvec3-x and so on, are doubles, so setf writes them with doubles:

(let ((position (gm:make-dvec3 :x 1 :y 2 :z 3)))
  (setf (gm:dvec3-x position) 1d0)   ; not 1.0, a single float
  position)
;; => #(1.0d0 2.0d0 3.0d0)

The constructors take any reals, as those of single floats do. mref takes a matrix of either precision, and radians and degrees give a double for a double.

Between precisions

dvec3-from-vec3 and its kin, one for each type, convert exactly, and vec3-from-dvec3 and its kin round each component to the nearest single float:

(gm:dvec3-from-vec3 (gm:make-vec3 :x 0.1))      ; => #(0.10000000149011612d0 0.0d0 0.0d0)
(gm:vec3-from-dvec3 (gm:make-dvec3 :x 0.1d0))   ; => #(0.1 0.0 0.0)

The single float nearest 0.1 is 0.10000000149011612, which a double holds exactly.

Allocation

The functions of doubles allocate nothing, as those of single floats do: those that return a number are inline, as SBCL boxes a double that leaves a function.