diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,62 @@
 # Changelog for geomancy
 
+## 0.4.0.0
+
+A generally safe upgrade, but quite a bit of changes across the board.
+
+- Added double-precision `DVec2`, `DVec3` (with `Packed`), `DVec4`, `DMat4` and `DQuaternion`.
+  Includes SSE2/NEON kernels for `DMat4` products and `DMat4 !* DVec4`.
+- Added `DTransform` (with `DTransform.Tree`), `Vulkan.DProjection` and `Vulkan.DView`.
+  Compose in double and convert with `fromTransform`/`toTransform` to keep precision far from the origin.
+- Added `DPoint2`, `DPoint3`, `DPoint3P` and `DPoint4`.
+  `Point`'s `AffineSpace`, `qd`, `distance` and `lerp` now work over any scalar, not just `Float`.
+- Added 64-bit integer vectors `I64Vec2`, `I64Vec3` (with `Packed`), `I64Vec4`,
+  `U64Vec2`, `U64Vec3` (with `Packed`), `U64Vec4`.
+- Added `fromVecN`/`toVecN`, `fromMat4`/`toMat4` and `fromQuaternion`/`toQuaternion`
+  for single-precision conversions.
+- Added `HasField` instances for the lanes of every vector type, for `v.x`, `v.y`, `v.z`, `v.w` with `OverloadedRecordDot`.
+  * `Packed` vectors have them too, and a `Point` forwards each lane to the vector it wraps.
+  * Optimized code is the same as with `withVecN`: one unpack, and only the lanes used get read.
+- Added rewrite rules that fuse `Vec4` and `DVec4` producers into their consumers.
+  * Intermediate vectors in expressions like `dot (a + b) c`, `lerp t a b` or `(a + b) * c - d` are no longer allocated.
+  * Folds over such expressions got 20-30% faster.
+  * When the rules fire, only the lanes the consumer uses are evaluated, so a fused expression may avoid forcing an undefined lane.
+- Added `HasField` swizzles for every vector family, in `Geomancy.Swizzle.<Family>.Shuffle`, `.Down` and `.Up`
+  (families: `Vec`, `DVec`, `IVec`, `UVec`, `I64Vec`, `U64Vec`).
+  * `Shuffle` keeps the size (`v.zyx`, and the identity `v.xyz`), `Down` narrows (`v.xy` of a `Vec4`), `Up` widens (`v.xyxy` of a `Vec2`).
+  * The instances are orphans. `import Geomancy.Swizzle ()` brings all of them,
+    or import just the modules you need, like `import Geomancy.Swizzle.Vec.Down ()`.
+  * Chains like `v.wzyx.zyx.yx.y` compile to a single lane read.
+- Added `Extend` swizzles that widen a vector with constant lanes, in `Geomancy.Swizzle.<Family>.Extend`.
+  * The source lanes stay in order and get `0` or `1` appended: `flatPos.xy01`, `pos.xyz1`, `uv.xy0`.
+  * Masks compose from extending and narrowing: `white.xyz0.wyz` is `(0, y, z)`.
+- Changed `Geomancy.Swizzle` labels to use the `HasField` swizzles, so `v .@ #xzy` works for every family.
+
+- Modified Quaternion rotation to use a unit shortcut.
+  * The contract was already "use normalized" quaternions for rotations.
+  * Float got a modest speedup, Double is twice-ish as fast. Both are faster than Linear.
+
+- Added `Eq` for `Mat4`, `DMat4`, `Transform` and `DTransform`.
+  Elements are compared pointwise with IEEE semantics, like the derived `Eq` of `Vec3`:
+  `0 == -0` and a matrix containing `NaN` is not equal to itself.
+- Changed `Eq` and `Ord` for `Vec4` from bytewise to pointwise, matching `Vec3`.
+  * `Ord` is now lexicographic over x, y, z, w. Previously it compared the raw bytes, which is not a numeric order.
+  * `Map`/`Set` keyed by `Vec4` will order differently, and keys differing only in the sign of zero now collapse.
+    + Keys containing `NaN` are no longer found by lookups, since `Ord` is no longer total for them.
+    + Basically, don't use floats for keys.
+
+- Fixed `abs` for `IVec3` and `IVec4`, which returned the vector unchanged.
+- Fixed `Block` layout for `IVec3.Packed`, whose `alignment140` and `sizeOf140` were swapped in 0.3.1.0 (now 16 and 12).
+- Fixed `peek` for `Vec4` and `Mat4` returning the wrong element under optimization.
+  * `Data.Vector.Storable` indexing runs `peek` with a shared `realWorld#` token, which let GHC merge the
+    buffer allocations of neighbouring reads, so every read in a strict context got the last element.
+  * `peek` now loads on the caller's token and builds the value in a private buffer.
+  * `Vec4` `peek` and `poke` are about twice as fast, since the 16-byte copies they replace were done bytewise.
+
+- Changed `Vec4` and `Mat4` storage from aligned pinned to regular unpinned byte arrays, like the new `DVec4` and `DMat4`.
+  * SIMD kernels now use unaligned loads and stores.
+  * Code reaching into the exported constructors must not take `byteArrayContents#` or pass the array to `safe` foreign calls, since the GC may now move it.
+
 ## 0.3.1.0
 
 - Fixed Block.sizeOf40 for Packed 3-vectors (was 16, now 12).
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Alexander Bondarenko (c) 2020
+Copyright IC Rainbow (c) 2020-2026
 
 All rights reserved.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -8,56 +8,54 @@
 
 ## The Numbers
 
-Storing a list of 1000 transformations (e.g. rendering instance data):
+Storing a list of transformations (e.g. rendering instance data):
 
 ```
-benchmarking 4x4 poke/1000/geomancy
-time                 11.76 μs   (11.66 μs .. 11.92 μs)
-                     0.999 R²   (0.998 R² .. 1.000 R²)
-mean                 11.75 μs   (11.69 μs .. 11.86 μs)
-std dev              283.4 ns   (199.0 ns .. 399.0 ns)
-variance introduced by outliers: 26% (moderately inflated)
+    poke
+      10
+        geomancy: OK
+          42.3 ns ± 1.4 ns, 0.47x
+        linear:   OK
+          90.5 ns ± 3.1 ns
+        linear/T: OK
+          81.6 ns ± 2.7 ns
+...
+      1000
+        geomancy: OK
+          2.85 μs ±  37 ns, 0.36x
+        linear:   OK
+          7.93 μs ± 132 ns
+        linear/T: OK
+          7.08 μs ± 348 ns
 ```
 
-If you're willing to adjust your shaders, it's only 2.4 times slower.
+Folding down a `gloss`-style scene tree is where it is all started:
 
 ```
-benchmarking 4x4 poke/1000/linear
-time                 28.29 μs   (28.21 μs .. 28.38 μs)
-                     1.000 R²   (1.000 R² .. 1.000 R²)
-mean                 28.40 μs   (28.34 μs .. 28.50 μs)
-std dev              267.4 ns   (145.5 ns .. 419.9 ns)
+    multiply
+      2
+        geomancy: OK
+          12.3 ns ± 164 ps, 0.34x
+        linear:   OK
+          36.1 ns ± 1.3 ns
+...
+      1000
+        geomancy: OK
+          7.71 μs ±  93 ns, 0.23x
+        linear:   OK
+          34.0 μs ± 1.3 μs
 ```
 
-Keeping your shaders straight make the affair 6.1x slower.
-
-```
-benchmarking 4x4 poke/1000/linear/T
-time                 73.70 μs   (73.06 μs .. 74.49 μs)
-                     1.000 R²   (0.999 R² .. 1.000 R²)
-mean                 72.77 μs   (72.50 μs .. 73.22 μs)
-std dev              1.129 μs   (793.5 ns .. 1.580 μs)
-```
+Add that time to the poking that'll follow.
 
-Folding down a `gloss`-style scene graph is where it is all started:
+Sure, it is in the lower microseconds range, but this budget can be used elsewhere.
 
-```
-benchmarking 4x4 multiply/1000/geomancy
-time                 20.79 μs   (20.77 μs .. 20.83 μs)
-                     1.000 R²   (1.000 R² .. 1.000 R²)
-mean                 20.80 μs   (20.78 μs .. 20.83 μs)
-std dev              76.71 ns   (60.01 ns .. 99.06 ns)
+### Benchmarking and comparing
 
-benchmarking 4x4 multiply/1000/linear
-time                 173.9 μs   (173.6 μs .. 174.4 μs)
-                     1.000 R²   (1.000 R² .. 1.000 R²)
-mean                 173.5 μs   (173.2 μs .. 174.4 μs)
-std dev              1.733 μs   (727.8 ns .. 3.422 μs)
+```sh
+stack bench --ba '--csv baseline.csv --stdev 2 --timeout 120'
+stack bench --ba '--baseline baseline.csv --fail-if-slower 5'
 ```
-
-Add that time to the poking that'll follow.
-
-Sure, it is in the lower microseconds range, but this budget can be used elsewhere.
 
 ## Conventions
 
diff --git a/bench/Bench/Common.hs b/bench/Bench/Common.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench/Common.hs
@@ -0,0 +1,15 @@
+module Bench.Common
+  ( clones
+  , chain
+  ) where
+
+import qualified Data.List as List
+
+clones :: Applicative f => Int -> a -> b -> f ([a], [b])
+clones n geo lin = (,) <$> genMat4s <*> genM44s
+  where
+    genMat4s = pure $! replicate n geo
+    genM44s = pure $! replicate n lin
+
+chain :: (a -> a) -> a -> Int -> a
+chain f x0 n = List.foldl' (\x _ -> f x) x0 [1 .. n]
diff --git a/bench/Bench/DMat4.hs b/bench/Bench/DMat4.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench/DMat4.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE BlockArguments #-}
+
+module Bench.DMat4 (benchmarks) where
+
+import Test.Tasty.Bench
+
+import Data.List (foldl1')
+import qualified Foreign
+
+import qualified Geomancy
+import qualified Geomancy.DMat4
+
+import qualified Linear
+import qualified Linear.Matrix
+
+import Bench.Common (clones)
+
+benchmarks :: Benchmark
+benchmarks = bgroup "dmat4"
+  [ bgroup "transpose" dmat4transpose
+
+  , bgroup "multiply" $ flip map [2, 3, 10, 100, 1000] \size ->
+      env (clones size mempty Linear.identity) $
+        dmat4multiply size
+
+  , bgroup "poke" $ flip map [10, 100, 1000, 10000] \size ->
+      env (clones size mempty Linear.identity) $
+        dmat4poke size
+  ]
+
+dmat4transpose :: [Benchmark]
+dmat4transpose =
+  [ bench "geomancy" $ whnf Geomancy.DMat4.transpose mempty
+  , bench "linear"   $ whnf Linear.Matrix.transpose (Linear.identity :: Linear.M44 Double)
+  ]
+
+dmat4multiply
+  :: Int
+  -> ([Geomancy.DMat4], [Linear.M44 Double])
+  -> Benchmark
+dmat4multiply size ~(dmat4s, m44s) = bgroup (show size)
+  [ bench "geomancy" $ whnf multGeomancy dmat4s
+  , bench "linear"   $ whnf multLinear m44s
+  ]
+  where
+    multGeomancy = foldl1' (<>)
+    multLinear = foldl1' (Linear.!*!)
+
+dmat4poke
+  :: Int
+  -> ([Geomancy.DMat4], [Linear.M44 Double])
+  -> Benchmark
+dmat4poke size ~(dmat4s, m44s) = bgroup (show size)
+  [ bench "geomancy" $ nfIO pokeGeomancy
+  , bench "linear"   $ nfIO pokeLinear
+  , bench "linear/T" $ nfIO pokeLinearTranspose
+  ]
+  where
+    pokeGeomancy =
+      Foreign.withArray dmat4s \_ptr ->
+        pure ()
+
+    pokeLinear =
+      Foreign.withArray m44s \_ptr ->
+        pure ()
+
+    pokeLinearTranspose =
+      Foreign.withArray (map Linear.transpose m44s) \_ptr ->
+        pure ()
diff --git a/bench/Bench/DQuaternion.hs b/bench/Bench/DQuaternion.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench/DQuaternion.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE BlockArguments #-}
+
+module Bench.DQuaternion (benchmarks) where
+
+import Test.Tasty.Bench
+
+import Data.List (foldl1')
+
+import qualified Geomancy
+import qualified Geomancy.DQuaternion
+
+import qualified Linear
+import qualified Linear.Quaternion
+
+import Bench.Common (chain, clones)
+
+benchmarks :: Benchmark
+benchmarks = bgroup "dquaternion"
+  [ bgroup "euler" dquatFromEuler
+  , bgroup "axisAngle" dquatAxisAngle
+  , bgroup "multiply" $ flip map [10, 100, 1000] \size ->
+      env (clones size benchDQuat benchLQuat) $
+        dquatMultiply size
+  , bgroup "rotate" $ flip map [10, 100, 1000] \size ->
+      env (clones size (Geomancy.dvec3 1 2 3) (Linear.V3 1 2 3)) $
+        dquatRotate size
+  , bgroup "rotate chain" dquatRotateChain
+  ]
+
+dquatFromEuler :: [Benchmark]
+dquatFromEuler =
+  [ bench "fused" $ whnf (\a -> Geomancy.DQuaternion.intrinsic a a a) (pi/3)
+  , bench "composed" $ whnf (\a -> Geomancy.DQuaternion.extrinsic a a a) (pi/3)
+  ]
+
+dquatAxisAngle :: [Benchmark]
+dquatAxisAngle =
+  [ bench "geomancy" $ whnf (Geomancy.DQuaternion.axisAngle (Geomancy.dvec3 1 2 3)) (pi/7)
+  , bench "linear"   $ whnf (Linear.Quaternion.axisAngle (Linear.V3 1 2 3 :: Linear.V3 Double)) (pi/7)
+  ]
+
+benchDQuat :: Geomancy.DQuaternion
+benchDQuat = Geomancy.DQuaternion.axisAngle (Geomancy.dvec3 1 2 3) (pi/7)
+
+benchLQuat :: Linear.Quaternion.Quaternion Double
+benchLQuat = Linear.Quaternion.axisAngle (Linear.V3 1 2 3) (pi/7)
+
+dquatMultiply
+  :: Int
+  -> ([Geomancy.DQuaternion], [Linear.Quaternion.Quaternion Double])
+  -> Benchmark
+dquatMultiply size ~(dquats, lquats) = bgroup (show size)
+  [ bench "geomancy" $ whnf (foldl1' (*)) dquats
+  , bench "linear"   $ whnf (foldl1' (*)) lquats
+  ]
+
+dquatRotate
+  :: Int
+  -> ([Geomancy.DVec3], [Linear.V3 Double])
+  -> Benchmark
+dquatRotate size ~(dvecs, lvecs) = bgroup (show size)
+  [ bench "geomancy" $ nf (map (Geomancy.DQuaternion.rotate benchDQuat)) dvecs
+  , bench "linear"   $ nf (map (Linear.Quaternion.rotate benchLQuat)) lvecs
+  ]
+
+dquatRotateChain :: [Benchmark]
+dquatRotateChain =
+  [ bench "geomancy" $ whnf (chain (Geomancy.DQuaternion.rotate benchDQuat) (Geomancy.dvec3 1 2 3)) 1000
+  , bench "linear"   $ whnf (chain (Linear.Quaternion.rotate benchLQuat) (Linear.V3 1 2 3)) 1000
+  ]
diff --git a/bench/Bench/Mat4.hs b/bench/Bench/Mat4.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench/Mat4.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE BlockArguments #-}
+
+module Bench.Mat4 (benchmarks) where
+
+import Test.Tasty.Bench
+
+import Data.List (foldl1')
+import qualified Foreign
+
+import qualified Geomancy
+import qualified Geomancy.Mat4
+
+import qualified Linear
+import qualified Linear.Matrix
+
+import Bench.Common (clones)
+
+benchmarks :: Benchmark
+benchmarks = bgroup "mat4"
+  [ bgroup "transpose" mat4transpose
+
+  , bgroup "multiply" $ flip map [2, 3, 10, 100, 1000] \size ->
+      env (clones size mempty Linear.identity) $
+        mat4multiply size
+
+  , bgroup "poke" $ flip map [10, 100, 1000, 10000] \size ->
+      env (clones size mempty Linear.identity) $
+        mat4poke size
+  ]
+
+mat4transpose :: [Benchmark]
+mat4transpose =
+  [ bench "geomancy" $ whnf Geomancy.Mat4.transpose mempty
+  , bench "linear"   $ whnf Linear.Matrix.transpose (Linear.identity :: Linear.M44 Float)
+  ]
+
+mat4multiply
+  :: Int
+  -> ([Geomancy.Mat4], [Linear.M44 Float])
+  -> Benchmark
+mat4multiply size ~(mat4s, m44s) = bgroup (show size)
+  [ bench "geomancy" $ whnf multGeomancy mat4s
+  , bench "linear"   $ whnf multLinear m44s
+  ]
+  where
+    multGeomancy = foldl1' (<>)
+    multLinear = foldl1' (Linear.!*!)
+
+mat4poke
+  :: Int
+  -> ([Geomancy.Mat4], [Linear.M44 Float])
+  -> Benchmark
+mat4poke size ~(mat4s, m44s) = bgroup (show size)
+  [ bench "geomancy" $ nfIO pokeGeomancy --  mat4s
+  , bench "linear"   $ nfIO pokeLinear --  m44s
+  , bench "linear/T" $ nfIO pokeLinearTranspose
+  ]
+  where
+    pokeGeomancy =
+      Foreign.withArray mat4s \_ptr ->
+        pure ()
+
+    pokeLinear =
+      Foreign.withArray m44s \_ptr ->
+        pure ()
+
+    pokeLinearTranspose =
+      Foreign.withArray (map Linear.transpose m44s) \_ptr ->
+        pure ()
diff --git a/bench/Bench/Quaternion.hs b/bench/Bench/Quaternion.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench/Quaternion.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE BlockArguments #-}
+
+module Bench.Quaternion (benchmarks) where
+
+import Test.Tasty.Bench
+
+import qualified Geomancy
+import qualified Geomancy.Quaternion
+
+import qualified Linear
+import qualified Linear.Quaternion
+
+import Bench.Common (chain, clones)
+
+benchmarks :: Benchmark
+benchmarks = bgroup "quaternion"
+  [ bgroup "euler" quatFromEuler
+  , bgroup "rotate" $ flip map [10, 100, 1000] \size ->
+      env (clones size (Geomancy.vec3 1 2 3) (Linear.V3 1 2 3)) $
+        quatRotate size
+  , bgroup "rotate chain" quatRotateChain
+  ]
+
+quatFromEuler :: [Benchmark]
+quatFromEuler =
+  [ bench "fused" $ whnf (\a -> Geomancy.Quaternion.intrinsic a a a) (pi/3)
+  , bench "composed" $ whnf (\a -> Geomancy.Quaternion.extrinsic a a a) (pi/3)
+  ]
+
+benchQuat :: Geomancy.Quaternion
+benchQuat = Geomancy.Quaternion.axisAngle (Geomancy.vec3 1 2 3) (pi/7)
+
+benchLQuatF :: Linear.Quaternion.Quaternion Float
+benchLQuatF = Linear.Quaternion.axisAngle (Linear.V3 1 2 3) (pi/7)
+
+quatRotate
+  :: Int
+  -> ([Geomancy.Vec3], [Linear.V3 Float])
+  -> Benchmark
+quatRotate size ~(vecs, lvecs) = bgroup (show size)
+  [ bench "geomancy" $ nf (map (Geomancy.Quaternion.rotate benchQuat)) vecs
+  , bench "linear"   $ nf (map (Linear.Quaternion.rotate benchLQuatF)) lvecs
+  ]
+
+quatRotateChain :: [Benchmark]
+quatRotateChain =
+  [ bench "geomancy" $ whnf (chain (Geomancy.Quaternion.rotate benchQuat) (Geomancy.vec3 1 2 3)) 1000
+  , bench "linear"   $ whnf (chain (Linear.Quaternion.rotate benchLQuatF) (Linear.V3 1 2 3)) 1000
+  ]
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -1,86 +1,21 @@
-{-# LANGUAGE BlockArguments #-}
-{-# LANGUAGE TypeApplications #-}
-
-module Main where
-
-import Criterion.Main
-
-import Data.List (foldl1')
-import qualified Foreign
+module Main (main) where
 
-import qualified Geomancy
-import qualified Geomancy.Mat4
-import qualified Geomancy.Quaternion
+import Test.Tasty.Bench (Benchmark, bcompare, defaultMain, locateBenchmark, mapLeafBenchmarks)
+import Test.Tasty.Patterns.Printer (printAwkExpr)
 
-import qualified Linear
-import qualified Linear.Matrix
+import qualified Bench.DMat4
+import qualified Bench.DQuaternion
+import qualified Bench.Mat4
+import qualified Bench.Quaternion
 
 main :: IO ()
-main = defaultMain
-  [ bgroup "4x4 transpose"
-      mat4transpose
-
-  , bgroup "4x4 multiply" $ flip map [2, 3, 10, 100, 1000] \size ->
-      env (clones size mempty Linear.identity) $
-        mat4multiply size
-
-  , bgroup "4x4 poke" $ flip map [10, 100, 1000, 10000] \size ->
-      env (clones size mempty Linear.identity) $
-        mat4poke size
-
-  , bgroup "quaternion"
-      [ bgroup "euler" quatFromEuler
-      ]
-  ]
-
-mat4transpose :: [Benchmark]
-mat4transpose =
-  [ bench "geomancy" $ whnf Geomancy.Mat4.transpose mempty
-  , bench "linear"   $ whnf Linear.Matrix.transpose (Linear.identity :: Linear.M44 Float)
+main = defaultMain $ map (mapLeafBenchmarks vsLinear)
+  [ Bench.Mat4.benchmarks
+  , Bench.DMat4.benchmarks
+  , Bench.Quaternion.benchmarks
+  , Bench.DQuaternion.benchmarks
   ]
 
-mat4multiply
-  :: Int
-  -> ([Geomancy.Mat4], [Linear.M44 Float])
-  -> Benchmark
-mat4multiply size ~(mat4s, m44s) = bgroup (show size)
-  [ bench "geomancy" $ whnf multGeomancy mat4s
-  , bench "linear"   $ whnf multLinear m44s
-  ]
-  where
-    multGeomancy = foldl1' (<>)
-    multLinear = foldl1' (Linear.!*!)
-
-clones :: Applicative f => Int -> a -> b -> f ([a], [b])
-clones n geo lin = (,) <$> genMat4s <*> genM44s
-  where
-    genMat4s = pure $! replicate n geo
-    genM44s = pure $! replicate n lin
-
-mat4poke
-  :: Int
-  -> ([Geomancy.Mat4], [Linear.M44 Float])
-  -> Benchmark
-mat4poke size ~(mat4s, m44s) = bgroup (show size)
-  [ bench "geomancy" $ nfIO pokeGeomancy --  mat4s
-  , bench "linear"   $ nfIO pokeLinear --  m44s
-  , bench "linear/T" $ nfIO pokeLinearTranspose
-  ]
-  where
-    pokeGeomancy =
-      Foreign.withArray mat4s \_ptr ->
-        pure ()
-
-    pokeLinear =
-      Foreign.withArray m44s \_ptr ->
-        pure ()
-
-    pokeLinearTranspose =
-      Foreign.withArray (map Linear.transpose m44s) \_ptr ->
-        pure ()
-
-quatFromEuler :: [Benchmark]
-quatFromEuler =
-  [ bench "fused" $ whnf (\a -> Geomancy.Quaternion.intrinsic a a a) (pi/3)
-  , bench "composed" $ whnf (\a -> Geomancy.Quaternion.extrinsic a a a) (pi/3)
-  ]
+vsLinear :: [String] -> Benchmark -> Benchmark
+vsLinear ("geomancy" : path) = bcompare (printAwkExpr $ locateBenchmark ("linear" : path))
+vsLinear _ = id
diff --git a/cbits/dmat4.c b/cbits/dmat4.c
new file mode 100644
--- /dev/null
+++ b/cbits/dmat4.c
@@ -0,0 +1,153 @@
+#if defined(__SSE2__)
+
+#include <emmintrin.h>
+
+void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
+  __m128d row0lo = _mm_loadu_pd(&A[0]);
+  __m128d row0hi = _mm_loadu_pd(&A[2]);
+  __m128d row1lo = _mm_loadu_pd(&A[4]);
+  __m128d row1hi = _mm_loadu_pd(&A[6]);
+  __m128d row2lo = _mm_loadu_pd(&A[8]);
+  __m128d row2hi = _mm_loadu_pd(&A[10]);
+  __m128d row3lo = _mm_loadu_pd(&A[12]);
+  __m128d row3hi = _mm_loadu_pd(&A[14]);
+  for(int i=0; i<4; i++) {
+    __m128d brod0 = _mm_set1_pd(B[4*i + 0]);
+    __m128d brod1 = _mm_set1_pd(B[4*i + 1]);
+    __m128d brod2 = _mm_set1_pd(B[4*i + 2]);
+    __m128d brod3 = _mm_set1_pd(B[4*i + 3]);
+    __m128d rowlo = _mm_add_pd(
+      _mm_add_pd(
+        _mm_mul_pd(brod0, row0lo),
+        _mm_mul_pd(brod1, row1lo)),
+      _mm_add_pd(
+        _mm_mul_pd(brod2, row2lo),
+        _mm_mul_pd(brod3, row3lo)));
+    __m128d rowhi = _mm_add_pd(
+      _mm_add_pd(
+        _mm_mul_pd(brod0, row0hi),
+        _mm_mul_pd(brod1, row1hi)),
+      _mm_add_pd(
+        _mm_mul_pd(brod2, row2hi),
+        _mm_mul_pd(brod3, row3hi)));
+    _mm_storeu_pd(&O[4*i], rowlo);
+    _mm_storeu_pd(&O[4*i + 2], rowhi);
+  }
+}
+
+void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
+  __m128d row0lo = _mm_loadu_pd(&M[0]);
+  __m128d row0hi = _mm_loadu_pd(&M[2]);
+  __m128d row1lo = _mm_loadu_pd(&M[4]);
+  __m128d row1hi = _mm_loadu_pd(&M[6]);
+  __m128d row2lo = _mm_loadu_pd(&M[8]);
+  __m128d row2hi = _mm_loadu_pd(&M[10]);
+  __m128d row3lo = _mm_loadu_pd(&M[12]);
+  __m128d row3hi = _mm_loadu_pd(&M[14]);
+
+  __m128d vec00 = _mm_set1_pd(V[0]);
+  __m128d vec01 = _mm_set1_pd(V[1]);
+  __m128d vec02 = _mm_set1_pd(V[2]);
+  __m128d vec03 = _mm_set1_pd(V[3]);
+
+  __m128d reslo = _mm_mul_pd(row0lo, vec00);
+  reslo = _mm_add_pd(reslo, _mm_mul_pd(row1lo, vec01));
+  reslo = _mm_add_pd(reslo, _mm_mul_pd(row2lo, vec02));
+  reslo = _mm_add_pd(reslo, _mm_mul_pd(row3lo, vec03));
+
+  __m128d reshi = _mm_mul_pd(row0hi, vec00);
+  reshi = _mm_add_pd(reshi, _mm_mul_pd(row1hi, vec01));
+  reshi = _mm_add_pd(reshi, _mm_mul_pd(row2hi, vec02));
+  reshi = _mm_add_pd(reshi, _mm_mul_pd(row3hi, vec03));
+
+  _mm_storeu_pd(&O[0], reslo);
+  _mm_storeu_pd(&O[2], reshi);
+}
+
+#elif defined(__aarch64__)
+
+#include <arm_neon.h>
+
+void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
+  float64x2_t A0lo = vld1q_f64(&A[0]);
+  float64x2_t A0hi = vld1q_f64(&A[2]);
+  float64x2_t A1lo = vld1q_f64(&A[4]);
+  float64x2_t A1hi = vld1q_f64(&A[6]);
+  float64x2_t A2lo = vld1q_f64(&A[8]);
+  float64x2_t A2hi = vld1q_f64(&A[10]);
+  float64x2_t A3lo = vld1q_f64(&A[12]);
+  float64x2_t A3hi = vld1q_f64(&A[14]);
+
+  for(int i=0; i<4; i++) {
+    float64x2_t Blo = vld1q_f64(&B[4*i]);
+    float64x2_t Bhi = vld1q_f64(&B[4*i + 2]);
+
+    float64x2_t Clo = vmovq_n_f64(0);
+    Clo = vfmaq_laneq_f64(Clo, A0lo, Blo, 0);
+    Clo = vfmaq_laneq_f64(Clo, A1lo, Blo, 1);
+    Clo = vfmaq_laneq_f64(Clo, A2lo, Bhi, 0);
+    Clo = vfmaq_laneq_f64(Clo, A3lo, Bhi, 1);
+
+    float64x2_t Chi = vmovq_n_f64(0);
+    Chi = vfmaq_laneq_f64(Chi, A0hi, Blo, 0);
+    Chi = vfmaq_laneq_f64(Chi, A1hi, Blo, 1);
+    Chi = vfmaq_laneq_f64(Chi, A2hi, Bhi, 0);
+    Chi = vfmaq_laneq_f64(Chi, A3hi, Bhi, 1);
+
+    vst1q_f64(&O[4*i], Clo);
+    vst1q_f64(&O[4*i + 2], Chi);
+  }
+}
+
+void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
+  float64x2_t M0lo = vld1q_f64(&M[0]);
+  float64x2_t M0hi = vld1q_f64(&M[2]);
+  float64x2_t M1lo = vld1q_f64(&M[4]);
+  float64x2_t M1hi = vld1q_f64(&M[6]);
+  float64x2_t M2lo = vld1q_f64(&M[8]);
+  float64x2_t M2hi = vld1q_f64(&M[10]);
+  float64x2_t M3lo = vld1q_f64(&M[12]);
+  float64x2_t M3hi = vld1q_f64(&M[14]);
+
+  float64x2_t Vlo = vld1q_f64(&V[0]);
+  float64x2_t Vhi = vld1q_f64(&V[2]);
+
+  float64x2_t Llo = vmovq_n_f64(0);
+  Llo = vfmaq_laneq_f64(Llo, M0lo, Vlo, 0);
+  Llo = vfmaq_laneq_f64(Llo, M1lo, Vlo, 1);
+  Llo = vfmaq_laneq_f64(Llo, M2lo, Vhi, 0);
+  Llo = vfmaq_laneq_f64(Llo, M3lo, Vhi, 1);
+
+  float64x2_t Lhi = vmovq_n_f64(0);
+  Lhi = vfmaq_laneq_f64(Lhi, M0hi, Vlo, 0);
+  Lhi = vfmaq_laneq_f64(Lhi, M1hi, Vlo, 1);
+  Lhi = vfmaq_laneq_f64(Lhi, M2hi, Vhi, 0);
+  Lhi = vfmaq_laneq_f64(Lhi, M3hi, Vhi, 1);
+
+  vst1q_f64(&O[0], Llo);
+  vst1q_f64(&O[2], Lhi);
+}
+
+#else
+
+void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
+  for(int i=0; i<4; i++) {
+    for(int j=0; j<4; j++) {
+      O[4*i + j] =
+        (B[4*i + 0] * A[0 + j] + B[4*i + 1] * A[4 + j]) +
+        (B[4*i + 2] * A[8 + j] + B[4*i + 3] * A[12 + j]);
+    }
+  }
+}
+
+void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
+  for(int j=0; j<4; j++) {
+    O[j] =
+      M[0 + j] * V[0] +
+      M[4 + j] * V[1] +
+      M[8 + j] * V[2] +
+      M[12 + j] * V[3];
+  }
+}
+
+#endif
diff --git a/cbits/mat4.c b/cbits/mat4.c
--- a/cbits/mat4.c
+++ b/cbits/mat4.c
@@ -3,10 +3,10 @@
 #include <xmmintrin.h>
 
 void Mat4xMat4_SIMD(float *A, float *B, float *O) {
-  __m128 row0 = _mm_load_ps(&A[0]);
-  __m128 row1 = _mm_load_ps(&A[4]);
-  __m128 row2 = _mm_load_ps(&A[8]);
-  __m128 row3 = _mm_load_ps(&A[12]);
+  __m128 row0 = _mm_loadu_ps(&A[0]);
+  __m128 row1 = _mm_loadu_ps(&A[4]);
+  __m128 row2 = _mm_loadu_ps(&A[8]);
+  __m128 row3 = _mm_loadu_ps(&A[12]);
   for(int i=0; i<4; i++) {
     __m128 brod0 = _mm_set1_ps(B[4*i + 0]);
     __m128 brod1 = _mm_set1_ps(B[4*i + 1]);
@@ -19,17 +19,17 @@
       _mm_add_ps(
         _mm_mul_ps(brod2, row2),
         _mm_mul_ps(brod3, row3)));
-    _mm_store_ps(&O[4*i], row);
+    _mm_storeu_ps(&O[4*i], row);
   }
 }
 
 void Mat4xVec4_SIMD(float *M, float *V, float *O) {
-  __m128 row0 = _mm_load_ps(&M[0]);
-  __m128 row1 = _mm_load_ps(&M[4]);
-  __m128 row2 = _mm_load_ps(&M[8]);
-  __m128 row3 = _mm_load_ps(&M[12]);
+  __m128 row0 = _mm_loadu_ps(&M[0]);
+  __m128 row1 = _mm_loadu_ps(&M[4]);
+  __m128 row2 = _mm_loadu_ps(&M[8]);
+  __m128 row3 = _mm_loadu_ps(&M[12]);
 
-  __m128 vec0 = _mm_load_ps(V);
+  __m128 vec0 = _mm_loadu_ps(V);
 
   __m128 vec00 = _mm_shuffle_ps(vec0, vec0, _MM_SHUFFLE(0, 0, 0, 0));
   __m128 vec01 = _mm_shuffle_ps(vec0, vec0, _MM_SHUFFLE(1, 1, 1, 1));
diff --git a/geomancy.cabal b/geomancy.cabal
--- a/geomancy.cabal
+++ b/geomancy.cabal
@@ -1,18 +1,18 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.39.1.
+-- This file has been generated from package.yaml by hpack version 0.39.6.
 --
 -- see: https://github.com/sol/hpack
 
 name:           geomancy
-version:        0.3.1.0
+version:        0.4.0.0
 synopsis:       Vectors and matrix manipulation
 description:    Sometimes it is unavoidable you have to do stuff on CPU.
                 Let's at least do it faster.
 category:       Graphics
 author:         IC Rainbow
 maintainer:     aenor.realm@gmail.com
-copyright:      2021-2025 IC Rainbow
+copyright:      2020-2026 IC Rainbow
 license:        BSD3
 license-file:   LICENSE
 build-type:     Simple
@@ -35,8 +35,19 @@
 library
   exposed-modules:
       Geomancy
+      Geomancy.DMat4
+      Geomancy.DMat4.Internal
+      Geomancy.DQuaternion
+      Geomancy.DTransform
+      Geomancy.DTransform.Tree
+      Geomancy.DVec2
+      Geomancy.DVec3
+      Geomancy.DVec4
       Geomancy.Elementwise
       Geomancy.Gl.Funs
+      Geomancy.I64Vec2
+      Geomancy.I64Vec3
+      Geomancy.I64Vec4
       Geomancy.Interpolate
       Geomancy.IVec2
       Geomancy.IVec3
@@ -46,9 +57,36 @@
       Geomancy.Point
       Geomancy.Quaternion
       Geomancy.Swizzle
+      Geomancy.Swizzle.DVec.Down
+      Geomancy.Swizzle.DVec.Extend
+      Geomancy.Swizzle.DVec.Shuffle
+      Geomancy.Swizzle.DVec.Up
+      Geomancy.Swizzle.I64Vec.Down
+      Geomancy.Swizzle.I64Vec.Extend
+      Geomancy.Swizzle.I64Vec.Shuffle
+      Geomancy.Swizzle.I64Vec.Up
+      Geomancy.Swizzle.IVec.Down
+      Geomancy.Swizzle.IVec.Extend
+      Geomancy.Swizzle.IVec.Shuffle
+      Geomancy.Swizzle.IVec.Up
+      Geomancy.Swizzle.U64Vec.Down
+      Geomancy.Swizzle.U64Vec.Extend
+      Geomancy.Swizzle.U64Vec.Shuffle
+      Geomancy.Swizzle.U64Vec.Up
+      Geomancy.Swizzle.UVec.Down
+      Geomancy.Swizzle.UVec.Extend
+      Geomancy.Swizzle.UVec.Shuffle
+      Geomancy.Swizzle.UVec.Up
+      Geomancy.Swizzle.Vec.Down
+      Geomancy.Swizzle.Vec.Extend
+      Geomancy.Swizzle.Vec.Shuffle
+      Geomancy.Swizzle.Vec.Up
       Geomancy.Transform
       Geomancy.Transform.Tree
       Geomancy.Tree
+      Geomancy.U64Vec2
+      Geomancy.U64Vec3
+      Geomancy.U64Vec4
       Geomancy.UVec2
       Geomancy.UVec3
       Geomancy.UVec4
@@ -56,6 +94,8 @@
       Geomancy.Vec3
       Geomancy.Vec4
       Geomancy.Vector
+      Geomancy.Vulkan.DProjection
+      Geomancy.Vulkan.DView
       Geomancy.Vulkan.Projection
       Geomancy.Vulkan.View
   other-modules:
@@ -65,6 +105,7 @@
   ghc-options: -Wall
   c-sources:
       cbits/mat4.c
+      cbits/dmat4.c
   build-depends:
       base >=4.7 && <5
     , containers
@@ -86,8 +127,34 @@
 
 test-suite geomancy-test
   type: exitcode-stdio-1.0
-  main-is: Spec.hs
+  main-is: Main.hs
   other-modules:
+      Spec.DMat4
+      Spec.DQuaternion
+      Spec.DTransform
+      Spec.DVec
+      Spec.Fusion
+      Spec.Mat4
+      Spec.Point
+      Spec.Quaternion
+      Spec.Storable
+      Spec.Swizzle
+      Spec.Transform
+      Spec.Vec4
+      Spec.Vec64
+      Spec.Vulkan
+      Support.Ball
+      Support.Fixtures
+      Support.Gen
+      Support.Linear
+      Support.Property
+      Support.Reference.Linear
+      Support.Reference.Mat4
+      Support.Reference.Quaternion
+      Support.Reference.Transform
+      Support.Reference.Vec3
+      Support.Reference.Vulkan
+      Support.Swizzle
       Paths_geomancy
   hs-source-dirs:
       test
@@ -96,24 +163,34 @@
       base >=4.7 && <5
     , deepseq
     , geomancy
+    , gl-block
     , hedgehog
     , linear
     , simple-affine-space
+    , tasty
+    , tasty-hedgehog
+    , vector
   default-language: Haskell2010
 
 benchmark geomancy-bench
   type: exitcode-stdio-1.0
   main-is: Main.hs
   other-modules:
+      Bench.Common
+      Bench.DMat4
+      Bench.DQuaternion
+      Bench.Mat4
+      Bench.Quaternion
       Paths_geomancy
   hs-source-dirs:
       bench
-  ghc-options: -Wall -O2 -threaded -rtsopts "-with-rtsopts=-N1 -A128m -s"
+  ghc-options: -Wall -rtsopts "-with-rtsopts=-A32m -T"
   build-depends:
       base >=4.7 && <5
-    , criterion
     , deepseq
     , geomancy
     , linear
     , simple-affine-space
+    , tasty
+    , tasty-bench
   default-language: Haskell2010
diff --git a/src/Geomancy.hs b/src/Geomancy.hs
--- a/src/Geomancy.hs
+++ b/src/Geomancy.hs
@@ -25,6 +25,27 @@
   , pattern WithVec4
   , Point4
 
+  -- ** Double-precision / float64s
+
+  , DVec2
+  , dvec2
+  , withDVec2
+  , pattern WithDVec2
+  , DPoint2
+
+  , DVec3
+  , dvec3
+  , withDVec3
+  , pattern WithDVec3
+  , DPoint3
+  , DPoint3P
+
+  , DVec4
+  , dvec4
+  , withDVec4
+  , pattern WithDVec4
+  , DPoint4
+
   -- ** Signed / int32s
 
   , IVec2
@@ -59,6 +80,40 @@
   , withUVec4
   , pattern WithUVec4
 
+  -- ** Signed / int64s
+
+  , I64Vec2
+  , i64vec2
+  , withI64Vec2
+  , pattern WithI64Vec2
+
+  , I64Vec3
+  , i64vec3
+  , withI64Vec3
+  , pattern WithI64Vec3
+
+  , I64Vec4
+  , i64vec4
+  , withI64Vec4
+  , pattern WithI64Vec4
+
+  -- ** Unsigned / word64s
+
+  , U64Vec2
+  , u64vec2
+  , withU64Vec2
+  , pattern WithU64Vec2
+
+  , U64Vec3
+  , u64vec3
+  , withU64Vec3
+  , pattern WithU64Vec3
+
+  , U64Vec4
+  , u64vec4
+  , withU64Vec4
+  , pattern WithU64Vec4
+
   -- ** Generic maps
 
   , Elementwise(..)
@@ -66,7 +121,9 @@
   -- * Matrices
 
   , Mat4
+  , DMat4
   , Transform(..)
+  , DTransform(..)
 
   -- * Other beasts
 
@@ -74,6 +131,10 @@
   , quaternion
   , withQuaternion
 
+  , DQuaternion
+  , dquaternion
+  , withDQuaternion
+
   -- * Spaces
 
   , Point(..)
@@ -88,6 +149,10 @@
 import Geomancy.Vec3 (Vec3, vec3, withVec3, pattern WithVec3)
 import Geomancy.Vec4 (Vec4, vec4, withVec4, pattern WithVec4)
 
+import Geomancy.DVec2 (DVec2, dvec2, withDVec2, pattern WithDVec2)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3, pattern WithDVec3)
+import Geomancy.DVec4 (DVec4, dvec4, withDVec4, pattern WithDVec4)
+
 import Geomancy.IVec2 (IVec2, ivec2, withIVec2, pattern WithIVec2)
 import Geomancy.IVec3 (IVec3, ivec3, withIVec3, pattern WithIVec3)
 import Geomancy.IVec4 (IVec4, ivec4, withIVec4, pattern WithIVec4)
@@ -96,12 +161,23 @@
 import Geomancy.UVec3 (UVec3, uvec3, withUVec3, pattern WithUVec3)
 import Geomancy.UVec4 (UVec4, uvec4, withUVec4, pattern WithUVec4)
 
+import Geomancy.I64Vec2 (I64Vec2, i64vec2, withI64Vec2, pattern WithI64Vec2)
+import Geomancy.I64Vec3 (I64Vec3, i64vec3, withI64Vec3, pattern WithI64Vec3)
+import Geomancy.I64Vec4 (I64Vec4, i64vec4, withI64Vec4, pattern WithI64Vec4)
+
+import Geomancy.U64Vec2 (U64Vec2, u64vec2, withU64Vec2, pattern WithU64Vec2)
+import Geomancy.U64Vec3 (U64Vec3, u64vec3, withU64Vec3, pattern WithU64Vec3)
+import Geomancy.U64Vec4 (U64Vec4, u64vec4, withU64Vec4, pattern WithU64Vec4)
+
 import Geomancy.Elementwise (Elementwise(..))
 
 import Geomancy.Mat4 (Mat4)
+import Geomancy.DMat4 (DMat4)
 import Geomancy.Transform (Transform(..))
+import Geomancy.DTransform (DTransform(..))
 
 import Geomancy.Quaternion (Quaternion, quaternion, withQuaternion)
+import Geomancy.DQuaternion (DQuaternion, dquaternion, withDQuaternion)
 
-import Geomancy.Point (AffineSpace(..), Point(..), Point2, Point3, Point3P, Point4)
+import Geomancy.Point (AffineSpace(..), Point(..), Point2, Point3, Point3P, Point4, DPoint2, DPoint3, DPoint3P, DPoint4)
 import Geomancy.Vector (VectorSpace(..), lerp, quadrance, (^*))
diff --git a/src/Geomancy/DMat4.hs b/src/Geomancy/DMat4.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DMat4.hs
@@ -0,0 +1,351 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnliftedFFITypes #-}
+{-# LANGUAGE ViewPatterns #-}
+
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.DMat4
+  ( DMat4
+    -- * Operations
+  , identity
+  , transpose
+  , inverse
+  , det
+  , pointwise
+  , zipWith
+  , matrixProduct
+  , scalarMultiply
+  , (!*)
+
+    -- * Construction
+
+    -- ** Col-major
+  , colMajor
+  , withColMajor
+  , toListColMajor
+  , toListColMajor2d
+  , showColumns
+
+    -- ** Row-major
+  , rowMajor
+  , withRowMajor
+  , toListRowMajor
+  , toListRowMajor2d
+  , fromRowMajor2d
+  , showRows
+
+    -- * Precision conversion
+  , fromMat4
+  , toMat4
+  ) where
+
+import Prelude hiding (zipWith)
+import GHC.Exts hiding (VecCount(..), toList)
+import GHC.Float (double2Float, float2Double)
+import Geomancy.DMat4.Internal
+
+import System.IO.Unsafe (unsafePerformIO)
+import Text.Printf (printf)
+
+import qualified Data.Foldable as Foldable
+
+import Geomancy.DVec4 (DVec4(..), newDVec4)
+import Geomancy.Mat4.Internal (Mat4)
+import qualified Geomancy.Mat4.Internal as Mat4
+
+{-# INLINE fromMat4 #-}
+fromMat4 :: Coercible a Mat4 => a -> DMat4
+fromMat4 m = Mat4.withMemory (coerce m)
+  \ e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF ->
+  fromMemory
+    (float2Double e0) (float2Double e1) (float2Double e2) (float2Double e3)
+    (float2Double e4) (float2Double e5) (float2Double e6) (float2Double e7)
+    (float2Double e8) (float2Double e9) (float2Double eA) (float2Double eB)
+    (float2Double eC) (float2Double eD) (float2Double eE) (float2Double eF)
+
+{-# INLINE toMat4 #-}
+toMat4 :: DMat4 -> Mat4
+toMat4 m = withMemory m
+  \ e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF ->
+  Mat4.fromMemory
+    (double2Float e0) (double2Float e1) (double2Float e2) (double2Float e3)
+    (double2Float e4) (double2Float e5) (double2Float e6) (double2Float e7)
+    (double2Float e8) (double2Float e9) (double2Float eA) (double2Float eB)
+    (double2Float eC) (double2Float eD) (double2Float eE) (double2Float eF)
+
+toListColMajor :: Coercible a DMat4 => a -> [Double]
+toListColMajor = toListTrans . coerce
+
+toListColMajor2d :: Coercible a DMat4 => a -> [[Double]]
+toListColMajor2d = toList2dTrans . coerce
+
+rowMajor
+  :: Coercible DMat4 a
+  => Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> a
+rowMajor
+  e0 e1 e2 e3
+  e4 e5 e6 e7
+  e8 e9 eA eB
+  eC eD eE eF =
+    coerce $ fromMemory
+      e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF
+
+fromRowMajor2d
+  :: forall t a
+  .  ( Foldable t
+     , Coercible DMat4 a
+     )
+  => t (t Double)
+  -> Maybe a
+fromRowMajor2d rows =
+  case Foldable.toList rows of
+    [r0, r1, r2, r3] ->
+      withRow r0 \e0 e1 e2 e3 ->
+      withRow r1 \e4 e5 e6 e7 ->
+      withRow r2 \e8 e9 eA eB ->
+      withRow r3 \eC eD eE eF ->
+        Just . coerce @a $ rowMajor
+          e0 e1 e2 e3
+          e4 e5 e6 e7
+          e8 e9 eA eB
+          eC eD eE eF
+    _ ->
+      Nothing
+  where
+    withRow row f =
+      case Foldable.toList row of
+        [c0, c1, c2, c3] ->
+          f c0 c1 c2 c3
+        _ ->
+          Nothing
+
+{-# INLINE withRowMajor #-}
+withRowMajor
+  :: Coercible a DMat4
+  => a
+  ->
+    ( Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      r
+    )
+  -> r
+withRowMajor m f = withMemory (coerce m)
+  \ e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF ->
+  f
+    e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF
+
+{-# INLINE colMajor #-}
+colMajor
+  :: forall a . Coercible DMat4 a
+  => Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> a
+colMajor
+  e0 e4 e8 eC
+  e1 e5 e9 eD
+  e2 e6 eA eE
+  e3 e7 eB eF =
+    coerce $ fromMemory
+      e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF
+
+{-# INLINE withColMajor #-}
+withColMajor
+  :: Coercible a DMat4
+  => a
+  ->
+    ( Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      r
+    )
+  -> r
+withColMajor m f = withMemory (coerce m)
+  \ e0 e4 e8 eC
+    e1 e5 e9 eD
+    e2 e6 eA eE
+    e3 e7 eB eF ->
+  f
+    e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF
+
+toListRowMajor :: Coercible a DMat4 => a -> [Double]
+toListRowMajor = toListMemory . coerce
+
+toListRowMajor2d :: Coercible a DMat4 => a -> [[Double]]
+toListRowMajor2d = toList2dMemory . coerce
+
+det :: Coercible DMat4 a => a -> Double
+det m =
+  withRowMajor m
+    \ m00 m01 m02 m03
+      m10 m11 m12 m13
+      m20 m21 m22 m23
+      m30 m31 m32 m33 ->
+        let
+          s0 = m00 * m11 - m10 * m01
+          s1 = m00 * m12 - m10 * m02
+          s2 = m00 * m13 - m10 * m03
+          s3 = m01 * m12 - m11 * m02
+          s4 = m01 * m13 - m11 * m03
+          s5 = m02 * m13 - m12 * m03
+
+          c5 = m22 * m33 - m32 * m23
+          c4 = m21 * m33 - m31 * m23
+          c3 = m21 * m32 - m31 * m22
+          c2 = m20 * m33 - m30 * m23
+          c1 = m20 * m32 - m30 * m22
+          c0 = m20 * m31 - m30 * m21
+        in
+            s0 * c5
+          - s1 * c4
+          + s2 * c3
+          + s3 * c2
+          - s4 * c1
+          + s5 * c0
+
+inverse :: Coercible DMat4 a => a -> a
+inverse m =
+  withRowMajor m
+    \ m00 m01 m02 m03
+      m10 m11 m12 m13
+      m20 m21 m22 m23
+      m30 m31 m32 m33 ->
+        let
+          invDet = recip $
+              s0 * c5
+            - s1 * c4
+            + s2 * c3
+            + s3 * c2
+            - s4 * c1
+            + s5 * c0
+
+          s0 = m00 * m11 - m10 * m01
+          s1 = m00 * m12 - m10 * m02
+          s2 = m00 * m13 - m10 * m03
+          s3 = m01 * m12 - m11 * m02
+          s4 = m01 * m13 - m11 * m03
+          s5 = m02 * m13 - m12 * m03
+
+          c5 = m22 * m33 - m32 * m23
+          c4 = m21 * m33 - m31 * m23
+          c3 = m21 * m32 - m31 * m22
+          c2 = m20 * m33 - m30 * m23
+          c1 = m20 * m32 - m30 * m22
+          c0 = m20 * m31 - m30 * m21
+
+          i00 = ( m11 * c5 - m12 * c4 + m13 * c3) * invDet
+          i01 = (-m01 * c5 + m02 * c4 - m03 * c3) * invDet
+          i02 = ( m31 * s5 - m32 * s4 + m33 * s3) * invDet
+          i03 = (-m21 * s5 + m22 * s4 - m23 * s3) * invDet
+
+          i10 = (-m10 * c5 + m12 * c2 - m13 * c1) * invDet
+          i11 = ( m00 * c5 - m02 * c2 + m03 * c1) * invDet
+          i12 = (-m30 * s5 + m32 * s2 - m33 * s1) * invDet
+          i13 = ( m20 * s5 - m22 * s2 + m23 * s1) * invDet
+
+          i20 = ( m10 * c4 - m11 * c2 + m13 * c0) * invDet
+          i21 = (-m00 * c4 + m01 * c2 - m03 * c0) * invDet
+          i22 = ( m30 * s4 - m31 * s2 + m33 * s0) * invDet
+          i23 = (-m20 * s4 + m21 * s2 - m23 * s0) * invDet
+
+          i30 = (-m10 * c3 + m11 * c1 - m12 * c0) * invDet
+          i31 = ( m00 * c3 - m01 * c1 + m02 * c0) * invDet
+          i32 = (-m30 * s3 + m31 * s1 - m32 * s0) * invDet
+          i33 = ( m20 * s3 - m21 * s1 + m22 * s0) * invDet
+        in
+          rowMajor
+            i00 i01 i02 i03
+            i10 i11 i12 i13
+            i20 i21 i22 i23
+            i30 i31 i32 i33
+
+foreign import ccall unsafe "DMat4xDMat4_SIMD" m4m4simd :: ByteArray# -> ByteArray# -> ByteArray# -> IO ()
+
+{-# INLINE matrixProduct #-}
+matrixProduct :: DMat4 -> DMat4 -> DMat4
+matrixProduct (DMat4 l) (DMat4 r) = unsafePerformIO do
+  result@(DMat4 m) <- newDMat4
+  m4m4simd l r m
+  pure result
+
+foreign import ccall unsafe "DMat4xDVec4_SIMD" m4v4simd :: ByteArray# -> ByteArray# -> ByteArray# -> IO ()
+
+(!*) :: Coercible a DMat4 => a -> DVec4 -> DVec4
+(!*) (coerce -> DMat4 m) (DVec4 v) = unsafePerformIO do
+  result@(DVec4 o) <- newDVec4
+  !() <- m4v4simd m v o
+  pure result
+
+infixr 5 !*
+
+instance Semigroup DMat4 where
+  {-# INLINE (<>) #-}
+  (<>) = matrixProduct
+
+instance Monoid DMat4 where
+  {-# INLINE mempty #-}
+  mempty = identity
+
+instance Show DMat4 where
+  show = showColumns
+
+showColumns :: DMat4 -> String
+showColumns cm = withColMajor cm
+  \ e0 e4 e8 eC
+    e1 e5 e9 eD
+    e2 e6 eA eE
+    e3 e7 eB eF ->
+  unlines
+    [ printf  "/ %.4f %.4f %.4f %.4f \\" e0 e4 e8 eC
+    , printf  "| %.4f %.4f %.4f %.4f |"  e1 e5 e9 eD
+    , printf  "| %.4f %.4f %.4f %.4f |"  e2 e6 eA eE
+    , printf "\\ %.4f %.4f %.4f %.4f /"  e3 e7 eB eF
+    ]
+
+showRows :: DMat4 -> String
+showRows rm = withRowMajor rm
+  \ e0 e1 e2 e3
+    e4 e5 e6 e7
+    e8 e9 eA eB
+    eC eD eE eF ->
+  unlines
+    [ printf "[ %.4f %.4f %.4f %.4f |" e0 e1 e2 e3
+    , printf "| %.4f %.4f %.4f %.4f |" e4 e5 e6 e7
+    , printf "| %.4f %.4f %.4f %.4f |" e8 e9 eA eB
+    , printf "| %.4f %.4f %.4f %.4f ]" eC eD eE eF
+    ]
diff --git a/src/Geomancy/DMat4/Internal.hs b/src/Geomancy/DMat4/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DMat4/Internal.hs
@@ -0,0 +1,392 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UnboxedTuples #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE TemplateHaskell #-}
+#endif
+
+module Geomancy.DMat4.Internal
+  ( DMat4(..)
+  , fromMemory
+  , withMemory
+  , newDMat4
+    -- * Order-independent operations
+  , identity
+  , transpose
+  , pointwise
+  , scalarMultiply
+    -- * List operations in memory order
+  , toListMemory
+  , toList2dMemory
+  , toListTrans
+  , toList2dTrans
+  , zipWith
+  ) where
+
+import Prelude hiding (zipWith)
+import GHC.Exts hiding (VecCount(..), toList)
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift(..))
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Control.DeepSeq (NFData(rnf))
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.IO (IO(..))
+
+import qualified Data.List as List
+
+import Graphics.Gl.Block (Block(..))
+
+data DMat4 = DMat4 ByteArray#
+
+instance Eq DMat4 where
+  DMat4 a == DMat4 b = go 0#
+    where
+      go i
+        | isTrue# (i ==# 16#) = True
+        | isTrue# (indexDoubleArray# a i ==## indexDoubleArray# b i) = go (i +# 1#)
+        | otherwise = False
+
+instance NFData DMat4 where
+  rnf DMat4{} = ()
+
+{-# INLINE fromMemory #-}
+fromMemory
+  :: Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> Double -> Double -> Double -> Double
+  -> DMat4
+fromMemory
+  e0 e1 e2 e3
+  e4 e5 e6 e7
+  e8 e9 ea eb
+  ec ed ee ef =
+  runRW# \world ->
+    let
+      !(# world_, arr #) = newByteArray# 128# world
+
+      write i (D# e) = writeDoubleArray# arr i e
+
+      world0 = write 0x0# e0 world_
+      world1 = write 0x1# e1 world0
+      world2 = write 0x2# e2 world1
+      world3 = write 0x3# e3 world2
+
+      world4 = write 0x4# e4 world3
+      world5 = write 0x5# e5 world4
+      world6 = write 0x6# e6 world5
+      world7 = write 0x7# e7 world6
+
+      world8 = write 0x8# e8 world7
+      world9 = write 0x9# e9 world8
+      worldA = write 0xA# ea world9
+      worldB = write 0xB# eb worldA
+
+      worldC = write 0xC# ec worldB
+      worldD = write 0xD# ed worldC
+      worldE = write 0xE# ee worldD
+      worldF = write 0xF# ef worldE
+
+      !(# _world', arr' #) = unsafeFreezeByteArray# arr worldF
+    in
+      DMat4 arr'
+
+{-# INLINE withMemory #-}
+withMemory
+  :: DMat4
+  ->
+    ( Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      Double -> Double -> Double -> Double ->
+      r
+    )
+  -> r
+withMemory (DMat4 arr) f =
+  f
+    (D# (indexDoubleArray# arr 0x0#))
+    (D# (indexDoubleArray# arr 0x1#))
+    (D# (indexDoubleArray# arr 0x2#))
+    (D# (indexDoubleArray# arr 0x3#))
+
+    (D# (indexDoubleArray# arr 0x4#))
+    (D# (indexDoubleArray# arr 0x5#))
+    (D# (indexDoubleArray# arr 0x6#))
+    (D# (indexDoubleArray# arr 0x7#))
+
+    (D# (indexDoubleArray# arr 0x8#))
+    (D# (indexDoubleArray# arr 0x9#))
+    (D# (indexDoubleArray# arr 0xA#))
+    (D# (indexDoubleArray# arr 0xB#))
+
+    (D# (indexDoubleArray# arr 0xC#))
+    (D# (indexDoubleArray# arr 0xD#))
+    (D# (indexDoubleArray# arr 0xE#))
+    (D# (indexDoubleArray# arr 0xF#))
+
+#ifdef TH_LIFT
+instance Lift DMat4 where
+  lift m = withMemory m
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+      [|
+        fromMemory
+          $(lift e0) $(lift e1) $(lift e2) $(lift e3)
+          $(lift e4) $(lift e5) $(lift e6) $(lift e7)
+          $(lift e8) $(lift e9) $(lift eA) $(lift eB)
+          $(lift eC) $(lift eD) $(lift eE) $(lift eF)
+      |]
+  liftTyped m = withMemory m
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+      [||
+        fromMemory
+          $$(liftTyped e0) $$(liftTyped e1) $$(liftTyped e2) $$(liftTyped e3)
+          $$(liftTyped e4) $$(liftTyped e5) $$(liftTyped e6) $$(liftTyped e7)
+          $$(liftTyped e8) $$(liftTyped e9) $$(liftTyped eA) $$(liftTyped eB)
+          $$(liftTyped eC) $$(liftTyped eD) $$(liftTyped eE) $$(liftTyped eF)
+      ||]
+#endif
+
+
+{-# INLINE identity #-}
+identity :: DMat4
+identity = fromMemory
+  1 0 0 0
+  0 1 0 0
+  0 0 1 0
+  0 0 0 1
+
+{-# INLINE transpose #-}
+transpose :: DMat4 -> DMat4
+transpose =
+  flip withMemory
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+    fromMemory
+      e0 e4 e8 eC
+      e1 e5 e9 eD
+      e2 e6 eA eE
+      e3 e7 eB eF
+
+pointwise :: DMat4 -> DMat4 -> (Double -> Double -> Double) -> DMat4
+pointwise a b f =
+  withMemory a
+    \ a0 a1 a2 a3
+      a4 a5 a6 a7
+      a8 a9 aA aB
+      aC aD aE aF ->
+  withMemory b
+    \ b0 b1 b2 b3
+      b4 b5 b6 b7
+      b8 b9 bA bB
+      bC bD bE bF ->
+  fromMemory
+    (f a0 b0) (f a1 b1) (f a2 b2) (f a3 b3)
+    (f a4 b4) (f a5 b5) (f a6 b6) (f a7 b7)
+    (f a8 b8) (f a9 b9) (f aA bA) (f aB bB)
+    (f aC bC) (f aD bD) (f aE bE) (f aF bF)
+
+{-# INLINE newDMat4 #-}
+newDMat4 :: IO DMat4
+newDMat4 =
+  IO \world ->
+    let
+      !(# world_, arr_ #) = newByteArray# 128# world
+      !(# world', arr #) = unsafeFreezeByteArray# arr_ world_
+    in
+      (# world', DMat4 arr #)
+
+{-# INLINE scalarMultiply #-}
+scalarMultiply :: Double -> DMat4 -> DMat4
+scalarMultiply x m =
+  withMemory m
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+      fromMemory
+      (e0 * x) (e1 * x) (e2 * x) (e3 * x)
+      (e4 * x) (e5 * x) (e6 * x) (e7 * x)
+      (e8 * x) (e9 * x) (eA * x) (eB * x)
+      (eC * x) (eD * x) (eE * x) (eF * x)
+
+instance Storable DMat4 where
+  sizeOf _mat4 = 128
+
+  alignment _mat4 = 32
+
+  {-# INLINE poke #-}
+  poke (Ptr addr) (DMat4 arr) = IO \world ->
+    let
+      world' = copyByteArrayToAddr# arr 0# addr 128# world
+    in
+      (# world', () #)
+
+  {-# INLINE peek #-}
+  peek (Ptr addr) = IO \world ->
+    let
+      load i = readDoubleOffAddr# addr i
+
+      !(# world0, e0 #) = load 0x0# world
+      !(# world1, e1 #) = load 0x1# world0
+      !(# world2, e2 #) = load 0x2# world1
+      !(# world3, e3 #) = load 0x3# world2
+
+      !(# world4, e4 #) = load 0x4# world3
+      !(# world5, e5 #) = load 0x5# world4
+      !(# world6, e6 #) = load 0x6# world5
+      !(# world7, e7 #) = load 0x7# world6
+
+      !(# world8, e8 #) = load 0x8# world7
+      !(# world9, e9 #) = load 0x9# world8
+      !(# worldA, eA #) = load 0xA# world9
+      !(# worldB, eB #) = load 0xB# worldA
+
+      !(# worldC, eC #) = load 0xC# worldB
+      !(# worldD, eD #) = load 0xD# worldC
+      !(# worldE, eE #) = load 0xE# worldD
+      !(# world', eF #) = load 0xF# worldE
+
+      !mat = fromMemory
+        (D# e0) (D# e1) (D# e2) (D# e3)
+        (D# e4) (D# e5) (D# e6) (D# e7)
+        (D# e8) (D# e9) (D# eA) (D# eB)
+        (D# eC) (D# eD) (D# eE) (D# eF)
+    in
+      (# world', mat #)
+
+instance Block DMat4 where
+  type PackedSize DMat4 = 128
+  alignment140 _  = 32
+  sizeOf140       = sizeOfPacked
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+#ifdef SERIALISE
+instance Serialise DMat4 where
+  encode m =
+    withMemory m
+      \ e0 e1 e2 e3
+        e4 e5 e6 e7
+        e8 e9 eA eB
+        eC eD eE eF ->
+          Serialise.encodeListLen 16 <>
+          encode e0 <>
+          encode e1 <> encode e2 <> encode e3 <>
+          encode e4 <> encode e5 <> encode e6  <> encode e7 <>
+          encode e8 <> encode e9 <> encode eA  <> encode eB <>
+          encode eC <> encode eD <> encode eE  <> encode eF
+  decode = do
+    Serialise.decodeListLenOf 16
+    e0 <- decode
+    e1 <- decode
+    e2 <- decode
+    e3 <- decode
+    e4 <- decode
+    e5 <- decode
+    e6 <- decode
+    e7 <- decode
+    e8 <- decode
+    e9 <- decode
+    eA <- decode
+    eB <- decode
+    eC <- decode
+    eD <- decode
+    eE <- decode
+    eF <- decode
+    pure $! fromMemory
+      e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF
+#endif
+
+toListMemory :: DMat4 -> [Double]
+toListMemory = flip withMemory
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+    [ e0, e1, e2, e3
+    , e4, e5, e6, e7
+    , e8, e9, eA, eB
+    , eC, eD, eE, eF
+    ]
+
+toList2dMemory :: DMat4 -> [[Double]]
+toList2dMemory = flip withMemory
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+    [ [e0, e1, e2, e3]
+    , [e4, e5, e6, e7]
+    , [e8, e9, eA, eB]
+    , [eC, eD, eE, eF]
+    ]
+
+toListTrans :: DMat4 -> [Double]
+toListTrans = flip withMemory
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+    [ e0, e4, e8, eC
+    , e1, e5, e9, eD
+    , e2, e6, eA, eE
+    , e3, e7, eB, eF
+    ]
+
+toList2dTrans :: DMat4 -> [[Double]]
+toList2dTrans = flip withMemory
+    \ e0 e1 e2 e3
+      e4 e5 e6 e7
+      e8 e9 eA eB
+      eC eD eE eF ->
+    [ [e0, e4, e8, eC]
+    , [e1, e5, e9, eD]
+    , [e2, e6, eA, eE]
+    , [e3, e7, eB, eF]
+    ]
+
+zipWith :: (Double -> Double -> c) -> DMat4 -> DMat4 -> [c]
+zipWith f a b = List.zipWith f (toListMemory a) (toListMemory b)
diff --git a/src/Geomancy/DQuaternion.hs b/src/Geomancy/DQuaternion.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DQuaternion.hs
@@ -0,0 +1,358 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeFamilies #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+module Geomancy.DQuaternion
+  ( DQuaternion
+  , dquaternion
+  , withDQuaternion
+
+  , axisAngle
+  , intrinsic
+  , extrinsic
+  , rotate
+  , rotatePoint
+  , rotationBetween
+  , lookAtUp
+
+  , (^*)
+  , (^/)
+  , slerp
+
+  , conjugate
+  , norm
+  , quadrance
+  , dot
+  , normalize
+  , qNaN
+
+  , fromQuaternion
+  , toQuaternion
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Foreign (Storable(..), castPtr)
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Float (double2Float, float2Double)
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Graphics.Gl.Block (Block(..))
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.Quaternion (Quaternion, quaternion, withQuaternion)
+
+import qualified Geomancy.DVec3 as DVec3
+
+data DQuaternion = DQuaternion
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE dquaternion #-}
+dquaternion :: Double -> Double -> Double -> Double -> DQuaternion
+dquaternion = DQuaternion
+
+{-# INLINE withDQuaternion #-}
+withDQuaternion
+  :: DQuaternion
+  -> (Double -> Double -> Double -> Double -> r)
+  -> r
+withDQuaternion (DQuaternion a b c d) f = f a b c d
+
+{-# INLINE fromQuaternion #-}
+fromQuaternion :: Quaternion -> DQuaternion
+fromQuaternion q =
+  withQuaternion q \a b c d ->
+    dquaternion (float2Double a) (float2Double b) (float2Double c) (float2Double d)
+
+{-# INLINE toQuaternion #-}
+toQuaternion :: DQuaternion -> Quaternion
+toQuaternion q =
+  withDQuaternion q \a b c d ->
+    quaternion (double2Float a) (double2Float b) (double2Float c) (double2Float d)
+
+{-# INLINE (^*) #-}
+(^*) :: DQuaternion -> Double -> DQuaternion
+DQuaternion a b c d ^* x =
+  DQuaternion
+    (a * x)
+    (b * x)
+    (c * x)
+    (d * x)
+
+{-# INLINE (^/) #-}
+(^/) :: DQuaternion -> Double -> DQuaternion
+DQuaternion a b c d ^/ x =
+  DQuaternion
+    (a / x)
+    (b / x)
+    (c / x)
+    (d / x)
+
+slerp :: DQuaternion -> DQuaternion -> Double -> DQuaternion
+slerp q p t
+  | 1.0 - cosphi < 1e-12 =
+      q
+  | otherwise =
+      ( (q   ^* sin ((1 - t) * phi)) +
+         f p ^* sin (t * phi)
+      ) ^/ sin phi
+  where
+    phi = acos cosphi
+
+    (cosphi, f) =
+      if dqp < 0 then
+        (-dqp, negate)
+      else
+        (dqp, id)
+
+    dqp = dot q p
+
+{-# INLINE conjugate #-}
+conjugate :: DQuaternion -> DQuaternion
+conjugate (DQuaternion e x y z) = DQuaternion e (-x) (-y) (-z)
+
+{-# INLINE norm #-}
+norm :: DQuaternion -> Double
+norm = sqrt . quadrance
+
+{-# INLINE quadrance #-}
+quadrance :: DQuaternion -> Double
+quadrance q = dot q q
+
+{-# INLINE dot #-}
+dot :: DQuaternion -> DQuaternion -> Double
+dot (DQuaternion a b c d) (DQuaternion e f g h) =
+  a * e +
+  b * f +
+  c * g +
+  d * h
+
+{-# INLINE normalize #-}
+normalize :: DQuaternion -> DQuaternion
+normalize v =
+  if nearZero q || nearZero (1-q) then
+    v
+  else
+    let
+      DQuaternion e i j k = v
+    in
+      DQuaternion (e / l) (i / l) (j / l) (k / l)
+
+  where
+    q = dot v v
+    l = sqrt q
+
+    nearZero a = abs a <= 1e-12
+
+instance NFData DQuaternion where
+  rnf DQuaternion{} = ()
+
+instance Num DQuaternion where
+  {-# INLINE (+) #-}
+  DQuaternion a b c d + DQuaternion e f g h =
+    DQuaternion
+      (a + e)
+      (b + f)
+      (c + g)
+      (d + h)
+
+  {-# INLINE (-) #-}
+  DQuaternion a b c d - DQuaternion e f g h =
+    DQuaternion
+      (a - e)
+      (b - f)
+      (c - g)
+      (d - h)
+
+  {-# INLINE (*) #-}
+  DQuaternion as ax ay az * DQuaternion bs bx by bz =
+    withDVec3 v \x y z ->
+      DQuaternion s x y z
+    where
+      s = as * bs - DVec3.dot v1 v2
+      v = DVec3.cross v1 v2 + v2 DVec3.^* as + v1 DVec3.^* bs
+      v1 = dvec3 ax ay az
+      v2 = dvec3 bx by bz
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = DQuaternion (fromInteger x) 0 0 0
+
+  {-# INLINE abs #-}
+  abs z = DQuaternion (norm z) 0 0 0
+
+  {-# INLINE signum #-}
+  signum q@(DQuaternion e i j k)
+    | m == 0 =
+        q
+    | not (isInfinite m || isNaN m) =
+        DQuaternion (e * misqrt) (i * misqrt) (j * misqrt) (k * misqrt)
+    | any isNaN [e, i, j, k] = qNaN
+    | not (ii || ij || ik) = DQuaternion 1 0 0 0
+    | not (ie || ij || ik) = DQuaternion 0 1 0 0
+    | not (ie || ii || ik) = DQuaternion 0 0 1 0
+    | not (ie || ii || ij) = DQuaternion 0 0 0 1
+    | otherwise = qNaN
+    where
+      m = quadrance q
+      misqrt = recip (sqrt m)
+
+      ie = isInfinite e
+      ii = isInfinite i
+      ij = isInfinite j
+      ik = isInfinite k
+
+{-# INLINE qNaN #-}
+qNaN :: DQuaternion
+qNaN = DQuaternion dNaN dNaN dNaN dNaN
+  where
+    dNaN = 0/0
+
+instance Storable DQuaternion where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 32
+
+  {-# INLINE poke #-}
+  poke ptr (DQuaternion a b c d) = do
+    poke ptr' a
+    pokeElemOff ptr' 1 b
+    pokeElemOff ptr' 2 c
+    pokeElemOff ptr' 3 d
+    where
+      ptr' = castPtr ptr
+
+  {-# INLINE peek #-}
+  peek ptr = DQuaternion
+    <$> peek ptr'
+    <*> peekElemOff ptr' 1
+    <*> peekElemOff ptr' 2
+    <*> peekElemOff ptr' 3
+    where
+      ptr' = castPtr ptr
+
+{-# INLINE axisAngle #-}
+axisAngle :: DVec3 -> Double -> DQuaternion
+axisAngle axis rads =
+  withDVec3 (DVec3.normalize axis DVec3.^* sin half) $
+    dquaternion (cos half)
+  where
+    half = rads / 2
+
+intrinsic :: Double -> Double -> Double -> DQuaternion
+intrinsic roll pitch yaw =
+  dquaternion
+    (cx * cy * cz + sx * sy * sz)
+    (sx * cy * cz + cx * sy * sz)
+    (cx * sy * cz - sx * cy * sz)
+    (cx * cy * sz - sx * sy * cz)
+  where
+    cx = cos (pitch * 0.5)
+    sx = sin (pitch * 0.5)
+    cy = cos (yaw * 0.5)
+    sy = sin (yaw * 0.5)
+    cz = cos (roll * 0.5)
+    sz = sin (roll * 0.5)
+
+extrinsic :: Double -> Double -> Double -> DQuaternion
+extrinsic heading elevation tilt =
+  axisAngle (dvec3 0 0 1) tilt *
+  axisAngle (dvec3 1 0 0) elevation *
+  axisAngle (dvec3 0 1 0) heading
+
+{-# INLINE rotate #-}
+rotate :: DQuaternion -> DVec3 -> DVec3
+rotate (DQuaternion w x y z) v =
+  withDVec3 v \vx vy vz ->
+    let
+      x2 = x + x
+      y2 = y + y
+      z2 = z + z
+      tx = y2 * vz - z2 * vy
+      ty = z2 * vx - x2 * vz
+      tz = x2 * vy - y2 * vx
+    in
+      dvec3
+        (vx + w * tx + y * tz - z * ty)
+        (vy + w * ty + z * tx - x * tz)
+        (vz + w * tz + x * ty - y * tx)
+
+{-# INLINE rotatePoint #-}
+rotatePoint :: DQuaternion -> DVec3 -> DVec3 -> DVec3
+rotatePoint q origin point =
+  origin + rotate q (point - origin)
+
+rotationBetween :: DVec3 -> DVec3 -> DQuaternion
+rotationBetween v1 v2 = axisAngle axis angle
+  where
+    axis = DVec3.cross v1 v2
+    angle = acos cosAngle
+    cosAngle =
+      max (-1) . min 1 $
+        DVec3.dot (DVec3.normalize v1) (DVec3.normalize v2)
+
+lookAtUp :: DVec3 -> DVec3 -> DVec3 -> DQuaternion
+lookAtUp src dst up = rot2 * rot1
+  where
+    dir3 = dst - src
+
+    rot1 = rotationBetween (dvec3 0 0 1) dir3
+
+    rot2 = rotationBetween newUp fixedUp
+
+    newUp = rotate rot1 up
+    fixedUp = DVec3.cross (DVec3.cross dir3 up) dir3
+
+instance Block DQuaternion where
+  type PackedSize DQuaternion = 32
+  alignment140 _  = 32
+  sizeOf140       = sizeOfPacked
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = True
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+#ifdef SERIALISE
+instance Serialise DQuaternion where
+  encode v = withDQuaternion v \x y z w ->
+    Serialise.encodeListLen 4 <> encode x <> encode y <> encode z <> encode w
+  decode =
+    Serialise.decodeListLenOf 4 *> (dquaternion <$> decode <*> decode <*> decode <*> decode)
+#endif
diff --git a/src/Geomancy/DTransform.hs b/src/Geomancy/DTransform.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DTransform.hs
@@ -0,0 +1,226 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralisedNewtypeDeriving #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TypeFamilies #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+#endif
+
+module Geomancy.DTransform
+  ( DTransform(..)
+  , DMat4.inverse
+
+  , apply
+  , (!.)
+
+  , translate
+  , translateV
+
+  , rotateX
+  , rotateY
+  , rotateZ
+  , rotateQ
+
+  , scale
+  , scaleX
+  , scaleY
+  , scaleZ
+  , scaleXY
+  , scale3
+  , scaleV
+
+  , dirPos
+  , node
+
+  , fromTransform
+  , toTransform
+  ) where
+
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise)
+#endif
+
+import Geomancy.DMat4 (DMat4, colMajor)
+import Geomancy.DQuaternion (DQuaternion, withDQuaternion)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.DVec4 (fromDVec3, withDVec4)
+import Geomancy.DMat4 qualified as DMat4
+import Geomancy.Transform (Transform(..))
+
+import Graphics.Gl.Block (Block(..))
+
+newtype DTransform = DTransform { unDTransform :: DMat4 }
+  deriving newtype (Eq, Show, Semigroup, Monoid, Storable)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+#ifdef SERIALISE
+  deriving Serialise
+#endif
+
+instance Block DTransform where
+  type PackedSize DTransform = 128
+  alignment140 _  = 32
+  sizeOf140       = sizeOfPacked
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+{-# INLINE fromTransform #-}
+fromTransform :: Transform -> DTransform
+fromTransform = DTransform . DMat4.fromMat4
+
+{-# INLINE toTransform #-}
+toTransform :: DTransform -> Transform
+toTransform = Transform . DMat4.toMat4 . unDTransform
+
+apply :: DVec3 -> DTransform -> DVec3
+apply = flip (!.)
+
+(!.) :: DTransform -> DVec3 -> DVec3
+(!.) mat vec =
+  withDVec4 res \x y z w ->
+    dvec3 (x / w) (y / w) (z / w)
+  where
+    res = mat DMat4.!* fromDVec3 vec 1.0
+
+infixr 5 !.
+
+{-# INLINE translate #-}
+translate :: Double -> Double -> Double -> DTransform
+translate x y z = colMajor
+  1 0 0 x
+  0 1 0 y
+  0 0 1 z
+  0 0 0 1
+
+{-# INLINE translateV #-}
+translateV :: DVec3 -> DTransform
+translateV vec = withDVec3 vec translate
+
+{-# INLINE scale3 #-}
+scale3 :: Double -> Double -> Double -> DTransform
+scale3 x y z = colMajor
+  x 0 0 0
+  0 y 0 0
+  0 0 z 0
+  0 0 0 1
+
+{-# INLINE scale #-}
+scale :: Double -> DTransform
+scale s = scale3 s s s
+
+{-# INLINE scaleX #-}
+scaleX :: Double -> DTransform
+scaleX x = scale3 x 1 1
+
+{-# INLINE scaleY #-}
+scaleY :: Double -> DTransform
+scaleY y = scale3 1 y 1
+
+{-# INLINE scaleZ #-}
+scaleZ :: Double -> DTransform
+scaleZ z = scale3 1 1 z
+
+{-# INLINE scaleXY #-}
+scaleXY :: Double -> Double -> DTransform
+scaleXY x y = scale3 x y 1
+
+{-# INLINE scaleV #-}
+scaleV :: DVec3 -> DTransform
+scaleV s = withDVec3 s scale3
+
+{-# INLINE rotateX #-}
+rotateX :: Double -> DTransform
+rotateX rads =
+  colMajor
+    1 0   0  0
+    0 c (-s) 0
+    0 s   c  0
+    0 0   0  1
+  where
+    c = cos rads
+    s = sin rads
+
+{-# INLINE rotateY #-}
+rotateY :: Double -> DTransform
+rotateY rads =
+  colMajor
+    c  0 s 0
+    0  1 0 0
+  (-s) 0 c 0
+    0  0 0 1
+  where
+    c = cos rads
+    s = sin rads
+
+{-# INLINE rotateZ #-}
+rotateZ :: Double -> DTransform
+rotateZ rads =
+  colMajor
+    c (-s) 0 0
+    s   c  0 0
+    0   0  1 0
+    0   0  0 1
+  where
+   c = cos rads
+   s = sin rads
+
+{-# INLINE rotateQ #-}
+rotateQ :: DQuaternion -> DTransform
+rotateQ dir = dirPos dir 0
+
+{-# INLINE dirPos #-}
+dirPos :: DQuaternion -> DVec3 -> DTransform
+dirPos rs t =
+  withDQuaternion rs \w x y z ->
+  withDVec3 t \tx ty tz ->
+    let
+      x2 = x * x
+      y2 = y * y
+      z2 = z * z
+      xy = x * y
+      xz = x * z
+      xw = x * w
+      yz = y * z
+      yw = y * w
+      zw = z * w
+    in
+      colMajor
+        (1 - 2 * (y2 + z2)) (    2 * (xy - zw)) (    2 * (xz + yw)) tx
+        (    2 * (xy + zw)) (1 - 2 * (x2 + z2)) (    2 * (yz - xw)) ty
+        (    2 * (xz - yw)) (    2 * (yz + xw)) (1 - 2 * (x2 + y2)) tz
+        0                   0                   0                    1
+
+node :: DVec3 -> DQuaternion -> DVec3 -> DTransform
+node t r s
+ | s == 1.0 = dirPos r t
+ | otherwise = dirPos r t <> scaleV s
diff --git a/src/Geomancy/DTransform/Tree.hs b/src/Geomancy/DTransform/Tree.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DTransform/Tree.hs
@@ -0,0 +1,132 @@
+module Geomancy.DTransform.Tree
+  ( Transformed
+  , apply
+  , node_
+  , leaf_
+  , collect_
+
+  , translate_
+  , translateV_
+
+  , rotateX_
+  , rotateY_
+  , rotateZ_
+  , rotateQ_
+
+  , scale_
+  , scaleX_
+  , scaleY_
+  , scaleZ_
+  , scaleXY_
+  , scale3_
+  ) where
+
+import Geomancy.DQuaternion (DQuaternion)
+import Geomancy.DTransform (DTransform)
+import Geomancy.Tree (Tree, apply, node_, leaf_, collect_)
+import Geomancy.DVec3 (DVec3)
+
+import qualified Geomancy.DTransform as DTransform
+
+type Transformed a = Tree (DTransform, Maybe a)
+
+{-# INLINE translate_ #-}
+translate_
+  :: Double
+  -> Double
+  -> Double
+  -> [Transformed a]
+  -> Transformed a
+translate_ x y z =
+  node_ (DTransform.translate x y z)
+
+{-# INLINE translateV_ #-}
+translateV_
+  :: DVec3
+  -> [Transformed a]
+  -> Transformed a
+translateV_ xyz =
+  node_ (DTransform.translateV xyz)
+
+{-# INLINE rotateX_ #-}
+rotateX_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+rotateX_ rads =
+  node_ (DTransform.rotateX rads)
+
+{-# INLINE rotateY_ #-}
+rotateY_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+rotateY_ rads =
+  node_ (DTransform.rotateY rads)
+
+{-# INLINE rotateZ_ #-}
+rotateZ_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+rotateZ_ rads =
+  node_ (DTransform.rotateZ rads)
+
+{-# INLINE rotateQ_ #-}
+rotateQ_
+  :: DQuaternion
+  -> [Transformed a]
+  -> Transformed a
+rotateQ_ rot =
+  node_ (DTransform.rotateQ rot)
+
+{-# INLINE scale_ #-}
+scale_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+scale_ x =
+  node_ (DTransform.scale x)
+
+{-# INLINE scaleX_ #-}
+scaleX_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+scaleX_ rads =
+  node_ (DTransform.scaleX rads)
+
+{-# INLINE scaleY_ #-}
+scaleY_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+scaleY_ rads =
+  node_ (DTransform.scaleY rads)
+
+{-# INLINE scaleZ_ #-}
+scaleZ_
+  :: Double
+  -> [Transformed a]
+  -> Transformed a
+scaleZ_ rads =
+  node_ (DTransform.scaleZ rads)
+
+{-# INLINE scaleXY_ #-}
+scaleXY_
+  :: Double
+  -> Double
+  -> [Transformed a]
+  -> Transformed a
+scaleXY_ x y =
+  node_ (DTransform.scaleXY x y)
+
+{-# INLINE scale3_ #-}
+scale3_
+  :: Double
+  -> Double
+  -> Double
+  -> [Transformed a]
+  -> Transformed a
+scale3_ x y z =
+  node_ (DTransform.scale3 x y z)
diff --git a/src/Geomancy/DVec2.hs b/src/Geomancy/DVec2.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DVec2.hs
@@ -0,0 +1,340 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+module Geomancy.DVec2
+  ( DVec2
+  , dvec2
+  , withDVec2
+  , pattern WithDVec2
+  , fromTuple
+  , convert
+
+  , (^*)
+  , (^/)
+  , lerp
+
+  , dot
+  , normalize
+
+  , fromVec2
+  , toVec2
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.VectorSpace (VectorSpace)
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Float (double2Float, float2Double)
+import GHC.Records (HasField(..))
+import qualified Data.VectorSpace as VectorSpace
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+import Geomancy.Vec2 (Vec2)
+import qualified Geomancy.Vec2 as Vec2
+
+data DVec2 = DVec2
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE dvec2 #-}
+dvec2 :: Double -> Double -> DVec2
+dvec2 = DVec2
+
+{-# INLINE withDVec2 #-}
+withDVec2
+  :: DVec2
+  -> (Double -> Double -> r)
+  -> r
+withDVec2 (DVec2 a b) f = f a b
+
+{-# INLINE convert #-}
+convert :: Coercible v DVec2 => (Double -> a) -> (a -> a -> r) -> v -> r
+convert f t v =
+  withDVec2 (coerce v) \a b ->
+    t (f a) (f b)
+
+pattern WithDVec2 :: Double -> Double -> DVec2
+pattern WithDVec2 a b <- ((`withDVec2` (,)) -> (a, b))
+{-# COMPLETE WithDVec2 #-}
+
+instance HasField "x" DVec2 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x _ -> x
+
+instance HasField "y" DVec2 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \_ y -> y
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Double, Double) -> DVec2
+fromTuple (x, y) = dvec2 x y
+
+{-# INLINE fromVec2 #-}
+fromVec2 :: Vec2 -> DVec2
+fromVec2 = Vec2.convert float2Double dvec2
+
+{-# INLINE toVec2 #-}
+toVec2 :: DVec2 -> Vec2
+toVec2 = convert double2Float Vec2.vec2
+
+instance NFData DVec2 where
+  rnf DVec2{} = ()
+
+type instance Element DVec2 = Double
+
+instance MonoFunctor DVec2 where
+  {-# INLINE omap #-}
+  omap f v =
+    withDVec2 v \x y ->
+      dvec2 (f x) (f y)
+
+instance MonoPointed DVec2 where
+  opoint x = dvec2 x x
+
+instance Elementwise DVec2 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withDVec2 p0 \x0 y0 ->
+    withDVec2 p1 \x1 y1 ->
+      dvec2
+        (f x0 x1)
+        (f y0 y1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withDVec2 p0 \x0 y0 ->
+    withDVec2 p1 \x1 y1 ->
+    withDVec2 p2 \x2 y2 ->
+      dvec2
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withDVec2 p0 \x0 y0 ->
+    withDVec2 p1 \x1 y1 ->
+    withDVec2 p2 \x2 y2 ->
+    withDVec2 p3 \x3 y3 ->
+      dvec2
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withDVec2 p0 \x0 y0 ->
+    withDVec2 p1 \x1 y1 ->
+    withDVec2 p2 \x2 y2 ->
+    withDVec2 p3 \x3 y3 ->
+    withDVec2 p4 \x4 y4 ->
+      dvec2
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+
+instance Num DVec2 where
+  {-# INLINE (+) #-}
+  DVec2 l1 l2 + DVec2 r1 r2 =
+    DVec2
+      (l1 + r1)
+      (l2 + r2)
+
+  {-# INLINE (-) #-}
+  DVec2 l1 l2 - DVec2 r1 r2 =
+    DVec2
+      (l1 - r1)
+      (l2 - r2)
+
+  {-# INLINE (*) #-}
+  DVec2 l1 l2 * DVec2 r1 r2 =
+    DVec2
+      (l1 * r1)
+      (l2 * r2)
+
+  {-# INLINE abs #-}
+  abs (DVec2 a b) =
+    DVec2 (abs a) (abs b)
+
+  {-# INLINE signum #-}
+  signum (DVec2 a b) =
+    DVec2 (signum a) (signum b)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = DVec2 x' x'
+    where
+      x' = fromInteger x
+
+instance Fractional DVec2 where
+  {-# INLINE (/) #-}
+  DVec2 l1 l2 / DVec2 r1 r2 =
+    DVec2 (l1 / r1) (l2 / r2)
+
+  {-# INLINE recip #-}
+  recip (DVec2 a b) =
+    DVec2 (recip a) (recip b)
+
+  {-# INLINE fromRational #-}
+  fromRational x = DVec2 x' x'
+    where
+      x' = fromRational x
+
+instance Floating DVec2 where
+  pi = opoint pi
+
+  exp = omap exp
+  log = omap log
+  sqrt = omap sqrt
+  sin = omap sin
+  cos = omap cos
+  asin = omap asin
+  acos = omap acos
+  atan = omap atan
+  sinh = omap sinh
+  cosh = omap cosh
+  asinh = omap asinh
+  acosh = omap acosh
+  atanh = omap atanh
+
+  (**) = emap2 (**)
+
+{-# INLINE (^*) #-}
+(^*) :: DVec2 -> Double -> DVec2
+DVec2 a b ^* x =
+  DVec2
+    (a * x)
+    (b * x)
+
+{-# INLINE (^/) #-}
+(^/) :: DVec2 -> Double -> DVec2
+DVec2 a b ^/ x =
+  DVec2
+    (a / x)
+    (b / x)
+
+{-# INLINE lerp #-}
+lerp :: Double -> DVec2 -> DVec2 -> DVec2
+lerp alpha u v = u ^* alpha + v ^* (1 - alpha)
+
+{-# INLINE dot #-}
+dot :: DVec2 -> DVec2 -> Double
+dot (DVec2 l1 l2) (DVec2 r1 r2) =
+  l1 * r1 + l2 * r2
+
+{-# INLINE normalize #-}
+normalize :: DVec2 -> DVec2
+normalize v =
+  if nearZero q || nearZero (1 - q) then
+    v
+  else
+    let
+      DVec2 x y = v
+    in
+      DVec2 (x / l) (y / l)
+
+  where
+    q = dot v v
+    l = sqrt q
+
+    nearZero a = abs a <= 1e-12
+
+instance Storable DVec2 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 16
+
+  {-# INLINE alignment #-}
+  alignment _ = 16
+
+  {-# INLINE poke #-}
+  poke ptr v2 =
+    withDVec2 v2 \a b -> do
+      pokeByteOff ptr 0 a
+      pokeByteOff ptr 8 b
+
+  {-# INLINE peek #-}
+  peek ptr = dvec2
+    <$> peekByteOff ptr 0
+    <*> peekByteOff ptr 8
+
+instance Block DVec2 where
+  type PackedSize DVec2 = 16
+  alignment140 _  = 16
+  sizeOf140 _     = 16
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+#ifdef SERIALISE
+instance Serialise DVec2 where
+  encode v = withDVec2 v \x y ->
+    Serialise.encodeListLen 2 <> encode x <> encode y
+  decode =
+    Serialise.decodeListLenOf 2 *> (dvec2 <$> decode <*> decode)
+#endif
+
+instance VectorSpace DVec2 Double where
+  zeroVector = epoint 0
+
+  {-# INLINE (*^) #-}
+  a *^ v = v Geomancy.DVec2.^* a
+
+  {-# INLINE (^/) #-}
+  v ^/ a = v Geomancy.DVec2.^/ a
+
+  {-# INLINE (^+^) #-}
+  (^+^) = emap2 (+)
+
+  {-# INLINE (^-^) #-}
+  (^-^) = emap2 (-)
+
+  {-# INLINE negateVector #-}
+  negateVector = emap negate
+
+  {-# INLINE dot #-}
+  dot = Geomancy.DVec2.dot
+
+  {-# INLINE normalize #-}
+  normalize = Geomancy.DVec2.normalize
diff --git a/src/Geomancy/DVec3.hs b/src/Geomancy/DVec3.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DVec3.hs
@@ -0,0 +1,510 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+#endif
+
+module Geomancy.DVec3
+  ( DVec3
+  , dvec3
+  , withDVec3
+  , pattern WithDVec3
+  , convert
+  , fromDVec2
+  , fromTuple
+
+  , (^*)
+  , (^/)
+  , lerp
+
+  , cross
+  , dot
+  , normalize
+
+  , Packed(..)
+  , packed
+
+  , emap2
+  , emap3
+  , emap4
+
+  , fromVec3
+  , toVec3
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.VectorSpace (VectorSpace)
+import Data.VectorSpace qualified as VectorSpace
+import Foreign (Storable(..), castPtr)
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Float (double2Float, float2Double)
+import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
+import WebColor.Labels (IsWebColor(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift(..))
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.DVec2 (DVec2, withDVec2)
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+import Geomancy.Vec3 (Vec3)
+import Geomancy.Vec3 qualified as Vec3
+
+data DVec3 = DVec3
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  {-# UNPACK #-} !Double
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE dvec3 #-}
+dvec3 :: Double -> Double -> Double -> DVec3
+dvec3 = DVec3
+
+{-# INLINE withDVec3 #-}
+withDVec3
+  :: DVec3
+  -> (Double -> Double -> Double -> r)
+  -> r
+withDVec3 (DVec3 a b c) f = f a b c
+
+{-# INLINE convert #-}
+convert :: Coercible v DVec3 => (Double -> a) -> (a -> a -> a -> r) -> v -> r
+convert f t v =
+  withDVec3 (coerce v) \a b c ->
+    t (f a) (f b) (f c)
+
+pattern WithDVec3 :: Double -> Double -> Double -> DVec3
+pattern WithDVec3 a b c <- ((`withDVec3` (,,)) -> (a, b, c))
+{-# COMPLETE WithDVec3 #-}
+
+instance HasField "x" DVec3 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ _ -> x
+
+instance HasField "y" DVec3 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y _ -> y
+
+instance HasField "z" DVec3 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ _ z -> z
+
+{-# INLINE fromDVec2 #-}
+fromDVec2 :: Coercible DVec3 a => DVec2 -> Double -> a
+fromDVec2 xy z =
+  withDVec2 xy \x y ->
+    coerce (dvec3 x y z)
+
+{-# INLINE fromTuple #-}
+fromTuple :: Coercible DVec3 a => (Double, Double, Double) -> a
+fromTuple (x, y, z) = coerce (dvec3 x y z)
+
+{-# INLINE fromVec3 #-}
+fromVec3 :: Vec3 -> DVec3
+fromVec3 = Vec3.convert float2Double dvec3
+
+{-# INLINE toVec3 #-}
+toVec3 :: DVec3 -> Vec3
+toVec3 = convert double2Float Vec3.vec3
+
+instance IsWebColor s => IsLabel s DVec3 where
+  {-# INLINE fromLabel #-}
+  fromLabel =
+    webColor @s \r g b ->
+      dvec3
+        (fromIntegral r / 255)
+        (fromIntegral g / 255)
+        (fromIntegral b / 255)
+
+instance NFData DVec3 where
+  rnf DVec3{} = ()
+
+type instance Element DVec3 = Double
+
+instance MonoFunctor DVec3 where
+  {-# INLINE omap #-}
+  omap f v =
+    withDVec3 v \x y z ->
+      dvec3 (f x) (f y) (f z)
+
+instance MonoPointed DVec3 where
+  opoint x = dvec3 x x x
+
+instance Elementwise DVec3 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withDVec3 p0 \x0 y0 z0 ->
+    withDVec3 p1 \x1 y1 z1 ->
+      dvec3
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withDVec3 p0 \x0 y0 z0 ->
+    withDVec3 p1 \x1 y1 z1 ->
+    withDVec3 p2 \x2 y2 z2 ->
+      dvec3
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withDVec3 p0 \x0 y0 z0 ->
+    withDVec3 p1 \x1 y1 z1 ->
+    withDVec3 p2 \x2 y2 z2 ->
+    withDVec3 p3 \x3 y3 z3 ->
+      dvec3
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withDVec3 p0 \x0 y0 z0 ->
+    withDVec3 p1 \x1 y1 z1 ->
+    withDVec3 p2 \x2 y2 z2 ->
+    withDVec3 p3 \x3 y3 z3 ->
+    withDVec3 p4 \x4 y4 z4 ->
+      dvec3
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+
+instance Num DVec3 where
+  {-# INLINE (+) #-}
+  DVec3 a b c + DVec3 d e f =
+    DVec3
+      (a + d)
+      (b + e)
+      (c + f)
+
+  {-# INLINE (-) #-}
+  DVec3 a b c - DVec3 d e f =
+    DVec3
+      (a - d)
+      (b - e)
+      (c - f)
+
+  {-# INLINE (*) #-}
+  DVec3 a b c * DVec3 d e f =
+    DVec3
+      (a * d)
+      (b * e)
+      (c * f)
+
+  {-# INLINE abs #-}
+  abs (DVec3 a b c) =
+    DVec3 (abs a) (abs b) (abs c)
+
+  {-# INLINE signum #-}
+  signum (DVec3 a b c) =
+    DVec3 (signum a) (signum b) (signum c)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = DVec3 x' x' x'
+    where
+      x' = fromInteger x
+
+instance Fractional DVec3 where
+  {-# INLINE (/) #-}
+  DVec3 l1 l2 l3 / DVec3 r1 r2 r3 =
+    DVec3 (l1 / r1) (l2 / r2) (l3 / r3)
+
+  {-# INLINE recip #-}
+  recip (DVec3 a b c) =
+    DVec3 (recip a) (recip b) (recip c)
+
+  {-# INLINE fromRational #-}
+  fromRational x = DVec3 x' x' x'
+    where
+      x' = fromRational x
+
+instance Floating DVec3 where
+  pi = opoint pi
+
+  exp = omap exp
+  log = omap log
+  sqrt = omap sqrt
+  sin = omap sin
+  cos = omap cos
+  asin = omap asin
+  acos = omap acos
+  atan = omap atan
+  sinh = omap sinh
+  cosh = omap cosh
+  asinh = omap asinh
+  acosh = omap acosh
+  atanh = omap atanh
+
+  a ** b =
+    withDVec3 a \ax ay az ->
+    withDVec3 b \bx by bz ->
+      dvec3
+        (ax ** bx)
+        (ay ** by)
+        (az ** bz)
+
+instance Storable DVec3 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr v3 =
+    withDVec3 v3 \a b c -> do
+      poke ptr' a
+      pokeElemOff ptr' 1 b
+      pokeElemOff ptr' 2 c
+      pokeElemOff ptr' 3 (1.0 :: Double)
+    where
+      ptr' = castPtr ptr
+
+  {-# INLINE peek #-}
+  peek ptr =
+    dvec3 <$> peek ptr' <*> peekElemOff ptr' 1 <*> peekElemOff ptr' 2
+    where
+      ptr' = castPtr ptr
+
+instance Block DVec3 where
+  type PackedSize DVec3 = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 32
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked ptr diff = pokeDiffOff ptr (coerce diff) . Packed
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+#ifdef SERIALISE
+instance Serialise DVec3 where
+  encode v = withDVec3 v \x y z ->
+    Serialise.encodeListLen 3 <> encode x <> encode y <> encode z
+  decode =
+    Serialise.decodeListLenOf 3 *> (dvec3 <$> decode <*> decode <*> decode)
+#endif
+
+{-# INLINE (^*) #-}
+(^*) :: DVec3 -> Double -> DVec3
+DVec3 a b c ^* x =
+  DVec3
+    (a * x)
+    (b * x)
+    (c * x)
+
+{-# INLINE (^/) #-}
+(^/) :: DVec3 -> Double -> DVec3
+DVec3 a b c ^/ x =
+  DVec3
+    (a / x)
+    (b / x)
+    (c / x)
+
+{-# INLINE lerp #-}
+lerp :: Double -> DVec3 -> DVec3 -> DVec3
+lerp alpha u v = u ^* alpha + v ^* (1 - alpha)
+
+{-# INLINE cross #-}
+cross :: DVec3 -> DVec3 -> DVec3
+cross (DVec3 a b c) (DVec3 d e f) =
+  DVec3
+    (b * f - c * e)
+    (c * d - a * f)
+    (a * e - b * d)
+
+{-# INLINE dot #-}
+dot :: DVec3 -> DVec3 -> Double
+dot (DVec3 a b c) (DVec3 d e f) =
+  a * d +
+  b * e +
+  c * f
+
+{-# INLINE normalize #-}
+normalize :: DVec3 -> DVec3
+normalize v =
+  if nearZero q || nearZero (1-q) then
+    v
+  else
+    let
+      DVec3 x y z = v
+    in
+      DVec3 (x / l) (y / l) (z / l)
+
+  where
+    q = dot v v
+    l = sqrt q
+
+    nearZero a = abs a <= 1e-12
+
+instance VectorSpace DVec3 Double where
+  zeroVector = epoint 0
+
+  {-# INLINE (*^) #-}
+  (*^) = flip (Geomancy.DVec3.^*)
+
+  {-# INLINE (^/) #-}
+  (^/) = (Geomancy.DVec3.^/)
+
+  {-# INLINE (^+^) #-}
+  (^+^) = emap2 (+)
+
+  {-# INLINE (^-^) #-}
+  (^-^) = emap2 (-)
+
+  {-# INLINE negateVector #-}
+  negateVector = emap negate
+
+  {-# INLINE dot #-}
+  dot = Geomancy.DVec3.dot
+
+  {-# INLINE normalize #-}
+  normalize = Geomancy.DVec3.normalize
+
+type instance Element Packed = Double
+
+newtype Packed = Packed { unPacked :: DVec3 }
+  deriving stock
+    ( Eq, Ord, Show
+    )
+  deriving newtype
+    ( NFData, Num, Fractional, Floating
+    , MonoFunctor, MonoPointed
+    , Elementwise
+    )
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE packed #-}
+packed :: Double -> Double -> Double -> Packed
+packed x y z = Packed (dvec3 x y z)
+
+instance HasField "x" Packed Double where
+  {-# INLINE getField #-}
+  getField (Packed v) = withDVec3 v \x _ _ -> x
+
+instance HasField "y" Packed Double where
+  {-# INLINE getField #-}
+  getField (Packed v) = withDVec3 v \_ y _ -> y
+
+instance HasField "z" Packed Double where
+  {-# INLINE getField #-}
+  getField (Packed v) = withDVec3 v \_ _ z -> z
+
+instance Storable Packed where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 24
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr (Packed v3) =
+    withDVec3 v3 \a b c -> do
+      poke ptr' a
+      pokeElemOff ptr' 1 b
+      pokeElemOff ptr' 2 c
+    where
+      ptr' = castPtr ptr
+
+  {-# INLINE peek #-}
+  peek ptr = packed
+    <$> peek ptr'
+    <*> peekElemOff ptr' 1
+    <*> peekElemOff ptr' 2
+    where
+      ptr' = castPtr ptr
+
+instance Block Packed where
+  type PackedSize Packed = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 24
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance VectorSpace Packed Double where
+  zeroVector = epoint 0
+
+  {-# INLINE (*^) #-}
+  (*^) = flip $ coerce (Geomancy.DVec3.^*)
+
+  {-# INLINE (^/) #-}
+  (^/) = coerce (Geomancy.DVec3.^/)
+
+  {-# INLINE (^+^) #-}
+  v1 ^+^ v2 = v1 + v2
+
+  {-# INLINE (^-^) #-}
+  v1 ^-^ v2 = v1 - v2
+
+  {-# INLINE negateVector #-}
+  negateVector = emap negate
+
+  {-# INLINE dot #-}
+  dot = coerce Geomancy.DVec3.dot
+
+  {-# INLINE normalize #-}
+  normalize = coerce Geomancy.DVec3.normalize
diff --git a/src/Geomancy/DVec4.hs b/src/Geomancy/DVec4.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/DVec4.hs
@@ -0,0 +1,516 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE TemplateHaskell #-}
+#endif
+
+module Geomancy.DVec4
+  ( DVec4(..)
+  , dvec4
+  , withDVec4
+  , pattern WithDVec4
+  , convert
+  , fromDVec2
+  , fromDVec22
+  , fromDVec3
+  , fromTuple
+
+  , (^*)
+  , (^/)
+  , lerp
+
+  , dot
+  , normalize
+
+  , newDVec4
+
+  , fromVec4
+  , toVec4
+  ) where
+
+import GHC.Exts hiding (VecCount(..), toList)
+
+import Control.DeepSeq (NFData(rnf))
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.VectorSpace (VectorSpace)
+import Data.VectorSpace qualified as VectorSpace
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Float (double2Float, float2Double)
+import GHC.IO (IO(..))
+import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
+import Text.Printf (printf)
+import WebColor.Labels (IsWebColorAlpha(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift(..))
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.DVec2 (DVec2, withDVec2)
+import Geomancy.DVec3 (DVec3, withDVec3)
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+import Geomancy.Vec4 (Vec4)
+import Geomancy.Vec4 qualified as Vec4
+
+data DVec4 = DVec4 ByteArray#
+
+{-# INLINE [1] dvec4 #-}
+dvec4 :: Double -> Double -> Double -> Double -> DVec4
+dvec4 v0 v1 v2 v3 =
+  runRW# \world ->
+    let
+      !(# world_, arr #) = newByteArray# 32# world
+
+      write i (D# v) = writeDoubleArray# arr i v
+
+      world0 = write 0x0# v0 world_
+      world1 = write 0x1# v1 world0
+      world2 = write 0x2# v2 world1
+      world3 = write 0x3# v3 world2
+      !(# _world', arr' #) = unsafeFreezeByteArray# arr world3
+    in
+      DVec4 arr'
+
+{-# INLINE [1] withDVec4 #-}
+withDVec4
+  :: DVec4
+  -> (Double -> Double -> Double -> Double -> r)
+  -> r
+withDVec4 (DVec4 arr) f =
+  f
+    (D# (indexDoubleArray# arr 0x0#))
+    (D# (indexDoubleArray# arr 0x1#))
+    (D# (indexDoubleArray# arr 0x2#))
+    (D# (indexDoubleArray# arr 0x3#))
+
+{-# RULES
+"withDVec4/dvec4" forall a b c d f.
+  withDVec4 (dvec4 a b c d) f = f a b c d
+"withDVec4/withDVec4" forall v k f.
+  withDVec4 (withDVec4 v k) f = withDVec4 v \a b c d -> withDVec4 (k a b c d) f
+  #-}
+
+{-# INLINE convert #-}
+convert :: Coercible v DVec4 => (Double -> a) -> (a -> a -> a -> a -> r) -> v -> r
+convert f t v =
+  withDVec4 (coerce v) \a b c d->
+    t (f a) (f b) (f c) (f d)
+
+instance Eq DVec4 where
+  DVec4 a == DVec4 b = go 0#
+    where
+      go i
+        | isTrue# (i ==# 4#) = True
+        | isTrue# (indexDoubleArray# a i ==## indexDoubleArray# b i) = go (i +# 1#)
+        | otherwise = False
+
+instance Ord DVec4 where
+  compare = lexicographic LT GT compare
+  a < b = lexicographic True False (<) a b
+  a <= b = not (b < a)
+  a > b = b < a
+  a >= b = not (a < b)
+
+{-# INLINE lexicographic #-}
+lexicographic :: r -> r -> (Double -> Double -> r) -> DVec4 -> DVec4 -> r
+lexicographic lt gt lastElement (DVec4 a) (DVec4 b) = go 0#
+  where
+    go 3# = lastElement (D# (indexDoubleArray# a 3#)) (D# (indexDoubleArray# b 3#))
+    go i =
+      case compare (D# (indexDoubleArray# a i)) (D# (indexDoubleArray# b i)) of
+        LT -> lt
+        EQ -> go (i +# 1#)
+        GT -> gt
+
+instance Show DVec4 where
+  show v =
+    withDVec4 v $
+      printf "DVec4 %.4f %.4f %.4f %.4f"
+
+pattern WithDVec4 :: Double -> Double -> Double -> Double -> DVec4
+pattern WithDVec4 a b c d <- ((`withDVec4` (,,,)) -> (a, b, c, d))
+{-# COMPLETE WithDVec4 #-}
+
+instance HasField "x" DVec4 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ _ -> x
+
+instance HasField "y" DVec4 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ _ -> y
+
+instance HasField "z" DVec4 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z _ -> z
+
+instance HasField "w" DVec4 Double where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ _ w -> w
+
+{-# INLINE fromDVec2 #-}
+fromDVec2 :: DVec2 -> Double -> Double -> DVec4
+fromDVec2 xy z w =
+  withDVec2 xy \x y ->
+    dvec4 x y z w
+
+{-# INLINE fromDVec22 #-}
+fromDVec22 :: DVec2 -> DVec2 -> DVec4
+fromDVec22 xy zw =
+  withDVec2 xy \x y ->
+  withDVec2 zw \z w ->
+    dvec4 x y z w
+
+{-# INLINE fromDVec3 #-}
+fromDVec3 :: Coercible a DVec3 => a -> Double -> DVec4
+fromDVec3 xyz w =
+  withDVec3 (coerce xyz) \x y z ->
+    dvec4 x y z w
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Double, Double, Double, Double) -> DVec4
+fromTuple (x, y, z, w) = dvec4 x y z w
+
+{-# INLINE fromVec4 #-}
+fromVec4 :: Vec4 -> DVec4
+fromVec4 = Vec4.convert float2Double dvec4
+
+{-# INLINE toVec4 #-}
+toVec4 :: DVec4 -> Vec4
+toVec4 = convert double2Float Vec4.vec4
+
+instance IsWebColorAlpha s => IsLabel s DVec4 where
+  {-# INLINE fromLabel #-}
+  fromLabel =
+    webColorAlpha @s \r g b a ->
+      dvec4
+        (fromIntegral r / 255)
+        (fromIntegral g / 255)
+        (fromIntegral b / 255)
+        (fromIntegral a / 255)
+
+instance NFData DVec4 where
+  rnf DVec4{} = ()
+
+#ifdef TH_LIFT
+instance Lift DVec4 where
+  lift (WithDVec4 a b c d) = [| dvec4 $(lift a) $(lift b) $(lift c) $(lift d) |]
+  liftTyped (WithDVec4 a b c d) = [|| dvec4 $$(liftTyped a) $$(liftTyped b) $$(liftTyped c) $$(liftTyped d) ||]
+#endif
+
+type instance Element DVec4 = Double
+
+instance MonoFunctor DVec4 where
+  {-# INLINE omap #-}
+  omap f v =
+    withDVec4 v \x y z w ->
+      dvec4 (f x) (f y) (f z) (f w)
+
+instance MonoPointed DVec4 where
+  {-# INLINE opoint #-}
+  opoint x = dvec4 x x x x
+
+instance Elementwise DVec4 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withDVec4 p0 \x0 y0 z0 w0 ->
+    withDVec4 p1 \x1 y1 z1 w1 ->
+      dvec4
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+        (f w0 w1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withDVec4 p0 \x0 y0 z0 w0 ->
+    withDVec4 p1 \x1 y1 z1 w1 ->
+    withDVec4 p2 \x2 y2 z2 w2 ->
+      dvec4
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+        (f w0 w1 w2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withDVec4 p0 \x0 y0 z0 w0 ->
+    withDVec4 p1 \x1 y1 z1 w1 ->
+    withDVec4 p2 \x2 y2 z2 w2 ->
+    withDVec4 p3 \x3 y3 z3 w3 ->
+      dvec4
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+        (f w0 w1 w2 w3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withDVec4 p0 \x0 y0 z0 w0 ->
+    withDVec4 p1 \x1 y1 z1 w1 ->
+    withDVec4 p2 \x2 y2 z2 w2 ->
+    withDVec4 p3 \x3 y3 z3 w3 ->
+    withDVec4 p4 \x4 y4 z4 w4 ->
+      dvec4
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+        (f w0 w1 w2 w3 w4)
+
+instance Num DVec4 where
+  {-# INLINE (+) #-}
+  (+) l r =
+    withDVec4 l \l1 l2 l3 l4 ->
+      withDVec4 r \r1 r2 r3 r4 ->
+        dvec4
+          (l1 + r1)
+          (l2 + r2)
+          (l3 + r3)
+          (l4 + r4)
+
+  {-# INLINE (-) #-}
+  (-) l r =
+    withDVec4 l \l1 l2 l3 l4 ->
+      withDVec4 r \r1 r2 r3 r4 ->
+        dvec4
+          (l1 - r1)
+          (l2 - r2)
+          (l3 - r3)
+          (l4 - r4)
+
+  {-# INLINE (*) #-}
+  (*) l r =
+    withDVec4 l \l1 l2 l3 l4 ->
+      withDVec4 r \r1 r2 r3 r4 ->
+        dvec4
+          (l1 * r1)
+          (l2 * r2)
+          (l3 * r3)
+          (l4 * r4)
+
+  {-# INLINE abs #-}
+  abs v =
+    withDVec4 v \a b c d ->
+      dvec4 (abs a) (abs b) (abs c) (abs d)
+
+  {-# INLINE signum #-}
+  signum v =
+    withDVec4 v \a b c d ->
+      dvec4 (signum a) (signum b) (signum c) (signum d)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = dvec4 x' x' x' x'
+    where
+      x' = fromInteger x
+
+instance Fractional DVec4 where
+  {-# INLINE (/) #-}
+  (/) l r =
+    withDVec4 l \l1 l2 l3 l4 ->
+      withDVec4 r \r1 r2 r3 r4 ->
+        dvec4 (l1 / r1) (l2 / r2) (l3 / r3) (l4 / r4)
+
+  {-# INLINE recip #-}
+  recip v =
+    withDVec4 v \a b c d ->
+      dvec4 (recip a) (recip b) (recip c) (recip d)
+
+  {-# INLINE fromRational #-}
+  fromRational x = dvec4 x' x' x' x'
+    where
+      x' = fromRational x
+
+instance Floating DVec4 where
+  pi = opoint pi
+
+  {-# INLINE exp #-}
+  exp = omap exp
+  {-# INLINE log #-}
+  log = omap log
+  {-# INLINE sqrt #-}
+  sqrt = omap sqrt
+  {-# INLINE sin #-}
+  sin = omap sin
+  {-# INLINE cos #-}
+  cos = omap cos
+  {-# INLINE asin #-}
+  asin = omap asin
+  {-# INLINE acos #-}
+  acos = omap acos
+  {-# INLINE atan #-}
+  atan = omap atan
+  {-# INLINE sinh #-}
+  sinh = omap sinh
+  {-# INLINE cosh #-}
+  cosh = omap cosh
+  {-# INLINE asinh #-}
+  asinh = omap asinh
+  {-# INLINE acosh #-}
+  acosh = omap acosh
+  {-# INLINE atanh #-}
+  atanh = omap atanh
+
+  {-# INLINE (**) #-}
+  a ** b =
+    withDVec4 a \ax ay az aw ->
+    withDVec4 b \bx by bz bw ->
+      dvec4
+        (ax ** bx)
+        (ay ** by)
+        (az ** bz)
+        (aw ** bw)
+
+instance Storable DVec4 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 32
+
+  {-# INLINE poke #-}
+  poke (Ptr addr) (DVec4 arr) = IO \world ->
+    let
+      world' = copyByteArrayToAddr# arr 0# addr 32# world
+    in
+      (# world', () #)
+
+  {-# INLINE peek #-}
+  peek (Ptr addr) = IO \world ->
+    let
+      !(# world0, v0 #) = readDoubleOffAddr# addr 0x0# world
+      !(# world1, v1 #) = readDoubleOffAddr# addr 0x1# world0
+      !(# world2, v2 #) = readDoubleOffAddr# addr 0x2# world1
+      !(# world3, v3 #) = readDoubleOffAddr# addr 0x3# world2
+      !v = dvec4 (D# v0) (D# v1) (D# v2) (D# v3)
+    in
+      (# world3, v #)
+
+instance Block DVec4 where
+  type PackedSize DVec4 = 32
+  alignment140 _  = 32
+  sizeOf140       = sizeOfPacked
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+#ifdef SERIALISE
+instance Serialise DVec4 where
+  encode v = withDVec4 v \x y z w ->
+    Serialise.encodeListLen 4 <> encode x <> encode y <> encode z <> encode w
+  decode =
+    Serialise.decodeListLenOf 4 *> (dvec4 <$> decode <*> decode <*> decode <*> decode)
+#endif
+
+instance VectorSpace DVec4 Double where
+  zeroVector = epoint 0
+
+  {-# INLINE (*^) #-}
+  (*^) = flip (Geomancy.DVec4.^*)
+
+  {-# INLINE (^/) #-}
+  (^/) = (Geomancy.DVec4.^/)
+
+  {-# INLINE (^+^) #-}
+  (^+^) = emap2 (+)
+
+  {-# INLINE (^-^) #-}
+  (^-^) = emap2 (-)
+
+  {-# INLINE negateVector #-}
+  negateVector = emap negate
+
+  {-# INLINE dot #-}
+  dot = Geomancy.DVec4.dot
+
+  {-# INLINE normalize #-}
+  normalize = Geomancy.DVec4.normalize
+
+{-# INLINE (^*) #-}
+(^*) :: DVec4 -> Double -> DVec4
+(^*) v x =
+  withDVec4 v \a b c d ->
+    dvec4
+      (a * x)
+      (b * x)
+      (c * x)
+      (d * x)
+
+{-# INLINE (^/) #-}
+(^/) :: DVec4 -> Double -> DVec4
+v ^/ x = v ^* recip x
+
+{-# INLINE lerp #-}
+lerp :: Double -> DVec4 -> DVec4 -> DVec4
+lerp alpha u v = u ^* alpha + v ^* (1 - alpha)
+
+{-# INLINE dot #-}
+dot :: DVec4 -> DVec4 -> Double
+dot a b =
+  withDVec4 a \a1 a2 a3 a4 ->
+    withDVec4 b \b1 b2 b3 b4 ->
+      a1 * b1 +
+      a2 * b2 +
+      a3 * b3 +
+      a4 * b4
+
+{-# INLINE normalize #-}
+normalize :: DVec4 -> DVec4
+normalize v =
+  if nearZero q || nearZero (1-q) then
+    v
+  else
+    v ^/ l
+
+  where
+    q = dot v v
+    l = sqrt q
+
+    nearZero a = abs a <= 1e-12
+
+{-# INLINE newDVec4 #-}
+newDVec4 :: IO DVec4
+newDVec4 =
+  IO \world ->
+    let
+      !(# world_, arr_ #) = newByteArray# 32# world
+      !(# world', arr #) = unsafeFreezeByteArray# arr_ world_
+    in
+      (# world', DVec4 arr #)
diff --git a/src/Geomancy/I64Vec2.hs b/src/Geomancy/I64Vec2.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/I64Vec2.hs
@@ -0,0 +1,255 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.I64Vec2
+  ( I64Vec2
+  , i64vec2
+  , withI64Vec2
+  , pattern WithI64Vec2
+  , convert
+  , fromTuple
+  , dot
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.Int (Int64)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift(..))
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data I64Vec2 = I64Vec2
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE i64vec2 #-}
+i64vec2 :: Int64 -> Int64 -> I64Vec2
+i64vec2 = I64Vec2
+
+{-# INLINE withI64Vec2 #-}
+withI64Vec2
+  :: I64Vec2
+  -> (Int64 -> Int64 -> r)
+  -> r
+withI64Vec2 (I64Vec2 a b) f = f a b
+
+{-# INLINE convert #-}
+convert :: Coercible v I64Vec2 => (Int64 -> a) -> (a -> a -> r) -> v -> r
+convert f t v =
+  withI64Vec2 (coerce v) \a b ->
+    t (f a) (f b)
+
+pattern WithI64Vec2 :: Int64 -> Int64 -> I64Vec2
+pattern WithI64Vec2 a b <- ((`withI64Vec2` (,)) -> (a, b))
+{-# COMPLETE WithI64Vec2 #-}
+
+instance HasField "x" I64Vec2 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x _ -> x
+
+instance HasField "y" I64Vec2 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \_ y -> y
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Int64, Int64) -> I64Vec2
+fromTuple (x, y) = i64vec2 x y
+
+{-# INLINE dot #-}
+dot :: I64Vec2 -> I64Vec2 -> Int64
+dot (I64Vec2 l1 l2) (I64Vec2 r1 r2) =
+  l1 * r1 + l2 * r2
+
+instance NFData I64Vec2 where
+  rnf I64Vec2{} = ()
+
+type instance Element I64Vec2 = Int64
+
+instance MonoFunctor I64Vec2 where
+  {-# INLINE omap #-}
+  omap f v =
+    withI64Vec2 v \x y ->
+      i64vec2 (f x) (f y)
+
+instance MonoPointed I64Vec2 where
+  {-# INLINE opoint #-}
+  opoint x = i64vec2 x x
+
+instance Elementwise I64Vec2 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withI64Vec2 p0 \x0 y0 ->
+    withI64Vec2 p1 \x1 y1 ->
+      i64vec2
+        (f x0 x1)
+        (f y0 y1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withI64Vec2 p0 \x0 y0 ->
+    withI64Vec2 p1 \x1 y1 ->
+    withI64Vec2 p2 \x2 y2 ->
+      i64vec2
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withI64Vec2 p0 \x0 y0 ->
+    withI64Vec2 p1 \x1 y1 ->
+    withI64Vec2 p2 \x2 y2 ->
+    withI64Vec2 p3 \x3 y3 ->
+      i64vec2
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withI64Vec2 p0 \x0 y0 ->
+    withI64Vec2 p1 \x1 y1 ->
+    withI64Vec2 p2 \x2 y2 ->
+    withI64Vec2 p3 \x3 y3 ->
+    withI64Vec2 p4 \x4 y4 ->
+      i64vec2
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+
+instance Num I64Vec2 where
+  {-# INLINE (+) #-}
+  I64Vec2 l1 l2 + I64Vec2 r1 r2 =
+    I64Vec2
+      (l1 + r1)
+      (l2 + r2)
+
+  {-# INLINE (-) #-}
+  I64Vec2 l1 l2 - I64Vec2 r1 r2 =
+    I64Vec2
+      (l1 - r1)
+      (l2 - r2)
+
+  {-# INLINE (*) #-}
+  I64Vec2 l1 l2 * I64Vec2 r1 r2 =
+    I64Vec2
+      (l1 * r1)
+      (l2 * r2)
+
+  {-# INLINE abs #-}
+  abs (I64Vec2 a b) =
+    I64Vec2 (abs a) (abs b)
+
+  {-# INLINE signum #-}
+  signum v2 = withI64Vec2 v2 \a b ->
+    i64vec2 (signum a) (signum b)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = I64Vec2 x' x'
+    where
+      x' = fromInteger x
+
+instance Storable I64Vec2 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 16
+
+  {-# INLINE alignment #-}
+  alignment _ = 16
+
+  {-# INLINE poke #-}
+  poke ptr v4 =
+    withI64Vec2 v4 \a b -> do
+      pokeByteOff ptr 0 a
+      pokeByteOff ptr 8 b
+
+  {-# INLINE peek #-}
+  peek ptr = i64vec2
+    <$> peekByteOff ptr 0
+    <*> peekByteOff ptr 8
+
+instance Block I64Vec2 where
+  type PackedSize I64Vec2 = 16
+  alignment140 _  = 16
+  sizeOf140 _     = 16
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix I64Vec2 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withI64Vec2 l \l1 l2 ->
+      withI64Vec2 u \u1 u2 ->
+        i64vec2
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withI64Vec2 l \l1 l2 ->
+      withI64Vec2 u \u1 u2 ->
+        withI64Vec2 i \i1 i2 ->
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) *
+          unsafeIndex (l1, u1) i1
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withI64Vec2 l \l1 l2 ->
+      withI64Vec2 u \u1 u2 ->
+        withI64Vec2 i \i1 i2 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2
+
+#ifdef SERIALISE
+instance Serialise I64Vec2 where
+  encode v = withI64Vec2 v \x y ->
+    Serialise.encodeListLen 2 <> encode x <> encode y
+  decode =
+    Serialise.decodeListLenOf 2 *> (i64vec2 <$> decode <*> decode)
+#endif
diff --git a/src/Geomancy/I64Vec3.hs b/src/Geomancy/I64Vec3.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/I64Vec3.hs
@@ -0,0 +1,339 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.I64Vec3
+  ( I64Vec3
+  , i64vec3
+  , withI64Vec3
+  , pattern WithI64Vec3
+  , convert
+  , fromTuple
+  , dot
+
+  , Packed(..)
+  , packed
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.Int (Int64)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data I64Vec3 = I64Vec3
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE i64vec3 #-}
+i64vec3 :: Int64 -> Int64 -> Int64 -> I64Vec3
+i64vec3 = I64Vec3
+
+{-# INLINE withI64Vec3 #-}
+withI64Vec3
+  :: I64Vec3
+  -> (Int64 -> Int64 -> Int64 -> r)
+  -> r
+withI64Vec3 (I64Vec3 a b c) f = f a b c
+
+pattern WithI64Vec3 :: Int64 -> Int64 -> Int64 -> I64Vec3
+pattern WithI64Vec3 a b c <- ((`withI64Vec3` (,,)) -> (a, b, c))
+{-# COMPLETE WithI64Vec3 #-}
+
+instance HasField "x" I64Vec3 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ _ -> x
+
+instance HasField "y" I64Vec3 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y _ -> y
+
+instance HasField "z" I64Vec3 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ _ z -> z
+
+{-# INLINE convert #-}
+convert :: Coercible v I64Vec3 => (Int64 -> a) -> (a -> a -> a -> r) -> v -> r
+convert f t v =
+  withI64Vec3 (coerce v) \a b c ->
+    t (f a) (f b) (f c)
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Int64, Int64, Int64) -> I64Vec3
+fromTuple (a, b, c) = i64vec3 a b c
+
+{-# INLINE dot #-}
+dot :: I64Vec3 -> I64Vec3 -> Int64
+dot (I64Vec3 l1 l2 l3) (I64Vec3 r1 r2 r3) =
+  l1 * r1 + l2 * r2 + l3 * r3
+
+instance NFData I64Vec3 where
+  rnf I64Vec3{} = ()
+
+type instance Element I64Vec3 = Int64
+
+instance MonoFunctor I64Vec3 where
+  {-# INLINE omap #-}
+  omap f v =
+    withI64Vec3 v \x y z ->
+      i64vec3 (f x) (f y) (f z)
+
+instance MonoPointed I64Vec3 where
+  opoint x = i64vec3 x x x
+
+instance Elementwise I64Vec3 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withI64Vec3 p0 \x0 y0 z0 ->
+    withI64Vec3 p1 \x1 y1 z1 ->
+      i64vec3
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withI64Vec3 p0 \x0 y0 z0 ->
+    withI64Vec3 p1 \x1 y1 z1 ->
+    withI64Vec3 p2 \x2 y2 z2 ->
+      i64vec3
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withI64Vec3 p0 \x0 y0 z0 ->
+    withI64Vec3 p1 \x1 y1 z1 ->
+    withI64Vec3 p2 \x2 y2 z2 ->
+    withI64Vec3 p3 \x3 y3 z3 ->
+      i64vec3
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withI64Vec3 p0 \x0 y0 z0 ->
+    withI64Vec3 p1 \x1 y1 z1 ->
+    withI64Vec3 p2 \x2 y2 z2 ->
+    withI64Vec3 p3 \x3 y3 z3 ->
+    withI64Vec3 p4 \x4 y4 z4 ->
+      i64vec3
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+
+instance Num I64Vec3 where
+  {-# INLINE (+) #-}
+  I64Vec3 l1 l2 l3 + I64Vec3 r1 r2 r3 =
+    I64Vec3
+      (l1 + r1)
+      (l2 + r2)
+      (l3 + r3)
+
+  {-# INLINE (-) #-}
+  I64Vec3 l1 l2 l3 - I64Vec3 r1 r2 r3 =
+    I64Vec3
+      (l1 - r1)
+      (l2 - r2)
+      (l3 - r3)
+
+  {-# INLINE (*) #-}
+  I64Vec3 l1 l2 l3 * I64Vec3 r1 r2 r3 =
+    I64Vec3
+      (l1 * r1)
+      (l2 * r2)
+      (l3 * r3)
+
+  {-# INLINE abs #-}
+  abs v3 = withI64Vec3 v3 \a b c ->
+    i64vec3 (abs a) (abs b) (abs c)
+
+  {-# INLINE signum #-}
+  signum v3 = withI64Vec3 v3 \a b c ->
+    i64vec3 (signum a) (signum b) (signum c)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = I64Vec3 x' x' x'
+    where
+      x' = fromInteger x
+
+instance Storable I64Vec3 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr v3 =
+    withI64Vec3 v3 \a b c -> do
+      pokeByteOff ptr  0 a
+      pokeByteOff ptr  8 b
+      pokeByteOff ptr 16 c
+
+  {-# INLINE peek #-}
+  peek ptr = i64vec3
+    <$> peekByteOff ptr  0
+    <*> peekByteOff ptr  8
+    <*> peekByteOff ptr  16
+
+newtype Packed = Packed { unPacked :: I64Vec3 }
+  deriving (Eq, Ord, Show, NFData, Num)
+
+{-# INLINE packed #-}
+packed :: Int64 -> Int64 -> Int64 -> Packed
+packed a b c = Packed (i64vec3 a b c)
+
+instance HasField "x" Packed Int64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withI64Vec3 v \x _ _ -> x
+
+instance HasField "y" Packed Int64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withI64Vec3 v \_ y _ -> y
+
+instance HasField "z" Packed Int64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withI64Vec3 v \_ _ z -> z
+
+instance Storable Packed where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 24
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr (Packed v3) =
+    withI64Vec3 v3 \a b c -> do
+      pokeByteOff ptr 0 a
+      pokeByteOff ptr 8 b
+      pokeByteOff ptr 16 c
+
+  {-# INLINE peek #-}
+  peek ptr = packed
+    <$> peekByteOff ptr 0
+    <*> peekByteOff ptr 8
+    <*> peekByteOff ptr 16
+
+instance Block I64Vec3 where
+  type PackedSize I64Vec3 = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 32
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Block Packed where
+  type PackedSize Packed = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 24
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix I64Vec3 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withI64Vec3 l \l1 l2 l3 ->
+      withI64Vec3 u \u1 u2 u3 ->
+        i64vec3
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+          <*> range (l3, u3)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withI64Vec3 l \l1 l2 l3 ->
+      withI64Vec3 u \u1 u2 u3 ->
+        withI64Vec3 i \i1 i2 i3 ->
+          unsafeIndex (l3, u3) i3 + unsafeRangeSize (l3, u3) * (
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) * (
+          unsafeIndex (l1, u1) i1))
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withI64Vec3 l \l1 l2 l3 ->
+      withI64Vec3 u \u1 u2 u3 ->
+        withI64Vec3 i \i1 i2 i3 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2 &&
+          inRange (l3, u3) i3
+
+#ifdef SERIALISE
+instance Serialise I64Vec3 where
+  encode v = withI64Vec3 v \x y z ->
+    Serialise.encodeListLen 3 <> encode x <> encode y <> encode z
+  decode =
+    Serialise.decodeListLenOf 3 *> (i64vec3 <$> decode <*> decode <*> decode)
+#endif
diff --git a/src/Geomancy/I64Vec4.hs b/src/Geomancy/I64Vec4.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/I64Vec4.hs
@@ -0,0 +1,288 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.I64Vec4
+  ( I64Vec4
+  , i64vec4
+  , withI64Vec4
+  , pattern WithI64Vec4
+  , convert
+  , fromTuple
+  , dot
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.Int (Int64)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data I64Vec4 = I64Vec4
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  {-# UNPACK #-} !Int64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE i64vec4 #-}
+i64vec4 :: Int64 -> Int64 -> Int64 -> Int64 -> I64Vec4
+i64vec4 = I64Vec4
+
+{-# INLINE withI64Vec4 #-}
+withI64Vec4
+  :: I64Vec4
+  -> (Int64 -> Int64 -> Int64 -> Int64 -> r)
+  -> r
+withI64Vec4 (I64Vec4 a b c d) f = f a b c d
+
+pattern WithI64Vec4 :: Int64 -> Int64 -> Int64 -> Int64 -> I64Vec4
+pattern WithI64Vec4 a b c d <- ((`withI64Vec4` (,,,)) -> (a, b, c, d))
+{-# COMPLETE WithI64Vec4 #-}
+
+instance HasField "x" I64Vec4 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ _ -> x
+
+instance HasField "y" I64Vec4 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ _ -> y
+
+instance HasField "z" I64Vec4 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z _ -> z
+
+instance HasField "w" I64Vec4 Int64 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ _ w -> w
+
+{-# INLINE convert #-}
+convert :: Coercible v I64Vec4 => (Int64 -> a) -> (a -> a -> a -> a -> r) -> v -> r
+convert f t v =
+  withI64Vec4 (coerce v) \a b c d ->
+    t (f a) (f b) (f c) (f d)
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Int64, Int64, Int64, Int64) -> I64Vec4
+fromTuple (x, y, z, w) = i64vec4 x y z w
+
+{-# INLINE dot #-}
+dot :: I64Vec4 -> I64Vec4 -> Int64
+dot (I64Vec4 l1 l2 l3 l4) (I64Vec4 r1 r2 r3 r4) =
+  l1 * r1 + l2 * r2 + l3 * r3 + l4 * r4
+
+instance NFData I64Vec4 where
+  rnf I64Vec4{} = ()
+
+type instance Element I64Vec4 = Int64
+
+instance MonoFunctor I64Vec4 where
+  {-# INLINE omap #-}
+  omap f v =
+    withI64Vec4 v \x y z w ->
+      i64vec4 (f x) (f y) (f z) (f w)
+
+instance MonoPointed I64Vec4 where
+  opoint x = i64vec4 x x x x
+
+instance Elementwise I64Vec4 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withI64Vec4 p0 \x0 y0 z0 w0 ->
+    withI64Vec4 p1 \x1 y1 z1 w1 ->
+      i64vec4
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+        (f w0 w1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withI64Vec4 p0 \x0 y0 z0 w0 ->
+    withI64Vec4 p1 \x1 y1 z1 w1 ->
+    withI64Vec4 p2 \x2 y2 z2 w2 ->
+      i64vec4
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+        (f w0 w1 w2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withI64Vec4 p0 \x0 y0 z0 w0 ->
+    withI64Vec4 p1 \x1 y1 z1 w1 ->
+    withI64Vec4 p2 \x2 y2 z2 w2 ->
+    withI64Vec4 p3 \x3 y3 z3 w3 ->
+      i64vec4
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+        (f w0 w1 w2 w3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withI64Vec4 p0 \x0 y0 z0 w0 ->
+    withI64Vec4 p1 \x1 y1 z1 w1 ->
+    withI64Vec4 p2 \x2 y2 z2 w2 ->
+    withI64Vec4 p3 \x3 y3 z3 w3 ->
+    withI64Vec4 p4 \x4 y4 z4 w4 ->
+      i64vec4
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+        (f w0 w1 w2 w3 w4)
+
+instance Num I64Vec4 where
+  {-# INLINE (+) #-}
+  I64Vec4 l1 l2 l3 l4 + I64Vec4 r1 r2 r3 r4 =
+    I64Vec4
+      (l1 + r1)
+      (l2 + r2)
+      (l3 + r3)
+      (l4 + r4)
+
+  {-# INLINE (-) #-}
+  I64Vec4 l1 l2 l3 l4 - I64Vec4 r1 r2 r3 r4 =
+    I64Vec4
+      (l1 - r1)
+      (l2 - r2)
+      (l3 - r3)
+      (l4 - r4)
+
+  {-# INLINE (*) #-}
+  I64Vec4 l1 l2 l3 l4 * I64Vec4 r1 r2 r3 r4 =
+    I64Vec4
+      (l1 * r1)
+      (l2 * r2)
+      (l3 * r3)
+      (l4 * r4)
+
+  {-# INLINE abs #-}
+  abs v4 = withI64Vec4 v4 \a b c d ->
+    i64vec4 (abs a) (abs b) (abs c) (abs d)
+
+  {-# INLINE signum #-}
+  signum v4 = withI64Vec4 v4 \a b c d ->
+    i64vec4 (signum a) (signum b) (signum c) (signum d)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = I64Vec4 x' x' x' x'
+    where
+      x' = fromInteger x
+
+instance Storable I64Vec4 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr v4 =
+    withI64Vec4 v4 \a b c d -> do
+      pokeByteOff ptr  0 a
+      pokeByteOff ptr  8 b
+      pokeByteOff ptr 16 c
+      pokeByteOff ptr 24 d
+
+  {-# INLINE peek #-}
+  peek ptr = i64vec4
+    <$> peekByteOff ptr  0
+    <*> peekByteOff ptr  8
+    <*> peekByteOff ptr  16
+    <*> peekByteOff ptr 24
+
+instance Block I64Vec4 where
+  type PackedSize I64Vec4 = 32
+  alignment140 _  = 32
+  sizeOf140 _     = 32
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix I64Vec4 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withI64Vec4 l \l1 l2 l3 l4 ->
+      withI64Vec4 u \u1 u2 u3 u4 ->
+        i64vec4
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+          <*> range (l3, u3)
+          <*> range (l4, u4)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withI64Vec4 l \l1 l2 l3 l4 ->
+      withI64Vec4 u \u1 u2 u3 u4 ->
+        withI64Vec4 i \i1 i2 i3 i4 ->
+          unsafeIndex (l4, u4) i4 + unsafeRangeSize (l4, u4) * (
+          unsafeIndex (l3, u3) i3 + unsafeRangeSize (l3, u3) * (
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) * (
+          unsafeIndex (l1, u1) i1)))
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withI64Vec4 l \l1 l2 l3 l4 ->
+      withI64Vec4 u \u1 u2 u3 u4 ->
+        withI64Vec4 i \i1 i2 i3 i4 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2 &&
+          inRange (l3, u3) i3 &&
+          inRange (l4, u4) i4
+
+#ifdef SERIALISE
+instance Serialise I64Vec4 where
+  encode v = withI64Vec4 v \x y z w ->
+    Serialise.encodeListLen 4 <> encode x <> encode y <> encode z <> encode w
+  decode =
+    Serialise.decodeListLenOf 4 *> (i64vec4 <$> decode <*> decode <*> decode <*> decode)
+#endif
diff --git a/src/Geomancy/IVec2.hs b/src/Geomancy/IVec2.hs
--- a/src/Geomancy/IVec2.hs
+++ b/src/Geomancy/IVec2.hs
@@ -2,6 +2,8 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
@@ -30,6 +32,7 @@
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
 
 #ifdef TH_LIFT
 import Language.Haskell.TH.Syntax (Lift(..))
@@ -72,6 +75,14 @@
 pattern WithIVec2 :: Int32 -> Int32 -> IVec2
 pattern WithIVec2 a b <- ((`withIVec2` (,)) -> (a, b))
 {-# COMPLETE WithIVec2 #-}
+
+instance HasField "x" IVec2 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x _ -> x
+
+instance HasField "y" IVec2 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \_ y -> y
 
 {-# INLINE fromTuple #-}
 fromTuple :: (Int32, Int32) -> IVec2
diff --git a/src/Geomancy/IVec3.hs b/src/Geomancy/IVec3.hs
--- a/src/Geomancy/IVec3.hs
+++ b/src/Geomancy/IVec3.hs
@@ -2,7 +2,9 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
@@ -34,6 +36,7 @@
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
 
 #ifdef TH_LIFT
 import Language.Haskell.TH.Syntax (Lift)
@@ -72,6 +75,18 @@
 pattern WithIVec3 a b c <- ((`withIVec3` (,,)) -> (a, b, c))
 {-# COMPLETE WithIVec3 #-}
 
+instance HasField "x" IVec3 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ _ -> x
+
+instance HasField "y" IVec3 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y _ -> y
+
+instance HasField "z" IVec3 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ _ z -> z
+
 {-# INLINE convert #-}
 convert :: Coercible v IVec3 => (Int32 -> a) -> (a -> a -> a -> r) -> v -> r
 convert f t v =
@@ -168,7 +183,8 @@
       (l3 * r3)
 
   {-# INLINE abs #-}
-  abs x = x
+  abs v3 = withIVec3 v3 \a b c ->
+    ivec3 (abs a) (abs b) (abs c)
 
   {-# INLINE signum #-}
   signum v3 = withIVec3 v3 \a b c ->
@@ -206,6 +222,18 @@
 packed :: Int32 -> Int32 -> Int32 -> Packed
 packed a b c = Packed (ivec3 a b c)
 
+instance HasField "x" Packed Int32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withIVec3 v \x _ _ -> x
+
+instance HasField "y" Packed Int32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withIVec3 v \_ y _ -> y
+
+instance HasField "z" Packed Int32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withIVec3 v \_ _ z -> z
+
 instance Storable Packed where
   {-# INLINE sizeOf #-}
   sizeOf _ = 12
@@ -253,8 +281,8 @@
 
 instance Block Packed where
   type PackedSize Packed = 12
-  alignment140 _  = 12
-  sizeOf140 _     = 16
+  alignment140 _  = 16
+  sizeOf140 _     = 12
   alignment430    = alignment140
   sizeOf430       = sizeOf140
   isStruct _      = False
diff --git a/src/Geomancy/IVec4.hs b/src/Geomancy/IVec4.hs
--- a/src/Geomancy/IVec4.hs
+++ b/src/Geomancy/IVec4.hs
@@ -2,6 +2,8 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
@@ -30,6 +32,7 @@
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
 
 #ifdef TH_LIFT
 import Language.Haskell.TH.Syntax (Lift)
@@ -69,6 +72,22 @@
 pattern WithIVec4 a b c d <- ((`withIVec4` (,,,)) -> (a, b, c, d))
 {-# COMPLETE WithIVec4 #-}
 
+instance HasField "x" IVec4 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ _ -> x
+
+instance HasField "y" IVec4 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ _ -> y
+
+instance HasField "z" IVec4 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z _ -> z
+
+instance HasField "w" IVec4 Int32 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ _ w -> w
+
 {-# INLINE convert #-}
 convert :: Coercible v IVec4 => (Int32 -> a) -> (a -> a -> a -> a -> r) -> v -> r
 convert f t v =
@@ -172,7 +191,8 @@
       (l4 * r4)
 
   {-# INLINE abs #-}
-  abs x = x
+  abs v4 = withIVec4 v4 \a b c d ->
+    ivec4 (abs a) (abs b) (abs c) (abs d)
 
   {-# INLINE signum #-}
   signum v4 = withIVec4 v4 \a b c d ->
diff --git a/src/Geomancy/Mat4/Internal.hs b/src/Geomancy/Mat4/Internal.hs
--- a/src/Geomancy/Mat4/Internal.hs
+++ b/src/Geomancy/Mat4/Internal.hs
@@ -54,6 +54,14 @@
 
 data Mat4 = Mat4 ByteArray#
 
+instance Eq Mat4 where
+  Mat4 a == Mat4 b = go 0#
+    where
+      go i
+        | isTrue# (i ==# 16#) = True
+        | isTrue# (eqFloat# (indexFloatArray# a i) (indexFloatArray# b i)) = go (i +# 1#)
+        | otherwise = False
+
 instance NFData Mat4 where
   rnf Mat4{} = ()
 
@@ -67,34 +75,36 @@
   -> Float -> Float -> Float -> Float
   -> Mat4
 fromMemory
-  (F# e0) (F# e1) (F# e2) (F# e3)
-  (F# e4) (F# e5) (F# e6) (F# e7)
-  (F# e8) (F# e9) (F# ea) (F# eb)
-  (F# ec) (F# ed) (F# ee) (F# ef) =
+  e0 e1 e2 e3
+  e4 e5 e6 e7
+  e8 e9 ea eb
+  ec ed ee ef =
   runRW# \world ->
     let
-      !(# world_, arr #) = newAlignedPinnedByteArray# 64# 16# world
+      !(# world_, arr #) = newByteArray# 64# world
 
-      world0 = writeFloatArray# arr 0x0# e0 world_
-      world1 = writeFloatArray# arr 0x1# e1 world0
-      world2 = writeFloatArray# arr 0x2# e2 world1
-      world3 = writeFloatArray# arr 0x3# e3 world2
+      write i (F# e) = writeFloatArray# arr i e
 
-      world4 = writeFloatArray# arr 0x4# e4 world3
-      world5 = writeFloatArray# arr 0x5# e5 world4
-      world6 = writeFloatArray# arr 0x6# e6 world5
-      world7 = writeFloatArray# arr 0x7# e7 world6
+      world0 = write 0x0# e0 world_
+      world1 = write 0x1# e1 world0
+      world2 = write 0x2# e2 world1
+      world3 = write 0x3# e3 world2
 
-      world8 = writeFloatArray# arr 0x8# e8 world7
-      world9 = writeFloatArray# arr 0x9# e9 world8
-      worldA = writeFloatArray# arr 0xA# ea world9
-      worldB = writeFloatArray# arr 0xB# eb worldA
+      world4 = write 0x4# e4 world3
+      world5 = write 0x5# e5 world4
+      world6 = write 0x6# e6 world5
+      world7 = write 0x7# e7 world6
 
-      worldC = writeFloatArray# arr 0xC# ec worldB
-      worldD = writeFloatArray# arr 0xD# ed worldC
-      worldE = writeFloatArray# arr 0xE# ee worldD
-      worldF = writeFloatArray# arr 0xF# ef worldE
+      world8 = write 0x8# e8 world7
+      world9 = write 0x9# e9 world8
+      worldA = write 0xA# ea world9
+      worldB = write 0xB# eb worldA
 
+      worldC = write 0xC# ec worldB
+      worldD = write 0xD# ed worldC
+      worldE = write 0xE# ee worldD
+      worldF = write 0xF# ef worldE
+
       !(# _world', arr' #) = unsafeFreezeByteArray# arr worldF
     in
       Mat4 arr'
@@ -213,10 +223,10 @@
 newMat4 =
   IO \world ->
     let
-      !(# world_, arr_ #) = newAlignedPinnedByteArray# 64# 16# world
-      !(# _world', arr #) = unsafeFreezeByteArray# arr_ world_
+      !(# world_, arr_ #) = newByteArray# 64# world
+      !(# world', arr #) = unsafeFreezeByteArray# arr_ world_
     in
-      (# world, Mat4 arr #)
+      (# world', Mat4 arr #)
 
 {-# INLINE scalarMultiply #-}
 scalarMultiply :: Float -> Mat4 -> Mat4
@@ -247,11 +257,36 @@
   {-# INLINE peek #-}
   peek (Ptr addr) = IO \world ->
     let
-      !(# world0, arr #)  = newAlignedPinnedByteArray# 64# 16# world
-      world1              = copyAddrToByteArray# addr arr 0# 64# world0
-      !(# world', arr' #) = unsafeFreezeByteArray# arr world1
+      loadPair i = readWord64OffAddr# addr i
+
+      !(# world0, pair0 #) = loadPair 0x0# world
+      !(# world1, pair1 #) = loadPair 0x1# world0
+      !(# world2, pair2 #) = loadPair 0x2# world1
+      !(# world3, pair3 #) = loadPair 0x3# world2
+      !(# world4, pair4 #) = loadPair 0x4# world3
+      !(# world5, pair5 #) = loadPair 0x5# world4
+      !(# world6, pair6 #) = loadPair 0x6# world5
+      !(# world', pair7 #) = loadPair 0x7# world6
+
+      !mat = runRW# \fresh ->
+        let
+          !(# fresh_, arr #) = newByteArray# 64# fresh
+
+          storePair i pair = writeWord64Array# arr i pair
+
+          fresh0 = storePair 0x0# pair0 fresh_
+          fresh1 = storePair 0x1# pair1 fresh0
+          fresh2 = storePair 0x2# pair2 fresh1
+          fresh3 = storePair 0x3# pair3 fresh2
+          fresh4 = storePair 0x4# pair4 fresh3
+          fresh5 = storePair 0x5# pair5 fresh4
+          fresh6 = storePair 0x6# pair6 fresh5
+          fresh7 = storePair 0x7# pair7 fresh6
+          !(# _fresh', arr' #) = unsafeFreezeByteArray# arr fresh7
+        in
+          Mat4 arr'
     in
-      (# world', Mat4 arr' #)
+      (# world', mat #)
 
 instance Block Mat4 where
   type PackedSize Mat4 = 64
diff --git a/src/Geomancy/Point.hs b/src/Geomancy/Point.hs
--- a/src/Geomancy/Point.hs
+++ b/src/Geomancy/Point.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveAnyClass #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE DerivingStrategies #-}
@@ -11,6 +12,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 
@@ -26,6 +28,11 @@
   , Point3P
   , Point4
 
+  , DPoint2
+  , DPoint3
+  , DPoint3P
+  , DPoint4
+
   , AffineSpace
   , (AffineSpace..+^)
   , (AffineSpace..-^)
@@ -42,6 +49,7 @@
 import Foreign.Storable (Storable)
 import GHC.Generics (Generic)
 import GHC.Ix (Ix)
+import GHC.Records (HasField(..))
 import GHC.TypeNats (KnownNat)
 import qualified Data.AffineSpace as AffineSpace
 
@@ -53,12 +61,16 @@
 import Codec.Serialise (Serialise)
 #endif
 
+import Geomancy.DVec2 (DVec2)
+import Geomancy.DVec3 (DVec3)
 import Geomancy.Elementwise (Elementwise(..))
 import Graphics.Gl.Block (Block(..))
 import Geomancy.Vec2 (Vec2)
 import Geomancy.Vec3 (Vec3, Packed)
 import Geomancy.Vec4 (Vec4)
+import Geomancy.DVec4 (DVec4)
 import Geomancy.Vector (VectorSpace(..))
+import qualified Geomancy.DVec3 as DVec3
 import qualified Geomancy.Vector as Vector
 
 newtype Point v = Point v
@@ -79,12 +91,33 @@
 
 type instance Element (Point v) = Element v
 
+instance HasField "x" v a => HasField "x" (Point v) a where
+  {-# INLINE getField #-}
+  getField (Point v) = getField @"x" v
+
+instance HasField "y" v a => HasField "y" (Point v) a where
+  {-# INLINE getField #-}
+  getField (Point v) = getField @"y" v
+
+instance HasField "z" v a => HasField "z" (Point v) a where
+  {-# INLINE getField #-}
+  getField (Point v) = getField @"z" v
+
+instance HasField "w" v a => HasField "w" (Point v) a where
+  {-# INLINE getField #-}
+  getField (Point v) = getField @"w" v
+
 type Point2 = Point Vec2
 type Point3 = Point Vec3
 type Point3P = Point Packed
 type Point4 = Point Vec4
 
-instance VectorSpace v Float => AffineSpace (Point v) v Float where
+type DPoint2 = Point DVec2
+type DPoint3 = Point DVec3
+type DPoint3P = Point DVec3.Packed
+type DPoint4 = Point DVec4
+
+instance (Floating a, VectorSpace v a) => AffineSpace (Point v) v a where
   origin = Point zeroVector
 
   {-# INLINE (.+^) #-}
@@ -97,13 +130,13 @@
   Point a .-. Point b = a ^-^ b
 
 {-# INLINE qd #-}
-qd :: VectorSpace v Float => Point v -> Point v -> Float
+qd :: (Floating a, VectorSpace v a) => Point v -> Point v -> a
 qd a b = Vector.quadrance (a AffineSpace..-. b)
 
 {-# INLINE distance #-}
-distance :: VectorSpace v Float => Point v -> Point v -> Float
+distance :: (Floating a, VectorSpace v a) => Point v -> Point v -> a
 distance a b = sqrt (qd a b)
 
 {-# INLINE lerp #-}
-lerp :: VectorSpace v Float => Point v -> Point v -> Float -> Point v
+lerp :: (Num a, VectorSpace v a) => Point v -> Point v -> a -> Point v
 lerp (Point a) (Point b) = Point . Vector.lerp a b
diff --git a/src/Geomancy/Quaternion.hs b/src/Geomancy/Quaternion.hs
--- a/src/Geomancy/Quaternion.hs
+++ b/src/Geomancy/Quaternion.hs
@@ -301,10 +301,20 @@
 -}
 {-# INLINE rotate #-}
 rotate :: Quaternion -> Vec3 -> Vec3
-rotate q v = withQuaternion q' \_a b c d -> vec3 b c d
-  where
-    q' = withVec3 v \x y z ->
-      q * quaternion 0 x y z * conjugate q
+rotate (Quaternion w x y z) v =
+  withVec3 v \vx vy vz ->
+    let
+      x2 = x + x
+      y2 = y + y
+      z2 = z + z
+      tx = y2 * vz - z2 * vy
+      ty = z2 * vx - x2 * vz
+      tz = x2 * vy - y2 * vx
+    in
+      vec3
+        (vx + w * tx + y * tz - z * ty)
+        (vy + w * ty + z * tx - x * tz)
+        (vz + w * tz + x * ty - y * tx)
 
 {- | Rotate point around another point with a unit quaternion.
 -}
diff --git a/src/Geomancy/Swizzle.hs b/src/Geomancy/Swizzle.hs
--- a/src/Geomancy/Swizzle.hs
+++ b/src/Geomancy/Swizzle.hs
@@ -1,1513 +1,83 @@
-{-# LANGUAGE BlockArguments #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Geomancy.Swizzle
-  ( swizzle
-  , (.@)
-  ) where
-
-import GHC.OverloadedLabels
-
-import Geomancy.Vec2 (Vec2, vec2, withVec2)
-import Geomancy.Vec3 (Vec3, vec3, withVec3)
-import Geomancy.Vec4 (Vec4, vec4, withVec4)
-
-newtype Swizzle to fro = Swizzle { swizzle :: fro -> to }
-
-{-# INLINE (.@) #-}
-(.@) :: forall to fro . fro -> Swizzle to fro -> to
-v .@ Swizzle f = f v
-
--- * From Vec2
-
--- ** To Float
-
-instance IsLabel "x" (Swizzle Float Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x _ -> x
-
-instance IsLabel "y" (Swizzle Float Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \_ y -> y
-
--- ** To Vec2
-
-instance IsLabel "xx" (Swizzle Vec2 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x _ -> vec2 x x
-
-instance IsLabel "yx" (Swizzle Vec2 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec2 y x
-
-instance IsLabel "yy" (Swizzle Vec2 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \_ y -> vec2 y y
-
--- ** To Vec3
-
-instance IsLabel "xxx" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x _ -> vec3 x x x
-
-instance IsLabel "xxy" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 x x y
-
-instance IsLabel "xyx" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 x y x
-
-instance IsLabel "xyy" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 x y y
-
-instance IsLabel "yxx" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 y x x
-
-instance IsLabel "yxy" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 y x y
-
-instance IsLabel "yyx" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec3 y y x
-
-instance IsLabel "yyy" (Swizzle Vec3 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \_ y -> vec3 y y y
-
--- ** To Vec4
-
-instance IsLabel "xxxx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x _ -> vec4 x x x x
-
-instance IsLabel "xxxy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x x x y
-
-instance IsLabel "xxyx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x x y x
-
-instance IsLabel "xxyy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x x y y
-
-instance IsLabel "xyxx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x y x x
-
-instance IsLabel "xyxy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x y x y
-
-instance IsLabel "xyyx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x y y x
-
-instance IsLabel "xyyy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 x y y y
-
-instance IsLabel "yxxx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y x x x
-
-instance IsLabel "yxxy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y x x y
-
-instance IsLabel "yxyx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y x y x
-
-instance IsLabel "yxyy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y x y y
-
-instance IsLabel "yyxx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y y x x
-
-instance IsLabel "yyxy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y y x y
-
-instance IsLabel "yyyx" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \x y -> vec4 y y y x
-
-instance IsLabel "yyyy" (Swizzle Vec4 Vec2) where
-  fromLabel = Swizzle \v -> withVec2 v \_ y -> vec4 y y y y
-
--- * From Vec3
-
--- * To Float
-
-instance IsLabel "x" (Swizzle Float Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ _ -> x
-
-instance IsLabel "y" (Swizzle Float Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y _ -> y
-
-instance IsLabel "z" (Swizzle Float Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ _ z -> z
-
--- * To Vec2
-
-instance IsLabel "xx" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ _ -> vec2 x x
-
-instance IsLabel "xy" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec2 x y
-
-instance IsLabel "xz" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec2 x z
-
-instance IsLabel "yx" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec2 y x
-
-instance IsLabel "yy" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y _ -> vec2 y y
-
-instance IsLabel "yz" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec2 y z
-
-instance IsLabel "zx" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec2 z x
-
-instance IsLabel "zy" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec2 z y
-
-instance IsLabel "zz" (Swizzle Vec2 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ _ z -> vec2 z z
-
--- * To Vec3
-
-instance IsLabel "xxx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ _ -> vec3 x x x
-
-instance IsLabel "xxy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 x x y
-
-instance IsLabel "xxz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 x x z
-
-instance IsLabel "xyx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 x y x
-
-instance IsLabel "xyy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 x y y
-
-instance IsLabel "xzx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 x z x
-
-instance IsLabel "xzy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec3 x z y
-
-instance IsLabel "xzz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 x z z
-
-instance IsLabel "yxx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 y x x
-
-instance IsLabel "yxy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 y x y
-
-instance IsLabel "yxz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec3 y x z
-
-instance IsLabel "yyx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec3 y y x
-
-instance IsLabel "yyy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y _ -> vec3 y y y
-
-instance IsLabel "yyz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 y y z
-
-instance IsLabel "yzx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec3 y z x
-
-instance IsLabel "yzy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 y z y
-
-instance IsLabel "yzz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 y z z
-
-instance IsLabel "zxx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 z x x
-
-instance IsLabel "zxy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec3 z x y
-
-instance IsLabel "zxz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 z x z
-
-instance IsLabel "zyx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec3 z y x
-
-instance IsLabel "zyy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 z y y
-
-instance IsLabel "zyz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 z y z
-
-instance IsLabel "zzx" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec3 z z x
-
-instance IsLabel "zzy" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec3 z z y
-
-instance IsLabel "zzz" (Swizzle Vec3 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ _ z -> vec3 z z z
-
--- * To Vec4
-
-instance IsLabel "xxxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ _ -> vec4 x x x x
-
-instance IsLabel "xxxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x x x y
-
-instance IsLabel "xxxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x x x z
-
-instance IsLabel "xxyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x x y x
-
-instance IsLabel "xxyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x x y y
-
-instance IsLabel "xxyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x x y z
-
-instance IsLabel "xxzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x x z x
-
-instance IsLabel "xxzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x x z y
-
-instance IsLabel "xxzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x x z z
-
-instance IsLabel "xyxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x y x x
-
-instance IsLabel "xyxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x y x y
-
-instance IsLabel "xyxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x y x z
-
-instance IsLabel "xyyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x y y x
-
-instance IsLabel "xyyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 x y y y
-
-instance IsLabel "xyyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x y y z
-
-instance IsLabel "xyzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x y z x
-
-instance IsLabel "xyzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x y z y
-
-instance IsLabel "xyzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x y z z
-
-instance IsLabel "xzxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x z x x
-
-instance IsLabel "xzxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x z x y
-
-instance IsLabel "xzxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x z x z
-
-instance IsLabel "xzyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x z y x
-
-instance IsLabel "xzyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x z y y
-
-instance IsLabel "xzyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x z y z
-
-instance IsLabel "xzzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x z z x
-
-instance IsLabel "xzzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 x z z y
-
-instance IsLabel "xzzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 x z z z
-
-instance IsLabel "yxxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y x x x
-
-instance IsLabel "yxxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y x x y
-
-instance IsLabel "yxxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y x x z
-
-instance IsLabel "yxyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y x y x
-
-instance IsLabel "yxyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y x y y
-
-instance IsLabel "yxyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y x y z
-
-instance IsLabel "yxzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y x z x
-
-instance IsLabel "yxzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y x z y
-
-instance IsLabel "yxzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y x z z
-
-instance IsLabel "yyxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y y x x
-
-instance IsLabel "yyxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y y x y
-
-instance IsLabel "yyxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y y x z
-
-instance IsLabel "yyyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y _ -> vec4 y y y x
-
-instance IsLabel "yyyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y _ -> vec4 y y y y
-
-instance IsLabel "yyyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y y y z
-
-instance IsLabel "yyzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y y z x
-
-instance IsLabel "yyzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y y z y
-
-instance IsLabel "yyzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y y z z
-
-instance IsLabel "yzxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y z x x
-
-instance IsLabel "yzxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y z x y
-
-instance IsLabel "yzxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y z x z
-
-instance IsLabel "yzyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y z y x
-
-instance IsLabel "yzyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y z y y
-
-instance IsLabel "yzyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y z y z
-
-instance IsLabel "yzzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 y z z x
-
-instance IsLabel "yzzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y z z y
-
-instance IsLabel "yzzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 y z z z
-
-instance IsLabel "zxxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z x x x
-
-instance IsLabel "zxxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z x x y
-
-instance IsLabel "zxxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z x x z
-
-instance IsLabel "zxyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z x y x
-
-instance IsLabel "zxyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z x y y
-
-instance IsLabel "zxyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z x y z
-
-instance IsLabel "zxzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z x z x
-
-instance IsLabel "zxzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z x z y
-
-instance IsLabel "zxzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z x z z
-
-instance IsLabel "zyxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z y x x
-
-instance IsLabel "zyxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z y x y
-
-instance IsLabel "zyxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z y x z
-
-instance IsLabel "zyyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z y y x
-
-instance IsLabel "zyyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z y y y
-
-instance IsLabel "zyyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z y y z
-
-instance IsLabel "zyzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z y z x
-
-instance IsLabel "zyzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z y z y
-
-instance IsLabel "zyzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z y z z
-
-instance IsLabel "zzxx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z z x x
-
-instance IsLabel "zzxy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z z x y
-
-instance IsLabel "zzxz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z z x z
-
-instance IsLabel "zzyx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x y z -> vec4 z z y x
-
-instance IsLabel "zzyy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z z y y
-
-instance IsLabel "zzyz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z z y z
-
-instance IsLabel "zzzx" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \x _ z -> vec4 z z z x
-
-instance IsLabel "zzzy" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ y z -> vec4 z z z y
-
-instance IsLabel "zzzz" (Swizzle Vec4 Vec3) where
-  fromLabel = Swizzle \v -> withVec3 v \_ _ z -> vec4 z z z z
-
--- * From Vec4
-
--- ** To Float
-
-instance IsLabel "x" (Swizzle Float Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ _ -> x
-
-instance IsLabel "y" (Swizzle Float Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ _ -> y
-
-instance IsLabel "z" (Swizzle Float Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z _ -> z
-
-instance IsLabel "w" (Swizzle Float Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ _ w -> w
-
--- ** To Vec2
-
-instance IsLabel "xx" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ _ -> vec2 x x
-
-instance IsLabel "xy" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec2 x y
-
-instance IsLabel "xz" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec2 x z
-
-instance IsLabel "xw" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec2 x w
-
-instance IsLabel "yx" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec2 y x
-
-instance IsLabel "yy" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ _ -> vec2 y y
-
-instance IsLabel "yz" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec2 y z
-
-instance IsLabel "yw" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec2 y w
-
-instance IsLabel "zx" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec2 z x
-
-instance IsLabel "zy" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec2 z y
-
-instance IsLabel "zz" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z _ -> vec2 z z
-
-instance IsLabel "zw" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec2 z w
-
-instance IsLabel "wx" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec2 w x
-
-instance IsLabel "wy" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec2 w y
-
-instance IsLabel "wz" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec2 w z
-
-instance IsLabel "ww" (Swizzle Vec2 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ _ w -> vec2 w w
-
--- ** To Vec3
-
-instance IsLabel "xxx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ _ -> vec3 x x x
-
-instance IsLabel "xxy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 x x y
-
-instance IsLabel "xxz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 x x z
-
-instance IsLabel "xxw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 x x w
-
-instance IsLabel "xyx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 x y x
-
-instance IsLabel "xyy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 x y y
-
-instance IsLabel "xyz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 x y z
-
-instance IsLabel "xyw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 x y w
-
-instance IsLabel "xzx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 x z x
-
-instance IsLabel "xzy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 x z y
-
-instance IsLabel "xzz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 x z z
-
-instance IsLabel "xzw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 x z w
-
-instance IsLabel "xwx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 x w x
-
-instance IsLabel "xwy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 x w y
-
-instance IsLabel "xwz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 x w z
-
-instance IsLabel "xww" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 x w w
-
-instance IsLabel "yxx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 y x x
-
-instance IsLabel "yxy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 y x y
-
-instance IsLabel "yxz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 y x z
-
-instance IsLabel "yxw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 y x w
-
-instance IsLabel "yyx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec3 y y x
-
-instance IsLabel "yyy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ _ -> vec3 y y y
-
-instance IsLabel "yyz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 y y z
-
-instance IsLabel "yyw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 y y w
-
-instance IsLabel "yzx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 y z x
-
-instance IsLabel "yzy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 y z y
-
-instance IsLabel "yzz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 y z z
-
-instance IsLabel "yzw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 y z w
-
-instance IsLabel "ywx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 y w x
-
-instance IsLabel "ywy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 y w y
-
-instance IsLabel "ywz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 y w z
-
-instance IsLabel "yww" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 y w w
-
-instance IsLabel "zxx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 z x x
-
-instance IsLabel "zxy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 z x y
-
-instance IsLabel "zxz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 z x z
-
-instance IsLabel "zxw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 z x w
-
-instance IsLabel "zyx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec3 z y x
-
-instance IsLabel "zyy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 z y y
-
-instance IsLabel "zyz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 z y z
-
-instance IsLabel "zyw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 z y w
-
-instance IsLabel "zzx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec3 z z x
-
-instance IsLabel "zzy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec3 z z y
-
-instance IsLabel "zzz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z _ -> vec3 z z z
-
-instance IsLabel "zzw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 z z w
-
-instance IsLabel "zwx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 z w x
-
-instance IsLabel "zwy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 z w y
-
-instance IsLabel "zwz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 z w z
-
-instance IsLabel "zww" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 z w w
-
-instance IsLabel "wxx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 w x x
-
-instance IsLabel "wxy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 w x y
-
-instance IsLabel "wxz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 w x z
-
-instance IsLabel "wxw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 w x w
-
-instance IsLabel "wyx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec3 w y x
-
-instance IsLabel "wyy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 w y y
-
-instance IsLabel "wyz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 w y z
-
-instance IsLabel "wyw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 w y w
-
-instance IsLabel "wzx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec3 w z x
-
-instance IsLabel "wzy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec3 w z y
-
-instance IsLabel "wzz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 w z z
-
-instance IsLabel "wzw" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 w z w
-
-instance IsLabel "wwx" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec3 w w x
-
-instance IsLabel "wwy" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec3 w w y
-
-instance IsLabel "wwz" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec3 w w z
-
-instance IsLabel "www" (Swizzle Vec3 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ _ w -> vec3 w w w
-
--- ** To Vec4
-
-instance IsLabel "xxxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ _ -> vec4 x x x x
-
-instance IsLabel "xxxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x x x y
-
-instance IsLabel "xxxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x x x z
-
-instance IsLabel "xxxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x x x w
-
-instance IsLabel "xxyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x x y x
-
-instance IsLabel "xxyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x x y y
-
-instance IsLabel "xxyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x x y z
-
-instance IsLabel "xxyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x x y w
-
-instance IsLabel "xxzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x x z x
-
-instance IsLabel "xxzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x x z y
-
-instance IsLabel "xxzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x x z z
-
-instance IsLabel "xxzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x x z w
-
-instance IsLabel "xxwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x x w x
-
-instance IsLabel "xxwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x x w y
-
-instance IsLabel "xxwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x x w z
-
-instance IsLabel "xxww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x x w w
-
-instance IsLabel "xyxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x y x x
-
-instance IsLabel "xyxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x y x y
-
-instance IsLabel "xyxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x y x z
-
-instance IsLabel "xyxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x y x w
-
-instance IsLabel "xyyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x y y x
-
-instance IsLabel "xyyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 x y y y
-
-instance IsLabel "xyyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x y y z
-
-instance IsLabel "xyyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x y y w
-
-instance IsLabel "xyzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x y z x
-
-instance IsLabel "xyzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x y z y
-
-instance IsLabel "xyzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x y z z
-
-instance IsLabel "xywx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x y w x
-
-instance IsLabel "xywy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x y w y
-
-instance IsLabel "xywz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 x y w z
-
-instance IsLabel "xyww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x y w w
-
-instance IsLabel "xzxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x z x x
-
-instance IsLabel "xzxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x z x y
-
-instance IsLabel "xzxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x z x z
-
-instance IsLabel "xzxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x z x w
-
-instance IsLabel "xzyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x z y x
-
-instance IsLabel "xzyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x z y y
-
-instance IsLabel "xzyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x z y z
-
-instance IsLabel "xzyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 x z y w
-
-instance IsLabel "xzzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x z z x
-
-instance IsLabel "xzzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 x z z y
-
-instance IsLabel "xzzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 x z z z
-
-instance IsLabel "xzzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x z z w
-
-instance IsLabel "xzwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x z w x
-
-instance IsLabel "xzwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 x z w y
-
-instance IsLabel "xzwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x z w z
-
-instance IsLabel "xzww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x z w w
-
-instance IsLabel "xwxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x w x x
-
-instance IsLabel "xwxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x w x y
-
-instance IsLabel "xwxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x w x z
-
-instance IsLabel "xwxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x w x w
-
-instance IsLabel "xwyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x w y x
-
-instance IsLabel "xwyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x w y y
-
-instance IsLabel "xwyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 x w y z
-
-instance IsLabel "xwyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x w y w
-
-instance IsLabel "xwzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x w z x
-
-instance IsLabel "xwzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 x w z y
-
-instance IsLabel "xwzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x w z z
-
-instance IsLabel "xwzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x w z w
-
-instance IsLabel "xwwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x w w x
-
-instance IsLabel "xwwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 x w w y
-
-instance IsLabel "xwwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 x w w z
-
-instance IsLabel "xwww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 x w w w
-
-instance IsLabel "yxxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y x x x
-
-instance IsLabel "yxxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y x x y
-
-instance IsLabel "yxxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y x x z
-
-instance IsLabel "yxxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y x x w
-
-instance IsLabel "yxyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y x y x
-
-instance IsLabel "yxyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y x y y
-
-instance IsLabel "yxyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y x y z
-
-instance IsLabel "yxyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y x y w
-
-instance IsLabel "yxzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y x z x
-
-instance IsLabel "yxzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y x z y
-
-instance IsLabel "yxzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y x z z
-
-instance IsLabel "yxzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y x z w
-
-instance IsLabel "yxwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y x w x
-
-instance IsLabel "yxwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y x w y
-
-instance IsLabel "yxwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y x w z
-
-instance IsLabel "yxww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y x w w
-
-instance IsLabel "yyxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y y x x
-
-instance IsLabel "yyxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y y x y
-
-instance IsLabel "yyxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y y x z
-
-instance IsLabel "yyxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y y x w
-
-instance IsLabel "yyyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ _ -> vec4 y y y x
-
-instance IsLabel "yyyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ _ -> vec4 y y y y
-
-instance IsLabel "yyyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y y y z
-
-instance IsLabel "yyyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y y y w
-
-instance IsLabel "yyzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y y z x
-
-instance IsLabel "yyzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y y z y
-
-instance IsLabel "yyzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y y z z
-
-instance IsLabel "yyzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y y z w
-
-instance IsLabel "yywx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y y w x
-
-instance IsLabel "yywy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y y w y
-
-instance IsLabel "yywz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y y w z
-
-instance IsLabel "yyww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y y w w
-
-instance IsLabel "yzxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y z x x
-
-instance IsLabel "yzxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y z x y
-
-instance IsLabel "yzxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y z x z
-
-instance IsLabel "yzxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y z x w
-
-instance IsLabel "yzyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y z y x
-
-instance IsLabel "yzyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y z y y
-
-instance IsLabel "yzyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y z y z
-
-instance IsLabel "yzyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y z y w
-
-instance IsLabel "yzzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 y z z x
-
-instance IsLabel "yzzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y z z y
-
-instance IsLabel "yzzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 y z z z
-
-instance IsLabel "yzzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y z z w
-
-instance IsLabel "yzwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y z w x
-
-instance IsLabel "yzwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y z w y
-
-instance IsLabel "yzwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y z w z
-
-instance IsLabel "yzww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y z w w
-
-instance IsLabel "ywxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y w x x
-
-instance IsLabel "ywxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y w x y
-
-instance IsLabel "ywxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y w x z
-
-instance IsLabel "ywxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y w x w
-
-instance IsLabel "ywyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y w y x
-
-instance IsLabel "ywyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y w y y
-
-instance IsLabel "ywyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y w y z
-
-instance IsLabel "ywyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y w y w
-
-instance IsLabel "ywzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 y w z x
-
-instance IsLabel "ywzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y w z y
-
-instance IsLabel "ywzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y w z z
-
-instance IsLabel "ywzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y w z w
-
-instance IsLabel "ywwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 y w w x
-
-instance IsLabel "ywwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y w w y
-
-instance IsLabel "ywwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 y w w z
-
-instance IsLabel "ywww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 y w w w
-
-instance IsLabel "zxxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z x x x
-
-instance IsLabel "zxxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z x x y
-
-instance IsLabel "zxxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z x x z
-
-instance IsLabel "zxxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z x x w
-
-instance IsLabel "zxyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z x y x
-
-instance IsLabel "zxyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z x y y
-
-instance IsLabel "zxyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z x y z
-
-instance IsLabel "zxyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z x y w
-
-instance IsLabel "zxzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z x z x
-
-instance IsLabel "zxzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z x z y
-
-instance IsLabel "zxzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z x z z
-
-instance IsLabel "zxzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z x z w
-
-instance IsLabel "zxwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z x w x
-
-instance IsLabel "zxwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z x w y
-
-instance IsLabel "zxwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z x w z
-
-instance IsLabel "zxww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z x w w
-
-instance IsLabel "zyxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z y x x
-
-instance IsLabel "zyxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z y x y
-
-instance IsLabel "zyxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z y x z
-
-instance IsLabel "zyxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z y x w
-
-instance IsLabel "zyyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z y y x
-
-instance IsLabel "zyyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z y y y
-
-instance IsLabel "zyyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z y y z
-
-instance IsLabel "zyyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z y y w
-
-instance IsLabel "zyzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z y z x
-
-instance IsLabel "zyzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z y z y
-
-instance IsLabel "zyzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z y z z
-
-instance IsLabel "zyzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z y z w
-
-instance IsLabel "zywx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z y w x
-
-instance IsLabel "zywy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z y w y
-
-instance IsLabel "zywz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z y w z
-
-instance IsLabel "zyww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z y w w
-
-instance IsLabel "zzxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z z x x
-
-instance IsLabel "zzxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z z x y
-
-instance IsLabel "zzxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z z x z
-
-instance IsLabel "zzxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z z x w
-
-instance IsLabel "zzyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z _ -> vec4 z z y x
-
-instance IsLabel "zzyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z z y y
-
-instance IsLabel "zzyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z z y z
-
-instance IsLabel "zzyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z z y w
-
-instance IsLabel "zzzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z _ -> vec4 z z z x
-
-instance IsLabel "zzzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z _ -> vec4 z z z y
-
-instance IsLabel "zzzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z _ -> vec4 z z z z
-
-instance IsLabel "zzzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z z z w
-
-instance IsLabel "zzwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z z w x
-
-instance IsLabel "zzwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z z w y
-
-instance IsLabel "zzwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z z w z
-
-instance IsLabel "zzww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z z w w
-
-instance IsLabel "zwxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z w x x
-
-instance IsLabel "zwxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z w x y
-
-instance IsLabel "zwxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z w x z
-
-instance IsLabel "zwxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z w x w
-
-instance IsLabel "zwyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 z w y x
-
-instance IsLabel "zwyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z w y y
-
-instance IsLabel "zwyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z w y z
-
-instance IsLabel "zwyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z w y w
-
-instance IsLabel "zwzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z w z x
-
-instance IsLabel "zwzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z w z y
-
-instance IsLabel "zwzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z w z z
-
-instance IsLabel "zwzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z w z w
-
-instance IsLabel "zwwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 z w w x
-
-instance IsLabel "zwwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 z w w y
-
-instance IsLabel "zwwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z w w z
-
-instance IsLabel "zwww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 z w w w
-
-instance IsLabel "wxxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w x x x
-
-instance IsLabel "wxxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w x x y
-
-instance IsLabel "wxxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w x x z
-
-instance IsLabel "wxxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w x x w
-
-instance IsLabel "wxyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w x y x
-
-instance IsLabel "wxyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w x y y
-
-instance IsLabel "wxyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w x y z
-
-instance IsLabel "wxyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w x y w
-
-instance IsLabel "wxzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w x z x
-
-instance IsLabel "wxzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w x z y
-
-instance IsLabel "wxzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w x z z
-
-instance IsLabel "wxzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w x z w
-
-instance IsLabel "wxwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w x w x
-
-instance IsLabel "wxwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w x w y
-
-instance IsLabel "wxwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w x w z
-
-instance IsLabel "wxww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w x w w
-
-instance IsLabel "wyxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w y x x
-
-instance IsLabel "wyxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w y x y
-
-instance IsLabel "wyxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w y x z
-
-instance IsLabel "wyxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w y x w
-
-instance IsLabel "wyyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w y y x
-
-instance IsLabel "wyyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w y y y
-
-instance IsLabel "wyyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w y y z
-
-instance IsLabel "wyyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w y y w
-
-instance IsLabel "wyzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w y z x
-
-instance IsLabel "wyzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w y z y
-
-instance IsLabel "wyzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w y z z
-
-instance IsLabel "wyzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w y z w
-
-instance IsLabel "wywx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w y w x
-
-instance IsLabel "wywy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w y w y
-
-instance IsLabel "wywz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w y w z
-
-instance IsLabel "wyww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w y w w
-
-instance IsLabel "wzxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w z x x
-
-instance IsLabel "wzxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w z x y
-
-instance IsLabel "wzxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w z x z
-
-instance IsLabel "wzxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w z x w
-
-instance IsLabel "wzyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y z w -> vec4 w z y x
-
-instance IsLabel "wzyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w z y y
-
-instance IsLabel "wzyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w z y z
-
-instance IsLabel "wzyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w z y w
-
-instance IsLabel "wzzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w z z x
-
-instance IsLabel "wzzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w z z y
-
-instance IsLabel "wzzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w z z z
-
-instance IsLabel "wzzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w z z w
-
-instance IsLabel "wzwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w z w x
-
-instance IsLabel "wzwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w z w y
-
-instance IsLabel "wzwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w z w z
-
-instance IsLabel "wzww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w z w w
-
-instance IsLabel "wwxx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w w x x
-
-instance IsLabel "wwxy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w w x y
-
-instance IsLabel "wwxz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w w x z
-
-instance IsLabel "wwxw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w w x w
-
-instance IsLabel "wwyx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x y _ w -> vec4 w w y x
-
-instance IsLabel "wwyy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w w y y
-
-instance IsLabel "wwyz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w w y z
-
-instance IsLabel "wwyw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w w y w
-
-instance IsLabel "wwzx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ z w -> vec4 w w z x
-
-instance IsLabel "wwzy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y z w -> vec4 w w z y
-
-instance IsLabel "wwzz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w w z z
-
-instance IsLabel "wwzw" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w w z w
-
-instance IsLabel "wwwx" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \x _ _ w -> vec4 w w w x
-
-instance IsLabel "wwwy" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ y _ w -> vec4 w w w y
-
-instance IsLabel "wwwz" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ z w -> vec4 w w w z
-
-instance IsLabel "wwww" (Swizzle Vec4 Vec4) where
-  fromLabel = Swizzle \v -> withVec4 v \_ _ _ w -> vec4 w w w w
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+{- |
+GLSL-style swizzles for every vector family.
+
+Unlike the single-element fields, the swizzle instances are orphans.
+Import this module to bring them all into scope:
+
+> import Geomancy.Swizzle ()
+>
+> flip3 :: Vec3 -> Vec3
+> flip3 v = v.zyx
+
+Each family and kind of swizzle also has a module of its own,
+@Geomancy.Swizzle.\<Family\>.\<Kind\>@, for when you need only some of them.
+The families are @Vec@, @DVec@, @IVec@, @UVec@, @I64Vec@ and @U64Vec@, and the kinds are:
+
+[@Shuffle@] keeps the size: @v.zyx@, @v.xxyy@, and the identity @v.xyz@.
+
+[@Down@] narrows: @v.xy@ of a @Vec4@.
+
+[@Up@] widens: @v.xyxy@ of a @Vec2@.
+
+[@Extend@] widens with constant lanes, keeping the source in order: @v.xy0@, @v.xy01@, @v.xyz1@.
+
+Swizzles chain, and the chains compile to plain lane reads:
+@v.wzyx.zyx.yx.y@ is a single read of @v.y@.
+
+While mask-swizzles aren't provided, you can chain an extend with a shuffle for this:
+
+> white.xyz0.wyz      -- (0, y, z)
+> v.yzw.xyz0.wxyz     -- (0, y, z, w) of a Vec4
+> v.yz.xy01.zxyw      -- (0, y, z, 1) of a Vec3
+
+The same swizzles work as labels with '(.@)' and @OverloadedLabels@: @v .\@ #zyx@.
+-}
+module Geomancy.Swizzle
+  ( swizzle
+  , (.@)
+  ) where
+
+import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
+
+import Geomancy.Swizzle.DVec.Down ()
+import Geomancy.Swizzle.DVec.Extend ()
+import Geomancy.Swizzle.DVec.Shuffle ()
+import Geomancy.Swizzle.DVec.Up ()
+import Geomancy.Swizzle.I64Vec.Down ()
+import Geomancy.Swizzle.I64Vec.Extend ()
+import Geomancy.Swizzle.I64Vec.Shuffle ()
+import Geomancy.Swizzle.I64Vec.Up ()
+import Geomancy.Swizzle.IVec.Down ()
+import Geomancy.Swizzle.IVec.Extend ()
+import Geomancy.Swizzle.IVec.Shuffle ()
+import Geomancy.Swizzle.IVec.Up ()
+import Geomancy.Swizzle.U64Vec.Down ()
+import Geomancy.Swizzle.U64Vec.Extend ()
+import Geomancy.Swizzle.U64Vec.Shuffle ()
+import Geomancy.Swizzle.U64Vec.Up ()
+import Geomancy.Swizzle.UVec.Down ()
+import Geomancy.Swizzle.UVec.Extend ()
+import Geomancy.Swizzle.UVec.Shuffle ()
+import Geomancy.Swizzle.UVec.Up ()
+import Geomancy.Swizzle.Vec.Down ()
+import Geomancy.Swizzle.Vec.Extend ()
+import Geomancy.Swizzle.Vec.Shuffle ()
+import Geomancy.Swizzle.Vec.Up ()
+
+newtype Swizzle to fro = Swizzle { swizzle :: fro -> to }
+
+{-# INLINE (.@) #-}
+(.@) :: forall to fro . fro -> Swizzle to fro -> to
+v .@ Swizzle f = f v
+
+instance HasField s fro to => IsLabel s (Swizzle to fro) where
+  {-# INLINE fromLabel #-}
+  fromLabel = Swizzle (getField @s)
diff --git a/src/Geomancy/Swizzle/DVec/Down.hs b/src/Geomancy/Swizzle/DVec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/DVec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.DVec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.DVec2 (DVec2, dvec2)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.DVec4 (DVec4, withDVec4)
+
+instance HasField "xx" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ _ -> dvec2 x x
+
+instance HasField "xy" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec2 x y
+
+instance HasField "xz" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec2 x z
+
+instance HasField "yx" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec2 y x
+
+instance HasField "yy" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y _ -> dvec2 y y
+
+instance HasField "yz" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec2 y z
+
+instance HasField "zx" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec2 z x
+
+instance HasField "zy" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec2 z y
+
+instance HasField "zz" DVec3 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ _ z -> dvec2 z z
+
+instance HasField "xx" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ _ -> dvec2 x x
+
+instance HasField "xy" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec2 x y
+
+instance HasField "xz" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec2 x z
+
+instance HasField "xw" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec2 x w
+
+instance HasField "yx" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec2 y x
+
+instance HasField "yy" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ _ -> dvec2 y y
+
+instance HasField "yz" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec2 y z
+
+instance HasField "yw" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec2 y w
+
+instance HasField "zx" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec2 z x
+
+instance HasField "zy" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec2 z y
+
+instance HasField "zz" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z _ -> dvec2 z z
+
+instance HasField "zw" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec2 z w
+
+instance HasField "wx" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec2 w x
+
+instance HasField "wy" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec2 w y
+
+instance HasField "wz" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec2 w z
+
+instance HasField "ww" DVec4 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ _ w -> dvec2 w w
+
+instance HasField "xxx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ _ -> dvec3 x x x
+
+instance HasField "xxy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 x x y
+
+instance HasField "xxz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 x x z
+
+instance HasField "xxw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 x x w
+
+instance HasField "xyx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 x y x
+
+instance HasField "xyy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 x y y
+
+instance HasField "xyz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 x y z
+
+instance HasField "xyw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 x y w
+
+instance HasField "xzx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 x z x
+
+instance HasField "xzy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 x z y
+
+instance HasField "xzz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 x z z
+
+instance HasField "xzw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 x z w
+
+instance HasField "xwx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 x w x
+
+instance HasField "xwy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 x w y
+
+instance HasField "xwz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 x w z
+
+instance HasField "xww" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 x w w
+
+instance HasField "yxx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 y x x
+
+instance HasField "yxy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 y x y
+
+instance HasField "yxz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 y x z
+
+instance HasField "yxw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 y x w
+
+instance HasField "yyx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec3 y y x
+
+instance HasField "yyy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ _ -> dvec3 y y y
+
+instance HasField "yyz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 y y z
+
+instance HasField "yyw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 y y w
+
+instance HasField "yzx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 y z x
+
+instance HasField "yzy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 y z y
+
+instance HasField "yzz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 y z z
+
+instance HasField "yzw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 y z w
+
+instance HasField "ywx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 y w x
+
+instance HasField "ywy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 y w y
+
+instance HasField "ywz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 y w z
+
+instance HasField "yww" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 y w w
+
+instance HasField "zxx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 z x x
+
+instance HasField "zxy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 z x y
+
+instance HasField "zxz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 z x z
+
+instance HasField "zxw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 z x w
+
+instance HasField "zyx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec3 z y x
+
+instance HasField "zyy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 z y y
+
+instance HasField "zyz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 z y z
+
+instance HasField "zyw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 z y w
+
+instance HasField "zzx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec3 z z x
+
+instance HasField "zzy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec3 z z y
+
+instance HasField "zzz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z _ -> dvec3 z z z
+
+instance HasField "zzw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 z z w
+
+instance HasField "zwx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 z w x
+
+instance HasField "zwy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 z w y
+
+instance HasField "zwz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 z w z
+
+instance HasField "zww" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 z w w
+
+instance HasField "wxx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 w x x
+
+instance HasField "wxy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 w x y
+
+instance HasField "wxz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 w x z
+
+instance HasField "wxw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 w x w
+
+instance HasField "wyx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec3 w y x
+
+instance HasField "wyy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 w y y
+
+instance HasField "wyz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 w y z
+
+instance HasField "wyw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 w y w
+
+instance HasField "wzx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec3 w z x
+
+instance HasField "wzy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec3 w z y
+
+instance HasField "wzz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 w z z
+
+instance HasField "wzw" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 w z w
+
+instance HasField "wwx" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec3 w w x
+
+instance HasField "wwy" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec3 w w y
+
+instance HasField "wwz" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec3 w w z
+
+instance HasField "www" DVec4 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ _ w -> dvec3 w w w
diff --git a/src/Geomancy/Swizzle/DVec/Extend.hs b/src/Geomancy/Swizzle/DVec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/DVec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.DVec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.DVec2 (DVec2, withDVec2)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.DVec4 (DVec4, dvec4)
+
+instance HasField "xy0" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 x y 0
+
+instance HasField "xy1" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 x y 1
+
+instance HasField "xy00" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y 0 0
+
+instance HasField "xy01" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y 0 1
+
+instance HasField "xy10" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y 1 0
+
+instance HasField "xy11" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y 1 1
+
+instance HasField "xyz0" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y z 0
+
+instance HasField "xyz1" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y z 1
diff --git a/src/Geomancy/Swizzle/DVec/Shuffle.hs b/src/Geomancy/Swizzle/DVec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/DVec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.DVec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.DVec2 (DVec2, dvec2, withDVec2)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.DVec4 (DVec4, dvec4, withDVec4)
+
+instance HasField "xx" DVec2 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x _ -> dvec2 x x
+
+instance HasField "xy" DVec2 DVec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" DVec2 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec2 y x
+
+instance HasField "yy" DVec2 DVec2 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \_ y -> dvec2 y y
+
+instance HasField "xxx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ _ -> dvec3 x x x
+
+instance HasField "xxy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 x x y
+
+instance HasField "xxz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 x x z
+
+instance HasField "xyx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 x y x
+
+instance HasField "xyy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 x y y
+
+instance HasField "xyz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 x z x
+
+instance HasField "xzy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec3 x z y
+
+instance HasField "xzz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 x z z
+
+instance HasField "yxx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 y x x
+
+instance HasField "yxy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 y x y
+
+instance HasField "yxz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec3 y x z
+
+instance HasField "yyx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec3 y y x
+
+instance HasField "yyy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y _ -> dvec3 y y y
+
+instance HasField "yyz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 y y z
+
+instance HasField "yzx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec3 y z x
+
+instance HasField "yzy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 y z y
+
+instance HasField "yzz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 y z z
+
+instance HasField "zxx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 z x x
+
+instance HasField "zxy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec3 z x y
+
+instance HasField "zxz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 z x z
+
+instance HasField "zyx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec3 z y x
+
+instance HasField "zyy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 z y y
+
+instance HasField "zyz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 z y z
+
+instance HasField "zzx" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec3 z z x
+
+instance HasField "zzy" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec3 z z y
+
+instance HasField "zzz" DVec3 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ _ z -> dvec3 z z z
+
+instance HasField "xxxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ _ -> dvec4 x x x x
+
+instance HasField "xxxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x x x y
+
+instance HasField "xxxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x x x z
+
+instance HasField "xxxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x x x w
+
+instance HasField "xxyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x x y x
+
+instance HasField "xxyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x x y y
+
+instance HasField "xxyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x x y z
+
+instance HasField "xxyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x x y w
+
+instance HasField "xxzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x x z x
+
+instance HasField "xxzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x x z y
+
+instance HasField "xxzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x x z z
+
+instance HasField "xxzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x x z w
+
+instance HasField "xxwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x x w x
+
+instance HasField "xxwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x x w y
+
+instance HasField "xxwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x x w z
+
+instance HasField "xxww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x x w w
+
+instance HasField "xyxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x y x x
+
+instance HasField "xyxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x y x y
+
+instance HasField "xyxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x y x z
+
+instance HasField "xyxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x y x w
+
+instance HasField "xyyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x y y x
+
+instance HasField "xyyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 x y y y
+
+instance HasField "xyyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x y y z
+
+instance HasField "xyyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x y y w
+
+instance HasField "xyzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x y z x
+
+instance HasField "xyzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x y z y
+
+instance HasField "xyzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x y z z
+
+instance HasField "xyzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x y w x
+
+instance HasField "xywy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x y w y
+
+instance HasField "xywz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 x y w z
+
+instance HasField "xyww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x y w w
+
+instance HasField "xzxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x z x x
+
+instance HasField "xzxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x z x y
+
+instance HasField "xzxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x z x z
+
+instance HasField "xzxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x z x w
+
+instance HasField "xzyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x z y x
+
+instance HasField "xzyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x z y y
+
+instance HasField "xzyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x z y z
+
+instance HasField "xzyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 x z y w
+
+instance HasField "xzzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x z z x
+
+instance HasField "xzzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 x z z y
+
+instance HasField "xzzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 x z z z
+
+instance HasField "xzzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x z z w
+
+instance HasField "xzwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x z w x
+
+instance HasField "xzwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 x z w y
+
+instance HasField "xzwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x z w z
+
+instance HasField "xzww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x z w w
+
+instance HasField "xwxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x w x x
+
+instance HasField "xwxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x w x y
+
+instance HasField "xwxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x w x z
+
+instance HasField "xwxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x w x w
+
+instance HasField "xwyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x w y x
+
+instance HasField "xwyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x w y y
+
+instance HasField "xwyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 x w y z
+
+instance HasField "xwyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x w y w
+
+instance HasField "xwzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x w z x
+
+instance HasField "xwzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 x w z y
+
+instance HasField "xwzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x w z z
+
+instance HasField "xwzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x w z w
+
+instance HasField "xwwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x w w x
+
+instance HasField "xwwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 x w w y
+
+instance HasField "xwwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 x w w z
+
+instance HasField "xwww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 x w w w
+
+instance HasField "yxxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y x x x
+
+instance HasField "yxxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y x x y
+
+instance HasField "yxxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y x x z
+
+instance HasField "yxxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y x x w
+
+instance HasField "yxyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y x y x
+
+instance HasField "yxyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y x y y
+
+instance HasField "yxyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y x y z
+
+instance HasField "yxyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y x y w
+
+instance HasField "yxzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y x z x
+
+instance HasField "yxzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y x z y
+
+instance HasField "yxzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y x z z
+
+instance HasField "yxzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y x z w
+
+instance HasField "yxwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y x w x
+
+instance HasField "yxwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y x w y
+
+instance HasField "yxwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y x w z
+
+instance HasField "yxww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y x w w
+
+instance HasField "yyxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y y x x
+
+instance HasField "yyxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y y x y
+
+instance HasField "yyxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y y x z
+
+instance HasField "yyxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y y x w
+
+instance HasField "yyyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ _ -> dvec4 y y y x
+
+instance HasField "yyyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ _ -> dvec4 y y y y
+
+instance HasField "yyyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y y y z
+
+instance HasField "yyyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y y y w
+
+instance HasField "yyzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y y z x
+
+instance HasField "yyzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y y z y
+
+instance HasField "yyzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y y z z
+
+instance HasField "yyzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y y z w
+
+instance HasField "yywx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y y w x
+
+instance HasField "yywy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y y w y
+
+instance HasField "yywz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y y w z
+
+instance HasField "yyww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y y w w
+
+instance HasField "yzxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y z x x
+
+instance HasField "yzxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y z x y
+
+instance HasField "yzxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y z x z
+
+instance HasField "yzxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y z x w
+
+instance HasField "yzyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y z y x
+
+instance HasField "yzyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y z y y
+
+instance HasField "yzyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y z y z
+
+instance HasField "yzyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y z y w
+
+instance HasField "yzzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 y z z x
+
+instance HasField "yzzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y z z y
+
+instance HasField "yzzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 y z z z
+
+instance HasField "yzzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y z z w
+
+instance HasField "yzwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y z w x
+
+instance HasField "yzwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y z w y
+
+instance HasField "yzwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y z w z
+
+instance HasField "yzww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y z w w
+
+instance HasField "ywxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y w x x
+
+instance HasField "ywxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y w x y
+
+instance HasField "ywxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y w x z
+
+instance HasField "ywxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y w x w
+
+instance HasField "ywyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y w y x
+
+instance HasField "ywyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y w y y
+
+instance HasField "ywyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y w y z
+
+instance HasField "ywyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y w y w
+
+instance HasField "ywzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 y w z x
+
+instance HasField "ywzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y w z y
+
+instance HasField "ywzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y w z z
+
+instance HasField "ywzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y w z w
+
+instance HasField "ywwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 y w w x
+
+instance HasField "ywwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y w w y
+
+instance HasField "ywwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 y w w z
+
+instance HasField "ywww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 y w w w
+
+instance HasField "zxxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z x x x
+
+instance HasField "zxxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z x x y
+
+instance HasField "zxxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z x x z
+
+instance HasField "zxxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z x x w
+
+instance HasField "zxyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z x y x
+
+instance HasField "zxyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z x y y
+
+instance HasField "zxyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z x y z
+
+instance HasField "zxyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z x y w
+
+instance HasField "zxzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z x z x
+
+instance HasField "zxzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z x z y
+
+instance HasField "zxzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z x z z
+
+instance HasField "zxzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z x z w
+
+instance HasField "zxwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z x w x
+
+instance HasField "zxwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z x w y
+
+instance HasField "zxwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z x w z
+
+instance HasField "zxww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z x w w
+
+instance HasField "zyxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z y x x
+
+instance HasField "zyxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z y x y
+
+instance HasField "zyxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z y x z
+
+instance HasField "zyxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z y x w
+
+instance HasField "zyyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z y y x
+
+instance HasField "zyyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z y y y
+
+instance HasField "zyyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z y y z
+
+instance HasField "zyyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z y y w
+
+instance HasField "zyzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z y z x
+
+instance HasField "zyzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z y z y
+
+instance HasField "zyzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z y z z
+
+instance HasField "zyzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z y z w
+
+instance HasField "zywx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z y w x
+
+instance HasField "zywy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z y w y
+
+instance HasField "zywz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z y w z
+
+instance HasField "zyww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z y w w
+
+instance HasField "zzxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z z x x
+
+instance HasField "zzxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z z x y
+
+instance HasField "zzxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z z x z
+
+instance HasField "zzxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z z x w
+
+instance HasField "zzyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z _ -> dvec4 z z y x
+
+instance HasField "zzyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z z y y
+
+instance HasField "zzyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z z y z
+
+instance HasField "zzyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z z y w
+
+instance HasField "zzzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z _ -> dvec4 z z z x
+
+instance HasField "zzzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z _ -> dvec4 z z z y
+
+instance HasField "zzzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z _ -> dvec4 z z z z
+
+instance HasField "zzzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z z z w
+
+instance HasField "zzwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z z w x
+
+instance HasField "zzwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z z w y
+
+instance HasField "zzwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z z w z
+
+instance HasField "zzww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z z w w
+
+instance HasField "zwxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z w x x
+
+instance HasField "zwxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z w x y
+
+instance HasField "zwxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z w x z
+
+instance HasField "zwxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z w x w
+
+instance HasField "zwyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 z w y x
+
+instance HasField "zwyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z w y y
+
+instance HasField "zwyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z w y z
+
+instance HasField "zwyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z w y w
+
+instance HasField "zwzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z w z x
+
+instance HasField "zwzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z w z y
+
+instance HasField "zwzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z w z z
+
+instance HasField "zwzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z w z w
+
+instance HasField "zwwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 z w w x
+
+instance HasField "zwwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 z w w y
+
+instance HasField "zwwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z w w z
+
+instance HasField "zwww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 z w w w
+
+instance HasField "wxxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w x x x
+
+instance HasField "wxxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w x x y
+
+instance HasField "wxxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w x x z
+
+instance HasField "wxxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w x x w
+
+instance HasField "wxyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w x y x
+
+instance HasField "wxyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w x y y
+
+instance HasField "wxyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w x y z
+
+instance HasField "wxyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w x y w
+
+instance HasField "wxzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w x z x
+
+instance HasField "wxzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w x z y
+
+instance HasField "wxzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w x z z
+
+instance HasField "wxzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w x z w
+
+instance HasField "wxwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w x w x
+
+instance HasField "wxwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w x w y
+
+instance HasField "wxwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w x w z
+
+instance HasField "wxww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w x w w
+
+instance HasField "wyxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w y x x
+
+instance HasField "wyxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w y x y
+
+instance HasField "wyxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w y x z
+
+instance HasField "wyxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w y x w
+
+instance HasField "wyyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w y y x
+
+instance HasField "wyyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w y y y
+
+instance HasField "wyyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w y y z
+
+instance HasField "wyyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w y y w
+
+instance HasField "wyzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w y z x
+
+instance HasField "wyzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w y z y
+
+instance HasField "wyzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w y z z
+
+instance HasField "wyzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w y z w
+
+instance HasField "wywx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w y w x
+
+instance HasField "wywy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w y w y
+
+instance HasField "wywz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w y w z
+
+instance HasField "wyww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w y w w
+
+instance HasField "wzxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w z x x
+
+instance HasField "wzxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w z x y
+
+instance HasField "wzxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w z x z
+
+instance HasField "wzxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w z x w
+
+instance HasField "wzyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y z w -> dvec4 w z y x
+
+instance HasField "wzyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w z y y
+
+instance HasField "wzyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w z y z
+
+instance HasField "wzyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w z y w
+
+instance HasField "wzzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w z z x
+
+instance HasField "wzzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w z z y
+
+instance HasField "wzzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w z z z
+
+instance HasField "wzzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w z z w
+
+instance HasField "wzwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w z w x
+
+instance HasField "wzwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w z w y
+
+instance HasField "wzwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w z w z
+
+instance HasField "wzww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w z w w
+
+instance HasField "wwxx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w w x x
+
+instance HasField "wwxy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w w x y
+
+instance HasField "wwxz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w w x z
+
+instance HasField "wwxw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w w x w
+
+instance HasField "wwyx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x y _ w -> dvec4 w w y x
+
+instance HasField "wwyy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w w y y
+
+instance HasField "wwyz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w w y z
+
+instance HasField "wwyw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w w y w
+
+instance HasField "wwzx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ z w -> dvec4 w w z x
+
+instance HasField "wwzy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y z w -> dvec4 w w z y
+
+instance HasField "wwzz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w w z z
+
+instance HasField "wwzw" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w w z w
+
+instance HasField "wwwx" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \x _ _ w -> dvec4 w w w x
+
+instance HasField "wwwy" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ y _ w -> dvec4 w w w y
+
+instance HasField "wwwz" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ z w -> dvec4 w w w z
+
+instance HasField "wwww" DVec4 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec4 v \_ _ _ w -> dvec4 w w w w
diff --git a/src/Geomancy/Swizzle/DVec/Up.hs b/src/Geomancy/Swizzle/DVec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/DVec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.DVec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.DVec2 (DVec2, withDVec2)
+import Geomancy.DVec3 (DVec3, dvec3, withDVec3)
+import Geomancy.DVec4 (DVec4, dvec4)
+
+instance HasField "xxx" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x _ -> dvec3 x x x
+
+instance HasField "xxy" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 x x y
+
+instance HasField "xyx" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 x y x
+
+instance HasField "xyy" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 x y y
+
+instance HasField "yxx" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 y x x
+
+instance HasField "yxy" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 y x y
+
+instance HasField "yyx" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec3 y y x
+
+instance HasField "yyy" DVec2 DVec3 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \_ y -> dvec3 y y y
+
+instance HasField "xxxx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x _ -> dvec4 x x x x
+
+instance HasField "xxxy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x x x y
+
+instance HasField "xxyx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x x y x
+
+instance HasField "xxyy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x x y y
+
+instance HasField "xyxx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y x x
+
+instance HasField "xyxy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y x y
+
+instance HasField "xyyx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y y x
+
+instance HasField "xyyy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 x y y y
+
+instance HasField "yxxx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y x x x
+
+instance HasField "yxxy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y x x y
+
+instance HasField "yxyx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y x y x
+
+instance HasField "yxyy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y x y y
+
+instance HasField "yyxx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y y x x
+
+instance HasField "yyxy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y y x y
+
+instance HasField "yyyx" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \x y -> dvec4 y y y x
+
+instance HasField "yyyy" DVec2 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec2 v \_ y -> dvec4 y y y y
+
+instance HasField "xxxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ _ -> dvec4 x x x x
+
+instance HasField "xxxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x x x y
+
+instance HasField "xxxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x x x z
+
+instance HasField "xxyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x x y x
+
+instance HasField "xxyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x x y y
+
+instance HasField "xxyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x x y z
+
+instance HasField "xxzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x x z x
+
+instance HasField "xxzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x x z y
+
+instance HasField "xxzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x x z z
+
+instance HasField "xyxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x y x x
+
+instance HasField "xyxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x y x y
+
+instance HasField "xyxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y x z
+
+instance HasField "xyyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x y y x
+
+instance HasField "xyyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 x y y y
+
+instance HasField "xyyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y y z
+
+instance HasField "xyzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y z x
+
+instance HasField "xyzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y z y
+
+instance HasField "xyzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x y z z
+
+instance HasField "xzxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x z x x
+
+instance HasField "xzxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x z x y
+
+instance HasField "xzxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x z x z
+
+instance HasField "xzyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x z y x
+
+instance HasField "xzyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x z y y
+
+instance HasField "xzyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x z y z
+
+instance HasField "xzzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x z z x
+
+instance HasField "xzzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 x z z y
+
+instance HasField "xzzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 x z z z
+
+instance HasField "yxxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y x x x
+
+instance HasField "yxxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y x x y
+
+instance HasField "yxxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y x x z
+
+instance HasField "yxyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y x y x
+
+instance HasField "yxyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y x y y
+
+instance HasField "yxyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y x y z
+
+instance HasField "yxzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y x z x
+
+instance HasField "yxzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y x z y
+
+instance HasField "yxzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y x z z
+
+instance HasField "yyxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y y x x
+
+instance HasField "yyxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y y x y
+
+instance HasField "yyxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y y x z
+
+instance HasField "yyyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y _ -> dvec4 y y y x
+
+instance HasField "yyyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y _ -> dvec4 y y y y
+
+instance HasField "yyyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y y y z
+
+instance HasField "yyzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y y z x
+
+instance HasField "yyzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y y z y
+
+instance HasField "yyzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y y z z
+
+instance HasField "yzxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y z x x
+
+instance HasField "yzxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y z x y
+
+instance HasField "yzxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y z x z
+
+instance HasField "yzyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y z y x
+
+instance HasField "yzyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y z y y
+
+instance HasField "yzyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y z y z
+
+instance HasField "yzzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 y z z x
+
+instance HasField "yzzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y z z y
+
+instance HasField "yzzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 y z z z
+
+instance HasField "zxxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z x x x
+
+instance HasField "zxxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z x x y
+
+instance HasField "zxxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z x x z
+
+instance HasField "zxyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z x y x
+
+instance HasField "zxyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z x y y
+
+instance HasField "zxyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z x y z
+
+instance HasField "zxzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z x z x
+
+instance HasField "zxzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z x z y
+
+instance HasField "zxzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z x z z
+
+instance HasField "zyxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z y x x
+
+instance HasField "zyxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z y x y
+
+instance HasField "zyxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z y x z
+
+instance HasField "zyyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z y y x
+
+instance HasField "zyyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z y y y
+
+instance HasField "zyyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z y y z
+
+instance HasField "zyzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z y z x
+
+instance HasField "zyzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z y z y
+
+instance HasField "zyzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z y z z
+
+instance HasField "zzxx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z z x x
+
+instance HasField "zzxy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z z x y
+
+instance HasField "zzxz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z z x z
+
+instance HasField "zzyx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x y z -> dvec4 z z y x
+
+instance HasField "zzyy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z z y y
+
+instance HasField "zzyz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z z y z
+
+instance HasField "zzzx" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \x _ z -> dvec4 z z z x
+
+instance HasField "zzzy" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ y z -> dvec4 z z z y
+
+instance HasField "zzzz" DVec3 DVec4 where
+  {-# INLINE getField #-}
+  getField v = withDVec3 v \_ _ z -> dvec4 z z z z
diff --git a/src/Geomancy/Swizzle/I64Vec/Down.hs b/src/Geomancy/Swizzle/I64Vec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/I64Vec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.I64Vec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.I64Vec2 (I64Vec2, i64vec2)
+import Geomancy.I64Vec3 (I64Vec3, i64vec3, withI64Vec3)
+import Geomancy.I64Vec4 (I64Vec4, withI64Vec4)
+
+instance HasField "xx" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ _ -> i64vec2 x x
+
+instance HasField "xy" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec2 x y
+
+instance HasField "xz" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec2 x z
+
+instance HasField "yx" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec2 y x
+
+instance HasField "yy" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y _ -> i64vec2 y y
+
+instance HasField "yz" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec2 y z
+
+instance HasField "zx" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec2 z x
+
+instance HasField "zy" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec2 z y
+
+instance HasField "zz" I64Vec3 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ _ z -> i64vec2 z z
+
+instance HasField "xx" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ _ -> i64vec2 x x
+
+instance HasField "xy" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec2 x y
+
+instance HasField "xz" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec2 x z
+
+instance HasField "xw" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec2 x w
+
+instance HasField "yx" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec2 y x
+
+instance HasField "yy" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ _ -> i64vec2 y y
+
+instance HasField "yz" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec2 y z
+
+instance HasField "yw" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec2 y w
+
+instance HasField "zx" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec2 z x
+
+instance HasField "zy" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec2 z y
+
+instance HasField "zz" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z _ -> i64vec2 z z
+
+instance HasField "zw" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec2 z w
+
+instance HasField "wx" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec2 w x
+
+instance HasField "wy" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec2 w y
+
+instance HasField "wz" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec2 w z
+
+instance HasField "ww" I64Vec4 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ _ w -> i64vec2 w w
+
+instance HasField "xxx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ _ -> i64vec3 x x x
+
+instance HasField "xxy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 x x y
+
+instance HasField "xxz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 x x z
+
+instance HasField "xxw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 x x w
+
+instance HasField "xyx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 x y x
+
+instance HasField "xyy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 x y y
+
+instance HasField "xyz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 x y z
+
+instance HasField "xyw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 x y w
+
+instance HasField "xzx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 x z x
+
+instance HasField "xzy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 x z y
+
+instance HasField "xzz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 x z z
+
+instance HasField "xzw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 x z w
+
+instance HasField "xwx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 x w x
+
+instance HasField "xwy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 x w y
+
+instance HasField "xwz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 x w z
+
+instance HasField "xww" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 x w w
+
+instance HasField "yxx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 y x x
+
+instance HasField "yxy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 y x y
+
+instance HasField "yxz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 y x z
+
+instance HasField "yxw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 y x w
+
+instance HasField "yyx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec3 y y x
+
+instance HasField "yyy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ _ -> i64vec3 y y y
+
+instance HasField "yyz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 y y z
+
+instance HasField "yyw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 y y w
+
+instance HasField "yzx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 y z x
+
+instance HasField "yzy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 y z y
+
+instance HasField "yzz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 y z z
+
+instance HasField "yzw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 y z w
+
+instance HasField "ywx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 y w x
+
+instance HasField "ywy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 y w y
+
+instance HasField "ywz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 y w z
+
+instance HasField "yww" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 y w w
+
+instance HasField "zxx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 z x x
+
+instance HasField "zxy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 z x y
+
+instance HasField "zxz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 z x z
+
+instance HasField "zxw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 z x w
+
+instance HasField "zyx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec3 z y x
+
+instance HasField "zyy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 z y y
+
+instance HasField "zyz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 z y z
+
+instance HasField "zyw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 z y w
+
+instance HasField "zzx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec3 z z x
+
+instance HasField "zzy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec3 z z y
+
+instance HasField "zzz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z _ -> i64vec3 z z z
+
+instance HasField "zzw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 z z w
+
+instance HasField "zwx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 z w x
+
+instance HasField "zwy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 z w y
+
+instance HasField "zwz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 z w z
+
+instance HasField "zww" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 z w w
+
+instance HasField "wxx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 w x x
+
+instance HasField "wxy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 w x y
+
+instance HasField "wxz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 w x z
+
+instance HasField "wxw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 w x w
+
+instance HasField "wyx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec3 w y x
+
+instance HasField "wyy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 w y y
+
+instance HasField "wyz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 w y z
+
+instance HasField "wyw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 w y w
+
+instance HasField "wzx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec3 w z x
+
+instance HasField "wzy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec3 w z y
+
+instance HasField "wzz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 w z z
+
+instance HasField "wzw" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 w z w
+
+instance HasField "wwx" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec3 w w x
+
+instance HasField "wwy" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec3 w w y
+
+instance HasField "wwz" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec3 w w z
+
+instance HasField "www" I64Vec4 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ _ w -> i64vec3 w w w
diff --git a/src/Geomancy/Swizzle/I64Vec/Extend.hs b/src/Geomancy/Swizzle/I64Vec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/I64Vec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.I64Vec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.I64Vec2 (I64Vec2, withI64Vec2)
+import Geomancy.I64Vec3 (I64Vec3, i64vec3, withI64Vec3)
+import Geomancy.I64Vec4 (I64Vec4, i64vec4)
+
+instance HasField "xy0" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 x y 0
+
+instance HasField "xy1" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 x y 1
+
+instance HasField "xy00" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y 0 0
+
+instance HasField "xy01" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y 0 1
+
+instance HasField "xy10" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y 1 0
+
+instance HasField "xy11" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y 1 1
+
+instance HasField "xyz0" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y z 0
+
+instance HasField "xyz1" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y z 1
diff --git a/src/Geomancy/Swizzle/I64Vec/Shuffle.hs b/src/Geomancy/Swizzle/I64Vec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/I64Vec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.I64Vec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.I64Vec2 (I64Vec2, i64vec2, withI64Vec2)
+import Geomancy.I64Vec3 (I64Vec3, i64vec3, withI64Vec3)
+import Geomancy.I64Vec4 (I64Vec4, i64vec4, withI64Vec4)
+
+instance HasField "xx" I64Vec2 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x _ -> i64vec2 x x
+
+instance HasField "xy" I64Vec2 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" I64Vec2 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec2 y x
+
+instance HasField "yy" I64Vec2 I64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \_ y -> i64vec2 y y
+
+instance HasField "xxx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ _ -> i64vec3 x x x
+
+instance HasField "xxy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 x x y
+
+instance HasField "xxz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 x x z
+
+instance HasField "xyx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 x y x
+
+instance HasField "xyy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 x y y
+
+instance HasField "xyz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 x z x
+
+instance HasField "xzy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec3 x z y
+
+instance HasField "xzz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 x z z
+
+instance HasField "yxx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 y x x
+
+instance HasField "yxy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 y x y
+
+instance HasField "yxz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec3 y x z
+
+instance HasField "yyx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec3 y y x
+
+instance HasField "yyy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y _ -> i64vec3 y y y
+
+instance HasField "yyz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 y y z
+
+instance HasField "yzx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec3 y z x
+
+instance HasField "yzy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 y z y
+
+instance HasField "yzz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 y z z
+
+instance HasField "zxx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 z x x
+
+instance HasField "zxy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec3 z x y
+
+instance HasField "zxz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 z x z
+
+instance HasField "zyx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec3 z y x
+
+instance HasField "zyy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 z y y
+
+instance HasField "zyz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 z y z
+
+instance HasField "zzx" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec3 z z x
+
+instance HasField "zzy" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec3 z z y
+
+instance HasField "zzz" I64Vec3 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ _ z -> i64vec3 z z z
+
+instance HasField "xxxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ _ -> i64vec4 x x x x
+
+instance HasField "xxxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x x x y
+
+instance HasField "xxxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x x x z
+
+instance HasField "xxxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x x x w
+
+instance HasField "xxyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x x y x
+
+instance HasField "xxyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x x y y
+
+instance HasField "xxyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x x y z
+
+instance HasField "xxyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x x y w
+
+instance HasField "xxzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x x z x
+
+instance HasField "xxzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x x z y
+
+instance HasField "xxzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x x z z
+
+instance HasField "xxzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x x z w
+
+instance HasField "xxwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x x w x
+
+instance HasField "xxwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x x w y
+
+instance HasField "xxwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x x w z
+
+instance HasField "xxww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x x w w
+
+instance HasField "xyxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x y x x
+
+instance HasField "xyxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x y x y
+
+instance HasField "xyxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x y x z
+
+instance HasField "xyxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x y x w
+
+instance HasField "xyyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x y y x
+
+instance HasField "xyyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 x y y y
+
+instance HasField "xyyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x y y z
+
+instance HasField "xyyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x y y w
+
+instance HasField "xyzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x y z x
+
+instance HasField "xyzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x y z y
+
+instance HasField "xyzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x y z z
+
+instance HasField "xyzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x y w x
+
+instance HasField "xywy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x y w y
+
+instance HasField "xywz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 x y w z
+
+instance HasField "xyww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x y w w
+
+instance HasField "xzxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x z x x
+
+instance HasField "xzxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x z x y
+
+instance HasField "xzxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x z x z
+
+instance HasField "xzxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x z x w
+
+instance HasField "xzyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x z y x
+
+instance HasField "xzyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x z y y
+
+instance HasField "xzyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x z y z
+
+instance HasField "xzyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 x z y w
+
+instance HasField "xzzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x z z x
+
+instance HasField "xzzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 x z z y
+
+instance HasField "xzzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 x z z z
+
+instance HasField "xzzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x z z w
+
+instance HasField "xzwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x z w x
+
+instance HasField "xzwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 x z w y
+
+instance HasField "xzwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x z w z
+
+instance HasField "xzww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x z w w
+
+instance HasField "xwxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x w x x
+
+instance HasField "xwxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x w x y
+
+instance HasField "xwxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x w x z
+
+instance HasField "xwxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x w x w
+
+instance HasField "xwyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x w y x
+
+instance HasField "xwyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x w y y
+
+instance HasField "xwyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 x w y z
+
+instance HasField "xwyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x w y w
+
+instance HasField "xwzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x w z x
+
+instance HasField "xwzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 x w z y
+
+instance HasField "xwzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x w z z
+
+instance HasField "xwzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x w z w
+
+instance HasField "xwwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x w w x
+
+instance HasField "xwwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 x w w y
+
+instance HasField "xwwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 x w w z
+
+instance HasField "xwww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 x w w w
+
+instance HasField "yxxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y x x x
+
+instance HasField "yxxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y x x y
+
+instance HasField "yxxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y x x z
+
+instance HasField "yxxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y x x w
+
+instance HasField "yxyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y x y x
+
+instance HasField "yxyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y x y y
+
+instance HasField "yxyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y x y z
+
+instance HasField "yxyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y x y w
+
+instance HasField "yxzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y x z x
+
+instance HasField "yxzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y x z y
+
+instance HasField "yxzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y x z z
+
+instance HasField "yxzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y x z w
+
+instance HasField "yxwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y x w x
+
+instance HasField "yxwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y x w y
+
+instance HasField "yxwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y x w z
+
+instance HasField "yxww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y x w w
+
+instance HasField "yyxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y y x x
+
+instance HasField "yyxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y y x y
+
+instance HasField "yyxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y y x z
+
+instance HasField "yyxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y y x w
+
+instance HasField "yyyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ _ -> i64vec4 y y y x
+
+instance HasField "yyyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ _ -> i64vec4 y y y y
+
+instance HasField "yyyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y y y z
+
+instance HasField "yyyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y y y w
+
+instance HasField "yyzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y y z x
+
+instance HasField "yyzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y y z y
+
+instance HasField "yyzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y y z z
+
+instance HasField "yyzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y y z w
+
+instance HasField "yywx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y y w x
+
+instance HasField "yywy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y y w y
+
+instance HasField "yywz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y y w z
+
+instance HasField "yyww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y y w w
+
+instance HasField "yzxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y z x x
+
+instance HasField "yzxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y z x y
+
+instance HasField "yzxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y z x z
+
+instance HasField "yzxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y z x w
+
+instance HasField "yzyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y z y x
+
+instance HasField "yzyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y z y y
+
+instance HasField "yzyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y z y z
+
+instance HasField "yzyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y z y w
+
+instance HasField "yzzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 y z z x
+
+instance HasField "yzzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y z z y
+
+instance HasField "yzzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 y z z z
+
+instance HasField "yzzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y z z w
+
+instance HasField "yzwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y z w x
+
+instance HasField "yzwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y z w y
+
+instance HasField "yzwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y z w z
+
+instance HasField "yzww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y z w w
+
+instance HasField "ywxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y w x x
+
+instance HasField "ywxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y w x y
+
+instance HasField "ywxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y w x z
+
+instance HasField "ywxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y w x w
+
+instance HasField "ywyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y w y x
+
+instance HasField "ywyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y w y y
+
+instance HasField "ywyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y w y z
+
+instance HasField "ywyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y w y w
+
+instance HasField "ywzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 y w z x
+
+instance HasField "ywzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y w z y
+
+instance HasField "ywzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y w z z
+
+instance HasField "ywzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y w z w
+
+instance HasField "ywwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 y w w x
+
+instance HasField "ywwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y w w y
+
+instance HasField "ywwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 y w w z
+
+instance HasField "ywww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 y w w w
+
+instance HasField "zxxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z x x x
+
+instance HasField "zxxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z x x y
+
+instance HasField "zxxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z x x z
+
+instance HasField "zxxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z x x w
+
+instance HasField "zxyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z x y x
+
+instance HasField "zxyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z x y y
+
+instance HasField "zxyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z x y z
+
+instance HasField "zxyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z x y w
+
+instance HasField "zxzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z x z x
+
+instance HasField "zxzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z x z y
+
+instance HasField "zxzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z x z z
+
+instance HasField "zxzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z x z w
+
+instance HasField "zxwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z x w x
+
+instance HasField "zxwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z x w y
+
+instance HasField "zxwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z x w z
+
+instance HasField "zxww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z x w w
+
+instance HasField "zyxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z y x x
+
+instance HasField "zyxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z y x y
+
+instance HasField "zyxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z y x z
+
+instance HasField "zyxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z y x w
+
+instance HasField "zyyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z y y x
+
+instance HasField "zyyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z y y y
+
+instance HasField "zyyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z y y z
+
+instance HasField "zyyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z y y w
+
+instance HasField "zyzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z y z x
+
+instance HasField "zyzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z y z y
+
+instance HasField "zyzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z y z z
+
+instance HasField "zyzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z y z w
+
+instance HasField "zywx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z y w x
+
+instance HasField "zywy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z y w y
+
+instance HasField "zywz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z y w z
+
+instance HasField "zyww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z y w w
+
+instance HasField "zzxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z z x x
+
+instance HasField "zzxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z z x y
+
+instance HasField "zzxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z z x z
+
+instance HasField "zzxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z z x w
+
+instance HasField "zzyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z _ -> i64vec4 z z y x
+
+instance HasField "zzyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z z y y
+
+instance HasField "zzyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z z y z
+
+instance HasField "zzyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z z y w
+
+instance HasField "zzzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z _ -> i64vec4 z z z x
+
+instance HasField "zzzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z _ -> i64vec4 z z z y
+
+instance HasField "zzzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z _ -> i64vec4 z z z z
+
+instance HasField "zzzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z z z w
+
+instance HasField "zzwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z z w x
+
+instance HasField "zzwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z z w y
+
+instance HasField "zzwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z z w z
+
+instance HasField "zzww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z z w w
+
+instance HasField "zwxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z w x x
+
+instance HasField "zwxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z w x y
+
+instance HasField "zwxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z w x z
+
+instance HasField "zwxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z w x w
+
+instance HasField "zwyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 z w y x
+
+instance HasField "zwyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z w y y
+
+instance HasField "zwyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z w y z
+
+instance HasField "zwyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z w y w
+
+instance HasField "zwzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z w z x
+
+instance HasField "zwzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z w z y
+
+instance HasField "zwzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z w z z
+
+instance HasField "zwzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z w z w
+
+instance HasField "zwwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 z w w x
+
+instance HasField "zwwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 z w w y
+
+instance HasField "zwwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z w w z
+
+instance HasField "zwww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 z w w w
+
+instance HasField "wxxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w x x x
+
+instance HasField "wxxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w x x y
+
+instance HasField "wxxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w x x z
+
+instance HasField "wxxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w x x w
+
+instance HasField "wxyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w x y x
+
+instance HasField "wxyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w x y y
+
+instance HasField "wxyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w x y z
+
+instance HasField "wxyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w x y w
+
+instance HasField "wxzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w x z x
+
+instance HasField "wxzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w x z y
+
+instance HasField "wxzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w x z z
+
+instance HasField "wxzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w x z w
+
+instance HasField "wxwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w x w x
+
+instance HasField "wxwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w x w y
+
+instance HasField "wxwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w x w z
+
+instance HasField "wxww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w x w w
+
+instance HasField "wyxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w y x x
+
+instance HasField "wyxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w y x y
+
+instance HasField "wyxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w y x z
+
+instance HasField "wyxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w y x w
+
+instance HasField "wyyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w y y x
+
+instance HasField "wyyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w y y y
+
+instance HasField "wyyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w y y z
+
+instance HasField "wyyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w y y w
+
+instance HasField "wyzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w y z x
+
+instance HasField "wyzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w y z y
+
+instance HasField "wyzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w y z z
+
+instance HasField "wyzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w y z w
+
+instance HasField "wywx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w y w x
+
+instance HasField "wywy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w y w y
+
+instance HasField "wywz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w y w z
+
+instance HasField "wyww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w y w w
+
+instance HasField "wzxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w z x x
+
+instance HasField "wzxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w z x y
+
+instance HasField "wzxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w z x z
+
+instance HasField "wzxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w z x w
+
+instance HasField "wzyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y z w -> i64vec4 w z y x
+
+instance HasField "wzyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w z y y
+
+instance HasField "wzyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w z y z
+
+instance HasField "wzyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w z y w
+
+instance HasField "wzzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w z z x
+
+instance HasField "wzzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w z z y
+
+instance HasField "wzzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w z z z
+
+instance HasField "wzzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w z z w
+
+instance HasField "wzwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w z w x
+
+instance HasField "wzwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w z w y
+
+instance HasField "wzwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w z w z
+
+instance HasField "wzww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w z w w
+
+instance HasField "wwxx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w w x x
+
+instance HasField "wwxy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w w x y
+
+instance HasField "wwxz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w w x z
+
+instance HasField "wwxw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w w x w
+
+instance HasField "wwyx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x y _ w -> i64vec4 w w y x
+
+instance HasField "wwyy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w w y y
+
+instance HasField "wwyz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w w y z
+
+instance HasField "wwyw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w w y w
+
+instance HasField "wwzx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ z w -> i64vec4 w w z x
+
+instance HasField "wwzy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y z w -> i64vec4 w w z y
+
+instance HasField "wwzz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w w z z
+
+instance HasField "wwzw" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w w z w
+
+instance HasField "wwwx" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \x _ _ w -> i64vec4 w w w x
+
+instance HasField "wwwy" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ y _ w -> i64vec4 w w w y
+
+instance HasField "wwwz" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ z w -> i64vec4 w w w z
+
+instance HasField "wwww" I64Vec4 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec4 v \_ _ _ w -> i64vec4 w w w w
diff --git a/src/Geomancy/Swizzle/I64Vec/Up.hs b/src/Geomancy/Swizzle/I64Vec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/I64Vec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.I64Vec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.I64Vec2 (I64Vec2, withI64Vec2)
+import Geomancy.I64Vec3 (I64Vec3, i64vec3, withI64Vec3)
+import Geomancy.I64Vec4 (I64Vec4, i64vec4)
+
+instance HasField "xxx" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x _ -> i64vec3 x x x
+
+instance HasField "xxy" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 x x y
+
+instance HasField "xyx" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 x y x
+
+instance HasField "xyy" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 x y y
+
+instance HasField "yxx" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 y x x
+
+instance HasField "yxy" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 y x y
+
+instance HasField "yyx" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec3 y y x
+
+instance HasField "yyy" I64Vec2 I64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \_ y -> i64vec3 y y y
+
+instance HasField "xxxx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x _ -> i64vec4 x x x x
+
+instance HasField "xxxy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x x x y
+
+instance HasField "xxyx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x x y x
+
+instance HasField "xxyy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x x y y
+
+instance HasField "xyxx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y x x
+
+instance HasField "xyxy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y x y
+
+instance HasField "xyyx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y y x
+
+instance HasField "xyyy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 x y y y
+
+instance HasField "yxxx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y x x x
+
+instance HasField "yxxy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y x x y
+
+instance HasField "yxyx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y x y x
+
+instance HasField "yxyy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y x y y
+
+instance HasField "yyxx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y y x x
+
+instance HasField "yyxy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y y x y
+
+instance HasField "yyyx" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \x y -> i64vec4 y y y x
+
+instance HasField "yyyy" I64Vec2 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec2 v \_ y -> i64vec4 y y y y
+
+instance HasField "xxxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ _ -> i64vec4 x x x x
+
+instance HasField "xxxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x x x y
+
+instance HasField "xxxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x x x z
+
+instance HasField "xxyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x x y x
+
+instance HasField "xxyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x x y y
+
+instance HasField "xxyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x x y z
+
+instance HasField "xxzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x x z x
+
+instance HasField "xxzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x x z y
+
+instance HasField "xxzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x x z z
+
+instance HasField "xyxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x y x x
+
+instance HasField "xyxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x y x y
+
+instance HasField "xyxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y x z
+
+instance HasField "xyyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x y y x
+
+instance HasField "xyyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 x y y y
+
+instance HasField "xyyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y y z
+
+instance HasField "xyzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y z x
+
+instance HasField "xyzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y z y
+
+instance HasField "xyzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x y z z
+
+instance HasField "xzxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x z x x
+
+instance HasField "xzxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x z x y
+
+instance HasField "xzxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x z x z
+
+instance HasField "xzyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x z y x
+
+instance HasField "xzyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x z y y
+
+instance HasField "xzyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x z y z
+
+instance HasField "xzzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x z z x
+
+instance HasField "xzzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 x z z y
+
+instance HasField "xzzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 x z z z
+
+instance HasField "yxxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y x x x
+
+instance HasField "yxxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y x x y
+
+instance HasField "yxxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y x x z
+
+instance HasField "yxyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y x y x
+
+instance HasField "yxyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y x y y
+
+instance HasField "yxyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y x y z
+
+instance HasField "yxzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y x z x
+
+instance HasField "yxzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y x z y
+
+instance HasField "yxzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y x z z
+
+instance HasField "yyxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y y x x
+
+instance HasField "yyxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y y x y
+
+instance HasField "yyxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y y x z
+
+instance HasField "yyyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y _ -> i64vec4 y y y x
+
+instance HasField "yyyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y _ -> i64vec4 y y y y
+
+instance HasField "yyyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y y y z
+
+instance HasField "yyzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y y z x
+
+instance HasField "yyzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y y z y
+
+instance HasField "yyzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y y z z
+
+instance HasField "yzxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y z x x
+
+instance HasField "yzxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y z x y
+
+instance HasField "yzxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y z x z
+
+instance HasField "yzyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y z y x
+
+instance HasField "yzyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y z y y
+
+instance HasField "yzyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y z y z
+
+instance HasField "yzzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 y z z x
+
+instance HasField "yzzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y z z y
+
+instance HasField "yzzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 y z z z
+
+instance HasField "zxxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z x x x
+
+instance HasField "zxxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z x x y
+
+instance HasField "zxxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z x x z
+
+instance HasField "zxyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z x y x
+
+instance HasField "zxyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z x y y
+
+instance HasField "zxyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z x y z
+
+instance HasField "zxzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z x z x
+
+instance HasField "zxzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z x z y
+
+instance HasField "zxzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z x z z
+
+instance HasField "zyxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z y x x
+
+instance HasField "zyxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z y x y
+
+instance HasField "zyxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z y x z
+
+instance HasField "zyyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z y y x
+
+instance HasField "zyyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z y y y
+
+instance HasField "zyyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z y y z
+
+instance HasField "zyzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z y z x
+
+instance HasField "zyzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z y z y
+
+instance HasField "zyzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z y z z
+
+instance HasField "zzxx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z z x x
+
+instance HasField "zzxy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z z x y
+
+instance HasField "zzxz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z z x z
+
+instance HasField "zzyx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x y z -> i64vec4 z z y x
+
+instance HasField "zzyy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z z y y
+
+instance HasField "zzyz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z z y z
+
+instance HasField "zzzx" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \x _ z -> i64vec4 z z z x
+
+instance HasField "zzzy" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ y z -> i64vec4 z z z y
+
+instance HasField "zzzz" I64Vec3 I64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withI64Vec3 v \_ _ z -> i64vec4 z z z z
diff --git a/src/Geomancy/Swizzle/IVec/Down.hs b/src/Geomancy/Swizzle/IVec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/IVec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.IVec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.IVec2 (IVec2, ivec2)
+import Geomancy.IVec3 (IVec3, ivec3, withIVec3)
+import Geomancy.IVec4 (IVec4, withIVec4)
+
+instance HasField "xx" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ _ -> ivec2 x x
+
+instance HasField "xy" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec2 x y
+
+instance HasField "xz" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec2 x z
+
+instance HasField "yx" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec2 y x
+
+instance HasField "yy" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y _ -> ivec2 y y
+
+instance HasField "yz" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec2 y z
+
+instance HasField "zx" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec2 z x
+
+instance HasField "zy" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec2 z y
+
+instance HasField "zz" IVec3 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ _ z -> ivec2 z z
+
+instance HasField "xx" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ _ -> ivec2 x x
+
+instance HasField "xy" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec2 x y
+
+instance HasField "xz" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec2 x z
+
+instance HasField "xw" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec2 x w
+
+instance HasField "yx" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec2 y x
+
+instance HasField "yy" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ _ -> ivec2 y y
+
+instance HasField "yz" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec2 y z
+
+instance HasField "yw" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec2 y w
+
+instance HasField "zx" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec2 z x
+
+instance HasField "zy" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec2 z y
+
+instance HasField "zz" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z _ -> ivec2 z z
+
+instance HasField "zw" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec2 z w
+
+instance HasField "wx" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec2 w x
+
+instance HasField "wy" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec2 w y
+
+instance HasField "wz" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec2 w z
+
+instance HasField "ww" IVec4 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ _ w -> ivec2 w w
+
+instance HasField "xxx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ _ -> ivec3 x x x
+
+instance HasField "xxy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 x x y
+
+instance HasField "xxz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 x x z
+
+instance HasField "xxw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 x x w
+
+instance HasField "xyx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 x y x
+
+instance HasField "xyy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 x y y
+
+instance HasField "xyz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 x y z
+
+instance HasField "xyw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 x y w
+
+instance HasField "xzx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 x z x
+
+instance HasField "xzy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 x z y
+
+instance HasField "xzz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 x z z
+
+instance HasField "xzw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 x z w
+
+instance HasField "xwx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 x w x
+
+instance HasField "xwy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 x w y
+
+instance HasField "xwz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 x w z
+
+instance HasField "xww" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 x w w
+
+instance HasField "yxx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 y x x
+
+instance HasField "yxy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 y x y
+
+instance HasField "yxz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 y x z
+
+instance HasField "yxw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 y x w
+
+instance HasField "yyx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec3 y y x
+
+instance HasField "yyy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ _ -> ivec3 y y y
+
+instance HasField "yyz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 y y z
+
+instance HasField "yyw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 y y w
+
+instance HasField "yzx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 y z x
+
+instance HasField "yzy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 y z y
+
+instance HasField "yzz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 y z z
+
+instance HasField "yzw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 y z w
+
+instance HasField "ywx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 y w x
+
+instance HasField "ywy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 y w y
+
+instance HasField "ywz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 y w z
+
+instance HasField "yww" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 y w w
+
+instance HasField "zxx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 z x x
+
+instance HasField "zxy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 z x y
+
+instance HasField "zxz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 z x z
+
+instance HasField "zxw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 z x w
+
+instance HasField "zyx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec3 z y x
+
+instance HasField "zyy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 z y y
+
+instance HasField "zyz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 z y z
+
+instance HasField "zyw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 z y w
+
+instance HasField "zzx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec3 z z x
+
+instance HasField "zzy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec3 z z y
+
+instance HasField "zzz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z _ -> ivec3 z z z
+
+instance HasField "zzw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 z z w
+
+instance HasField "zwx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 z w x
+
+instance HasField "zwy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 z w y
+
+instance HasField "zwz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 z w z
+
+instance HasField "zww" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 z w w
+
+instance HasField "wxx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 w x x
+
+instance HasField "wxy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 w x y
+
+instance HasField "wxz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 w x z
+
+instance HasField "wxw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 w x w
+
+instance HasField "wyx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec3 w y x
+
+instance HasField "wyy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 w y y
+
+instance HasField "wyz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 w y z
+
+instance HasField "wyw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 w y w
+
+instance HasField "wzx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec3 w z x
+
+instance HasField "wzy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec3 w z y
+
+instance HasField "wzz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 w z z
+
+instance HasField "wzw" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 w z w
+
+instance HasField "wwx" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec3 w w x
+
+instance HasField "wwy" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec3 w w y
+
+instance HasField "wwz" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec3 w w z
+
+instance HasField "www" IVec4 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ _ w -> ivec3 w w w
diff --git a/src/Geomancy/Swizzle/IVec/Extend.hs b/src/Geomancy/Swizzle/IVec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/IVec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.IVec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.IVec2 (IVec2, withIVec2)
+import Geomancy.IVec3 (IVec3, ivec3, withIVec3)
+import Geomancy.IVec4 (IVec4, ivec4)
+
+instance HasField "xy0" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 x y 0
+
+instance HasField "xy1" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 x y 1
+
+instance HasField "xy00" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y 0 0
+
+instance HasField "xy01" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y 0 1
+
+instance HasField "xy10" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y 1 0
+
+instance HasField "xy11" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y 1 1
+
+instance HasField "xyz0" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y z 0
+
+instance HasField "xyz1" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y z 1
diff --git a/src/Geomancy/Swizzle/IVec/Shuffle.hs b/src/Geomancy/Swizzle/IVec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/IVec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.IVec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.IVec2 (IVec2, ivec2, withIVec2)
+import Geomancy.IVec3 (IVec3, ivec3, withIVec3)
+import Geomancy.IVec4 (IVec4, ivec4, withIVec4)
+
+instance HasField "xx" IVec2 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x _ -> ivec2 x x
+
+instance HasField "xy" IVec2 IVec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" IVec2 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec2 y x
+
+instance HasField "yy" IVec2 IVec2 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \_ y -> ivec2 y y
+
+instance HasField "xxx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ _ -> ivec3 x x x
+
+instance HasField "xxy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 x x y
+
+instance HasField "xxz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 x x z
+
+instance HasField "xyx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 x y x
+
+instance HasField "xyy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 x y y
+
+instance HasField "xyz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 x z x
+
+instance HasField "xzy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec3 x z y
+
+instance HasField "xzz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 x z z
+
+instance HasField "yxx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 y x x
+
+instance HasField "yxy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 y x y
+
+instance HasField "yxz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec3 y x z
+
+instance HasField "yyx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec3 y y x
+
+instance HasField "yyy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y _ -> ivec3 y y y
+
+instance HasField "yyz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 y y z
+
+instance HasField "yzx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec3 y z x
+
+instance HasField "yzy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 y z y
+
+instance HasField "yzz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 y z z
+
+instance HasField "zxx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 z x x
+
+instance HasField "zxy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec3 z x y
+
+instance HasField "zxz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 z x z
+
+instance HasField "zyx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec3 z y x
+
+instance HasField "zyy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 z y y
+
+instance HasField "zyz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 z y z
+
+instance HasField "zzx" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec3 z z x
+
+instance HasField "zzy" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec3 z z y
+
+instance HasField "zzz" IVec3 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ _ z -> ivec3 z z z
+
+instance HasField "xxxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ _ -> ivec4 x x x x
+
+instance HasField "xxxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x x x y
+
+instance HasField "xxxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x x x z
+
+instance HasField "xxxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x x x w
+
+instance HasField "xxyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x x y x
+
+instance HasField "xxyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x x y y
+
+instance HasField "xxyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x x y z
+
+instance HasField "xxyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x x y w
+
+instance HasField "xxzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x x z x
+
+instance HasField "xxzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x x z y
+
+instance HasField "xxzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x x z z
+
+instance HasField "xxzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x x z w
+
+instance HasField "xxwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x x w x
+
+instance HasField "xxwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x x w y
+
+instance HasField "xxwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x x w z
+
+instance HasField "xxww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x x w w
+
+instance HasField "xyxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x y x x
+
+instance HasField "xyxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x y x y
+
+instance HasField "xyxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x y x z
+
+instance HasField "xyxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x y x w
+
+instance HasField "xyyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x y y x
+
+instance HasField "xyyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 x y y y
+
+instance HasField "xyyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x y y z
+
+instance HasField "xyyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x y y w
+
+instance HasField "xyzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x y z x
+
+instance HasField "xyzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x y z y
+
+instance HasField "xyzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x y z z
+
+instance HasField "xyzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x y w x
+
+instance HasField "xywy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x y w y
+
+instance HasField "xywz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 x y w z
+
+instance HasField "xyww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x y w w
+
+instance HasField "xzxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x z x x
+
+instance HasField "xzxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x z x y
+
+instance HasField "xzxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x z x z
+
+instance HasField "xzxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x z x w
+
+instance HasField "xzyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x z y x
+
+instance HasField "xzyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x z y y
+
+instance HasField "xzyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x z y z
+
+instance HasField "xzyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 x z y w
+
+instance HasField "xzzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x z z x
+
+instance HasField "xzzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 x z z y
+
+instance HasField "xzzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 x z z z
+
+instance HasField "xzzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x z z w
+
+instance HasField "xzwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x z w x
+
+instance HasField "xzwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 x z w y
+
+instance HasField "xzwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x z w z
+
+instance HasField "xzww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x z w w
+
+instance HasField "xwxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x w x x
+
+instance HasField "xwxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x w x y
+
+instance HasField "xwxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x w x z
+
+instance HasField "xwxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x w x w
+
+instance HasField "xwyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x w y x
+
+instance HasField "xwyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x w y y
+
+instance HasField "xwyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 x w y z
+
+instance HasField "xwyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x w y w
+
+instance HasField "xwzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x w z x
+
+instance HasField "xwzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 x w z y
+
+instance HasField "xwzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x w z z
+
+instance HasField "xwzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x w z w
+
+instance HasField "xwwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x w w x
+
+instance HasField "xwwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 x w w y
+
+instance HasField "xwwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 x w w z
+
+instance HasField "xwww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 x w w w
+
+instance HasField "yxxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y x x x
+
+instance HasField "yxxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y x x y
+
+instance HasField "yxxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y x x z
+
+instance HasField "yxxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y x x w
+
+instance HasField "yxyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y x y x
+
+instance HasField "yxyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y x y y
+
+instance HasField "yxyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y x y z
+
+instance HasField "yxyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y x y w
+
+instance HasField "yxzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y x z x
+
+instance HasField "yxzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y x z y
+
+instance HasField "yxzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y x z z
+
+instance HasField "yxzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y x z w
+
+instance HasField "yxwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y x w x
+
+instance HasField "yxwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y x w y
+
+instance HasField "yxwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y x w z
+
+instance HasField "yxww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y x w w
+
+instance HasField "yyxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y y x x
+
+instance HasField "yyxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y y x y
+
+instance HasField "yyxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y y x z
+
+instance HasField "yyxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y y x w
+
+instance HasField "yyyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ _ -> ivec4 y y y x
+
+instance HasField "yyyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ _ -> ivec4 y y y y
+
+instance HasField "yyyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y y y z
+
+instance HasField "yyyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y y y w
+
+instance HasField "yyzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y y z x
+
+instance HasField "yyzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y y z y
+
+instance HasField "yyzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y y z z
+
+instance HasField "yyzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y y z w
+
+instance HasField "yywx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y y w x
+
+instance HasField "yywy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y y w y
+
+instance HasField "yywz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y y w z
+
+instance HasField "yyww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y y w w
+
+instance HasField "yzxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y z x x
+
+instance HasField "yzxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y z x y
+
+instance HasField "yzxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y z x z
+
+instance HasField "yzxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y z x w
+
+instance HasField "yzyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y z y x
+
+instance HasField "yzyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y z y y
+
+instance HasField "yzyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y z y z
+
+instance HasField "yzyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y z y w
+
+instance HasField "yzzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 y z z x
+
+instance HasField "yzzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y z z y
+
+instance HasField "yzzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 y z z z
+
+instance HasField "yzzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y z z w
+
+instance HasField "yzwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y z w x
+
+instance HasField "yzwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y z w y
+
+instance HasField "yzwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y z w z
+
+instance HasField "yzww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y z w w
+
+instance HasField "ywxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y w x x
+
+instance HasField "ywxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y w x y
+
+instance HasField "ywxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y w x z
+
+instance HasField "ywxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y w x w
+
+instance HasField "ywyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y w y x
+
+instance HasField "ywyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y w y y
+
+instance HasField "ywyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y w y z
+
+instance HasField "ywyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y w y w
+
+instance HasField "ywzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 y w z x
+
+instance HasField "ywzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y w z y
+
+instance HasField "ywzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y w z z
+
+instance HasField "ywzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y w z w
+
+instance HasField "ywwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 y w w x
+
+instance HasField "ywwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y w w y
+
+instance HasField "ywwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 y w w z
+
+instance HasField "ywww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 y w w w
+
+instance HasField "zxxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z x x x
+
+instance HasField "zxxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z x x y
+
+instance HasField "zxxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z x x z
+
+instance HasField "zxxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z x x w
+
+instance HasField "zxyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z x y x
+
+instance HasField "zxyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z x y y
+
+instance HasField "zxyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z x y z
+
+instance HasField "zxyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z x y w
+
+instance HasField "zxzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z x z x
+
+instance HasField "zxzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z x z y
+
+instance HasField "zxzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z x z z
+
+instance HasField "zxzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z x z w
+
+instance HasField "zxwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z x w x
+
+instance HasField "zxwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z x w y
+
+instance HasField "zxwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z x w z
+
+instance HasField "zxww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z x w w
+
+instance HasField "zyxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z y x x
+
+instance HasField "zyxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z y x y
+
+instance HasField "zyxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z y x z
+
+instance HasField "zyxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z y x w
+
+instance HasField "zyyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z y y x
+
+instance HasField "zyyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z y y y
+
+instance HasField "zyyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z y y z
+
+instance HasField "zyyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z y y w
+
+instance HasField "zyzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z y z x
+
+instance HasField "zyzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z y z y
+
+instance HasField "zyzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z y z z
+
+instance HasField "zyzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z y z w
+
+instance HasField "zywx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z y w x
+
+instance HasField "zywy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z y w y
+
+instance HasField "zywz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z y w z
+
+instance HasField "zyww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z y w w
+
+instance HasField "zzxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z z x x
+
+instance HasField "zzxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z z x y
+
+instance HasField "zzxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z z x z
+
+instance HasField "zzxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z z x w
+
+instance HasField "zzyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z _ -> ivec4 z z y x
+
+instance HasField "zzyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z z y y
+
+instance HasField "zzyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z z y z
+
+instance HasField "zzyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z z y w
+
+instance HasField "zzzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z _ -> ivec4 z z z x
+
+instance HasField "zzzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z _ -> ivec4 z z z y
+
+instance HasField "zzzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z _ -> ivec4 z z z z
+
+instance HasField "zzzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z z z w
+
+instance HasField "zzwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z z w x
+
+instance HasField "zzwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z z w y
+
+instance HasField "zzwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z z w z
+
+instance HasField "zzww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z z w w
+
+instance HasField "zwxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z w x x
+
+instance HasField "zwxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z w x y
+
+instance HasField "zwxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z w x z
+
+instance HasField "zwxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z w x w
+
+instance HasField "zwyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 z w y x
+
+instance HasField "zwyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z w y y
+
+instance HasField "zwyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z w y z
+
+instance HasField "zwyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z w y w
+
+instance HasField "zwzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z w z x
+
+instance HasField "zwzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z w z y
+
+instance HasField "zwzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z w z z
+
+instance HasField "zwzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z w z w
+
+instance HasField "zwwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 z w w x
+
+instance HasField "zwwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 z w w y
+
+instance HasField "zwwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z w w z
+
+instance HasField "zwww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 z w w w
+
+instance HasField "wxxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w x x x
+
+instance HasField "wxxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w x x y
+
+instance HasField "wxxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w x x z
+
+instance HasField "wxxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w x x w
+
+instance HasField "wxyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w x y x
+
+instance HasField "wxyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w x y y
+
+instance HasField "wxyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w x y z
+
+instance HasField "wxyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w x y w
+
+instance HasField "wxzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w x z x
+
+instance HasField "wxzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w x z y
+
+instance HasField "wxzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w x z z
+
+instance HasField "wxzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w x z w
+
+instance HasField "wxwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w x w x
+
+instance HasField "wxwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w x w y
+
+instance HasField "wxwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w x w z
+
+instance HasField "wxww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w x w w
+
+instance HasField "wyxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w y x x
+
+instance HasField "wyxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w y x y
+
+instance HasField "wyxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w y x z
+
+instance HasField "wyxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w y x w
+
+instance HasField "wyyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w y y x
+
+instance HasField "wyyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w y y y
+
+instance HasField "wyyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w y y z
+
+instance HasField "wyyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w y y w
+
+instance HasField "wyzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w y z x
+
+instance HasField "wyzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w y z y
+
+instance HasField "wyzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w y z z
+
+instance HasField "wyzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w y z w
+
+instance HasField "wywx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w y w x
+
+instance HasField "wywy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w y w y
+
+instance HasField "wywz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w y w z
+
+instance HasField "wyww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w y w w
+
+instance HasField "wzxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w z x x
+
+instance HasField "wzxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w z x y
+
+instance HasField "wzxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w z x z
+
+instance HasField "wzxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w z x w
+
+instance HasField "wzyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y z w -> ivec4 w z y x
+
+instance HasField "wzyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w z y y
+
+instance HasField "wzyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w z y z
+
+instance HasField "wzyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w z y w
+
+instance HasField "wzzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w z z x
+
+instance HasField "wzzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w z z y
+
+instance HasField "wzzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w z z z
+
+instance HasField "wzzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w z z w
+
+instance HasField "wzwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w z w x
+
+instance HasField "wzwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w z w y
+
+instance HasField "wzwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w z w z
+
+instance HasField "wzww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w z w w
+
+instance HasField "wwxx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w w x x
+
+instance HasField "wwxy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w w x y
+
+instance HasField "wwxz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w w x z
+
+instance HasField "wwxw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w w x w
+
+instance HasField "wwyx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x y _ w -> ivec4 w w y x
+
+instance HasField "wwyy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w w y y
+
+instance HasField "wwyz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w w y z
+
+instance HasField "wwyw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w w y w
+
+instance HasField "wwzx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ z w -> ivec4 w w z x
+
+instance HasField "wwzy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y z w -> ivec4 w w z y
+
+instance HasField "wwzz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w w z z
+
+instance HasField "wwzw" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w w z w
+
+instance HasField "wwwx" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \x _ _ w -> ivec4 w w w x
+
+instance HasField "wwwy" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ y _ w -> ivec4 w w w y
+
+instance HasField "wwwz" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ z w -> ivec4 w w w z
+
+instance HasField "wwww" IVec4 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec4 v \_ _ _ w -> ivec4 w w w w
diff --git a/src/Geomancy/Swizzle/IVec/Up.hs b/src/Geomancy/Swizzle/IVec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/IVec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.IVec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.IVec2 (IVec2, withIVec2)
+import Geomancy.IVec3 (IVec3, ivec3, withIVec3)
+import Geomancy.IVec4 (IVec4, ivec4)
+
+instance HasField "xxx" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x _ -> ivec3 x x x
+
+instance HasField "xxy" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 x x y
+
+instance HasField "xyx" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 x y x
+
+instance HasField "xyy" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 x y y
+
+instance HasField "yxx" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 y x x
+
+instance HasField "yxy" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 y x y
+
+instance HasField "yyx" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec3 y y x
+
+instance HasField "yyy" IVec2 IVec3 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \_ y -> ivec3 y y y
+
+instance HasField "xxxx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x _ -> ivec4 x x x x
+
+instance HasField "xxxy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x x x y
+
+instance HasField "xxyx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x x y x
+
+instance HasField "xxyy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x x y y
+
+instance HasField "xyxx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y x x
+
+instance HasField "xyxy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y x y
+
+instance HasField "xyyx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y y x
+
+instance HasField "xyyy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 x y y y
+
+instance HasField "yxxx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y x x x
+
+instance HasField "yxxy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y x x y
+
+instance HasField "yxyx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y x y x
+
+instance HasField "yxyy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y x y y
+
+instance HasField "yyxx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y y x x
+
+instance HasField "yyxy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y y x y
+
+instance HasField "yyyx" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \x y -> ivec4 y y y x
+
+instance HasField "yyyy" IVec2 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec2 v \_ y -> ivec4 y y y y
+
+instance HasField "xxxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ _ -> ivec4 x x x x
+
+instance HasField "xxxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x x x y
+
+instance HasField "xxxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x x x z
+
+instance HasField "xxyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x x y x
+
+instance HasField "xxyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x x y y
+
+instance HasField "xxyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x x y z
+
+instance HasField "xxzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x x z x
+
+instance HasField "xxzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x x z y
+
+instance HasField "xxzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x x z z
+
+instance HasField "xyxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x y x x
+
+instance HasField "xyxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x y x y
+
+instance HasField "xyxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y x z
+
+instance HasField "xyyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x y y x
+
+instance HasField "xyyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 x y y y
+
+instance HasField "xyyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y y z
+
+instance HasField "xyzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y z x
+
+instance HasField "xyzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y z y
+
+instance HasField "xyzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x y z z
+
+instance HasField "xzxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x z x x
+
+instance HasField "xzxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x z x y
+
+instance HasField "xzxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x z x z
+
+instance HasField "xzyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x z y x
+
+instance HasField "xzyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x z y y
+
+instance HasField "xzyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x z y z
+
+instance HasField "xzzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x z z x
+
+instance HasField "xzzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 x z z y
+
+instance HasField "xzzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 x z z z
+
+instance HasField "yxxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y x x x
+
+instance HasField "yxxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y x x y
+
+instance HasField "yxxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y x x z
+
+instance HasField "yxyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y x y x
+
+instance HasField "yxyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y x y y
+
+instance HasField "yxyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y x y z
+
+instance HasField "yxzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y x z x
+
+instance HasField "yxzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y x z y
+
+instance HasField "yxzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y x z z
+
+instance HasField "yyxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y y x x
+
+instance HasField "yyxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y y x y
+
+instance HasField "yyxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y y x z
+
+instance HasField "yyyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y _ -> ivec4 y y y x
+
+instance HasField "yyyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y _ -> ivec4 y y y y
+
+instance HasField "yyyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y y y z
+
+instance HasField "yyzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y y z x
+
+instance HasField "yyzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y y z y
+
+instance HasField "yyzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y y z z
+
+instance HasField "yzxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y z x x
+
+instance HasField "yzxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y z x y
+
+instance HasField "yzxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y z x z
+
+instance HasField "yzyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y z y x
+
+instance HasField "yzyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y z y y
+
+instance HasField "yzyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y z y z
+
+instance HasField "yzzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 y z z x
+
+instance HasField "yzzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y z z y
+
+instance HasField "yzzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 y z z z
+
+instance HasField "zxxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z x x x
+
+instance HasField "zxxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z x x y
+
+instance HasField "zxxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z x x z
+
+instance HasField "zxyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z x y x
+
+instance HasField "zxyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z x y y
+
+instance HasField "zxyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z x y z
+
+instance HasField "zxzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z x z x
+
+instance HasField "zxzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z x z y
+
+instance HasField "zxzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z x z z
+
+instance HasField "zyxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z y x x
+
+instance HasField "zyxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z y x y
+
+instance HasField "zyxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z y x z
+
+instance HasField "zyyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z y y x
+
+instance HasField "zyyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z y y y
+
+instance HasField "zyyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z y y z
+
+instance HasField "zyzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z y z x
+
+instance HasField "zyzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z y z y
+
+instance HasField "zyzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z y z z
+
+instance HasField "zzxx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z z x x
+
+instance HasField "zzxy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z z x y
+
+instance HasField "zzxz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z z x z
+
+instance HasField "zzyx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x y z -> ivec4 z z y x
+
+instance HasField "zzyy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z z y y
+
+instance HasField "zzyz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z z y z
+
+instance HasField "zzzx" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \x _ z -> ivec4 z z z x
+
+instance HasField "zzzy" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ y z -> ivec4 z z z y
+
+instance HasField "zzzz" IVec3 IVec4 where
+  {-# INLINE getField #-}
+  getField v = withIVec3 v \_ _ z -> ivec4 z z z z
diff --git a/src/Geomancy/Swizzle/U64Vec/Down.hs b/src/Geomancy/Swizzle/U64Vec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/U64Vec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.U64Vec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.U64Vec2 (U64Vec2, u64vec2)
+import Geomancy.U64Vec3 (U64Vec3, u64vec3, withU64Vec3)
+import Geomancy.U64Vec4 (U64Vec4, withU64Vec4)
+
+instance HasField "xx" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ _ -> u64vec2 x x
+
+instance HasField "xy" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec2 x y
+
+instance HasField "xz" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec2 x z
+
+instance HasField "yx" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec2 y x
+
+instance HasField "yy" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y _ -> u64vec2 y y
+
+instance HasField "yz" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec2 y z
+
+instance HasField "zx" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec2 z x
+
+instance HasField "zy" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec2 z y
+
+instance HasField "zz" U64Vec3 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ _ z -> u64vec2 z z
+
+instance HasField "xx" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ _ -> u64vec2 x x
+
+instance HasField "xy" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec2 x y
+
+instance HasField "xz" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec2 x z
+
+instance HasField "xw" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec2 x w
+
+instance HasField "yx" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec2 y x
+
+instance HasField "yy" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ _ -> u64vec2 y y
+
+instance HasField "yz" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec2 y z
+
+instance HasField "yw" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec2 y w
+
+instance HasField "zx" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec2 z x
+
+instance HasField "zy" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec2 z y
+
+instance HasField "zz" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z _ -> u64vec2 z z
+
+instance HasField "zw" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec2 z w
+
+instance HasField "wx" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec2 w x
+
+instance HasField "wy" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec2 w y
+
+instance HasField "wz" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec2 w z
+
+instance HasField "ww" U64Vec4 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ _ w -> u64vec2 w w
+
+instance HasField "xxx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ _ -> u64vec3 x x x
+
+instance HasField "xxy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 x x y
+
+instance HasField "xxz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 x x z
+
+instance HasField "xxw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 x x w
+
+instance HasField "xyx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 x y x
+
+instance HasField "xyy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 x y y
+
+instance HasField "xyz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 x y z
+
+instance HasField "xyw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 x y w
+
+instance HasField "xzx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 x z x
+
+instance HasField "xzy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 x z y
+
+instance HasField "xzz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 x z z
+
+instance HasField "xzw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 x z w
+
+instance HasField "xwx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 x w x
+
+instance HasField "xwy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 x w y
+
+instance HasField "xwz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 x w z
+
+instance HasField "xww" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 x w w
+
+instance HasField "yxx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 y x x
+
+instance HasField "yxy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 y x y
+
+instance HasField "yxz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 y x z
+
+instance HasField "yxw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 y x w
+
+instance HasField "yyx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec3 y y x
+
+instance HasField "yyy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ _ -> u64vec3 y y y
+
+instance HasField "yyz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 y y z
+
+instance HasField "yyw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 y y w
+
+instance HasField "yzx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 y z x
+
+instance HasField "yzy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 y z y
+
+instance HasField "yzz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 y z z
+
+instance HasField "yzw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 y z w
+
+instance HasField "ywx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 y w x
+
+instance HasField "ywy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 y w y
+
+instance HasField "ywz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 y w z
+
+instance HasField "yww" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 y w w
+
+instance HasField "zxx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 z x x
+
+instance HasField "zxy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 z x y
+
+instance HasField "zxz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 z x z
+
+instance HasField "zxw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 z x w
+
+instance HasField "zyx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec3 z y x
+
+instance HasField "zyy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 z y y
+
+instance HasField "zyz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 z y z
+
+instance HasField "zyw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 z y w
+
+instance HasField "zzx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec3 z z x
+
+instance HasField "zzy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec3 z z y
+
+instance HasField "zzz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z _ -> u64vec3 z z z
+
+instance HasField "zzw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 z z w
+
+instance HasField "zwx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 z w x
+
+instance HasField "zwy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 z w y
+
+instance HasField "zwz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 z w z
+
+instance HasField "zww" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 z w w
+
+instance HasField "wxx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 w x x
+
+instance HasField "wxy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 w x y
+
+instance HasField "wxz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 w x z
+
+instance HasField "wxw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 w x w
+
+instance HasField "wyx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec3 w y x
+
+instance HasField "wyy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 w y y
+
+instance HasField "wyz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 w y z
+
+instance HasField "wyw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 w y w
+
+instance HasField "wzx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec3 w z x
+
+instance HasField "wzy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec3 w z y
+
+instance HasField "wzz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 w z z
+
+instance HasField "wzw" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 w z w
+
+instance HasField "wwx" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec3 w w x
+
+instance HasField "wwy" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec3 w w y
+
+instance HasField "wwz" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec3 w w z
+
+instance HasField "www" U64Vec4 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ _ w -> u64vec3 w w w
diff --git a/src/Geomancy/Swizzle/U64Vec/Extend.hs b/src/Geomancy/Swizzle/U64Vec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/U64Vec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.U64Vec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.U64Vec2 (U64Vec2, withU64Vec2)
+import Geomancy.U64Vec3 (U64Vec3, u64vec3, withU64Vec3)
+import Geomancy.U64Vec4 (U64Vec4, u64vec4)
+
+instance HasField "xy0" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 x y 0
+
+instance HasField "xy1" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 x y 1
+
+instance HasField "xy00" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y 0 0
+
+instance HasField "xy01" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y 0 1
+
+instance HasField "xy10" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y 1 0
+
+instance HasField "xy11" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y 1 1
+
+instance HasField "xyz0" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y z 0
+
+instance HasField "xyz1" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y z 1
diff --git a/src/Geomancy/Swizzle/U64Vec/Shuffle.hs b/src/Geomancy/Swizzle/U64Vec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/U64Vec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.U64Vec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.U64Vec2 (U64Vec2, u64vec2, withU64Vec2)
+import Geomancy.U64Vec3 (U64Vec3, u64vec3, withU64Vec3)
+import Geomancy.U64Vec4 (U64Vec4, u64vec4, withU64Vec4)
+
+instance HasField "xx" U64Vec2 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x _ -> u64vec2 x x
+
+instance HasField "xy" U64Vec2 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" U64Vec2 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec2 y x
+
+instance HasField "yy" U64Vec2 U64Vec2 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \_ y -> u64vec2 y y
+
+instance HasField "xxx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ _ -> u64vec3 x x x
+
+instance HasField "xxy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 x x y
+
+instance HasField "xxz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 x x z
+
+instance HasField "xyx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 x y x
+
+instance HasField "xyy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 x y y
+
+instance HasField "xyz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 x z x
+
+instance HasField "xzy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec3 x z y
+
+instance HasField "xzz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 x z z
+
+instance HasField "yxx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 y x x
+
+instance HasField "yxy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 y x y
+
+instance HasField "yxz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec3 y x z
+
+instance HasField "yyx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec3 y y x
+
+instance HasField "yyy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y _ -> u64vec3 y y y
+
+instance HasField "yyz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 y y z
+
+instance HasField "yzx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec3 y z x
+
+instance HasField "yzy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 y z y
+
+instance HasField "yzz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 y z z
+
+instance HasField "zxx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 z x x
+
+instance HasField "zxy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec3 z x y
+
+instance HasField "zxz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 z x z
+
+instance HasField "zyx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec3 z y x
+
+instance HasField "zyy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 z y y
+
+instance HasField "zyz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 z y z
+
+instance HasField "zzx" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec3 z z x
+
+instance HasField "zzy" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec3 z z y
+
+instance HasField "zzz" U64Vec3 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ _ z -> u64vec3 z z z
+
+instance HasField "xxxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ _ -> u64vec4 x x x x
+
+instance HasField "xxxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x x x y
+
+instance HasField "xxxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x x x z
+
+instance HasField "xxxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x x x w
+
+instance HasField "xxyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x x y x
+
+instance HasField "xxyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x x y y
+
+instance HasField "xxyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x x y z
+
+instance HasField "xxyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x x y w
+
+instance HasField "xxzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x x z x
+
+instance HasField "xxzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x x z y
+
+instance HasField "xxzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x x z z
+
+instance HasField "xxzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x x z w
+
+instance HasField "xxwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x x w x
+
+instance HasField "xxwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x x w y
+
+instance HasField "xxwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x x w z
+
+instance HasField "xxww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x x w w
+
+instance HasField "xyxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x y x x
+
+instance HasField "xyxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x y x y
+
+instance HasField "xyxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x y x z
+
+instance HasField "xyxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x y x w
+
+instance HasField "xyyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x y y x
+
+instance HasField "xyyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 x y y y
+
+instance HasField "xyyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x y y z
+
+instance HasField "xyyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x y y w
+
+instance HasField "xyzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x y z x
+
+instance HasField "xyzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x y z y
+
+instance HasField "xyzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x y z z
+
+instance HasField "xyzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x y w x
+
+instance HasField "xywy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x y w y
+
+instance HasField "xywz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 x y w z
+
+instance HasField "xyww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x y w w
+
+instance HasField "xzxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x z x x
+
+instance HasField "xzxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x z x y
+
+instance HasField "xzxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x z x z
+
+instance HasField "xzxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x z x w
+
+instance HasField "xzyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x z y x
+
+instance HasField "xzyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x z y y
+
+instance HasField "xzyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x z y z
+
+instance HasField "xzyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 x z y w
+
+instance HasField "xzzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x z z x
+
+instance HasField "xzzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 x z z y
+
+instance HasField "xzzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 x z z z
+
+instance HasField "xzzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x z z w
+
+instance HasField "xzwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x z w x
+
+instance HasField "xzwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 x z w y
+
+instance HasField "xzwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x z w z
+
+instance HasField "xzww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x z w w
+
+instance HasField "xwxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x w x x
+
+instance HasField "xwxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x w x y
+
+instance HasField "xwxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x w x z
+
+instance HasField "xwxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x w x w
+
+instance HasField "xwyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x w y x
+
+instance HasField "xwyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x w y y
+
+instance HasField "xwyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 x w y z
+
+instance HasField "xwyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x w y w
+
+instance HasField "xwzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x w z x
+
+instance HasField "xwzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 x w z y
+
+instance HasField "xwzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x w z z
+
+instance HasField "xwzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x w z w
+
+instance HasField "xwwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x w w x
+
+instance HasField "xwwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 x w w y
+
+instance HasField "xwwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 x w w z
+
+instance HasField "xwww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 x w w w
+
+instance HasField "yxxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y x x x
+
+instance HasField "yxxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y x x y
+
+instance HasField "yxxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y x x z
+
+instance HasField "yxxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y x x w
+
+instance HasField "yxyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y x y x
+
+instance HasField "yxyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y x y y
+
+instance HasField "yxyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y x y z
+
+instance HasField "yxyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y x y w
+
+instance HasField "yxzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y x z x
+
+instance HasField "yxzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y x z y
+
+instance HasField "yxzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y x z z
+
+instance HasField "yxzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y x z w
+
+instance HasField "yxwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y x w x
+
+instance HasField "yxwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y x w y
+
+instance HasField "yxwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y x w z
+
+instance HasField "yxww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y x w w
+
+instance HasField "yyxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y y x x
+
+instance HasField "yyxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y y x y
+
+instance HasField "yyxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y y x z
+
+instance HasField "yyxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y y x w
+
+instance HasField "yyyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ _ -> u64vec4 y y y x
+
+instance HasField "yyyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ _ -> u64vec4 y y y y
+
+instance HasField "yyyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y y y z
+
+instance HasField "yyyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y y y w
+
+instance HasField "yyzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y y z x
+
+instance HasField "yyzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y y z y
+
+instance HasField "yyzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y y z z
+
+instance HasField "yyzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y y z w
+
+instance HasField "yywx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y y w x
+
+instance HasField "yywy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y y w y
+
+instance HasField "yywz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y y w z
+
+instance HasField "yyww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y y w w
+
+instance HasField "yzxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y z x x
+
+instance HasField "yzxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y z x y
+
+instance HasField "yzxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y z x z
+
+instance HasField "yzxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y z x w
+
+instance HasField "yzyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y z y x
+
+instance HasField "yzyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y z y y
+
+instance HasField "yzyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y z y z
+
+instance HasField "yzyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y z y w
+
+instance HasField "yzzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 y z z x
+
+instance HasField "yzzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y z z y
+
+instance HasField "yzzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 y z z z
+
+instance HasField "yzzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y z z w
+
+instance HasField "yzwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y z w x
+
+instance HasField "yzwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y z w y
+
+instance HasField "yzwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y z w z
+
+instance HasField "yzww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y z w w
+
+instance HasField "ywxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y w x x
+
+instance HasField "ywxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y w x y
+
+instance HasField "ywxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y w x z
+
+instance HasField "ywxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y w x w
+
+instance HasField "ywyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y w y x
+
+instance HasField "ywyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y w y y
+
+instance HasField "ywyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y w y z
+
+instance HasField "ywyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y w y w
+
+instance HasField "ywzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 y w z x
+
+instance HasField "ywzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y w z y
+
+instance HasField "ywzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y w z z
+
+instance HasField "ywzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y w z w
+
+instance HasField "ywwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 y w w x
+
+instance HasField "ywwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y w w y
+
+instance HasField "ywwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 y w w z
+
+instance HasField "ywww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 y w w w
+
+instance HasField "zxxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z x x x
+
+instance HasField "zxxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z x x y
+
+instance HasField "zxxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z x x z
+
+instance HasField "zxxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z x x w
+
+instance HasField "zxyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z x y x
+
+instance HasField "zxyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z x y y
+
+instance HasField "zxyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z x y z
+
+instance HasField "zxyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z x y w
+
+instance HasField "zxzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z x z x
+
+instance HasField "zxzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z x z y
+
+instance HasField "zxzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z x z z
+
+instance HasField "zxzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z x z w
+
+instance HasField "zxwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z x w x
+
+instance HasField "zxwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z x w y
+
+instance HasField "zxwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z x w z
+
+instance HasField "zxww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z x w w
+
+instance HasField "zyxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z y x x
+
+instance HasField "zyxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z y x y
+
+instance HasField "zyxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z y x z
+
+instance HasField "zyxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z y x w
+
+instance HasField "zyyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z y y x
+
+instance HasField "zyyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z y y y
+
+instance HasField "zyyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z y y z
+
+instance HasField "zyyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z y y w
+
+instance HasField "zyzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z y z x
+
+instance HasField "zyzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z y z y
+
+instance HasField "zyzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z y z z
+
+instance HasField "zyzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z y z w
+
+instance HasField "zywx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z y w x
+
+instance HasField "zywy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z y w y
+
+instance HasField "zywz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z y w z
+
+instance HasField "zyww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z y w w
+
+instance HasField "zzxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z z x x
+
+instance HasField "zzxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z z x y
+
+instance HasField "zzxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z z x z
+
+instance HasField "zzxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z z x w
+
+instance HasField "zzyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z _ -> u64vec4 z z y x
+
+instance HasField "zzyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z z y y
+
+instance HasField "zzyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z z y z
+
+instance HasField "zzyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z z y w
+
+instance HasField "zzzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z _ -> u64vec4 z z z x
+
+instance HasField "zzzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z _ -> u64vec4 z z z y
+
+instance HasField "zzzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z _ -> u64vec4 z z z z
+
+instance HasField "zzzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z z z w
+
+instance HasField "zzwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z z w x
+
+instance HasField "zzwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z z w y
+
+instance HasField "zzwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z z w z
+
+instance HasField "zzww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z z w w
+
+instance HasField "zwxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z w x x
+
+instance HasField "zwxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z w x y
+
+instance HasField "zwxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z w x z
+
+instance HasField "zwxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z w x w
+
+instance HasField "zwyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 z w y x
+
+instance HasField "zwyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z w y y
+
+instance HasField "zwyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z w y z
+
+instance HasField "zwyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z w y w
+
+instance HasField "zwzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z w z x
+
+instance HasField "zwzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z w z y
+
+instance HasField "zwzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z w z z
+
+instance HasField "zwzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z w z w
+
+instance HasField "zwwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 z w w x
+
+instance HasField "zwwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 z w w y
+
+instance HasField "zwwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z w w z
+
+instance HasField "zwww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 z w w w
+
+instance HasField "wxxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w x x x
+
+instance HasField "wxxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w x x y
+
+instance HasField "wxxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w x x z
+
+instance HasField "wxxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w x x w
+
+instance HasField "wxyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w x y x
+
+instance HasField "wxyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w x y y
+
+instance HasField "wxyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w x y z
+
+instance HasField "wxyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w x y w
+
+instance HasField "wxzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w x z x
+
+instance HasField "wxzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w x z y
+
+instance HasField "wxzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w x z z
+
+instance HasField "wxzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w x z w
+
+instance HasField "wxwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w x w x
+
+instance HasField "wxwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w x w y
+
+instance HasField "wxwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w x w z
+
+instance HasField "wxww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w x w w
+
+instance HasField "wyxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w y x x
+
+instance HasField "wyxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w y x y
+
+instance HasField "wyxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w y x z
+
+instance HasField "wyxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w y x w
+
+instance HasField "wyyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w y y x
+
+instance HasField "wyyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w y y y
+
+instance HasField "wyyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w y y z
+
+instance HasField "wyyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w y y w
+
+instance HasField "wyzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w y z x
+
+instance HasField "wyzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w y z y
+
+instance HasField "wyzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w y z z
+
+instance HasField "wyzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w y z w
+
+instance HasField "wywx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w y w x
+
+instance HasField "wywy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w y w y
+
+instance HasField "wywz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w y w z
+
+instance HasField "wyww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w y w w
+
+instance HasField "wzxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w z x x
+
+instance HasField "wzxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w z x y
+
+instance HasField "wzxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w z x z
+
+instance HasField "wzxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w z x w
+
+instance HasField "wzyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y z w -> u64vec4 w z y x
+
+instance HasField "wzyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w z y y
+
+instance HasField "wzyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w z y z
+
+instance HasField "wzyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w z y w
+
+instance HasField "wzzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w z z x
+
+instance HasField "wzzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w z z y
+
+instance HasField "wzzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w z z z
+
+instance HasField "wzzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w z z w
+
+instance HasField "wzwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w z w x
+
+instance HasField "wzwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w z w y
+
+instance HasField "wzwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w z w z
+
+instance HasField "wzww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w z w w
+
+instance HasField "wwxx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w w x x
+
+instance HasField "wwxy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w w x y
+
+instance HasField "wwxz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w w x z
+
+instance HasField "wwxw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w w x w
+
+instance HasField "wwyx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x y _ w -> u64vec4 w w y x
+
+instance HasField "wwyy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w w y y
+
+instance HasField "wwyz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w w y z
+
+instance HasField "wwyw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w w y w
+
+instance HasField "wwzx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ z w -> u64vec4 w w z x
+
+instance HasField "wwzy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y z w -> u64vec4 w w z y
+
+instance HasField "wwzz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w w z z
+
+instance HasField "wwzw" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w w z w
+
+instance HasField "wwwx" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ w -> u64vec4 w w w x
+
+instance HasField "wwwy" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ w -> u64vec4 w w w y
+
+instance HasField "wwwz" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z w -> u64vec4 w w w z
+
+instance HasField "wwww" U64Vec4 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ _ w -> u64vec4 w w w w
diff --git a/src/Geomancy/Swizzle/U64Vec/Up.hs b/src/Geomancy/Swizzle/U64Vec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/U64Vec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.U64Vec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.U64Vec2 (U64Vec2, withU64Vec2)
+import Geomancy.U64Vec3 (U64Vec3, u64vec3, withU64Vec3)
+import Geomancy.U64Vec4 (U64Vec4, u64vec4)
+
+instance HasField "xxx" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x _ -> u64vec3 x x x
+
+instance HasField "xxy" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 x x y
+
+instance HasField "xyx" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 x y x
+
+instance HasField "xyy" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 x y y
+
+instance HasField "yxx" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 y x x
+
+instance HasField "yxy" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 y x y
+
+instance HasField "yyx" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec3 y y x
+
+instance HasField "yyy" U64Vec2 U64Vec3 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \_ y -> u64vec3 y y y
+
+instance HasField "xxxx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x _ -> u64vec4 x x x x
+
+instance HasField "xxxy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x x x y
+
+instance HasField "xxyx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x x y x
+
+instance HasField "xxyy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x x y y
+
+instance HasField "xyxx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y x x
+
+instance HasField "xyxy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y x y
+
+instance HasField "xyyx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y y x
+
+instance HasField "xyyy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 x y y y
+
+instance HasField "yxxx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y x x x
+
+instance HasField "yxxy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y x x y
+
+instance HasField "yxyx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y x y x
+
+instance HasField "yxyy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y x y y
+
+instance HasField "yyxx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y y x x
+
+instance HasField "yyxy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y y x y
+
+instance HasField "yyyx" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x y -> u64vec4 y y y x
+
+instance HasField "yyyy" U64Vec2 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \_ y -> u64vec4 y y y y
+
+instance HasField "xxxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ _ -> u64vec4 x x x x
+
+instance HasField "xxxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x x x y
+
+instance HasField "xxxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x x x z
+
+instance HasField "xxyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x x y x
+
+instance HasField "xxyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x x y y
+
+instance HasField "xxyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x x y z
+
+instance HasField "xxzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x x z x
+
+instance HasField "xxzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x x z y
+
+instance HasField "xxzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x x z z
+
+instance HasField "xyxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x y x x
+
+instance HasField "xyxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x y x y
+
+instance HasField "xyxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y x z
+
+instance HasField "xyyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x y y x
+
+instance HasField "xyyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 x y y y
+
+instance HasField "xyyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y y z
+
+instance HasField "xyzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y z x
+
+instance HasField "xyzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y z y
+
+instance HasField "xyzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x y z z
+
+instance HasField "xzxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x z x x
+
+instance HasField "xzxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x z x y
+
+instance HasField "xzxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x z x z
+
+instance HasField "xzyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x z y x
+
+instance HasField "xzyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x z y y
+
+instance HasField "xzyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x z y z
+
+instance HasField "xzzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x z z x
+
+instance HasField "xzzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 x z z y
+
+instance HasField "xzzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 x z z z
+
+instance HasField "yxxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y x x x
+
+instance HasField "yxxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y x x y
+
+instance HasField "yxxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y x x z
+
+instance HasField "yxyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y x y x
+
+instance HasField "yxyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y x y y
+
+instance HasField "yxyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y x y z
+
+instance HasField "yxzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y x z x
+
+instance HasField "yxzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y x z y
+
+instance HasField "yxzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y x z z
+
+instance HasField "yyxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y y x x
+
+instance HasField "yyxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y y x y
+
+instance HasField "yyxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y y x z
+
+instance HasField "yyyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y _ -> u64vec4 y y y x
+
+instance HasField "yyyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y _ -> u64vec4 y y y y
+
+instance HasField "yyyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y y y z
+
+instance HasField "yyzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y y z x
+
+instance HasField "yyzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y y z y
+
+instance HasField "yyzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y y z z
+
+instance HasField "yzxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y z x x
+
+instance HasField "yzxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y z x y
+
+instance HasField "yzxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y z x z
+
+instance HasField "yzyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y z y x
+
+instance HasField "yzyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y z y y
+
+instance HasField "yzyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y z y z
+
+instance HasField "yzzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 y z z x
+
+instance HasField "yzzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y z z y
+
+instance HasField "yzzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 y z z z
+
+instance HasField "zxxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z x x x
+
+instance HasField "zxxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z x x y
+
+instance HasField "zxxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z x x z
+
+instance HasField "zxyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z x y x
+
+instance HasField "zxyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z x y y
+
+instance HasField "zxyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z x y z
+
+instance HasField "zxzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z x z x
+
+instance HasField "zxzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z x z y
+
+instance HasField "zxzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z x z z
+
+instance HasField "zyxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z y x x
+
+instance HasField "zyxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z y x y
+
+instance HasField "zyxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z y x z
+
+instance HasField "zyyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z y y x
+
+instance HasField "zyyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z y y y
+
+instance HasField "zyyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z y y z
+
+instance HasField "zyzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z y z x
+
+instance HasField "zyzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z y z y
+
+instance HasField "zyzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z y z z
+
+instance HasField "zzxx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z z x x
+
+instance HasField "zzxy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z z x y
+
+instance HasField "zzxz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z z x z
+
+instance HasField "zzyx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x y z -> u64vec4 z z y x
+
+instance HasField "zzyy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z z y y
+
+instance HasField "zzyz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z z y z
+
+instance HasField "zzzx" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ z -> u64vec4 z z z x
+
+instance HasField "zzzy" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y z -> u64vec4 z z z y
+
+instance HasField "zzzz" U64Vec3 U64Vec4 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ _ z -> u64vec4 z z z z
diff --git a/src/Geomancy/Swizzle/UVec/Down.hs b/src/Geomancy/Swizzle/UVec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/UVec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.UVec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.UVec2 (UVec2, uvec2)
+import Geomancy.UVec3 (UVec3, uvec3, withUVec3)
+import Geomancy.UVec4 (UVec4, withUVec4)
+
+instance HasField "xx" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ _ -> uvec2 x x
+
+instance HasField "xy" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec2 x y
+
+instance HasField "xz" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec2 x z
+
+instance HasField "yx" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec2 y x
+
+instance HasField "yy" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y _ -> uvec2 y y
+
+instance HasField "yz" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec2 y z
+
+instance HasField "zx" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec2 z x
+
+instance HasField "zy" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec2 z y
+
+instance HasField "zz" UVec3 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ _ z -> uvec2 z z
+
+instance HasField "xx" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ _ -> uvec2 x x
+
+instance HasField "xy" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec2 x y
+
+instance HasField "xz" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec2 x z
+
+instance HasField "xw" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec2 x w
+
+instance HasField "yx" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec2 y x
+
+instance HasField "yy" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ _ -> uvec2 y y
+
+instance HasField "yz" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec2 y z
+
+instance HasField "yw" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec2 y w
+
+instance HasField "zx" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec2 z x
+
+instance HasField "zy" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec2 z y
+
+instance HasField "zz" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z _ -> uvec2 z z
+
+instance HasField "zw" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec2 z w
+
+instance HasField "wx" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec2 w x
+
+instance HasField "wy" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec2 w y
+
+instance HasField "wz" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec2 w z
+
+instance HasField "ww" UVec4 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ _ w -> uvec2 w w
+
+instance HasField "xxx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ _ -> uvec3 x x x
+
+instance HasField "xxy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 x x y
+
+instance HasField "xxz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 x x z
+
+instance HasField "xxw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 x x w
+
+instance HasField "xyx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 x y x
+
+instance HasField "xyy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 x y y
+
+instance HasField "xyz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 x y z
+
+instance HasField "xyw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 x y w
+
+instance HasField "xzx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 x z x
+
+instance HasField "xzy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 x z y
+
+instance HasField "xzz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 x z z
+
+instance HasField "xzw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 x z w
+
+instance HasField "xwx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 x w x
+
+instance HasField "xwy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 x w y
+
+instance HasField "xwz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 x w z
+
+instance HasField "xww" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 x w w
+
+instance HasField "yxx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 y x x
+
+instance HasField "yxy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 y x y
+
+instance HasField "yxz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 y x z
+
+instance HasField "yxw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 y x w
+
+instance HasField "yyx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec3 y y x
+
+instance HasField "yyy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ _ -> uvec3 y y y
+
+instance HasField "yyz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 y y z
+
+instance HasField "yyw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 y y w
+
+instance HasField "yzx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 y z x
+
+instance HasField "yzy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 y z y
+
+instance HasField "yzz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 y z z
+
+instance HasField "yzw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 y z w
+
+instance HasField "ywx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 y w x
+
+instance HasField "ywy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 y w y
+
+instance HasField "ywz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 y w z
+
+instance HasField "yww" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 y w w
+
+instance HasField "zxx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 z x x
+
+instance HasField "zxy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 z x y
+
+instance HasField "zxz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 z x z
+
+instance HasField "zxw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 z x w
+
+instance HasField "zyx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec3 z y x
+
+instance HasField "zyy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 z y y
+
+instance HasField "zyz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 z y z
+
+instance HasField "zyw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 z y w
+
+instance HasField "zzx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec3 z z x
+
+instance HasField "zzy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec3 z z y
+
+instance HasField "zzz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z _ -> uvec3 z z z
+
+instance HasField "zzw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 z z w
+
+instance HasField "zwx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 z w x
+
+instance HasField "zwy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 z w y
+
+instance HasField "zwz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 z w z
+
+instance HasField "zww" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 z w w
+
+instance HasField "wxx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 w x x
+
+instance HasField "wxy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 w x y
+
+instance HasField "wxz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 w x z
+
+instance HasField "wxw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 w x w
+
+instance HasField "wyx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec3 w y x
+
+instance HasField "wyy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 w y y
+
+instance HasField "wyz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 w y z
+
+instance HasField "wyw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 w y w
+
+instance HasField "wzx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec3 w z x
+
+instance HasField "wzy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec3 w z y
+
+instance HasField "wzz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 w z z
+
+instance HasField "wzw" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 w z w
+
+instance HasField "wwx" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec3 w w x
+
+instance HasField "wwy" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec3 w w y
+
+instance HasField "wwz" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec3 w w z
+
+instance HasField "www" UVec4 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ _ w -> uvec3 w w w
diff --git a/src/Geomancy/Swizzle/UVec/Extend.hs b/src/Geomancy/Swizzle/UVec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/UVec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.UVec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.UVec2 (UVec2, withUVec2)
+import Geomancy.UVec3 (UVec3, uvec3, withUVec3)
+import Geomancy.UVec4 (UVec4, uvec4)
+
+instance HasField "xy0" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 x y 0
+
+instance HasField "xy1" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 x y 1
+
+instance HasField "xy00" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y 0 0
+
+instance HasField "xy01" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y 0 1
+
+instance HasField "xy10" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y 1 0
+
+instance HasField "xy11" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y 1 1
+
+instance HasField "xyz0" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y z 0
+
+instance HasField "xyz1" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y z 1
diff --git a/src/Geomancy/Swizzle/UVec/Shuffle.hs b/src/Geomancy/Swizzle/UVec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/UVec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.UVec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.UVec2 (UVec2, uvec2, withUVec2)
+import Geomancy.UVec3 (UVec3, uvec3, withUVec3)
+import Geomancy.UVec4 (UVec4, uvec4, withUVec4)
+
+instance HasField "xx" UVec2 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x _ -> uvec2 x x
+
+instance HasField "xy" UVec2 UVec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" UVec2 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec2 y x
+
+instance HasField "yy" UVec2 UVec2 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \_ y -> uvec2 y y
+
+instance HasField "xxx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ _ -> uvec3 x x x
+
+instance HasField "xxy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 x x y
+
+instance HasField "xxz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 x x z
+
+instance HasField "xyx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 x y x
+
+instance HasField "xyy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 x y y
+
+instance HasField "xyz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 x z x
+
+instance HasField "xzy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec3 x z y
+
+instance HasField "xzz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 x z z
+
+instance HasField "yxx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 y x x
+
+instance HasField "yxy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 y x y
+
+instance HasField "yxz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec3 y x z
+
+instance HasField "yyx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec3 y y x
+
+instance HasField "yyy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y _ -> uvec3 y y y
+
+instance HasField "yyz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 y y z
+
+instance HasField "yzx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec3 y z x
+
+instance HasField "yzy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 y z y
+
+instance HasField "yzz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 y z z
+
+instance HasField "zxx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 z x x
+
+instance HasField "zxy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec3 z x y
+
+instance HasField "zxz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 z x z
+
+instance HasField "zyx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec3 z y x
+
+instance HasField "zyy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 z y y
+
+instance HasField "zyz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 z y z
+
+instance HasField "zzx" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec3 z z x
+
+instance HasField "zzy" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec3 z z y
+
+instance HasField "zzz" UVec3 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ _ z -> uvec3 z z z
+
+instance HasField "xxxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ _ -> uvec4 x x x x
+
+instance HasField "xxxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x x x y
+
+instance HasField "xxxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x x x z
+
+instance HasField "xxxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x x x w
+
+instance HasField "xxyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x x y x
+
+instance HasField "xxyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x x y y
+
+instance HasField "xxyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x x y z
+
+instance HasField "xxyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x x y w
+
+instance HasField "xxzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x x z x
+
+instance HasField "xxzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x x z y
+
+instance HasField "xxzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x x z z
+
+instance HasField "xxzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x x z w
+
+instance HasField "xxwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x x w x
+
+instance HasField "xxwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x x w y
+
+instance HasField "xxwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x x w z
+
+instance HasField "xxww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x x w w
+
+instance HasField "xyxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x y x x
+
+instance HasField "xyxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x y x y
+
+instance HasField "xyxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x y x z
+
+instance HasField "xyxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x y x w
+
+instance HasField "xyyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x y y x
+
+instance HasField "xyyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 x y y y
+
+instance HasField "xyyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x y y z
+
+instance HasField "xyyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x y y w
+
+instance HasField "xyzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x y z x
+
+instance HasField "xyzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x y z y
+
+instance HasField "xyzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x y z z
+
+instance HasField "xyzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x y w x
+
+instance HasField "xywy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x y w y
+
+instance HasField "xywz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 x y w z
+
+instance HasField "xyww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x y w w
+
+instance HasField "xzxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x z x x
+
+instance HasField "xzxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x z x y
+
+instance HasField "xzxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x z x z
+
+instance HasField "xzxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x z x w
+
+instance HasField "xzyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x z y x
+
+instance HasField "xzyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x z y y
+
+instance HasField "xzyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x z y z
+
+instance HasField "xzyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 x z y w
+
+instance HasField "xzzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x z z x
+
+instance HasField "xzzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 x z z y
+
+instance HasField "xzzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 x z z z
+
+instance HasField "xzzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x z z w
+
+instance HasField "xzwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x z w x
+
+instance HasField "xzwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 x z w y
+
+instance HasField "xzwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x z w z
+
+instance HasField "xzww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x z w w
+
+instance HasField "xwxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x w x x
+
+instance HasField "xwxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x w x y
+
+instance HasField "xwxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x w x z
+
+instance HasField "xwxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x w x w
+
+instance HasField "xwyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x w y x
+
+instance HasField "xwyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x w y y
+
+instance HasField "xwyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 x w y z
+
+instance HasField "xwyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x w y w
+
+instance HasField "xwzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x w z x
+
+instance HasField "xwzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 x w z y
+
+instance HasField "xwzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x w z z
+
+instance HasField "xwzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x w z w
+
+instance HasField "xwwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x w w x
+
+instance HasField "xwwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 x w w y
+
+instance HasField "xwwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 x w w z
+
+instance HasField "xwww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 x w w w
+
+instance HasField "yxxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y x x x
+
+instance HasField "yxxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y x x y
+
+instance HasField "yxxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y x x z
+
+instance HasField "yxxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y x x w
+
+instance HasField "yxyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y x y x
+
+instance HasField "yxyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y x y y
+
+instance HasField "yxyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y x y z
+
+instance HasField "yxyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y x y w
+
+instance HasField "yxzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y x z x
+
+instance HasField "yxzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y x z y
+
+instance HasField "yxzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y x z z
+
+instance HasField "yxzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y x z w
+
+instance HasField "yxwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y x w x
+
+instance HasField "yxwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y x w y
+
+instance HasField "yxwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y x w z
+
+instance HasField "yxww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y x w w
+
+instance HasField "yyxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y y x x
+
+instance HasField "yyxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y y x y
+
+instance HasField "yyxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y y x z
+
+instance HasField "yyxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y y x w
+
+instance HasField "yyyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ _ -> uvec4 y y y x
+
+instance HasField "yyyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ _ -> uvec4 y y y y
+
+instance HasField "yyyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y y y z
+
+instance HasField "yyyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y y y w
+
+instance HasField "yyzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y y z x
+
+instance HasField "yyzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y y z y
+
+instance HasField "yyzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y y z z
+
+instance HasField "yyzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y y z w
+
+instance HasField "yywx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y y w x
+
+instance HasField "yywy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y y w y
+
+instance HasField "yywz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y y w z
+
+instance HasField "yyww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y y w w
+
+instance HasField "yzxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y z x x
+
+instance HasField "yzxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y z x y
+
+instance HasField "yzxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y z x z
+
+instance HasField "yzxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y z x w
+
+instance HasField "yzyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y z y x
+
+instance HasField "yzyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y z y y
+
+instance HasField "yzyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y z y z
+
+instance HasField "yzyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y z y w
+
+instance HasField "yzzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 y z z x
+
+instance HasField "yzzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y z z y
+
+instance HasField "yzzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 y z z z
+
+instance HasField "yzzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y z z w
+
+instance HasField "yzwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y z w x
+
+instance HasField "yzwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y z w y
+
+instance HasField "yzwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y z w z
+
+instance HasField "yzww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y z w w
+
+instance HasField "ywxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y w x x
+
+instance HasField "ywxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y w x y
+
+instance HasField "ywxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y w x z
+
+instance HasField "ywxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y w x w
+
+instance HasField "ywyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y w y x
+
+instance HasField "ywyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y w y y
+
+instance HasField "ywyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y w y z
+
+instance HasField "ywyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y w y w
+
+instance HasField "ywzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 y w z x
+
+instance HasField "ywzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y w z y
+
+instance HasField "ywzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y w z z
+
+instance HasField "ywzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y w z w
+
+instance HasField "ywwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 y w w x
+
+instance HasField "ywwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y w w y
+
+instance HasField "ywwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 y w w z
+
+instance HasField "ywww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 y w w w
+
+instance HasField "zxxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z x x x
+
+instance HasField "zxxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z x x y
+
+instance HasField "zxxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z x x z
+
+instance HasField "zxxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z x x w
+
+instance HasField "zxyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z x y x
+
+instance HasField "zxyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z x y y
+
+instance HasField "zxyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z x y z
+
+instance HasField "zxyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z x y w
+
+instance HasField "zxzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z x z x
+
+instance HasField "zxzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z x z y
+
+instance HasField "zxzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z x z z
+
+instance HasField "zxzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z x z w
+
+instance HasField "zxwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z x w x
+
+instance HasField "zxwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z x w y
+
+instance HasField "zxwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z x w z
+
+instance HasField "zxww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z x w w
+
+instance HasField "zyxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z y x x
+
+instance HasField "zyxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z y x y
+
+instance HasField "zyxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z y x z
+
+instance HasField "zyxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z y x w
+
+instance HasField "zyyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z y y x
+
+instance HasField "zyyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z y y y
+
+instance HasField "zyyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z y y z
+
+instance HasField "zyyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z y y w
+
+instance HasField "zyzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z y z x
+
+instance HasField "zyzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z y z y
+
+instance HasField "zyzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z y z z
+
+instance HasField "zyzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z y z w
+
+instance HasField "zywx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z y w x
+
+instance HasField "zywy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z y w y
+
+instance HasField "zywz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z y w z
+
+instance HasField "zyww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z y w w
+
+instance HasField "zzxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z z x x
+
+instance HasField "zzxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z z x y
+
+instance HasField "zzxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z z x z
+
+instance HasField "zzxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z z x w
+
+instance HasField "zzyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z _ -> uvec4 z z y x
+
+instance HasField "zzyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z z y y
+
+instance HasField "zzyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z z y z
+
+instance HasField "zzyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z z y w
+
+instance HasField "zzzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z _ -> uvec4 z z z x
+
+instance HasField "zzzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z _ -> uvec4 z z z y
+
+instance HasField "zzzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z _ -> uvec4 z z z z
+
+instance HasField "zzzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z z z w
+
+instance HasField "zzwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z z w x
+
+instance HasField "zzwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z z w y
+
+instance HasField "zzwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z z w z
+
+instance HasField "zzww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z z w w
+
+instance HasField "zwxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z w x x
+
+instance HasField "zwxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z w x y
+
+instance HasField "zwxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z w x z
+
+instance HasField "zwxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z w x w
+
+instance HasField "zwyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 z w y x
+
+instance HasField "zwyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z w y y
+
+instance HasField "zwyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z w y z
+
+instance HasField "zwyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z w y w
+
+instance HasField "zwzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z w z x
+
+instance HasField "zwzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z w z y
+
+instance HasField "zwzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z w z z
+
+instance HasField "zwzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z w z w
+
+instance HasField "zwwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 z w w x
+
+instance HasField "zwwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 z w w y
+
+instance HasField "zwwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z w w z
+
+instance HasField "zwww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 z w w w
+
+instance HasField "wxxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w x x x
+
+instance HasField "wxxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w x x y
+
+instance HasField "wxxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w x x z
+
+instance HasField "wxxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w x x w
+
+instance HasField "wxyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w x y x
+
+instance HasField "wxyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w x y y
+
+instance HasField "wxyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w x y z
+
+instance HasField "wxyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w x y w
+
+instance HasField "wxzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w x z x
+
+instance HasField "wxzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w x z y
+
+instance HasField "wxzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w x z z
+
+instance HasField "wxzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w x z w
+
+instance HasField "wxwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w x w x
+
+instance HasField "wxwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w x w y
+
+instance HasField "wxwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w x w z
+
+instance HasField "wxww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w x w w
+
+instance HasField "wyxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w y x x
+
+instance HasField "wyxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w y x y
+
+instance HasField "wyxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w y x z
+
+instance HasField "wyxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w y x w
+
+instance HasField "wyyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w y y x
+
+instance HasField "wyyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w y y y
+
+instance HasField "wyyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w y y z
+
+instance HasField "wyyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w y y w
+
+instance HasField "wyzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w y z x
+
+instance HasField "wyzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w y z y
+
+instance HasField "wyzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w y z z
+
+instance HasField "wyzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w y z w
+
+instance HasField "wywx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w y w x
+
+instance HasField "wywy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w y w y
+
+instance HasField "wywz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w y w z
+
+instance HasField "wyww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w y w w
+
+instance HasField "wzxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w z x x
+
+instance HasField "wzxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w z x y
+
+instance HasField "wzxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w z x z
+
+instance HasField "wzxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w z x w
+
+instance HasField "wzyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y z w -> uvec4 w z y x
+
+instance HasField "wzyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w z y y
+
+instance HasField "wzyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w z y z
+
+instance HasField "wzyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w z y w
+
+instance HasField "wzzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w z z x
+
+instance HasField "wzzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w z z y
+
+instance HasField "wzzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w z z z
+
+instance HasField "wzzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w z z w
+
+instance HasField "wzwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w z w x
+
+instance HasField "wzwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w z w y
+
+instance HasField "wzwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w z w z
+
+instance HasField "wzww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w z w w
+
+instance HasField "wwxx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w w x x
+
+instance HasField "wwxy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w w x y
+
+instance HasField "wwxz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w w x z
+
+instance HasField "wwxw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w w x w
+
+instance HasField "wwyx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x y _ w -> uvec4 w w y x
+
+instance HasField "wwyy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w w y y
+
+instance HasField "wwyz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w w y z
+
+instance HasField "wwyw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w w y w
+
+instance HasField "wwzx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ z w -> uvec4 w w z x
+
+instance HasField "wwzy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y z w -> uvec4 w w z y
+
+instance HasField "wwzz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w w z z
+
+instance HasField "wwzw" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w w z w
+
+instance HasField "wwwx" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ w -> uvec4 w w w x
+
+instance HasField "wwwy" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ w -> uvec4 w w w y
+
+instance HasField "wwwz" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z w -> uvec4 w w w z
+
+instance HasField "wwww" UVec4 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ _ w -> uvec4 w w w w
diff --git a/src/Geomancy/Swizzle/UVec/Up.hs b/src/Geomancy/Swizzle/UVec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/UVec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.UVec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.UVec2 (UVec2, withUVec2)
+import Geomancy.UVec3 (UVec3, uvec3, withUVec3)
+import Geomancy.UVec4 (UVec4, uvec4)
+
+instance HasField "xxx" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x _ -> uvec3 x x x
+
+instance HasField "xxy" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 x x y
+
+instance HasField "xyx" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 x y x
+
+instance HasField "xyy" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 x y y
+
+instance HasField "yxx" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 y x x
+
+instance HasField "yxy" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 y x y
+
+instance HasField "yyx" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec3 y y x
+
+instance HasField "yyy" UVec2 UVec3 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \_ y -> uvec3 y y y
+
+instance HasField "xxxx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x _ -> uvec4 x x x x
+
+instance HasField "xxxy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x x x y
+
+instance HasField "xxyx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x x y x
+
+instance HasField "xxyy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x x y y
+
+instance HasField "xyxx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y x x
+
+instance HasField "xyxy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y x y
+
+instance HasField "xyyx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y y x
+
+instance HasField "xyyy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 x y y y
+
+instance HasField "yxxx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y x x x
+
+instance HasField "yxxy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y x x y
+
+instance HasField "yxyx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y x y x
+
+instance HasField "yxyy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y x y y
+
+instance HasField "yyxx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y y x x
+
+instance HasField "yyxy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y y x y
+
+instance HasField "yyyx" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x y -> uvec4 y y y x
+
+instance HasField "yyyy" UVec2 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \_ y -> uvec4 y y y y
+
+instance HasField "xxxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ _ -> uvec4 x x x x
+
+instance HasField "xxxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x x x y
+
+instance HasField "xxxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x x x z
+
+instance HasField "xxyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x x y x
+
+instance HasField "xxyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x x y y
+
+instance HasField "xxyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x x y z
+
+instance HasField "xxzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x x z x
+
+instance HasField "xxzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x x z y
+
+instance HasField "xxzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x x z z
+
+instance HasField "xyxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x y x x
+
+instance HasField "xyxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x y x y
+
+instance HasField "xyxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y x z
+
+instance HasField "xyyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x y y x
+
+instance HasField "xyyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 x y y y
+
+instance HasField "xyyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y y z
+
+instance HasField "xyzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y z x
+
+instance HasField "xyzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y z y
+
+instance HasField "xyzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x y z z
+
+instance HasField "xzxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x z x x
+
+instance HasField "xzxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x z x y
+
+instance HasField "xzxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x z x z
+
+instance HasField "xzyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x z y x
+
+instance HasField "xzyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x z y y
+
+instance HasField "xzyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x z y z
+
+instance HasField "xzzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x z z x
+
+instance HasField "xzzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 x z z y
+
+instance HasField "xzzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 x z z z
+
+instance HasField "yxxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y x x x
+
+instance HasField "yxxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y x x y
+
+instance HasField "yxxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y x x z
+
+instance HasField "yxyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y x y x
+
+instance HasField "yxyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y x y y
+
+instance HasField "yxyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y x y z
+
+instance HasField "yxzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y x z x
+
+instance HasField "yxzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y x z y
+
+instance HasField "yxzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y x z z
+
+instance HasField "yyxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y y x x
+
+instance HasField "yyxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y y x y
+
+instance HasField "yyxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y y x z
+
+instance HasField "yyyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y _ -> uvec4 y y y x
+
+instance HasField "yyyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y _ -> uvec4 y y y y
+
+instance HasField "yyyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y y y z
+
+instance HasField "yyzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y y z x
+
+instance HasField "yyzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y y z y
+
+instance HasField "yyzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y y z z
+
+instance HasField "yzxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y z x x
+
+instance HasField "yzxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y z x y
+
+instance HasField "yzxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y z x z
+
+instance HasField "yzyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y z y x
+
+instance HasField "yzyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y z y y
+
+instance HasField "yzyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y z y z
+
+instance HasField "yzzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 y z z x
+
+instance HasField "yzzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y z z y
+
+instance HasField "yzzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 y z z z
+
+instance HasField "zxxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z x x x
+
+instance HasField "zxxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z x x y
+
+instance HasField "zxxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z x x z
+
+instance HasField "zxyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z x y x
+
+instance HasField "zxyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z x y y
+
+instance HasField "zxyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z x y z
+
+instance HasField "zxzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z x z x
+
+instance HasField "zxzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z x z y
+
+instance HasField "zxzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z x z z
+
+instance HasField "zyxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z y x x
+
+instance HasField "zyxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z y x y
+
+instance HasField "zyxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z y x z
+
+instance HasField "zyyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z y y x
+
+instance HasField "zyyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z y y y
+
+instance HasField "zyyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z y y z
+
+instance HasField "zyzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z y z x
+
+instance HasField "zyzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z y z y
+
+instance HasField "zyzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z y z z
+
+instance HasField "zzxx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z z x x
+
+instance HasField "zzxy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z z x y
+
+instance HasField "zzxz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z z x z
+
+instance HasField "zzyx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x y z -> uvec4 z z y x
+
+instance HasField "zzyy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z z y y
+
+instance HasField "zzyz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z z y z
+
+instance HasField "zzzx" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ z -> uvec4 z z z x
+
+instance HasField "zzzy" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y z -> uvec4 z z z y
+
+instance HasField "zzzz" UVec3 UVec4 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ _ z -> uvec4 z z z z
diff --git a/src/Geomancy/Swizzle/Vec/Down.hs b/src/Geomancy/Swizzle/Vec/Down.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/Vec/Down.hs
@@ -0,0 +1,369 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.Vec.Down () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.Vec2 (Vec2, vec2)
+import Geomancy.Vec3 (Vec3, vec3, withVec3)
+import Geomancy.Vec4 (Vec4, withVec4)
+
+instance HasField "xx" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ _ -> vec2 x x
+
+instance HasField "xy" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec2 x y
+
+instance HasField "xz" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec2 x z
+
+instance HasField "yx" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec2 y x
+
+instance HasField "yy" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y _ -> vec2 y y
+
+instance HasField "yz" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec2 y z
+
+instance HasField "zx" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec2 z x
+
+instance HasField "zy" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec2 z y
+
+instance HasField "zz" Vec3 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ _ z -> vec2 z z
+
+instance HasField "xx" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ _ -> vec2 x x
+
+instance HasField "xy" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec2 x y
+
+instance HasField "xz" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec2 x z
+
+instance HasField "xw" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec2 x w
+
+instance HasField "yx" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec2 y x
+
+instance HasField "yy" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ _ -> vec2 y y
+
+instance HasField "yz" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec2 y z
+
+instance HasField "yw" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec2 y w
+
+instance HasField "zx" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec2 z x
+
+instance HasField "zy" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec2 z y
+
+instance HasField "zz" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z _ -> vec2 z z
+
+instance HasField "zw" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec2 z w
+
+instance HasField "wx" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec2 w x
+
+instance HasField "wy" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec2 w y
+
+instance HasField "wz" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec2 w z
+
+instance HasField "ww" Vec4 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ _ w -> vec2 w w
+
+instance HasField "xxx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ _ -> vec3 x x x
+
+instance HasField "xxy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 x x y
+
+instance HasField "xxz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 x x z
+
+instance HasField "xxw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 x x w
+
+instance HasField "xyx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 x y x
+
+instance HasField "xyy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 x y y
+
+instance HasField "xyz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 x y z
+
+instance HasField "xyw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 x y w
+
+instance HasField "xzx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 x z x
+
+instance HasField "xzy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 x z y
+
+instance HasField "xzz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 x z z
+
+instance HasField "xzw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 x z w
+
+instance HasField "xwx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 x w x
+
+instance HasField "xwy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 x w y
+
+instance HasField "xwz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 x w z
+
+instance HasField "xww" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 x w w
+
+instance HasField "yxx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 y x x
+
+instance HasField "yxy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 y x y
+
+instance HasField "yxz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 y x z
+
+instance HasField "yxw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 y x w
+
+instance HasField "yyx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec3 y y x
+
+instance HasField "yyy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ _ -> vec3 y y y
+
+instance HasField "yyz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 y y z
+
+instance HasField "yyw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 y y w
+
+instance HasField "yzx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 y z x
+
+instance HasField "yzy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 y z y
+
+instance HasField "yzz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 y z z
+
+instance HasField "yzw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 y z w
+
+instance HasField "ywx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 y w x
+
+instance HasField "ywy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 y w y
+
+instance HasField "ywz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 y w z
+
+instance HasField "yww" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 y w w
+
+instance HasField "zxx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 z x x
+
+instance HasField "zxy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 z x y
+
+instance HasField "zxz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 z x z
+
+instance HasField "zxw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 z x w
+
+instance HasField "zyx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec3 z y x
+
+instance HasField "zyy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 z y y
+
+instance HasField "zyz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 z y z
+
+instance HasField "zyw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 z y w
+
+instance HasField "zzx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec3 z z x
+
+instance HasField "zzy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec3 z z y
+
+instance HasField "zzz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z _ -> vec3 z z z
+
+instance HasField "zzw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 z z w
+
+instance HasField "zwx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 z w x
+
+instance HasField "zwy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 z w y
+
+instance HasField "zwz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 z w z
+
+instance HasField "zww" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 z w w
+
+instance HasField "wxx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 w x x
+
+instance HasField "wxy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 w x y
+
+instance HasField "wxz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 w x z
+
+instance HasField "wxw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 w x w
+
+instance HasField "wyx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec3 w y x
+
+instance HasField "wyy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 w y y
+
+instance HasField "wyz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 w y z
+
+instance HasField "wyw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 w y w
+
+instance HasField "wzx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec3 w z x
+
+instance HasField "wzy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec3 w z y
+
+instance HasField "wzz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 w z z
+
+instance HasField "wzw" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 w z w
+
+instance HasField "wwx" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec3 w w x
+
+instance HasField "wwy" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec3 w w y
+
+instance HasField "wwz" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec3 w w z
+
+instance HasField "www" Vec4 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ _ w -> vec3 w w w
diff --git a/src/Geomancy/Swizzle/Vec/Extend.hs b/src/Geomancy/Swizzle/Vec/Extend.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/Vec/Extend.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.Vec.Extend () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.Vec2 (Vec2, withVec2)
+import Geomancy.Vec3 (Vec3, vec3, withVec3)
+import Geomancy.Vec4 (Vec4, vec4)
+
+instance HasField "xy0" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 x y 0
+
+instance HasField "xy1" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 x y 1
+
+instance HasField "xy00" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y 0 0
+
+instance HasField "xy01" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y 0 1
+
+instance HasField "xy10" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y 1 0
+
+instance HasField "xy11" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y 1 1
+
+instance HasField "xyz0" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y z 0
+
+instance HasField "xyz1" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y z 1
diff --git a/src/Geomancy/Swizzle/Vec/Shuffle.hs b/src/Geomancy/Swizzle/Vec/Shuffle.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/Vec/Shuffle.hs
@@ -0,0 +1,1161 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.Vec.Shuffle () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.Vec2 (Vec2, vec2, withVec2)
+import Geomancy.Vec3 (Vec3, vec3, withVec3)
+import Geomancy.Vec4 (Vec4, vec4, withVec4)
+
+instance HasField "xx" Vec2 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x _ -> vec2 x x
+
+instance HasField "xy" Vec2 Vec2 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "yx" Vec2 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec2 y x
+
+instance HasField "yy" Vec2 Vec2 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \_ y -> vec2 y y
+
+instance HasField "xxx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ _ -> vec3 x x x
+
+instance HasField "xxy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 x x y
+
+instance HasField "xxz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 x x z
+
+instance HasField "xyx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 x y x
+
+instance HasField "xyy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 x y y
+
+instance HasField "xyz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xzx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 x z x
+
+instance HasField "xzy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec3 x z y
+
+instance HasField "xzz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 x z z
+
+instance HasField "yxx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 y x x
+
+instance HasField "yxy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 y x y
+
+instance HasField "yxz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec3 y x z
+
+instance HasField "yyx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec3 y y x
+
+instance HasField "yyy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y _ -> vec3 y y y
+
+instance HasField "yyz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 y y z
+
+instance HasField "yzx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec3 y z x
+
+instance HasField "yzy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 y z y
+
+instance HasField "yzz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 y z z
+
+instance HasField "zxx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 z x x
+
+instance HasField "zxy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec3 z x y
+
+instance HasField "zxz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 z x z
+
+instance HasField "zyx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec3 z y x
+
+instance HasField "zyy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 z y y
+
+instance HasField "zyz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 z y z
+
+instance HasField "zzx" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec3 z z x
+
+instance HasField "zzy" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec3 z z y
+
+instance HasField "zzz" Vec3 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ _ z -> vec3 z z z
+
+instance HasField "xxxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ _ -> vec4 x x x x
+
+instance HasField "xxxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x x x y
+
+instance HasField "xxxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x x x z
+
+instance HasField "xxxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x x x w
+
+instance HasField "xxyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x x y x
+
+instance HasField "xxyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x x y y
+
+instance HasField "xxyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x x y z
+
+instance HasField "xxyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x x y w
+
+instance HasField "xxzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x x z x
+
+instance HasField "xxzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x x z y
+
+instance HasField "xxzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x x z z
+
+instance HasField "xxzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x x z w
+
+instance HasField "xxwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x x w x
+
+instance HasField "xxwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x x w y
+
+instance HasField "xxwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x x w z
+
+instance HasField "xxww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x x w w
+
+instance HasField "xyxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x y x x
+
+instance HasField "xyxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x y x y
+
+instance HasField "xyxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x y x z
+
+instance HasField "xyxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x y x w
+
+instance HasField "xyyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x y y x
+
+instance HasField "xyyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 x y y y
+
+instance HasField "xyyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x y y z
+
+instance HasField "xyyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x y y w
+
+instance HasField "xyzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x y z x
+
+instance HasField "xyzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x y z y
+
+instance HasField "xyzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x y z z
+
+instance HasField "xyzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = v
+
+instance HasField "xywx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x y w x
+
+instance HasField "xywy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x y w y
+
+instance HasField "xywz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 x y w z
+
+instance HasField "xyww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x y w w
+
+instance HasField "xzxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x z x x
+
+instance HasField "xzxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x z x y
+
+instance HasField "xzxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x z x z
+
+instance HasField "xzxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x z x w
+
+instance HasField "xzyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x z y x
+
+instance HasField "xzyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x z y y
+
+instance HasField "xzyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x z y z
+
+instance HasField "xzyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 x z y w
+
+instance HasField "xzzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x z z x
+
+instance HasField "xzzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 x z z y
+
+instance HasField "xzzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 x z z z
+
+instance HasField "xzzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x z z w
+
+instance HasField "xzwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x z w x
+
+instance HasField "xzwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 x z w y
+
+instance HasField "xzwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x z w z
+
+instance HasField "xzww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x z w w
+
+instance HasField "xwxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x w x x
+
+instance HasField "xwxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x w x y
+
+instance HasField "xwxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x w x z
+
+instance HasField "xwxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x w x w
+
+instance HasField "xwyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x w y x
+
+instance HasField "xwyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x w y y
+
+instance HasField "xwyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 x w y z
+
+instance HasField "xwyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x w y w
+
+instance HasField "xwzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x w z x
+
+instance HasField "xwzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 x w z y
+
+instance HasField "xwzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x w z z
+
+instance HasField "xwzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x w z w
+
+instance HasField "xwwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x w w x
+
+instance HasField "xwwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 x w w y
+
+instance HasField "xwwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 x w w z
+
+instance HasField "xwww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 x w w w
+
+instance HasField "yxxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y x x x
+
+instance HasField "yxxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y x x y
+
+instance HasField "yxxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y x x z
+
+instance HasField "yxxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y x x w
+
+instance HasField "yxyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y x y x
+
+instance HasField "yxyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y x y y
+
+instance HasField "yxyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y x y z
+
+instance HasField "yxyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y x y w
+
+instance HasField "yxzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y x z x
+
+instance HasField "yxzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y x z y
+
+instance HasField "yxzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y x z z
+
+instance HasField "yxzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y x z w
+
+instance HasField "yxwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y x w x
+
+instance HasField "yxwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y x w y
+
+instance HasField "yxwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y x w z
+
+instance HasField "yxww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y x w w
+
+instance HasField "yyxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y y x x
+
+instance HasField "yyxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y y x y
+
+instance HasField "yyxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y y x z
+
+instance HasField "yyxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y y x w
+
+instance HasField "yyyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ _ -> vec4 y y y x
+
+instance HasField "yyyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ _ -> vec4 y y y y
+
+instance HasField "yyyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y y y z
+
+instance HasField "yyyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y y y w
+
+instance HasField "yyzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y y z x
+
+instance HasField "yyzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y y z y
+
+instance HasField "yyzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y y z z
+
+instance HasField "yyzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y y z w
+
+instance HasField "yywx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y y w x
+
+instance HasField "yywy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y y w y
+
+instance HasField "yywz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y y w z
+
+instance HasField "yyww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y y w w
+
+instance HasField "yzxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y z x x
+
+instance HasField "yzxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y z x y
+
+instance HasField "yzxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y z x z
+
+instance HasField "yzxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y z x w
+
+instance HasField "yzyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y z y x
+
+instance HasField "yzyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y z y y
+
+instance HasField "yzyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y z y z
+
+instance HasField "yzyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y z y w
+
+instance HasField "yzzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 y z z x
+
+instance HasField "yzzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y z z y
+
+instance HasField "yzzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 y z z z
+
+instance HasField "yzzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y z z w
+
+instance HasField "yzwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y z w x
+
+instance HasField "yzwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y z w y
+
+instance HasField "yzwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y z w z
+
+instance HasField "yzww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y z w w
+
+instance HasField "ywxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y w x x
+
+instance HasField "ywxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y w x y
+
+instance HasField "ywxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y w x z
+
+instance HasField "ywxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y w x w
+
+instance HasField "ywyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y w y x
+
+instance HasField "ywyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y w y y
+
+instance HasField "ywyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y w y z
+
+instance HasField "ywyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y w y w
+
+instance HasField "ywzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 y w z x
+
+instance HasField "ywzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y w z y
+
+instance HasField "ywzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y w z z
+
+instance HasField "ywzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y w z w
+
+instance HasField "ywwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 y w w x
+
+instance HasField "ywwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y w w y
+
+instance HasField "ywwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 y w w z
+
+instance HasField "ywww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 y w w w
+
+instance HasField "zxxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z x x x
+
+instance HasField "zxxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z x x y
+
+instance HasField "zxxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z x x z
+
+instance HasField "zxxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z x x w
+
+instance HasField "zxyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z x y x
+
+instance HasField "zxyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z x y y
+
+instance HasField "zxyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z x y z
+
+instance HasField "zxyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z x y w
+
+instance HasField "zxzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z x z x
+
+instance HasField "zxzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z x z y
+
+instance HasField "zxzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z x z z
+
+instance HasField "zxzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z x z w
+
+instance HasField "zxwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z x w x
+
+instance HasField "zxwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z x w y
+
+instance HasField "zxwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z x w z
+
+instance HasField "zxww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z x w w
+
+instance HasField "zyxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z y x x
+
+instance HasField "zyxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z y x y
+
+instance HasField "zyxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z y x z
+
+instance HasField "zyxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z y x w
+
+instance HasField "zyyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z y y x
+
+instance HasField "zyyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z y y y
+
+instance HasField "zyyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z y y z
+
+instance HasField "zyyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z y y w
+
+instance HasField "zyzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z y z x
+
+instance HasField "zyzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z y z y
+
+instance HasField "zyzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z y z z
+
+instance HasField "zyzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z y z w
+
+instance HasField "zywx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z y w x
+
+instance HasField "zywy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z y w y
+
+instance HasField "zywz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z y w z
+
+instance HasField "zyww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z y w w
+
+instance HasField "zzxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z z x x
+
+instance HasField "zzxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z z x y
+
+instance HasField "zzxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z z x z
+
+instance HasField "zzxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z z x w
+
+instance HasField "zzyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z _ -> vec4 z z y x
+
+instance HasField "zzyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z z y y
+
+instance HasField "zzyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z z y z
+
+instance HasField "zzyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z z y w
+
+instance HasField "zzzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z _ -> vec4 z z z x
+
+instance HasField "zzzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z _ -> vec4 z z z y
+
+instance HasField "zzzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z _ -> vec4 z z z z
+
+instance HasField "zzzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z z z w
+
+instance HasField "zzwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z z w x
+
+instance HasField "zzwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z z w y
+
+instance HasField "zzwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z z w z
+
+instance HasField "zzww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z z w w
+
+instance HasField "zwxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z w x x
+
+instance HasField "zwxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z w x y
+
+instance HasField "zwxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z w x z
+
+instance HasField "zwxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z w x w
+
+instance HasField "zwyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 z w y x
+
+instance HasField "zwyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z w y y
+
+instance HasField "zwyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z w y z
+
+instance HasField "zwyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z w y w
+
+instance HasField "zwzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z w z x
+
+instance HasField "zwzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z w z y
+
+instance HasField "zwzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z w z z
+
+instance HasField "zwzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z w z w
+
+instance HasField "zwwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 z w w x
+
+instance HasField "zwwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 z w w y
+
+instance HasField "zwwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z w w z
+
+instance HasField "zwww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 z w w w
+
+instance HasField "wxxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w x x x
+
+instance HasField "wxxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w x x y
+
+instance HasField "wxxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w x x z
+
+instance HasField "wxxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w x x w
+
+instance HasField "wxyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w x y x
+
+instance HasField "wxyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w x y y
+
+instance HasField "wxyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w x y z
+
+instance HasField "wxyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w x y w
+
+instance HasField "wxzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w x z x
+
+instance HasField "wxzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w x z y
+
+instance HasField "wxzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w x z z
+
+instance HasField "wxzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w x z w
+
+instance HasField "wxwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w x w x
+
+instance HasField "wxwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w x w y
+
+instance HasField "wxwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w x w z
+
+instance HasField "wxww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w x w w
+
+instance HasField "wyxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w y x x
+
+instance HasField "wyxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w y x y
+
+instance HasField "wyxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w y x z
+
+instance HasField "wyxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w y x w
+
+instance HasField "wyyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w y y x
+
+instance HasField "wyyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w y y y
+
+instance HasField "wyyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w y y z
+
+instance HasField "wyyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w y y w
+
+instance HasField "wyzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w y z x
+
+instance HasField "wyzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w y z y
+
+instance HasField "wyzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w y z z
+
+instance HasField "wyzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w y z w
+
+instance HasField "wywx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w y w x
+
+instance HasField "wywy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w y w y
+
+instance HasField "wywz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w y w z
+
+instance HasField "wyww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w y w w
+
+instance HasField "wzxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w z x x
+
+instance HasField "wzxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w z x y
+
+instance HasField "wzxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w z x z
+
+instance HasField "wzxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w z x w
+
+instance HasField "wzyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y z w -> vec4 w z y x
+
+instance HasField "wzyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w z y y
+
+instance HasField "wzyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w z y z
+
+instance HasField "wzyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w z y w
+
+instance HasField "wzzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w z z x
+
+instance HasField "wzzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w z z y
+
+instance HasField "wzzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w z z z
+
+instance HasField "wzzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w z z w
+
+instance HasField "wzwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w z w x
+
+instance HasField "wzwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w z w y
+
+instance HasField "wzwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w z w z
+
+instance HasField "wzww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w z w w
+
+instance HasField "wwxx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w w x x
+
+instance HasField "wwxy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w w x y
+
+instance HasField "wwxz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w w x z
+
+instance HasField "wwxw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w w x w
+
+instance HasField "wwyx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x y _ w -> vec4 w w y x
+
+instance HasField "wwyy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w w y y
+
+instance HasField "wwyz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w w y z
+
+instance HasField "wwyw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w w y w
+
+instance HasField "wwzx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ z w -> vec4 w w z x
+
+instance HasField "wwzy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y z w -> vec4 w w z y
+
+instance HasField "wwzz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w w z z
+
+instance HasField "wwzw" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w w z w
+
+instance HasField "wwwx" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ w -> vec4 w w w x
+
+instance HasField "wwwy" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ w -> vec4 w w w y
+
+instance HasField "wwwz" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z w -> vec4 w w w z
+
+instance HasField "wwww" Vec4 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ _ w -> vec4 w w w w
diff --git a/src/Geomancy/Swizzle/Vec/Up.hs b/src/Geomancy/Swizzle/Vec/Up.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Swizzle/Vec/Up.hs
@@ -0,0 +1,433 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+module Geomancy.Swizzle.Vec.Up () where
+
+import GHC.Records (HasField(..))
+
+import Geomancy.Vec2 (Vec2, withVec2)
+import Geomancy.Vec3 (Vec3, vec3, withVec3)
+import Geomancy.Vec4 (Vec4, vec4)
+
+instance HasField "xxx" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x _ -> vec3 x x x
+
+instance HasField "xxy" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 x x y
+
+instance HasField "xyx" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 x y x
+
+instance HasField "xyy" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 x y y
+
+instance HasField "yxx" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 y x x
+
+instance HasField "yxy" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 y x y
+
+instance HasField "yyx" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec3 y y x
+
+instance HasField "yyy" Vec2 Vec3 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \_ y -> vec3 y y y
+
+instance HasField "xxxx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x _ -> vec4 x x x x
+
+instance HasField "xxxy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x x x y
+
+instance HasField "xxyx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x x y x
+
+instance HasField "xxyy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x x y y
+
+instance HasField "xyxx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y x x
+
+instance HasField "xyxy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y x y
+
+instance HasField "xyyx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y y x
+
+instance HasField "xyyy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 x y y y
+
+instance HasField "yxxx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y x x x
+
+instance HasField "yxxy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y x x y
+
+instance HasField "yxyx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y x y x
+
+instance HasField "yxyy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y x y y
+
+instance HasField "yyxx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y y x x
+
+instance HasField "yyxy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y y x y
+
+instance HasField "yyyx" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x y -> vec4 y y y x
+
+instance HasField "yyyy" Vec2 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \_ y -> vec4 y y y y
+
+instance HasField "xxxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ _ -> vec4 x x x x
+
+instance HasField "xxxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x x x y
+
+instance HasField "xxxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x x x z
+
+instance HasField "xxyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x x y x
+
+instance HasField "xxyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x x y y
+
+instance HasField "xxyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x x y z
+
+instance HasField "xxzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x x z x
+
+instance HasField "xxzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x x z y
+
+instance HasField "xxzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x x z z
+
+instance HasField "xyxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x y x x
+
+instance HasField "xyxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x y x y
+
+instance HasField "xyxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y x z
+
+instance HasField "xyyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x y y x
+
+instance HasField "xyyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 x y y y
+
+instance HasField "xyyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y y z
+
+instance HasField "xyzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y z x
+
+instance HasField "xyzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y z y
+
+instance HasField "xyzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x y z z
+
+instance HasField "xzxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x z x x
+
+instance HasField "xzxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x z x y
+
+instance HasField "xzxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x z x z
+
+instance HasField "xzyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x z y x
+
+instance HasField "xzyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x z y y
+
+instance HasField "xzyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x z y z
+
+instance HasField "xzzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x z z x
+
+instance HasField "xzzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 x z z y
+
+instance HasField "xzzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 x z z z
+
+instance HasField "yxxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y x x x
+
+instance HasField "yxxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y x x y
+
+instance HasField "yxxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y x x z
+
+instance HasField "yxyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y x y x
+
+instance HasField "yxyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y x y y
+
+instance HasField "yxyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y x y z
+
+instance HasField "yxzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y x z x
+
+instance HasField "yxzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y x z y
+
+instance HasField "yxzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y x z z
+
+instance HasField "yyxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y y x x
+
+instance HasField "yyxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y y x y
+
+instance HasField "yyxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y y x z
+
+instance HasField "yyyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y _ -> vec4 y y y x
+
+instance HasField "yyyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y _ -> vec4 y y y y
+
+instance HasField "yyyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y y y z
+
+instance HasField "yyzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y y z x
+
+instance HasField "yyzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y y z y
+
+instance HasField "yyzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y y z z
+
+instance HasField "yzxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y z x x
+
+instance HasField "yzxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y z x y
+
+instance HasField "yzxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y z x z
+
+instance HasField "yzyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y z y x
+
+instance HasField "yzyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y z y y
+
+instance HasField "yzyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y z y z
+
+instance HasField "yzzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 y z z x
+
+instance HasField "yzzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y z z y
+
+instance HasField "yzzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 y z z z
+
+instance HasField "zxxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z x x x
+
+instance HasField "zxxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z x x y
+
+instance HasField "zxxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z x x z
+
+instance HasField "zxyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z x y x
+
+instance HasField "zxyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z x y y
+
+instance HasField "zxyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z x y z
+
+instance HasField "zxzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z x z x
+
+instance HasField "zxzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z x z y
+
+instance HasField "zxzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z x z z
+
+instance HasField "zyxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z y x x
+
+instance HasField "zyxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z y x y
+
+instance HasField "zyxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z y x z
+
+instance HasField "zyyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z y y x
+
+instance HasField "zyyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z y y y
+
+instance HasField "zyyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z y y z
+
+instance HasField "zyzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z y z x
+
+instance HasField "zyzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z y z y
+
+instance HasField "zyzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z y z z
+
+instance HasField "zzxx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z z x x
+
+instance HasField "zzxy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z z x y
+
+instance HasField "zzxz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z z x z
+
+instance HasField "zzyx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x y z -> vec4 z z y x
+
+instance HasField "zzyy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z z y y
+
+instance HasField "zzyz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z z y z
+
+instance HasField "zzzx" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ z -> vec4 z z z x
+
+instance HasField "zzzy" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y z -> vec4 z z z y
+
+instance HasField "zzzz" Vec3 Vec4 where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ _ z -> vec4 z z z z
diff --git a/src/Geomancy/Transform.hs b/src/Geomancy/Transform.hs
--- a/src/Geomancy/Transform.hs
+++ b/src/Geomancy/Transform.hs
@@ -57,7 +57,7 @@
 import Graphics.Gl.Block (Block(..))
 
 newtype Transform = Transform { unTransform :: Mat4 }
-  deriving newtype (Show, Semigroup, Monoid, Storable)
+  deriving newtype (Eq, Show, Semigroup, Monoid, Storable)
 #ifdef TH_LIFT
   deriving Lift
 #endif
diff --git a/src/Geomancy/U64Vec2.hs b/src/Geomancy/U64Vec2.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/U64Vec2.hs
@@ -0,0 +1,255 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.U64Vec2
+  ( U64Vec2
+  , u64vec2
+  , withU64Vec2
+  , pattern WithU64Vec2
+  , convert
+  , fromTuple
+  , dot
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.Word (Word64)
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data U64Vec2 = U64Vec2
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE u64vec2 #-}
+u64vec2 :: Word64 -> Word64 -> U64Vec2
+u64vec2 = U64Vec2
+
+{-# INLINE withU64Vec2 #-}
+withU64Vec2
+  :: U64Vec2
+  -> (Word64 -> Word64 -> r)
+  -> r
+withU64Vec2 (U64Vec2 a b) f = f a b
+
+pattern WithU64Vec2 :: Word64 -> Word64 -> U64Vec2
+pattern WithU64Vec2 a b <- ((`withU64Vec2` (,)) -> (a, b))
+{-# COMPLETE WithU64Vec2 #-}
+
+instance HasField "x" U64Vec2 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \x _ -> x
+
+instance HasField "y" U64Vec2 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec2 v \_ y -> y
+
+{-# INLINE convert #-}
+convert :: Coercible v U64Vec2 => (Word64 -> a) -> (a -> a -> r) -> v -> r
+convert f t v =
+  withU64Vec2 (coerce v) \a b ->
+    t (f a) (f b)
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Word64, Word64) -> U64Vec2
+fromTuple (x, y) = u64vec2 x y
+
+instance NFData U64Vec2 where
+  rnf U64Vec2{} = ()
+
+type instance Element U64Vec2 = Word64
+
+instance MonoFunctor U64Vec2 where
+  {-# INLINE omap #-}
+  omap f v =
+    withU64Vec2 v \x y ->
+      u64vec2 (f x) (f y)
+
+instance MonoPointed U64Vec2 where
+  {-# INLINE opoint #-}
+  opoint x = u64vec2 x x
+
+instance Elementwise U64Vec2 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withU64Vec2 p0 \x0 y0 ->
+    withU64Vec2 p1 \x1 y1 ->
+      u64vec2
+        (f x0 x1)
+        (f y0 y1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withU64Vec2 p0 \x0 y0 ->
+    withU64Vec2 p1 \x1 y1 ->
+    withU64Vec2 p2 \x2 y2 ->
+      u64vec2
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withU64Vec2 p0 \x0 y0 ->
+    withU64Vec2 p1 \x1 y1 ->
+    withU64Vec2 p2 \x2 y2 ->
+    withU64Vec2 p3 \x3 y3 ->
+      u64vec2
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withU64Vec2 p0 \x0 y0 ->
+    withU64Vec2 p1 \x1 y1 ->
+    withU64Vec2 p2 \x2 y2 ->
+    withU64Vec2 p3 \x3 y3 ->
+    withU64Vec2 p4 \x4 y4 ->
+      u64vec2
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+
+instance Num U64Vec2 where
+  {-# INLINE (+) #-}
+  U64Vec2 l1 l2 + U64Vec2 r1 r2 =
+    U64Vec2
+      (l1 + r1)
+      (l2 + r2)
+
+  {-# INLINE (-) #-}
+  U64Vec2 l1 l2 - U64Vec2 r1 r2 =
+    U64Vec2
+      (l1 - r1)
+      (l2 - r2)
+
+  {-# INLINE (*) #-}
+  U64Vec2 l1 l2 * U64Vec2 r1 r2 =
+    U64Vec2
+      (l1 * r1)
+      (l2 * r2)
+
+  {-# INLINE abs #-}
+  abs (U64Vec2 a b) =
+    U64Vec2 (abs a) (abs b)
+
+  {-# INLINE signum #-}
+  signum v2 = withU64Vec2 v2 \a b ->
+    u64vec2 (signum a) (signum b)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = U64Vec2 x' x'
+    where
+      x' = fromInteger x
+
+{-# INLINE dot #-}
+dot :: U64Vec2 -> U64Vec2 -> Word64
+dot (U64Vec2 l1 l2) (U64Vec2 r1 r2) =
+  l1 * r1 + l2 * r2
+
+instance Storable U64Vec2 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 16
+
+  {-# INLINE alignment #-}
+  alignment _ = 16
+
+  {-# INLINE poke #-}
+  poke ptr v4 =
+    withU64Vec2 v4 \a b -> do
+      pokeByteOff ptr 0 a
+      pokeByteOff ptr 8 b
+
+  {-# INLINE peek #-}
+  peek ptr = u64vec2
+    <$> peekByteOff ptr 0
+    <*> peekByteOff ptr 8
+
+instance Block U64Vec2 where
+  type PackedSize U64Vec2 = 16
+  alignment140 _  = 16
+  sizeOf140 _     = 16
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix U64Vec2 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withU64Vec2 l \l1 l2 ->
+      withU64Vec2 u \u1 u2 ->
+        u64vec2
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withU64Vec2 l \l1 l2 ->
+      withU64Vec2 u \u1 u2 ->
+        withU64Vec2 i \i1 i2 ->
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) *
+          unsafeIndex (l1, u1) i1
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withU64Vec2 l \l1 l2 ->
+      withU64Vec2 u \u1 u2 ->
+        withU64Vec2 i \i1 i2 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2
+
+#ifdef SERIALISE
+instance Serialise U64Vec2 where
+  encode v = withU64Vec2 v \x y ->
+    Serialise.encodeListLen 2 <> encode x <> encode y
+  decode =
+    Serialise.decodeListLenOf 2 *> (u64vec2 <$> decode <*> decode)
+#endif
diff --git a/src/Geomancy/U64Vec3.hs b/src/Geomancy/U64Vec3.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/U64Vec3.hs
@@ -0,0 +1,349 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.U64Vec3
+  ( U64Vec3
+  , u64vec3
+  , withU64Vec3
+  , pattern WithU64Vec3
+  , convert
+  , fromTuple
+  , dot
+
+  , Packed(..)
+  , packed
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.Word (Word64)
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
+import WebColor.Labels (IsWebColor(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data U64Vec3 = U64Vec3
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE u64vec3 #-}
+u64vec3 :: Word64 -> Word64 -> Word64 -> U64Vec3
+u64vec3 = U64Vec3
+
+{-# INLINE withU64Vec3 #-}
+withU64Vec3
+  :: U64Vec3
+  -> (Word64 -> Word64 -> Word64 -> r)
+  -> r
+withU64Vec3 (U64Vec3 a b c) f = f a b c
+
+pattern WithU64Vec3 :: Word64 -> Word64 -> Word64 -> U64Vec3
+pattern WithU64Vec3 a b c <- ((`withU64Vec3` (,,)) -> (a, b, c))
+{-# COMPLETE WithU64Vec3 #-}
+
+instance HasField "x" U64Vec3 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \x _ _ -> x
+
+instance HasField "y" U64Vec3 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ y _ -> y
+
+instance HasField "z" U64Vec3 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec3 v \_ _ z -> z
+
+{-# INLINE convert #-}
+convert :: Coercible v U64Vec3 => (Word64 -> a) -> (a -> a -> a -> r) -> v -> r
+convert f t v =
+  withU64Vec3 (coerce v) \a b c ->
+    t (f a) (f b) (f c)
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Word64, Word64, Word64) -> U64Vec3
+fromTuple (a, b, c) = u64vec3 a b c
+
+{-# INLINE dot #-}
+dot :: U64Vec3 -> U64Vec3 -> Word64
+dot (U64Vec3 l1 l2 l3) (U64Vec3 r1 r2 r3) =
+  l1 * r1 + l2 * r2 + l3 * r3
+
+instance IsWebColor s => IsLabel s U64Vec3 where
+  {-# INLINE fromLabel #-}
+  fromLabel =
+    webColor @s \r g b ->
+      u64vec3 (fromIntegral r) (fromIntegral g) (fromIntegral b)
+
+instance NFData U64Vec3 where
+  rnf U64Vec3{} = ()
+
+type instance Element U64Vec3 = Word64
+
+instance MonoFunctor U64Vec3 where
+  {-# INLINE omap #-}
+  omap f v =
+    withU64Vec3 v \x y z ->
+      u64vec3 (f x) (f y) (f z)
+
+instance MonoPointed U64Vec3 where
+  {-# INLINE opoint #-}
+  opoint x = u64vec3 x x x
+
+instance Elementwise U64Vec3 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withU64Vec3 p0 \x0 y0 z0 ->
+    withU64Vec3 p1 \x1 y1 z1 ->
+      u64vec3
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withU64Vec3 p0 \x0 y0 z0 ->
+    withU64Vec3 p1 \x1 y1 z1 ->
+    withU64Vec3 p2 \x2 y2 z2 ->
+      u64vec3
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withU64Vec3 p0 \x0 y0 z0 ->
+    withU64Vec3 p1 \x1 y1 z1 ->
+    withU64Vec3 p2 \x2 y2 z2 ->
+    withU64Vec3 p3 \x3 y3 z3 ->
+      u64vec3
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withU64Vec3 p0 \x0 y0 z0 ->
+    withU64Vec3 p1 \x1 y1 z1 ->
+    withU64Vec3 p2 \x2 y2 z2 ->
+    withU64Vec3 p3 \x3 y3 z3 ->
+    withU64Vec3 p4 \x4 y4 z4 ->
+      u64vec3
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+
+instance Num U64Vec3 where
+  {-# INLINE (+) #-}
+  U64Vec3 l1 l2 l3 + U64Vec3 r1 r2 r3 =
+    U64Vec3
+      (l1 + r1)
+      (l2 + r2)
+      (l3 + r3)
+
+  {-# INLINE (-) #-}
+  U64Vec3 l1 l2 l3 - U64Vec3 r1 r2 r3 =
+    U64Vec3
+      (l1 - r1)
+      (l2 - r2)
+      (l3 - r3)
+
+  {-# INLINE (*) #-}
+  U64Vec3 l1 l2 l3 * U64Vec3 r1 r2 r3 =
+    U64Vec3
+      (l1 * r1)
+      (l2 * r2)
+      (l3 * r3)
+
+  {-# INLINE abs #-}
+  abs x = x
+
+  {-# INLINE signum #-}
+  signum v3 = withU64Vec3 v3 \a b c ->
+    u64vec3 (signum a) (signum b) (signum c)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = U64Vec3 x' x' x'
+    where
+      x' = fromInteger x
+
+instance Storable U64Vec3 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr v3 =
+    withU64Vec3 v3 \a b c -> do
+      pokeByteOff ptr  0 a
+      pokeByteOff ptr  8 b
+      pokeByteOff ptr 16 c
+
+  {-# INLINE peek #-}
+  peek ptr = u64vec3
+    <$> peekByteOff ptr  0
+    <*> peekByteOff ptr  8
+    <*> peekByteOff ptr  16
+
+newtype Packed = Packed { unPacked :: U64Vec3 }
+  deriving (Eq, Ord, Show, NFData, Num)
+
+{-# INLINE packed #-}
+packed :: Word64 -> Word64 -> Word64 -> Packed
+packed a b c = Packed (u64vec3 a b c)
+
+instance HasField "x" Packed Word64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withU64Vec3 v \x _ _ -> x
+
+instance HasField "y" Packed Word64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withU64Vec3 v \_ y _ -> y
+
+instance HasField "z" Packed Word64 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withU64Vec3 v \_ _ z -> z
+
+instance Storable Packed where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 24
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr (Packed v3) =
+    withU64Vec3 v3 \a b c -> do
+      pokeByteOff ptr 0 a
+      pokeByteOff ptr 8 b
+      pokeByteOff ptr 16 c
+
+  {-# INLINE peek #-}
+  peek ptr = packed
+    <$> peekByteOff ptr 0
+    <*> peekByteOff ptr 8
+    <*> peekByteOff ptr 16
+
+instance Block U64Vec3 where
+  type PackedSize U64Vec3 = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 32
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Block Packed where
+  type PackedSize Packed = 24
+  alignment140 _  = 32
+  sizeOf140 _     = 24
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix U64Vec3 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withU64Vec3 l \l1 l2 l3 ->
+      withU64Vec3 u \u1 u2 u3 ->
+        u64vec3
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+          <*> range (l3, u3)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withU64Vec3 l \l1 l2 l3 ->
+      withU64Vec3 u \u1 u2 u3 ->
+        withU64Vec3 i \i1 i2 i3 ->
+          unsafeIndex (l3, u3) i3 + unsafeRangeSize (l3, u3) * (
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) * (
+          unsafeIndex (l1, u1) i1))
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withU64Vec3 l \l1 l2 l3 ->
+      withU64Vec3 u \u1 u2 u3 ->
+        withU64Vec3 i \i1 i2 i3 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2 &&
+          inRange (l3, u3) i3
+
+#ifdef SERIALISE
+instance Serialise U64Vec3 where
+  encode v = withU64Vec3 v \x y z ->
+    Serialise.encodeListLen 3 <> encode x <> encode y <> encode z
+  decode =
+    Serialise.decodeListLenOf 3 *> (u64vec3 <$> decode <*> decode <*> decode)
+#endif
diff --git a/src/Geomancy/U64Vec4.hs b/src/Geomancy/U64Vec4.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/U64Vec4.hs
@@ -0,0 +1,288 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+
+#ifdef TH_LIFT
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE DerivingStrategies #-}
+#endif
+
+
+module Geomancy.U64Vec4
+  ( U64Vec4
+  , u64vec4
+  , withU64Vec4
+  , pattern WithU64Vec4
+  , convert
+  , fromTuple
+  , dot
+  ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.Coerce (Coercible, coerce)
+import Data.MonoTraversable (Element, MonoFunctor(..), MonoPointed(..))
+import Data.Word (Word64)
+import Foreign (Storable(..))
+import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
+
+#ifdef TH_LIFT
+import Language.Haskell.TH.Syntax (Lift)
+#endif
+
+#ifdef SERIALISE
+import Codec.Serialise (Serialise(..))
+import qualified Codec.Serialise.Encoding as Serialise
+import qualified Codec.Serialise.Decoding as Serialise
+#endif
+
+import Geomancy.Elementwise (Elementwise(..))
+import Graphics.Gl.Block (Block(..))
+
+data U64Vec4 = U64Vec4
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  {-# UNPACK #-} !Word64
+  deriving (Eq, Ord, Show)
+#ifdef TH_LIFT
+  deriving Lift
+#endif
+
+{-# INLINE u64vec4 #-}
+u64vec4 :: Word64 -> Word64 -> Word64 -> Word64 -> U64Vec4
+u64vec4 = U64Vec4
+
+{-# INLINE withU64Vec4 #-}
+withU64Vec4
+  :: U64Vec4
+  -> (Word64 -> Word64 -> Word64 -> Word64 -> r)
+  -> r
+withU64Vec4 (U64Vec4 a b c d) f = f a b c d
+
+pattern WithU64Vec4 :: Word64 -> Word64 -> Word64 -> Word64 -> U64Vec4
+pattern WithU64Vec4 a b c d <- ((`withU64Vec4` (,,,)) -> (a, b, c, d))
+{-# COMPLETE WithU64Vec4 #-}
+
+instance HasField "x" U64Vec4 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \x _ _ _ -> x
+
+instance HasField "y" U64Vec4 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ y _ _ -> y
+
+instance HasField "z" U64Vec4 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ z _ -> z
+
+instance HasField "w" U64Vec4 Word64 where
+  {-# INLINE getField #-}
+  getField v = withU64Vec4 v \_ _ _ w -> w
+
+{-# INLINE convert #-}
+convert :: Coercible v U64Vec4 => (Word64 -> a) -> (a -> a -> a -> a -> r) -> v -> r
+convert f t v =
+  withU64Vec4 (coerce v) \a b c d ->
+    t (f a) (f b) (f c) (f d)
+
+{-# INLINE fromTuple #-}
+fromTuple :: (Word64, Word64, Word64, Word64) -> U64Vec4
+fromTuple (x, y, z, w) = u64vec4 x y z w
+
+instance NFData U64Vec4 where
+  rnf U64Vec4{} = ()
+
+type instance Element U64Vec4 = Word64
+
+instance MonoFunctor U64Vec4 where
+  {-# INLINE omap #-}
+  omap f v =
+    withU64Vec4 v \x y z w ->
+      u64vec4 (f x) (f y) (f z) (f w)
+
+instance MonoPointed U64Vec4 where
+  {-# INLINE opoint #-}
+  opoint x = u64vec4 x x x x
+
+instance Elementwise U64Vec4 where
+  {-# INLINE emap2 #-}
+  emap2 f p0 p1 =
+    withU64Vec4 p0 \x0 y0 z0 w0 ->
+    withU64Vec4 p1 \x1 y1 z1 w1 ->
+      u64vec4
+        (f x0 x1)
+        (f y0 y1)
+        (f z0 z1)
+        (f w0 w1)
+
+  {-# INLINE emap3 #-}
+  emap3 f p0 p1 p2 =
+    withU64Vec4 p0 \x0 y0 z0 w0 ->
+    withU64Vec4 p1 \x1 y1 z1 w1 ->
+    withU64Vec4 p2 \x2 y2 z2 w2 ->
+      u64vec4
+        (f x0 x1 x2)
+        (f y0 y1 y2)
+        (f z0 z1 z2)
+        (f w0 w1 w2)
+
+  {-# INLINE emap4 #-}
+  emap4 f p0 p1 p2 p3 =
+    withU64Vec4 p0 \x0 y0 z0 w0 ->
+    withU64Vec4 p1 \x1 y1 z1 w1 ->
+    withU64Vec4 p2 \x2 y2 z2 w2 ->
+    withU64Vec4 p3 \x3 y3 z3 w3 ->
+      u64vec4
+        (f x0 x1 x2 x3)
+        (f y0 y1 y2 y3)
+        (f z0 z1 z2 z3)
+        (f w0 w1 w2 w3)
+
+  {-# INLINE emap5 #-}
+  emap5 f p0 p1 p2 p3 p4 =
+    withU64Vec4 p0 \x0 y0 z0 w0 ->
+    withU64Vec4 p1 \x1 y1 z1 w1 ->
+    withU64Vec4 p2 \x2 y2 z2 w2 ->
+    withU64Vec4 p3 \x3 y3 z3 w3 ->
+    withU64Vec4 p4 \x4 y4 z4 w4 ->
+      u64vec4
+        (f x0 x1 x2 x3 x4)
+        (f y0 y1 y2 y3 y4)
+        (f z0 z1 z2 z3 z4)
+        (f w0 w1 w2 w3 w4)
+
+instance Num U64Vec4 where
+  {-# INLINE (+) #-}
+  U64Vec4 l1 l2 l3 l4 + U64Vec4 r1 r2 r3 r4 =
+    U64Vec4
+      (l1 + r1)
+      (l2 + r2)
+      (l3 + r3)
+      (l4 + r4)
+
+  {-# INLINE (-) #-}
+  U64Vec4 l1 l2 l3 l4 - U64Vec4 r1 r2 r3 r4 =
+    U64Vec4
+      (l1 - r1)
+      (l2 - r2)
+      (l3 - r3)
+      (l4 - r4)
+
+  {-# INLINE (*) #-}
+  U64Vec4 l1 l2 l3 l4 * U64Vec4 r1 r2 r3 r4 =
+    U64Vec4
+      (l1 * r1)
+      (l2 * r2)
+      (l3 * r3)
+      (l4 * r4)
+
+  {-# INLINE abs #-}
+  abs x = x
+
+  {-# INLINE signum #-}
+  signum v4 = withU64Vec4 v4 \a b c d ->
+    u64vec4 (signum a) (signum b) (signum c) (signum d)
+
+  {-# INLINE fromInteger #-}
+  fromInteger x = U64Vec4 x' x' x' x'
+    where
+      x' = fromInteger x
+
+instance Storable U64Vec4 where
+  {-# INLINE sizeOf #-}
+  sizeOf _ = 32
+
+  {-# INLINE alignment #-}
+  alignment _ = 8
+
+  {-# INLINE poke #-}
+  poke ptr v4 =
+    withU64Vec4 v4 \a b c d -> do
+      pokeByteOff ptr  0 a
+      pokeByteOff ptr  8 b
+      pokeByteOff ptr 16 c
+      pokeByteOff ptr 24 d
+
+  {-# INLINE peek #-}
+  peek ptr = u64vec4
+    <$> peekByteOff ptr  0
+    <*> peekByteOff ptr  8
+    <*> peekByteOff ptr  16
+    <*> peekByteOff ptr 24
+
+instance Block U64Vec4 where
+  type PackedSize U64Vec4 = 32
+  alignment140 _  = 32
+  sizeOf140 _     = 32
+  alignment430    = alignment140
+  sizeOf430       = sizeOf140
+  isStruct _      = False
+  read140     = peekDiffOff
+  write140    = pokeDiffOff
+  read430     = read140
+  write430    = write140
+  readPacked  = read140
+  writePacked = write140
+  {-# INLINE alignment140 #-}
+  {-# INLINE sizeOf140 #-}
+  {-# INLINE alignment430 #-}
+  {-# INLINE sizeOf430 #-}
+  {-# INLINE isStruct #-}
+  {-# INLINE read140 #-}
+  {-# INLINE write140 #-}
+  {-# INLINE read430 #-}
+  {-# INLINE write430 #-}
+  {-# INLINE readPacked #-}
+  {-# INLINE writePacked #-}
+
+instance Ix U64Vec4 where
+  {-# INLINE range #-}
+  range (l, u) =
+    withU64Vec4 l \l1 l2 l3 l4 ->
+      withU64Vec4 u \u1 u2 u3 u4 ->
+        u64vec4
+          <$> range (l1, u1)
+          <*> range (l2, u2)
+          <*> range (l3, u3)
+          <*> range (l4, u4)
+
+  {-# INLINE unsafeIndex #-}
+  unsafeIndex (l, u) i =
+    withU64Vec4 l \l1 l2 l3 l4 ->
+      withU64Vec4 u \u1 u2 u3 u4 ->
+        withU64Vec4 i \i1 i2 i3 i4 ->
+          unsafeIndex (l4, u4) i4 + unsafeRangeSize (l4, u4) * (
+          unsafeIndex (l3, u3) i3 + unsafeRangeSize (l3, u3) * (
+          unsafeIndex (l2, u2) i2 + unsafeRangeSize (l2, u2) * (
+          unsafeIndex (l1, u1) i1)))
+
+  {-# INLINE inRange #-}
+  inRange (l, u) i =
+    withU64Vec4 l \l1 l2 l3 l4 ->
+      withU64Vec4 u \u1 u2 u3 u4 ->
+        withU64Vec4 i \i1 i2 i3 i4 ->
+          inRange (l1, u1) i1 &&
+          inRange (l2, u2) i2 &&
+          inRange (l3, u3) i3 &&
+          inRange (l4, u4) i4
+
+{-# INLINE dot #-}
+dot :: U64Vec4 -> U64Vec4 -> Word64
+dot (U64Vec4 l1 l2 l3 l4) (U64Vec4 r1 r2 r3 r4) =
+  l1 * r1 + l2 * r2 + l3 * r3 + l4 * r4
+
+#ifdef SERIALISE
+instance Serialise U64Vec4 where
+  encode v = withU64Vec4 v \x y z w ->
+    Serialise.encodeListLen 4 <> encode x <> encode y <> encode z <> encode w
+  decode =
+    Serialise.decodeListLenOf 4 *> (u64vec4 <$> decode <*> decode <*> decode <*> decode)
+#endif
diff --git a/src/Geomancy/UVec2.hs b/src/Geomancy/UVec2.hs
--- a/src/Geomancy/UVec2.hs
+++ b/src/Geomancy/UVec2.hs
@@ -2,6 +2,8 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
@@ -30,6 +32,7 @@
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
 
 #ifdef TH_LIFT
 import Language.Haskell.TH.Syntax (Lift)
@@ -66,6 +69,14 @@
 pattern WithUVec2 :: Word32 -> Word32 -> UVec2
 pattern WithUVec2 a b <- ((`withUVec2` (,)) -> (a, b))
 {-# COMPLETE WithUVec2 #-}
+
+instance HasField "x" UVec2 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \x _ -> x
+
+instance HasField "y" UVec2 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec2 v \_ y -> y
 
 {-# INLINE convert #-}
 convert :: Coercible v UVec2 => (Word32 -> a) -> (a -> a -> r) -> v -> r
diff --git a/src/Geomancy/UVec3.hs b/src/Geomancy/UVec3.hs
--- a/src/Geomancy/UVec3.hs
+++ b/src/Geomancy/UVec3.hs
@@ -39,6 +39,7 @@
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
 import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
 import WebColor.Labels (IsWebColor(..))
 
 #ifdef TH_LIFT
@@ -78,6 +79,18 @@
 pattern WithUVec3 a b c <- ((`withUVec3` (,,)) -> (a, b, c))
 {-# COMPLETE WithUVec3 #-}
 
+instance HasField "x" UVec3 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \x _ _ -> x
+
+instance HasField "y" UVec3 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ y _ -> y
+
+instance HasField "z" UVec3 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec3 v \_ _ z -> z
+
 {-# INLINE convert #-}
 convert :: Coercible v UVec3 => (Word32 -> a) -> (a -> a -> a -> r) -> v -> r
 convert f t v =
@@ -218,6 +231,18 @@
 {-# INLINE packed #-}
 packed :: Word32 -> Word32 -> Word32 -> Packed
 packed a b c = Packed (uvec3 a b c)
+
+instance HasField "x" Packed Word32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withUVec3 v \x _ _ -> x
+
+instance HasField "y" Packed Word32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withUVec3 v \_ y _ -> y
+
+instance HasField "z" Packed Word32 where
+  {-# INLINE getField #-}
+  getField (Packed v) = withUVec3 v \_ _ z -> z
 
 instance Storable Packed where
   {-# INLINE sizeOf #-}
diff --git a/src/Geomancy/UVec4.hs b/src/Geomancy/UVec4.hs
--- a/src/Geomancy/UVec4.hs
+++ b/src/Geomancy/UVec4.hs
@@ -2,6 +2,8 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
@@ -30,6 +32,7 @@
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.Ix (Ix(..))
+import GHC.Records (HasField(..))
 
 #ifdef TH_LIFT
 import Language.Haskell.TH.Syntax (Lift)
@@ -68,6 +71,22 @@
 pattern WithUVec4 :: Word32 -> Word32 -> Word32 -> Word32 -> UVec4
 pattern WithUVec4 a b c d <- ((`withUVec4` (,,,)) -> (a, b, c, d))
 {-# COMPLETE WithUVec4 #-}
+
+instance HasField "x" UVec4 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \x _ _ _ -> x
+
+instance HasField "y" UVec4 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ y _ _ -> y
+
+instance HasField "z" UVec4 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ z _ -> z
+
+instance HasField "w" UVec4 Word32 where
+  {-# INLINE getField #-}
+  getField v = withUVec4 v \_ _ _ w -> w
 
 {-# INLINE convert #-}
 convert :: Coercible v UVec4 => (Word32 -> a) -> (a -> a -> a -> a -> r) -> v -> r
diff --git a/src/Geomancy/Vec2.hs b/src/Geomancy/Vec2.hs
--- a/src/Geomancy/Vec2.hs
+++ b/src/Geomancy/Vec2.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -36,6 +37,7 @@
 import Data.VectorSpace (VectorSpace)
 import Foreign (Storable(..))
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
+import GHC.Records (HasField(..))
 import qualified Data.VectorSpace as VectorSpace
 
 #ifdef TH_LIFT
@@ -80,6 +82,14 @@
 pattern WithVec2 :: Float -> Float -> Vec2
 pattern WithVec2 a b <- ((`withVec2` (,)) -> (a, b))
 {-# COMPLETE WithVec2 #-}
+
+instance HasField "x" Vec2 Float where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \x _ -> x
+
+instance HasField "y" Vec2 Float where
+  {-# INLINE getField #-}
+  getField v = withVec2 v \_ y -> y
 
 {-# INLINE fromTuple #-}
 fromTuple :: (Float, Float) -> Vec2
diff --git a/src/Geomancy/Vec3.hs b/src/Geomancy/Vec3.hs
--- a/src/Geomancy/Vec3.hs
+++ b/src/Geomancy/Vec3.hs
@@ -53,6 +53,7 @@
 import Foreign (Storable(..), castPtr)
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
 import WebColor.Labels (IsWebColor(..))
 
 #ifdef TH_LIFT
@@ -100,6 +101,18 @@
 pattern WithVec3 a b c <- ((`withVec3` (,,)) -> (a, b, c))
 {-# COMPLETE WithVec3 #-}
 
+instance HasField "x" Vec3 Float where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \x _ _ -> x
+
+instance HasField "y" Vec3 Float where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ y _ -> y
+
+instance HasField "z" Vec3 Float where
+  {-# INLINE getField #-}
+  getField v = withVec3 v \_ _ z -> z
+
 {-# INLINE fromVec2 #-}
 fromVec2 :: Coercible Vec3 a => Vec2 -> Float -> a
 fromVec2 xy z =
@@ -407,6 +420,18 @@
 {-# INLINE packed #-}
 packed :: Float -> Float -> Float -> Packed
 packed x y z = Packed (vec3 x y z)
+
+instance HasField "x" Packed Float where
+  {-# INLINE getField #-}
+  getField (Packed v) = withVec3 v \x _ _ -> x
+
+instance HasField "y" Packed Float where
+  {-# INLINE getField #-}
+  getField (Packed v) = withVec3 v \_ y _ -> y
+
+instance HasField "z" Packed Float where
+  {-# INLINE getField #-}
+  getField (Packed v) = withVec3 v \_ _ z -> z
 
 instance Storable Packed where
   {-# INLINE sizeOf #-}
diff --git a/src/Geomancy/Vec4.hs b/src/Geomancy/Vec4.hs
--- a/src/Geomancy/Vec4.hs
+++ b/src/Geomancy/Vec4.hs
@@ -52,6 +52,7 @@
 import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
 import GHC.IO (IO(..))
 import GHC.OverloadedLabels (IsLabel(..))
+import GHC.Records (HasField(..))
 import Text.Printf (printf)
 import WebColor.Labels (IsWebColorAlpha(..))
 
@@ -73,22 +74,24 @@
 
 data Vec4 = Vec4 ByteArray#
 
-{-# INLINE vec4 #-}
+{-# INLINE [1] vec4 #-}
 vec4 :: Float -> Float -> Float -> Float -> Vec4
-vec4 (F# v0) (F# v1) (F# v2) (F# v3) =
+vec4 v0 v1 v2 v3 =
   runRW# \world ->
     let
-      !(# world_, arr #) = newAlignedPinnedByteArray# 16# 16# world
+      !(# world_, arr #) = newByteArray# 16# world
 
-      world0 = writeFloatArray# arr 0x0# v0 world_
-      world1 = writeFloatArray# arr 0x1# v1 world0
-      world2 = writeFloatArray# arr 0x2# v2 world1
-      world3 = writeFloatArray# arr 0x3# v3 world2
+      write i (F# v) = writeFloatArray# arr i v
+
+      world0 = write 0x0# v0 world_
+      world1 = write 0x1# v1 world0
+      world2 = write 0x2# v2 world1
+      world3 = write 0x3# v3 world2
       !(# _world', arr' #) = unsafeFreezeByteArray# arr world3
     in
       Vec4 arr'
 
-{-# INLINE withVec4 #-}
+{-# INLINE [1] withVec4 #-}
 withVec4
   :: Vec4
   -> (Float -> Float -> Float -> Float -> r)
@@ -100,31 +103,45 @@
     (F# (indexFloatArray# arr 0x2#))
     (F# (indexFloatArray# arr 0x3#))
 
+{-# RULES
+"withVec4/vec4" forall a b c d f.
+  withVec4 (vec4 a b c d) f = f a b c d
+"withVec4/withVec4" forall v k f.
+  withVec4 (withVec4 v k) f = withVec4 v \a b c d -> withVec4 (k a b c d) f
+  #-}
+
 {-# INLINE convert #-}
 convert :: Coercible v Vec4 => (Float -> a) -> (a -> a -> a -> a -> r) -> v -> r
 convert f t v =
   withVec4 (coerce v) \a b c d->
     t (f a) (f b) (f c) (f d)
 
-{-# INLINE compareVec4 #-}
-compareVec4 :: Vec4 -> Vec4 -> Ordering
-compareVec4 (Vec4 src1) (Vec4 src2) =
-  compare (I# (compareByteArrays# src1 0# src2 0# 16#)) 0
-
 instance Eq Vec4 where
-  (==) a b =
-    case compareVec4 a b of
-      EQ -> True
-      _  -> False
-
-  (/=) a b =
-    case compareVec4 a b of
-      EQ -> False
-      _  -> True
+  Vec4 a == Vec4 b = go 0#
+    where
+      go i
+        | isTrue# (i ==# 4#) = True
+        | isTrue# (eqFloat# (indexFloatArray# a i) (indexFloatArray# b i)) = go (i +# 1#)
+        | otherwise = False
 
 instance Ord Vec4 where
-  compare = compareVec4
+  compare = lexicographic LT GT compare
+  a < b = lexicographic True False (<) a b
+  a <= b = not (b < a)
+  a > b = b < a
+  a >= b = not (a < b)
 
+{-# INLINE lexicographic #-}
+lexicographic :: r -> r -> (Float -> Float -> r) -> Vec4 -> Vec4 -> r
+lexicographic lt gt lastElement (Vec4 a) (Vec4 b) = go 0#
+  where
+    go 3# = lastElement (F# (indexFloatArray# a 3#)) (F# (indexFloatArray# b 3#))
+    go i =
+      case compare (F# (indexFloatArray# a i)) (F# (indexFloatArray# b i)) of
+        LT -> lt
+        EQ -> go (i +# 1#)
+        GT -> gt
+
 instance Show Vec4 where
   show v =
     withVec4 v $
@@ -134,6 +151,22 @@
 pattern WithVec4 a b c d <- ((`withVec4` (,,,)) -> (a, b, c, d))
 {-# COMPLETE WithVec4 #-}
 
+instance HasField "x" Vec4 Float where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \x _ _ _ -> x
+
+instance HasField "y" Vec4 Float where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ y _ _ -> y
+
+instance HasField "z" Vec4 Float where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ z _ -> z
+
+instance HasField "w" Vec4 Float where
+  {-# INLINE getField #-}
+  getField v = withVec4 v \_ _ _ w -> w
+
 {-# INLINE fromVec2 #-}
 fromVec2 :: Vec2 -> Float -> Float -> Vec4
 fromVec2 xy z w =
@@ -185,6 +218,7 @@
       vec4 (f x) (f y) (f z) (f w)
 
 instance MonoPointed Vec4 where
+  {-# INLINE opoint #-}
   opoint x = vec4 x x x x
 
 instance Elementwise Vec4 where
@@ -300,20 +334,34 @@
 instance Floating Vec4 where
   pi = opoint pi
 
+  {-# INLINE exp #-}
   exp = omap exp
+  {-# INLINE log #-}
   log = omap log
+  {-# INLINE sqrt #-}
   sqrt = omap sqrt
+  {-# INLINE sin #-}
   sin = omap sin
+  {-# INLINE cos #-}
   cos = omap cos
+  {-# INLINE asin #-}
   asin = omap asin
+  {-# INLINE acos #-}
   acos = omap acos
+  {-# INLINE atan #-}
   atan = omap atan
+  {-# INLINE sinh #-}
   sinh = omap sinh
+  {-# INLINE cosh #-}
   cosh = omap cosh
+  {-# INLINE asinh #-}
   asinh = omap asinh
+  {-# INLINE acosh #-}
   acosh = omap acosh
+  {-# INLINE atanh #-}
   atanh = omap atanh
 
+  {-# INLINE (**) #-}
   a ** b =
     withVec4 a \ax ay az aw ->
     withVec4 b \bx by bz bw ->
@@ -333,18 +381,25 @@
   {-# INLINE poke #-}
   poke (Ptr addr) (Vec4 arr) = IO \world ->
     let
-      world' = copyByteArrayToAddr# arr 0# addr 16# world
+      store i = writeFloatOffAddr# addr i (indexFloatArray# arr i)
+
+      world0 = store 0x0# world
+      world1 = store 0x1# world0
+      world2 = store 0x2# world1
+      world' = store 0x3# world2
     in
       (# world', () #)
 
   {-# INLINE peek #-}
   peek (Ptr addr) = IO \world ->
     let
-      !(# world0, arr #)  = newAlignedPinnedByteArray# 16# 16# world
-      world1              = copyAddrToByteArray# addr arr 0# 16# world0
-      !(# world', arr' #) = unsafeFreezeByteArray# arr world1
+      !(# world0, v0 #) = readFloatOffAddr# addr 0x0# world
+      !(# world1, v1 #) = readFloatOffAddr# addr 0x1# world0
+      !(# world2, v2 #) = readFloatOffAddr# addr 0x2# world1
+      !(# world3, v3 #) = readFloatOffAddr# addr 0x3# world2
+      !v = vec4 (F# v0) (F# v1) (F# v2) (F# v3)
     in
-      (# world', Vec4 arr' #)
+      (# world3, v #)
 
 instance Block Vec4 where
   type PackedSize Vec4 = 16
@@ -452,10 +507,10 @@
 newVec4 =
   IO \world ->
     let
-      !(# world_, arr_ #) = newAlignedPinnedByteArray# 16# 16# world
-      !(# _world', arr #) = unsafeFreezeByteArray# arr_ world_
+      !(# world_, arr_ #) = newByteArray# 16# world
+      !(# world', arr #) = unsafeFreezeByteArray# arr_ world_
     in
-      (# world, Vec4 arr #)
+      (# world', Vec4 arr #)
 
 instance GlNearest Vec4
 
diff --git a/src/Geomancy/Vulkan/DProjection.hs b/src/Geomancy/Vulkan/DProjection.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Vulkan/DProjection.hs
@@ -0,0 +1,51 @@
+module Geomancy.Vulkan.DProjection
+  ( reverseDepthRH
+  , reverseDepthOrthoRH
+  , orthoRH
+  ) where
+
+import Geomancy.DMat4 (colMajor)
+import Geomancy.DTransform (DTransform(..))
+
+reverseDepthRH
+  :: Double
+  -> Double
+  -> Double -> Double
+  -> DTransform
+reverseDepthRH fovRads zn width height =
+  colMajor
+    sx  0 0  0
+    0  sy 0  0
+    0   0 0 zn
+    0   0 1  0
+  where
+    sx = sy * recipAspect
+      where
+        recipAspect = height / width
+    sy = 1 / tan (fovRads / 2)
+
+orthoRH :: Double -> Double -> Double -> Double -> DTransform
+orthoRH near far width height =
+  colMajor
+    sx 0 0 0
+    0 sy 0 0
+    0  0 z w
+    0  0 0 1
+  where
+    sx = 2 / width
+    sy = 2 / height
+    z = 1 / (far - near)
+    w = near / (near - far)
+
+reverseDepthOrthoRH :: Double -> Double -> Double -> Double -> DTransform
+reverseDepthOrthoRH near far width height =
+  colMajor
+    sx 0 0 0
+    0 sy 0 0
+    0  0 z w
+    0  0 0 1
+  where
+    sx = 2 / width
+    sy = 2 / height
+    z = 1 / (near - far)
+    w = far / (far - near)
diff --git a/src/Geomancy/Vulkan/DView.hs b/src/Geomancy/Vulkan/DView.hs
new file mode 100644
--- /dev/null
+++ b/src/Geomancy/Vulkan/DView.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE BlockArguments #-}
+
+module Geomancy.Vulkan.DView
+  ( lookAtRH
+  , lookAtRH_
+  ) where
+
+import Geomancy.DMat4 (colMajor)
+import Geomancy.DTransform (DTransform(..))
+import Geomancy.DVec3 (DVec3, cross, dot, normalize, dvec3, withDVec3)
+
+lookAtRH
+  :: DVec3
+  -> DVec3
+  -> DVec3
+  -> DTransform
+lookAtRH eye target up =
+  withDVec3 rgt \rx ry rz ->
+  withDVec3 up' \ux uy uz ->
+  withDVec3 fwd \fx fy fz ->
+  colMajor
+    rx ry rz (-er)
+    ux uy uz (-eu)
+    fx fy fz (-ef)
+     0  0  0    1
+  where
+    fwd = normalize (target - eye)
+    rgt = normalize (cross fwd up)
+    up' = normalize (cross fwd rgt)
+    er = dot eye rgt
+    eu = dot eye up'
+    ef = dot eye fwd
+
+{-# INLINE lookAtRH_ #-}
+lookAtRH_ :: DVec3 -> DVec3 -> DTransform
+lookAtRH_ eye target = lookAtRH eye target yNeg
+  where
+    yNeg = dvec3 0 (-1) 0
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Main (main) where
+
+import Test.Tasty (defaultMain, testGroup)
+
+import Spec.DMat4 qualified
+import Spec.DQuaternion qualified
+import Spec.DTransform qualified
+import Spec.DVec qualified
+import Spec.Fusion qualified
+import Spec.Mat4 qualified
+import Spec.Point qualified
+import Spec.Quaternion qualified
+import Spec.Storable qualified
+import Spec.Swizzle qualified
+import Spec.Transform qualified
+import Spec.Vec4 qualified
+import Spec.Vec64 qualified
+import Spec.Vulkan qualified
+
+main :: IO ()
+main = defaultMain $ testGroup "geomancy"
+  [ Spec.Mat4.tests
+  , Spec.Transform.tests
+  , Spec.Quaternion.tests
+  , Spec.Vulkan.tests
+  , Spec.DMat4.tests
+  , Spec.DTransform.tests
+  , Spec.DQuaternion.tests
+  , Spec.DVec.tests
+  , Spec.Vec4.tests
+  , Spec.Vec64.tests
+  , Spec.Point.tests
+  , Spec.Storable.tests
+  , Spec.Fusion.tests
+  , Spec.Swizzle.tests
+  ]
diff --git a/test/Spec.hs b/test/Spec.hs
deleted file mode 100644
--- a/test/Spec.hs
+++ /dev/null
@@ -1,430 +0,0 @@
-{-# LANGUAGE BlockArguments #-}
-{-# LANGUAGE ImportQualifiedPost #-}
-{-# LANGUAGE NumericUnderscores #-}
-{-# LANGUAGE PatternSynonyms #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE TypeApplications #-}
-
-import Geomancy
-import Hedgehog
-
-import Control.Monad (when)
-import Data.Foldable (toList)
-import GHC.Stack (withFrozenCallStack)
-import Hedgehog.Gen qualified as Gen
-import Hedgehog.Range qualified as Range
-import Linear qualified
-import Linear.Quaternion qualified
-import System.Exit (exitFailure, exitSuccess)
-import Text.Printf (printf)
-
-import Geomancy.Mat4 (withRowMajor, (!*))
-import Geomancy.Mat4 qualified
-import Geomancy.Quaternion qualified
-import Geomancy.Transform ((!.))
-import Geomancy.Transform qualified as Transform
-import Geomancy.Vulkan.Projection qualified as Projection
-import Geomancy.Vulkan.View qualified as View
-
-import Linear ((!*!))
-
-main :: IO ()
-main = do
-  passed <- checkParallel discovered
-  if passed then
-    exitSuccess
-  else
-    exitFailure
-
--- | Enough tests to cover the principles
-pattern PROP_TESTS :: TestLimit
-pattern PROP_TESTS = 10_000
-
--- | Try harder to catch FP precision errors
-pattern PROP_TESTS_BRUTAL :: TestLimit
-pattern PROP_TESTS_BRUTAL = 10_000_000
-
-prop_mat4_assoc :: Property
-prop_mat4_assoc = withTests PROP_TESTS $ property do
-  (p, p_) <- forAllTransform
-  (v, v_) <- forAllTransform
-  (m, m_) <- forAllTransform
-
-  let
-    pv'm = (p <> v) <> m
-    p'vm = p <> (v <> m)
-    delta' = nearlyEqualMat4 pv'm p'vm
-  replicate 16 Nothing === delta'
-
-  let
-    mv_p = (m_ !*! v_) !*! p_
-    m_vp = m_ !*! (v_ !*! p_)
-    delta_ = nearlyEqualM44 mv_p m_vp
-  replicate 16 Nothing === delta_
-
-  -- Inter-library calculated values nearlyEqual
-  replicate 16 Nothing === nearlyEqualM44 m_vp (toM44 p'vm)
-  replicate 16 Nothing === nearlyEqualM44 mv_p (toM44 pv'm)
-
-prop_mat4_order :: Property
-prop_mat4_order = withTests 1 $ property do
-  let
-    cm = Geomancy.Mat4.colMajor @Geomancy.Mat4.Mat4
-      0 1 2 3
-      4 5 6 7
-      8 9 0 1
-      2 3 4 5
-    rm = Geomancy.Mat4.rowMajor @Geomancy.Mat4.Mat4
-      0 4 8 2
-      1 5 9 3
-      2 6 0 4
-      3 7 1 5
-  Geomancy.Mat4.toListColMajor2d cm === Geomancy.Mat4.toListColMajor2d rm
-
-  let
-    cmT = Geomancy.Mat4.transpose cm
-    rmT = Geomancy.Mat4.transpose rm
-  Geomancy.Mat4.toListColMajor2d cmT === Geomancy.Mat4.toListColMajor2d rmT
-
-prop_transform_det :: Property
-prop_transform_det = withTests 1 $ property do
-  1     === Geomancy.Mat4.det Geomancy.Mat4.identity
-  1     === Geomancy.Mat4.det (Transform.rotateY (pi/6))  -- area-preserving
-  1     === Geomancy.Mat4.det (Transform.translate 1 2 3) -- area-preserving too
-  0     === Geomancy.Mat4.det (Transform.scaleX 0)        -- space collapse, no inverse
-  -1    === Geomancy.Mat4.det (Transform.scaleZ (-1))     -- flips the space
-  8     === Geomancy.Mat4.det (Transform.scale 2)         -- stretches a little
-  (1/8) === Geomancy.Mat4.det (Transform.scale (1/2))     -- stretches backwards
-
-prop_projection_reverseDepthRH :: Property
-prop_projection_reverseDepthRH = withTests 1 $ property do
-  let fov90 = pi / 2
-  let zNear = 0.1
-  let Transform p = Projection.reverseDepthRH fov90 zNear 800 600
-  annotateShow p
-  let
-    -- stating the expected in transposed order for testing
-    Transform expected = Geomancy.Mat4.rowMajor
-      0.7500 0.0000 0.0000 0.0000
-      0.0000 1.0000 0.0000 0.0000
-      0.0000 0.0000 0.0000 1.0000
-      0.0000 0.0000  zNear 0.0000
-  annotateShow expected
-  let delta_ = nearlyEqualMat4 p expected
-  replicate 16 Nothing === delta_
-
-  let
-    centerNearIn = vec4 0 0 zNear 1
-    centerNearOut = p !* centerNearIn
-    centerNearNDC = toNDC centerNearOut
-  annotateShow (centerNearIn, centerNearOut)
-  vec3 0 0 1 === centerNearNDC
-
-prop_projection_orthoRH_identity :: Property
-prop_projection_orthoRH_identity = withTests 1 $ property do
-  let Transform pNative = Projection.orthoRH 0 1 2 2
-  annotateShow pNative
-  let delta_ = nearlyEqualMat4 pNative mempty
-  replicate 16 Nothing === delta_
-
-prop_projection_reverseDepthOrthoRH :: Property
-prop_projection_reverseDepthOrthoRH = withTests 1 $ property do
-  let t = Projection.reverseDepthOrthoRH 1 10 800 600
-  annotateShow t
-
-  vec4 0 0 1 1 === t !* vec4 0 0 1 1 -- center/near
-  vec4 0 0 0 1 === t !* vec4 0 0 10 1 -- center/far
-  vec4 1 1 0 1 === t !* vec4 400 300 10 1 -- edge/far
-  vec4 (-1/400) (-1/300) 1 1 === t !* vec4 (-1) (-1) 1 1 -- step/near
-  vec4 (1/400) (1/300) 0 1 === t !* vec4 1 1 10 1 -- step/far
-
-toNDC :: Vec4 -> Vec3
-toNDC v = withVec4 v \x y z w -> vec3 (x/w) (y/w) (z/w)
-
-prop_view_lookAtRH_identity :: Property
-prop_view_lookAtRH_identity = property do
-  let alreadyThere = View.lookAtRH_ (vec3 0 0 0) (vec3 0 0 1)
-  annotateShow alreadyThere
-
-  p <- forAll genVec3
-
-  p === Transform.apply p alreadyThere
-
-xPos :: Vec3
-xPos = vec3 1 0 0
-
-xNeg :: Vec3
-xNeg = vec3 (-1) 0 0
-
-yPos :: Vec3
-yPos = vec3 0 1 0
-
-yNeg :: Vec3
-yNeg = vec3 0 (-1) 0
-
-zPos :: Vec3
-zPos = vec3 0 0 1
-
-zNeg :: Vec3
-zNeg = vec3 0 0 (-1)
-
-prop_transform_rotateX :: Property
-prop_transform_rotateX = property do
-  let angle = pi / 2
-  let t = Transform.rotateX angle
-  let q = Transform.rotateQ (Geomancy.Quaternion.axisAngle (vec3 1 0 0) angle)
-  let yNegT = t !. zPos
-  annotateShow yNegT
-  let yNegQ = q !. zPos
-  annotateShow yNegQ
-  replicate 3 Nothing === nearlyEqualVec3 yNegT yNeg
-  replicate 3 Nothing === nearlyEqualVec3 yNegQ yNeg
-
-prop_transform_rotateY :: Property
-prop_transform_rotateY = property do
-  let angle = pi / 2
-  let t = Transform.rotateY angle
-  let q = Transform.rotateQ (Geomancy.Quaternion.axisAngle (vec3 0 1 0) angle)
-  let xPosT = t !. zPos
-  annotateShow xPosT
-  let xPosQ = q !. zPos
-  annotateShow xPosQ
-  replicate 3 Nothing === nearlyEqualVec3 xPosT xPos
-  replicate 3 Nothing === nearlyEqualVec3 xPosQ xPos
-
-prop_transform_rotateZ :: Property
-prop_transform_rotateZ = property do
-  let angle = pi / 2
-  let t = Transform.rotateZ angle
-  let q = Transform.rotateQ (Geomancy.Quaternion.axisAngle (vec3 0 0 1) angle)
-  let yPosT = t !. xPos
-  annotateShow yPosT
-  let yPosQ = q !. xPos
-  annotateShow yPosQ
-  replicate 3 Nothing === nearlyEqualVec3 yPosT yPos
-  replicate 3 Nothing === nearlyEqualVec3 yPosQ yPos
-
-prop_quaternion_ref :: Property
-prop_quaternion_ref = property do
-  annotate "Construction"
-  (axis, angle) <- forAll $ (,) <$> genVec3 <*> genAngle
-  let qg = Geomancy.Quaternion.axisAngle axis angle
-  let ql = Linear.Quaternion.axisAngle (withVec3 axis Linear.V3) angle
-  show qg === show (fromLQ ql)
-
-  annotate "Rotation"
-  p <- forAll genVec3
-  let rpg = Geomancy.Quaternion.rotate qg p
-  let rpl = Linear.Quaternion.rotate ql (withVec3 p Linear.V3)
-  show rpg === show (fromV3 rpl)
-
-  annotate "Multiplication"
-  (axisB, angleB) <- forAll $ (,) <$> genVec3 <*> genAngle
-  let qgB = Geomancy.Quaternion.axisAngle axisB angleB
-  let qlB = Linear.Quaternion.axisAngle (withVec3 axisB Linear.V3) angleB
-  let prodg = qg * qgB
-  let prodl = ql * qlB
-  show prodg === show (fromLQ prodl)
-
-prop_quaternion_associativity :: Property
-prop_quaternion_associativity = property do
-  (a, b, c) <- forAll $ (,,)
-    <$> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
-    <*> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
-    <*> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
-  let ab'c = (a * b) * c
-  annotateShow ab'c
-  let a'bc = a * (b * c)
-  annotateShow a'bc
-  replicate 4 Nothing === nearlyEqualQ ab'c a'bc
-
-prop_quaternion_intrinsic :: Property
-prop_quaternion_intrinsic = withTests 1 $ property do
-  let yaw = pi / 2
-  let pitch = pi / 2
-  let roll = 0
-  let q = Geomancy.Quaternion.intrinsic roll pitch yaw
-  let forward' = Geomancy.Quaternion.rotate q zPos
-  let right' = Geomancy.Quaternion.rotate q xPos
-  let up' = Geomancy.Quaternion.rotate q yNeg
-  replicate 3 Nothing === nearlyEqualVec3 yNeg forward'
-  replicate 3 Nothing === nearlyEqualVec3 zNeg right'
-  replicate 3 Nothing === nearlyEqualVec3 xNeg up'
-
-prop_quaternion_extrinsic :: Property
-prop_quaternion_extrinsic = withTests 1 $ property do
-  let heading = pi / 2
-  let elevation = pi / 2
-  let tilt = 0
-  let q = Geomancy.Quaternion.extrinsic heading elevation tilt
-  let forward' = Geomancy.Quaternion.rotate q zPos
-  let right' = Geomancy.Quaternion.rotate q xPos
-  let up' = Geomancy.Quaternion.rotate q yNeg
-  replicate 3 Nothing === nearlyEqualVec3 xPos forward'
-  replicate 3 Nothing === nearlyEqualVec3 yPos right'
-  replicate 3 Nothing === nearlyEqualVec3 zNeg up'
-
-prop_quaternion_intrinsic_ref :: Property
-prop_quaternion_intrinsic_ref = property do
-  (roll, pitch, yaw) <- forAll $ (,,) <$> genAngle <*> genAngle <*> genAngle
-  let fused = Geomancy.Quaternion.intrinsic roll pitch yaw
-  annotateShow fused
-  let composed = intrinsicComposed roll pitch yaw
-  annotateShow composed
-  let viaFused = Geomancy.Quaternion.rotate fused zPos
-  annotateShow viaFused
-  let viaComposed = Geomancy.Quaternion.rotate composed zPos
-  replicate 3 Nothing === nearlyEqualVec3 viaFused viaComposed
-
-intrinsicComposed :: Float -> Float -> Float -> Quaternion
-intrinsicComposed roll pitch yaw =
-  Geomancy.Quaternion.axisAngle (vec3 0 1 0) yaw *
-  Geomancy.Quaternion.axisAngle (vec3 1 0 0) pitch *
-  Geomancy.Quaternion.axisAngle (vec3 0 0 1) roll
-
-prop_transform_node :: Property
-prop_transform_node = withTests 1 $ property do
-  let t = vec3 2 3 5
-  let r = intrinsicComposed 0 0 (pi/7)
-  let s = 11
-  let dps = Transform.node t r s
-  let node = trs t r s
-  let v = vec3 0 0 1
-  replicate 3 Nothing === nearlyEqualVec3 (dps !. v) (node !. v)
-
-trs :: Vec3 -> Quaternion -> Vec3 -> Transform
-trs t r s = mconcat
-  [ Transform.translateV t
-  , Transform.rotateQ r
-  , Transform.scaleV s
-  ]
-
-prop_transform_order :: Property
-prop_transform_order = withTests 1 $ property do
-  let parent = Transform.node (vec3 4 5 6) (intrinsicComposed 0 0 (pi/6)) 2
-  let local = Transform.node (vec3 7 8 9) (intrinsicComposed 0 (pi/6) 0) (1/3)
-  let precomp = parent <> local !. vec3 0 0 1
-  let nocomp = parent !. local !. vec3 0 0 1
-
-  replicate 3 Nothing === nearlyEqualVec3 precomp nocomp
-
-forAllTransform :: PropertyT IO (Geomancy.Mat4.Mat4, Linear.M44 Float)
-forAllTransform = withFrozenCallStack do
-  (_name, Transform g) <- forAllWith fst genTransform
-  pure (g, toM44 g)
-
-genVec3 :: Gen Vec3
-genVec3 =
-  vec3
-    <$> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-    <*> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-    <*> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-
-genAngle :: Gen Float
-genAngle = Gen.float (Range.linearFracFrom 0.0 (-8*pi) (8*pi))
-
-genTransform :: Gen ([Char], Transform) -- TODO: cross-check with Linear
-genTransform = Gen.choice
-  [ genIdentity
-  , genTranslate
-  , genRotate
-  , genScale
-  ]
-  where
-    genIdentity = pure ("identity", mempty)
-
-    genTranslate = do
-      x <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-      y <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-      z <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
-      when (abs x == 0 && abs y == 0 && abs z == 0) Gen.discard
-      pure
-        ( printf "translate %0.4f %0.4f %0.4f" x y z
-        , Transform.translate x y z
-        )
-
-    genRotate = do
-      (name, axis) <- Gen.element
-        [ ("rotate/x", Transform.rotateX)
-        , ("rotate/y", Transform.rotateY)
-        , ("rotate/z", Transform.rotateZ)
-        ]
-      angle <- genAngle
-      when (abs angle == 0) Gen.discard
-      pure
-        ( printf "%s %0.4f" name angle
-        , axis angle
-        )
-
-    genScale = do
-      x <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
-      y <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
-      z <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
-      when (abs x == 1 && abs y == 1 && abs z == 1) Gen.discard
-      pure
-        ( printf "scale %0.4f %0.4f %0.4f" x y z
-        , Transform.scale3 x y z
-        )
-
-fromV3 :: Linear.V3 Float -> Vec3
-fromV3 (Linear.V3 x y z) = Geomancy.vec3 x y z
-
-fromLQ :: Linear.Quaternion.Quaternion Float -> Geomancy.Quaternion
-fromLQ (Linear.Quaternion.Quaternion s (Linear.V3 x y z)) = Geomancy.quaternion s x y z
-
-toM44 :: Geomancy.Mat4 -> Linear.M44 Float
-toM44 mat4 =
-  withRowMajor mat4
-    \ m00 m10 m20 m30
-      m01 m11 m21 m31
-      m02 m12 m22 m32
-      m03 m13 m23 m33 ->
-        Linear.V4
-          (Linear.V4 m00 m10 m20 m30)
-          (Linear.V4 m01 m11 m21 m31)
-          (Linear.V4 m02 m12 m22 m32)
-          (Linear.V4 m03 m13 m23 m33)
-
-nearlyEqualMat4 :: Geomancy.Mat4.Mat4 -> Geomancy.Mat4.Mat4 -> [Maybe Oops]
-nearlyEqualMat4 a b = Geomancy.Mat4.zipWith nearlyEqual a b
-
-nearlyEqualM44 :: Linear.M44 Float -> Linear.M44 Float -> [Maybe Oops]
-nearlyEqualM44 a b = zipWith nearlyEqual (concatMap toList a) (concatMap toList b)
-
-nearlyEqualVec3 :: Vec3 -> Vec3 -> [Maybe Oops]
-nearlyEqualVec3 a b =
-  withVec3 a \ax ay az ->
-  withVec3 b \bx by bz ->
-    [ nearlyEqual ax bx
-    , nearlyEqual ay by
-    , nearlyEqual az bz
-    ]
-
-nearlyEqualQ :: Geomancy.Quaternion -> Geomancy.Quaternion -> [Maybe Oops]
-nearlyEqualQ a b =
-  Geomancy.withQuaternion a \as ax ay az ->
-    Geomancy.withQuaternion b \bs bx by bz ->
-      [ nearlyEqual as bs
-      , nearlyEqual ax bx
-      , nearlyEqual ay by
-      , nearlyEqual az bz
-      ]
-
-nearlyEqual :: Float -> Float -> Maybe Oops
-nearlyEqual lhs rhs =
-  if lhs == rhs || absDiff < 1e-4 || relDiff < 1e-4 then
-    Nothing
-  else
-    Just Oops{..}
-  where
-    absDiff = abs $ lhs - rhs
-    relDiff = absDiff / (abs lhs + abs rhs)
-    -- fltEps = 1.19209290e-07
-    -- fltMin = 1.175494e-38
-
-data Oops = Oops {lhs :: Float, rhs :: Float, absDiff :: Float, relDiff :: Float}
-  deriving (Eq, Show)
-
-discovered :: Group
-discovered = $$(discover)
diff --git a/test/Spec/DMat4.hs b/test/Spec/DMat4.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/DMat4.hs
@@ -0,0 +1,159 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Spec.DMat4 (tests) where
+
+import Hedgehog
+import Hedgehog.Gen qualified as Gen
+import Hedgehog.Range qualified as Range
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Linear qualified
+import Linear ((!*!))
+
+import Geomancy.DMat4 qualified
+import Geomancy.DVec4 qualified
+import Geomancy.Mat4 ((!*))
+import Geomancy.Transform qualified as Transform
+
+import Support.Ball (balls, balls44, consistent, enclosed, narrow, widen)
+import Support.Gen (forAllDTransform, forAllTransform, genDVec4, genEdgeScalar, genMostlySame, genVec4)
+import Support.Linear (entries, toM44, toM44D, toV4, toV4D)
+import Support.Property (pattern PROP_TESTS)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+
+tests :: TestTree
+tests = testGroup "DMat4"
+  [ testPropertyNamed "assoc" "prop_dmat4_assoc" prop_dmat4_assoc
+  , testPropertyNamed "order" "prop_dmat4_order" prop_dmat4_order
+  , testPropertyNamed "eq" "prop_dmat4_eq" prop_dmat4_eq
+  , testPropertyNamed "det" "prop_dmat4_det" prop_dmat4_det
+  , testPropertyNamed "inverse" "prop_dmat4_inverse" prop_dmat4_inverse
+  , testPropertyNamed "apply" "prop_dmat4_apply" prop_dmat4_apply
+  , testPropertyNamed "float_parity" "prop_dmat4_float_parity" prop_dmat4_float_parity
+  ]
+
+prop_dmat4_assoc :: Property
+prop_dmat4_assoc = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (p, p_) <- forAllDTransform
+  (v, v_) <- forAllDTransform
+  (m, m_) <- forAllDTransform
+
+  let
+    pv'm = (p <> v) <> m
+    p'vm = p <> (v <> m)
+    pv'mBall = Ref.Mat4.compose (Ref.Mat4.compose (balls44 p_) (balls44 v_)) (balls44 m_)
+    p'vmBall = Ref.Mat4.compose (balls44 p_) (Ref.Mat4.compose (balls44 v_) (balls44 m_))
+  replicate 16 Nothing === enclosed (entries pv'mBall) (entries (toM44D pv'm))
+  replicate 16 Nothing === enclosed (entries p'vmBall) (entries (toM44D p'vm))
+
+  let
+    mv_p = (m_ !*! v_) !*! p_
+    m_vp = m_ !*! (v_ !*! p_)
+    mv_pBall = (balls44 m_ !*! balls44 v_) !*! balls44 p_
+    m_vpBall = balls44 m_ !*! (balls44 v_ !*! balls44 p_)
+  replicate 16 Nothing === enclosed (entries mv_pBall) (entries mv_p)
+  replicate 16 Nothing === enclosed (entries m_vpBall) (entries m_vp)
+
+  replicate 16 Nothing === consistent (entries pv'mBall) (entries p'vmBall)
+  replicate 16 Nothing === consistent (entries mv_pBall) (entries m_vpBall)
+  replicate 16 Nothing === consistent (entries pv'mBall) (entries mv_pBall)
+
+prop_dmat4_order :: Property
+prop_dmat4_order = withTests 1 $ property do
+  let
+    cm = Geomancy.DMat4.colMajor @Geomancy.DMat4.DMat4
+      0 1 2 3
+      4 5 6 7
+      8 9 0 1
+      2 3 4 5
+    rm = Geomancy.DMat4.rowMajor @Geomancy.DMat4.DMat4
+      0 4 8 2
+      1 5 9 3
+      2 6 0 4
+      3 7 1 5
+  Geomancy.DMat4.toListColMajor2d cm === Geomancy.DMat4.toListColMajor2d rm
+
+  let
+    cmT = Geomancy.DMat4.transpose cm
+    rmT = Geomancy.DMat4.transpose rm
+  Geomancy.DMat4.toListColMajor2d cmT === Geomancy.DMat4.toListColMajor2d rmT
+
+prop_dmat4_det :: Property
+prop_dmat4_det = withTests 1 $ property do
+  1     === Geomancy.DMat4.det Geomancy.DMat4.identity
+  1     === Geomancy.DMat4.det (Geomancy.DMat4.fromMat4 $ Transform.translate 1 2 3)
+  0     === Geomancy.DMat4.det (Geomancy.DMat4.fromMat4 $ Transform.scaleX 0)
+  -1    === Geomancy.DMat4.det (Geomancy.DMat4.fromMat4 $ Transform.scaleZ (-1))
+  8     === Geomancy.DMat4.det (Geomancy.DMat4.fromMat4 $ Transform.scale 2)
+  (1/8) === Geomancy.DMat4.det (Geomancy.DMat4.fromMat4 $ Transform.scale (1/2))
+
+prop_dmat4_inverse :: Property
+prop_dmat4_inverse = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (m, m_) <- forAllDTransform
+  let
+    mm' = m <> Geomancy.DMat4.inverse m
+    mBall = balls44 m_
+    mm'Ball = Ref.Mat4.compose mBall (Ref.Mat4.inverse mBall)
+  annotateShow mm'
+  replicate 16 Nothing === enclosed (entries mm'Ball) (entries (toM44D mm'))
+  replicate 16 Nothing === enclosed (entries mm'Ball) (entries (Linear.identity :: Linear.M44 Double))
+
+prop_dmat4_apply :: Property
+prop_dmat4_apply = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (m, m_) <- forAllDTransform
+  v <- forAll genDVec4
+  let
+    out = m Geomancy.DMat4.!* v
+    out_ = toV4D v Linear.*! m_
+    outBall = Ref.Mat4.apply (balls44 m_) (balls (toV4D v))
+    out_Ball = balls (toV4D v) Linear.*! balls44 m_
+  annotateShow out
+  annotateShow out_
+  replicate 4 Nothing === enclosed outBall (toV4D out)
+  replicate 4 Nothing === enclosed out_Ball out_
+  replicate 4 Nothing === consistent outBall out_Ball
+
+prop_dmat4_float_parity :: Property
+prop_dmat4_float_parity = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (a, a_) <- forAllTransform
+  (b, b_) <- forAllTransform
+  let
+    viaDouble =
+      Geomancy.DMat4.toMat4 $
+        Geomancy.DMat4.fromMat4 a <> Geomancy.DMat4.fromMat4 b
+    widened = fmap (fmap widen) . balls44
+    viaDoubleBall = fmap (fmap narrow) $ Ref.Mat4.compose (widened a_) (widened b_)
+    viaFloatBall = Ref.Mat4.compose (balls44 a_) (balls44 b_)
+  replicate 16 Nothing === enclosed (entries viaDoubleBall) (entries (toM44 viaDouble))
+  replicate 16 Nothing === enclosed (entries viaFloatBall) (entries (toM44 (a <> b)))
+  replicate 16 Nothing === consistent (entries viaDoubleBall) (entries viaFloatBall)
+
+  v <- forAll genVec4
+  let
+    viaDoubleV =
+      Geomancy.DVec4.toVec4 $
+        Geomancy.DMat4.fromMat4 a Geomancy.DMat4.!* Geomancy.DVec4.fromVec4 v
+    viaDoubleVBall =
+      fmap narrow $ Ref.Mat4.apply (widened a_) (fmap widen (balls (toV4 v)))
+    viaFloatVBall = Ref.Mat4.apply (balls44 a_) (balls (toV4 v))
+  replicate 4 Nothing === enclosed viaDoubleVBall (toV4 viaDoubleV)
+  replicate 4 Nothing === enclosed viaFloatVBall (toV4 (a !* v))
+  replicate 4 Nothing === consistent viaDoubleVBall viaFloatVBall
+
+prop_dmat4_eq :: Property
+prop_dmat4_eq = withTests PROP_TESTS $ property do
+  let
+    four = Gen.list (Range.singleton 4)
+    fromRows = evalMaybe . Geomancy.DMat4.fromRowMajor2d @[] @Geomancy.DMat4.DMat4
+  rowsA <- forAll $ four (four genEdgeScalar)
+  rowsB <- forAll $ traverse (traverse (genMostlySame 8)) rowsA
+  a <- fromRows rowsA
+  b <- fromRows rowsB
+  label $ if rowsA == rowsB then "equal" else "different"
+  (a == b) === (rowsA == rowsB)
+  (a /= b) === (rowsA /= rowsB)
diff --git a/test/Spec/DQuaternion.hs b/test/Spec/DQuaternion.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/DQuaternion.hs
@@ -0,0 +1,180 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Spec.DQuaternion (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Hedgehog.Gen qualified as Gen
+import Hedgehog.Range qualified as Range
+import Linear (V3(..))
+import Linear.Quaternion qualified
+
+import Geomancy.DQuaternion qualified
+import Geomancy.DTransform qualified as DTransform
+import Geomancy.Quaternion qualified
+
+import Support.Ball (balls, consistent, enclosed, exactly, narrow, widen)
+import Support.Fixtures (intrinsicComposedD, intrinsicComposedRef, quarterTurn, rotationsMatch)
+import Support.Gen (genAngle, genAngleD, genDVec3, genSmallDVec3, genVec3)
+import Support.Linear (toQ, toQD, toV3D)
+import Support.Reference.Linear qualified as Ref.Linear
+import Support.Reference.Quaternion qualified as Ref.Quaternion
+import Support.Reference.Transform qualified as Ref.Transform
+
+tests :: TestTree
+tests = testGroup "DQuaternion"
+  [ testPropertyNamed "ref" "prop_dquaternion_ref" prop_dquaternion_ref
+  , testPropertyNamed "rotate_matrix" "prop_dquaternion_rotate_matrix" prop_dquaternion_rotate_matrix
+  , testPropertyNamed "associativity" "prop_dquaternion_associativity" prop_dquaternion_associativity
+  , testPropertyNamed "intrinsic" "prop_dquaternion_intrinsic" prop_dquaternion_intrinsic
+  , testPropertyNamed "extrinsic" "prop_dquaternion_extrinsic" prop_dquaternion_extrinsic
+  , testPropertyNamed "intrinsic_ref" "prop_dquaternion_intrinsic_ref" prop_dquaternion_intrinsic_ref
+  , testPropertyNamed "float_parity" "prop_dquaternion_float_parity" prop_dquaternion_float_parity
+  ]
+
+prop_dquaternion_ref :: Property
+prop_dquaternion_ref = property do
+  annotate "Construction"
+  (axis, angle) <- forAll $ (,) <$> genDVec3 <*> genAngleD
+  let
+    qg = Geomancy.DQuaternion.axisAngle axis angle
+    ql = Linear.Quaternion.axisAngle (toV3D axis) angle
+    qgBall = Ref.Quaternion.axisAngle (balls (toV3D axis)) (exactly angle)
+    qlBall = Linear.Quaternion.axisAngle (balls (toV3D axis)) (exactly angle)
+  replicate 4 Nothing === enclosed qgBall (toQD qg)
+  replicate 4 Nothing === enclosed qlBall ql
+  replicate 4 Nothing === consistent qgBall qlBall
+
+  annotate "Rotation"
+  p <- forAll genSmallDVec3
+  let
+    rpg = Geomancy.DQuaternion.rotate qg p
+    rpl = Linear.Quaternion.rotate ql (toV3D p)
+    rpgBall = Ref.Quaternion.rotate qgBall (balls (toV3D p))
+    rplBall = Ref.Linear.rotate qlBall (balls (toV3D p))
+  replicate 3 Nothing === enclosed rpgBall (toV3D rpg)
+  replicate 3 Nothing === enclosed rplBall rpl
+  replicate 3 Nothing === consistent rpgBall rplBall
+
+  annotate "Multiplication"
+  (axisB, angleB) <- forAll $ (,) <$> genDVec3 <*> genAngleD
+  let
+    qgB = Geomancy.DQuaternion.axisAngle axisB angleB
+    qlB = Linear.Quaternion.axisAngle (toV3D axisB) angleB
+    productGBall =
+      qgBall `Ref.Quaternion.multiply`
+        Ref.Quaternion.axisAngle (balls (toV3D axisB)) (exactly angleB)
+    productLBall =
+      qlBall `Ref.Linear.multiply`
+        Linear.Quaternion.axisAngle (balls (toV3D axisB)) (exactly angleB)
+  replicate 4 Nothing === enclosed productGBall (toQD (qg * qgB))
+  replicate 4 Nothing === enclosed productLBall (ql * qlB)
+  replicate 4 Nothing === consistent productGBall productLBall
+
+prop_dquaternion_rotate_matrix :: Property
+prop_dquaternion_rotate_matrix = property do
+  q <- forAll $ dquaternion <$> genUnitish <*> genUnitish <*> genUnitish <*> genUnitish
+  p <- forAll genSmallDVec3
+  let
+    viaRotate = Geomancy.DQuaternion.rotate q p
+    viaMatrix = DTransform.rotateQ q DTransform.!. p
+    viaRotateBall = Ref.Quaternion.rotate (balls (toQD q)) (balls (toV3D p))
+    viaMatrixBall = Ref.Transform.rotateQ (balls (toQD q)) Ref.Transform.!. balls (toV3D p)
+  replicate 3 Nothing === enclosed viaRotateBall (toV3D viaRotate)
+  replicate 3 Nothing === enclosed viaMatrixBall (toV3D viaMatrix)
+  replicate 3 Nothing === consistent viaRotateBall viaMatrixBall
+  where
+    genUnitish = Gen.double (Range.linearFracFrom 0.0 (-1) 1)
+
+prop_dquaternion_associativity :: Property
+prop_dquaternion_associativity = property do
+  (a, b, c) <- forAll $ (,,)
+    <$> (Geomancy.DQuaternion.axisAngle <$> genDVec3 <*> genAngleD)
+    <*> (Geomancy.DQuaternion.axisAngle <$> genDVec3 <*> genAngleD)
+    <*> (Geomancy.DQuaternion.axisAngle <$> genDVec3 <*> genAngleD)
+  let ab'c = (a * b) * c
+  annotateShow ab'c
+  let a'bc = a * (b * c)
+  annotateShow a'bc
+  let
+    aBall = balls (toQD a)
+    bBall = balls (toQD b)
+    cBall = balls (toQD c)
+    ab'cBall = (aBall `Ref.Quaternion.multiply` bBall) `Ref.Quaternion.multiply` cBall
+    a'bcBall = aBall `Ref.Quaternion.multiply` (bBall `Ref.Quaternion.multiply` cBall)
+  replicate 4 Nothing === enclosed ab'cBall (toQD ab'c)
+  replicate 4 Nothing === enclosed a'bcBall (toQD a'bc)
+  replicate 4 Nothing === consistent ab'cBall a'bcBall
+
+prop_dquaternion_intrinsic :: Property
+prop_dquaternion_intrinsic = withTests 1 $ property do
+  let
+    q = Geomancy.DQuaternion.intrinsic 0 quarterTurn quarterTurn
+    qBall = Ref.Quaternion.intrinsic 0 quarterTurn quarterTurn
+  rotationsMatch toV3D
+    (Geomancy.DQuaternion.rotate q)
+    (Ref.Quaternion.rotate qBall)
+    [ (dvec3 0 0 1, dvec3 0 (-1) 0)
+    , (dvec3 1 0 0, dvec3 0 0 (-1))
+    , (dvec3 0 (-1) 0, dvec3 (-1) 0 0)
+    ]
+
+prop_dquaternion_extrinsic :: Property
+prop_dquaternion_extrinsic = withTests 1 $ property do
+  let
+    q = Geomancy.DQuaternion.extrinsic quarterTurn quarterTurn 0
+    qBall = Ref.Quaternion.extrinsic quarterTurn quarterTurn 0
+  rotationsMatch toV3D
+    (Geomancy.DQuaternion.rotate q)
+    (Ref.Quaternion.rotate qBall)
+    [ (dvec3 0 0 1, dvec3 1 0 0)
+    , (dvec3 1 0 0, dvec3 0 1 0)
+    , (dvec3 0 (-1) 0, dvec3 0 0 (-1))
+    ]
+
+prop_dquaternion_intrinsic_ref :: Property
+prop_dquaternion_intrinsic_ref = property do
+  (roll, pitch, yaw) <- forAll $ (,,) <$> genAngleD <*> genAngleD <*> genAngleD
+  let fused = Geomancy.DQuaternion.intrinsic roll pitch yaw
+  annotateShow fused
+  let composed = intrinsicComposedD roll pitch yaw
+  annotateShow composed
+  let
+    viaFused = Geomancy.DQuaternion.rotate fused (dvec3 0 0 1)
+    viaComposed = Geomancy.DQuaternion.rotate composed (dvec3 0 0 1)
+    viaFusedBall =
+      Ref.Quaternion.rotate
+        (Ref.Quaternion.intrinsic (exactly roll) (exactly pitch) (exactly yaw))
+        (V3 0 0 1)
+    viaComposedBall =
+      Ref.Quaternion.rotate
+        (intrinsicComposedRef (exactly roll) (exactly pitch) (exactly yaw))
+        (V3 0 0 1)
+  replicate 3 Nothing === enclosed viaFusedBall (toV3D viaFused)
+  replicate 3 Nothing === enclosed viaComposedBall (toV3D viaComposed)
+  replicate 3 Nothing === consistent viaFusedBall viaComposedBall
+
+prop_dquaternion_float_parity :: Property
+prop_dquaternion_float_parity = property do
+  (a, b) <- forAll $ (,)
+    <$> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
+    <*> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
+  a === Geomancy.DQuaternion.toQuaternion (Geomancy.DQuaternion.fromQuaternion a)
+  let
+    viaDouble =
+      Geomancy.DQuaternion.toQuaternion $
+        Geomancy.DQuaternion.fromQuaternion a * Geomancy.DQuaternion.fromQuaternion b
+    aBall = balls (toQ a)
+    bBall = balls (toQ b)
+    viaDoubleBall =
+      fmap narrow $
+        fmap widen aBall `Ref.Quaternion.multiply` fmap widen bBall
+    viaFloatBall = aBall `Ref.Quaternion.multiply` bBall
+  replicate 4 Nothing === enclosed viaDoubleBall (toQ viaDouble)
+  replicate 4 Nothing === enclosed viaFloatBall (toQ (a * b))
+  replicate 4 Nothing === consistent viaDoubleBall viaFloatBall
diff --git a/test/Spec/DTransform.hs b/test/Spec/DTransform.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/DTransform.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Spec.DTransform (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Data.Foldable (for_)
+import Linear (M44, V3(..))
+
+import Geomancy.DMat4 qualified
+import Geomancy.DQuaternion qualified
+import Geomancy.DTransform qualified as DTransform
+import Geomancy.Mat4 qualified
+import Geomancy.Transform ((!.))
+import Geomancy.Transform qualified as Transform
+import Geomancy.Vulkan.DView qualified as DView
+
+import Support.Ball (Ball, balls, consistent, enclosed, exactly, narrow)
+import Support.Fixtures
+  (fourteenthTurn, intrinsicComposedD, intrinsicComposedRef, quarterTurn, rotationsMatch, trsRef, twelfthTurn)
+import Support.Gen (genAngle, genTransform)
+import Support.Linear (entries, toM44, toV3, toV3D)
+import Support.Property (pattern PROP_TESTS)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+import Support.Reference.Quaternion qualified as Ref.Quaternion
+import Support.Reference.Transform qualified as Ref.Transform
+import Support.Reference.Vulkan qualified as Ref.Vulkan
+
+tests :: TestTree
+tests = testGroup "DTransform"
+  [ testPropertyNamed "det" "prop_dtransform_det" prop_dtransform_det
+  , testPropertyNamed "rotate" "prop_dtransform_rotate" prop_dtransform_rotate
+  , testPropertyNamed "node_order" "prop_dtransform_node_order" prop_dtransform_node_order
+  , testPropertyNamed "float_parity" "prop_dtransform_float_parity" prop_dtransform_float_parity
+  , testPropertyNamed "big_world" "prop_dtransform_big_world" prop_dtransform_big_world
+  ]
+
+prop_dtransform_det :: Property
+prop_dtransform_det = withTests 1 $ property do
+  1     === Geomancy.DMat4.det (DTransform.translate 1 2 3)
+  0     === Geomancy.DMat4.det (DTransform.scaleX 0)
+  -1    === Geomancy.DMat4.det (DTransform.scaleZ (-1))
+  8     === Geomancy.DMat4.det (DTransform.scale 2)
+  (1/8) === Geomancy.DMat4.det (DTransform.scale (1/2))
+
+  let
+    rotatedBall = Ref.Mat4.det (Ref.Transform.rotateY twelfthTurn) :: Ball Double
+  [Nothing] === enclosed [rotatedBall] [Geomancy.DMat4.det (DTransform.rotateY twelfthTurn)]
+  [Nothing] === enclosed [rotatedBall] [1 :: Double]
+
+prop_dtransform_rotate :: Property
+prop_dtransform_rotate = withTests 1 $ property do
+  let
+    axisQ axis = DTransform.rotateQ (Geomancy.DQuaternion.axisAngle axis quarterTurn)
+    axisQBall axis = Ref.Transform.rotateQ (Ref.Quaternion.axisAngle axis quarterTurn)
+    cases =
+      [ (DTransform.rotateX quarterTurn, Ref.Transform.rotateX quarterTurn, dvec3 0 0 1, dvec3 0 (-1) 0)
+      , (axisQ (dvec3 1 0 0), axisQBall (V3 1 0 0), dvec3 0 0 1, dvec3 0 (-1) 0)
+      , (DTransform.rotateY quarterTurn, Ref.Transform.rotateY quarterTurn, dvec3 0 0 1, dvec3 1 0 0)
+      , (axisQ (dvec3 0 1 0), axisQBall (V3 0 1 0), dvec3 0 0 1, dvec3 1 0 0)
+      , (DTransform.rotateZ quarterTurn, Ref.Transform.rotateZ quarterTurn, dvec3 1 0 0, dvec3 0 1 0)
+      , (axisQ (dvec3 0 0 1), axisQBall (V3 0 0 1), dvec3 1 0 0, dvec3 0 1 0)
+      ]
+  for_ cases \(t, tBall, input, expected) ->
+    rotationsMatch toV3D (t DTransform.!.) (tBall Ref.Transform.!.) [(input, expected)]
+
+prop_dtransform_node_order :: Property
+prop_dtransform_node_order = withTests 1 $ property do
+  let
+    t = dvec3 2 3 5
+    r = intrinsicComposedD 0 0 fourteenthTurn
+    s = 11
+    trsD = mconcat [DTransform.translateV t, DTransform.rotateQ r, DTransform.scaleV s]
+    v = dvec3 0 0 1
+
+    rBall = intrinsicComposedRef 0 0 fourteenthTurn
+    nodeBall = Ref.Transform.node (V3 2 3 5) rBall 11 :: M44 (Ball Double)
+    trsBall = trsRef (V3 2 3 5) rBall 11
+    viaNodeBall = nodeBall Ref.Transform.!. V3 0 0 1
+    viaTrsBall = trsBall Ref.Transform.!. V3 0 0 1
+  replicate 3 Nothing === enclosed viaNodeBall (toV3D (DTransform.node t r s DTransform.!. v))
+  replicate 3 Nothing === enclosed viaTrsBall (toV3D (trsD DTransform.!. v))
+  replicate 3 Nothing === consistent viaNodeBall viaTrsBall
+
+  let
+    parent = DTransform.node (dvec3 4 5 6) (intrinsicComposedD 0 0 twelfthTurn) 2
+    local = DTransform.node (dvec3 7 8 9) (intrinsicComposedD 0 twelfthTurn 0) (1/3)
+    parentBall = Ref.Transform.node (V3 4 5 6) (intrinsicComposedRef 0 0 twelfthTurn) 2 :: M44 (Ball Double)
+    localBall = Ref.Transform.node (V3 7 8 9) (intrinsicComposedRef 0 twelfthTurn 0) (1/3)
+    precompBall = Ref.Mat4.compose parentBall localBall Ref.Transform.!. V3 0 0 1
+    nocompBall = parentBall Ref.Transform.!. localBall Ref.Transform.!. V3 0 0 1
+  replicate 3 Nothing === enclosed precompBall (toV3D (parent <> local DTransform.!. v))
+  replicate 3 Nothing === enclosed nocompBall (toV3D (parent DTransform.!. local DTransform.!. v))
+  replicate 3 Nothing === consistent precompBall nocompBall
+
+prop_dtransform_float_parity :: Property
+prop_dtransform_float_parity = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (_name, t) <- forAllWith fst genTransform
+  Geomancy.Mat4.toListRowMajor t ===
+    Geomancy.Mat4.toListRowMajor (DTransform.toTransform (DTransform.fromTransform t))
+
+  angle <- forAll genAngle
+  let
+    a = realToFrac angle
+    viaDouble = unTransform $ DTransform.toTransform (DTransform.rotateY a)
+    viaFloat = unTransform $ Transform.rotateY angle
+    viaDoubleBall = fmap (fmap narrow) $ Ref.Transform.rotateY (exactly a)
+    viaFloatBall = Ref.Transform.rotateY (exactly angle)
+  replicate 16 Nothing === enclosed (entries viaDoubleBall) (entries (toM44 viaDouble))
+  replicate 16 Nothing === enclosed (entries viaFloatBall) (entries (toM44 viaFloat))
+  replicate 16 Nothing === consistent (entries viaDoubleBall) (entries viaFloatBall)
+
+prop_dtransform_big_world :: Property
+prop_dtransform_big_world = withTests 1 $ property do
+  let
+    far = 1e9
+    eye = dvec3 far 0 far
+    view = DView.lookAtRH_ eye (eye + dvec3 0 0 1)
+    model = DTransform.translate (far + 0.25) 0 (far + 5)
+    composedInDouble = DTransform.toTransform (view <> model)
+    composedInFloat = DTransform.toTransform view <> DTransform.toTransform model
+
+    farBall = exactly far
+    eyeBall = balls (toV3D eye)
+    viewBall = Ref.Vulkan.lookAtRH_ eyeBall (eyeBall + V3 0 0 1)
+    modelBall = Ref.Transform.translate (farBall + 0.25) 0 (farBall + 5)
+    composedInDoubleBall = fmap (fmap narrow) $ Ref.Mat4.compose viewBall modelBall
+    originBall = composedInDoubleBall Ref.Transform.!. V3 0 0 0
+  replicate 3 Nothing === enclosed originBall (toV3 (composedInDouble !. vec3 0 0 0))
+  replicate 3 Nothing === enclosed originBall (toV3 (vec3 0.25 0 5))
+  withVec3 (composedInFloat !. vec3 0 0 0) \x _y _z ->
+    diff x (/=) 0.25
diff --git a/test/Spec/DVec.hs b/test/Spec/DVec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/DVec.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Spec.DVec (tests) where
+
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Foreign (allocaBytes, peekByteOff, pokeByteOff)
+import Graphics.Gl.Block qualified as Block
+
+import Geomancy.DMat4 qualified
+import Geomancy.DVec2 qualified
+import Geomancy.DVec3 qualified
+import Geomancy.DVec4 qualified
+import Geomancy.Mat4 qualified
+
+import Support.Gen
+  ( forAllDTransform
+  , forAllTransform
+  , genDQuaternion
+  , genDVec2
+  , genDVec3
+  , genDVec4
+  , genVec2
+  , genVec3
+  , genVec4
+  )
+import Support.Property (pattern PROP_TESTS, storableRoundtrip)
+
+tests :: TestTree
+tests = testGroup "DVec"
+  [ testPropertyNamed "convert_roundtrip" "prop_dvec_convert_roundtrip" prop_dvec_convert_roundtrip
+  , testPropertyNamed "storable_roundtrip" "prop_dvec_storable_roundtrip" prop_dvec_storable_roundtrip
+  , testPropertyNamed "dvec3_packed_write_bounds" "prop_dvec3_packed_write_bounds" prop_dvec3_packed_write_bounds
+  ]
+
+prop_dvec_convert_roundtrip :: Property
+prop_dvec_convert_roundtrip = withDiscards 1000 . withTests PROP_TESTS $ property do
+  v2 <- forAll genVec2
+  v2 === Geomancy.DVec2.toVec2 (Geomancy.DVec2.fromVec2 v2)
+
+  v3 <- forAll genVec3
+  v3 === Geomancy.DVec3.toVec3 (Geomancy.DVec3.fromVec3 v3)
+
+  v4 <- forAll genVec4
+  v4 === Geomancy.DVec4.toVec4 (Geomancy.DVec4.fromVec4 v4)
+
+  (m, _m) <- forAllTransform
+  Geomancy.Mat4.toListRowMajor m ===
+    Geomancy.Mat4.toListRowMajor (Geomancy.DMat4.toMat4 $ Geomancy.DMat4.fromMat4 m)
+
+prop_dvec_storable_roundtrip :: Property
+prop_dvec_storable_roundtrip = withDiscards 1000 . withTests PROP_TESTS $ property do
+  d2 <- forAll genDVec2
+  storableRoundtrip d2 >>= (d2 ===)
+
+  d3 <- forAll genDVec3
+  storableRoundtrip d3 >>= (d3 ===)
+
+  let d3p = Geomancy.DVec3.Packed d3
+  storableRoundtrip d3p >>= (d3p ===)
+
+  d4 <- forAll genDVec4
+  storableRoundtrip d4 >>= (d4 ===)
+
+  (m, _m) <- forAllDTransform
+  m' <- storableRoundtrip m
+  Geomancy.DMat4.toListRowMajor m === Geomancy.DMat4.toListRowMajor m'
+
+  dq <- forAll genDQuaternion
+  storableRoundtrip dq >>= (dq ===)
+
+prop_dvec3_packed_write_bounds :: Property
+prop_dvec3_packed_write_bounds = withTests PROP_TESTS $ property do
+  d3 <- forAll genDVec3
+  let sentinel = 42 :: Double
+  (d3', afterSlot) <- evalIO $ allocaBytes 32 \ptr -> do
+    pokeByteOff ptr 24 sentinel
+    pokeByteOff ptr 0 (Block.Packed d3)
+    (,) <$> fmap Block.getPacked (peekByteOff ptr 0) <*> peekByteOff ptr 24
+  d3 === d3'
+  sentinel === afterSlot
diff --git a/test/Spec/Fusion.hs b/test/Spec/Fusion.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Fusion.hs
@@ -0,0 +1,258 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedLabels #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Spec.Fusion (tests) where
+
+import Control.DeepSeq (NFData, force)
+import Control.Concurrent (forkIO)
+import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
+import Control.Exception (SomeException, evaluate, throwIO, try)
+import Data.Int (Int64)
+import Data.List qualified as List
+import Data.Word (Word32, Word64)
+import GHC.Float (castDoubleToWord64, castFloatToWord32)
+import Hedgehog
+import System.Mem (getAllocationCounter)
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy.DVec4 (DVec4, dvec4, withDVec4)
+import Geomancy.DVec4 qualified as DVec4
+import Geomancy.Swizzle ((.@))
+import Geomancy.Vec4 (Vec4, vec4, withVec4)
+import Geomancy.Vec4 qualified as Vec4
+
+import Support.Gen (genDVec4, genDouble, genFloat, genVec4)
+import Support.Property (pattern PROP_TESTS)
+
+tests :: TestTree
+tests = testGroup "Fusion"
+  [ testPropertyNamed "vec4_bits" "prop_vec4_fusion_bits" prop_vec4_fusion_bits
+  , testPropertyNamed "dvec4_bits" "prop_dvec4_fusion_bits" prop_dvec4_fusion_bits
+  , testPropertyNamed "vec4_alloc" "prop_vec4_fusion_alloc" prop_vec4_fusion_alloc
+  , testPropertyNamed "dvec4_alloc" "prop_dvec4_fusion_alloc" prop_dvec4_fusion_alloc
+  ]
+
+{-# NOINLINE unfused #-}
+unfused :: a -> a
+unfused x = x
+
+bits4 :: Vec4 -> (Word32, Word32, Word32, Word32)
+bits4 v = withVec4 v \x y z w ->
+  (castFloatToWord32 x, castFloatToWord32 y, castFloatToWord32 z, castFloatToWord32 w)
+
+dbits4 :: DVec4 -> (Word64, Word64, Word64, Word64)
+dbits4 v = withDVec4 v \x y z w ->
+  (castDoubleToWord64 x, castDoubleToWord64 y, castDoubleToWord64 z, castDoubleToWord64 w)
+
+prop_vec4_fusion_bits :: Property
+prop_vec4_fusion_bits = withTests PROP_TESTS $ property do
+  t <- forAll genFloat
+  a <- forAll genVec4
+  b <- forAll genVec4
+  c <- forAll genVec4
+  d <- forAll genVec4
+  bits4 (Vec4.lerp t a b) ===
+    bits4 (unfused (unfused (a Vec4.^* t) + unfused (b Vec4.^* (1 - t))))
+  bits4 ((a + b) * c - d) ===
+    bits4 (unfused (unfused (unfused (a + b) * c) - d))
+  castFloatToWord32 (Vec4.dot (a + b) c) ===
+    castFloatToWord32 (Vec4.dot (unfused (a + b)) c)
+  bits4 (Vec4.normalize (a + b)) ===
+    bits4 (unfused (Vec4.normalize (unfused (a + b))))
+  bits4 (sqrt (a * b)) ===
+    bits4 (unfused (sqrt (unfused (a * b))))
+  bits4 ((a + b) .@ #wzyx) ===
+    bits4 (unfused (unfused (a + b) .@ #wzyx))
+  castFloatToWord32 ((a + b).wzyx.wzyx.y + c.xyzz.w) ===
+    castFloatToWord32 ((unfused (unfused (unfused (a + b)).wzyx).wzyx).y + (unfused c.xyzz).w)
+  castFloatToWord32 ((a + b).wzyx.zyx.yx.y) ===
+    castFloatToWord32 ((unfused (unfused (unfused (unfused (a + b)).wzyx).zyx).yx).y)
+  bits4 ((a + b).xyz.xyz1 + c.xy.xy01) ===
+    bits4 (unfused (unfused (unfused (a + b)).xyz).xyz1 + unfused (unfused c.xy).xy01)
+  bits4 (a + b).yzw.xyz0.wxyz ===
+    bits4 (withVec4 (unfused (a + b)) \_ y z w -> vec4 0 y z w)
+
+prop_dvec4_fusion_bits :: Property
+prop_dvec4_fusion_bits = withTests PROP_TESTS $ property do
+  t <- forAll genDouble
+  a <- forAll genDVec4
+  b <- forAll genDVec4
+  c <- forAll genDVec4
+  d <- forAll genDVec4
+  dbits4 (DVec4.lerp t a b) ===
+    dbits4 (unfused (unfused (a DVec4.^* t) + unfused (b DVec4.^* (1 - t))))
+  dbits4 ((a + b) * c - d) ===
+    dbits4 (unfused (unfused (unfused (a + b) * c) - d))
+  castDoubleToWord64 (DVec4.dot (a + b) c) ===
+    castDoubleToWord64 (DVec4.dot (unfused (a + b)) c)
+  dbits4 (DVec4.normalize (a + b)) ===
+    dbits4 (unfused (DVec4.normalize (unfused (a + b))))
+  dbits4 (sqrt (a * b)) ===
+    dbits4 (unfused (sqrt (unfused (a * b))))
+  castDoubleToWord64 ((a + b).wzyx.wzyx.y + c.xyzz.w) ===
+    castDoubleToWord64 ((unfused (unfused (unfused (a + b)).wzyx).wzyx).y + (unfused c.xyzz).w)
+  castDoubleToWord64 ((a + b).wzyx.zyx.yx.y) ===
+    castDoubleToWord64 ((unfused (unfused (unfused (unfused (a + b)).wzyx).zyx).yx).y)
+  dbits4 ((a + b).xyz.xyz1 + c.xy.xy01) ===
+    dbits4 (unfused (unfused (unfused (a + b)).xyz).xyz1 + unfused (unfused c.xy).xy01)
+  dbits4 (a + b).yzw.xyz0.wxyz ===
+    dbits4 (withDVec4 (unfused (a + b)) \_ y z w -> dvec4 0 y z w)
+
+samples :: Int
+samples = 1000
+
+scalarBudget :: Int64
+scalarBudget = 1024
+
+vectorBudget :: Int64 -> Int64
+vectorBudget bytesPerVector = bytesPerVector * fromIntegral samples + scalarBudget
+
+allocated :: (a -> b) -> a -> IO Int64
+allocated f x = do
+  result <- newEmptyMVar
+  _ <- forkIO $ try (allocatedOnFreshStack f x) >>= putMVar result
+  takeMVar result >>= either rethrow pure
+  where
+    rethrow :: SomeException -> IO Int64
+    rethrow = throwIO
+
+allocatedOnFreshStack :: (a -> b) -> a -> IO Int64
+allocatedOnFreshStack f x = do
+  before <- getAllocationCounter
+  _ <- evaluate (f x)
+  after <- getAllocationCounter
+  pure (before - after)
+
+inputs :: NFData v => (Float -> v) -> IO [v]
+inputs mk = evaluate $ force
+  [ mk (fromIntegral i / fromIntegral samples)
+  | i <- [1 .. samples]
+  ]
+
+overBudget :: Int64 -> [(String, Int64)] -> [(String, Int64)]
+overBudget budget = filter \(_name, bytes) -> bytes > budget
+
+{-# NOINLINE plainFloatSum #-}
+plainFloatSum :: [Float] -> Float
+plainFloatSum = List.foldl' (+) 0
+
+builtOptimized :: IO Bool
+builtOptimized = do
+  floats <- inputs id
+  bytes <- allocated plainFloatSum floats
+  pure $ bytes <= scalarBudget
+
+whenBuiltOptimized :: PropertyT IO () -> PropertyT IO ()
+whenBuiltOptimized checks = do
+  optimized <- evalIO builtOptimized
+  if optimized then
+    checks
+  else
+    annotate "Skipped: allocation budgets only hold in optimized builds"
+
+prop_vec4_fusion_alloc :: Property
+prop_vec4_fusion_alloc = withTests 1 $ property $ whenBuiltOptimized do
+  vs <- evalIO $ inputs \f -> vec4 f (f * 0.5) (f + 1) (2 - f)
+  let
+    b = vec4 1 2 3 4
+    c = vec4 0.5 0.25 0.125 1
+    d = vec4 3 2 1 0
+  scalars <- evalIO $ traverse (traverse ($ vs))
+    [ ("dot of sum", allocated (vec4DotSum b c))
+    , ("normalize", allocated vec4NormalizeDot)
+    , ("sqrt", allocated vec4SqrtDot)
+    , ("swizzle read", allocated vec4SwizzleRead)
+    , ("field swizzles", allocated vec4FieldSwizzles)
+    , ("field extensions", allocated vec4FieldExtensions)
+    ]
+  vectors <- evalIO $ traverse (traverse ($ vs))
+    [ ("lerp", allocated vec4Lerp)
+    , ("chain", allocated (vec4Chain b c d))
+    ]
+  overBudget scalarBudget scalars ++ overBudget (vectorBudget 32) vectors === []
+
+prop_dvec4_fusion_alloc :: Property
+prop_dvec4_fusion_alloc = withTests 1 $ property $ whenBuiltOptimized do
+  vs <- evalIO $ inputs \f ->
+    let f' = realToFrac f in dvec4 f' (f' * 0.5) (f' + 1) (2 - f')
+  let
+    b = dvec4 1 2 3 4
+    c = dvec4 0.5 0.25 0.125 1
+    d = dvec4 3 2 1 0
+  scalars <- evalIO $ traverse (traverse ($ vs))
+    [ ("dot of sum", allocated (dvec4DotSum b c))
+    , ("normalize", allocated dvec4NormalizeDot)
+    , ("sqrt", allocated dvec4SqrtDot)
+    , ("field swizzles", allocated dvec4FieldSwizzles)
+    , ("field extensions", allocated dvec4FieldExtensions)
+    ]
+  vectors <- evalIO $ traverse (traverse ($ vs))
+    [ ("lerp", allocated dvec4Lerp)
+    , ("chain", allocated (dvec4Chain b c d))
+    ]
+  overBudget scalarBudget scalars ++ overBudget (vectorBudget 48) vectors === []
+
+{-# NOINLINE vec4DotSum #-}
+vec4DotSum :: Vec4 -> Vec4 -> [Vec4] -> Float
+vec4DotSum b c = List.foldl' (\s v -> s + Vec4.dot (v + b) c) 0
+
+{-# NOINLINE vec4NormalizeDot #-}
+vec4NormalizeDot :: [Vec4] -> Float
+vec4NormalizeDot = List.foldl' (\s v -> s + Vec4.dot (Vec4.normalize v) v) 0
+
+{-# NOINLINE vec4SqrtDot #-}
+vec4SqrtDot :: [Vec4] -> Float
+vec4SqrtDot = List.foldl' (\s v -> s + Vec4.dot (sqrt v) v) 0
+
+{-# NOINLINE vec4SwizzleRead #-}
+vec4SwizzleRead :: [Vec4] -> Float
+vec4SwizzleRead = List.foldl' (\s v -> s + withVec4 (v .@ #wzyx) \x _ _ _ -> x) 0
+
+{-# NOINLINE vec4FieldSwizzles #-}
+vec4FieldSwizzles :: [Vec4] -> Float
+vec4FieldSwizzles = List.foldl' (\s v -> s + v.wzyx.wzyx.y + v.xyzz.w + v.wzyx.zyx.yx.y) 0
+
+{-# NOINLINE vec4FieldExtensions #-}
+vec4FieldExtensions :: [Vec4] -> Float
+vec4FieldExtensions = List.foldl' (\s v -> s + Vec4.dot v.xyz.xyz1 v + Vec4.dot v.wz.xy01 v) 0
+
+{-# NOINLINE vec4Lerp #-}
+vec4Lerp :: [Vec4] -> Vec4
+vec4Lerp = List.foldl' (\acc v -> Vec4.lerp 0.3 acc v) 0
+
+{-# NOINLINE vec4Chain #-}
+vec4Chain :: Vec4 -> Vec4 -> Vec4 -> [Vec4] -> Vec4
+vec4Chain b c d = List.foldl' (\acc v -> acc + ((v + b) * c - d)) 0
+
+{-# NOINLINE dvec4DotSum #-}
+dvec4DotSum :: DVec4 -> DVec4 -> [DVec4] -> Double
+dvec4DotSum b c = List.foldl' (\s v -> s + DVec4.dot (v + b) c) 0
+
+{-# NOINLINE dvec4NormalizeDot #-}
+dvec4NormalizeDot :: [DVec4] -> Double
+dvec4NormalizeDot = List.foldl' (\s v -> s + DVec4.dot (DVec4.normalize v) v) 0
+
+{-# NOINLINE dvec4SqrtDot #-}
+dvec4SqrtDot :: [DVec4] -> Double
+dvec4SqrtDot = List.foldl' (\s v -> s + DVec4.dot (sqrt v) v) 0
+
+{-# NOINLINE dvec4FieldSwizzles #-}
+dvec4FieldSwizzles :: [DVec4] -> Double
+dvec4FieldSwizzles = List.foldl' (\s v -> s + v.wzyx.wzyx.y + v.xyzz.w + v.wzyx.zyx.yx.y) 0
+
+{-# NOINLINE dvec4FieldExtensions #-}
+dvec4FieldExtensions :: [DVec4] -> Double
+dvec4FieldExtensions = List.foldl' (\s v -> s + DVec4.dot v.xyz.xyz1 v + DVec4.dot v.wz.xy01 v) 0
+
+{-# NOINLINE dvec4Lerp #-}
+dvec4Lerp :: [DVec4] -> DVec4
+dvec4Lerp = List.foldl' (\acc v -> DVec4.lerp 0.3 acc v) 0
+
+{-# NOINLINE dvec4Chain #-}
+dvec4Chain :: DVec4 -> DVec4 -> DVec4 -> [DVec4] -> DVec4
+dvec4Chain b c d = List.foldl' (\acc v -> acc + ((v + b) * c - d)) 0
diff --git a/test/Spec/Mat4.hs b/test/Spec/Mat4.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Mat4.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Spec.Mat4 (tests) where
+
+import Hedgehog
+import Hedgehog.Gen qualified as Gen
+import Hedgehog.Range qualified as Range
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy.Mat4 qualified
+import Linear ((!*!))
+
+import Support.Ball (balls44, consistent, enclosed)
+import Support.Gen (forAllTransform, genEdgeScalar, genMostlySame)
+import Support.Linear (entries, toM44)
+import Support.Property (pattern PROP_TESTS)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+
+tests :: TestTree
+tests = testGroup "Mat4"
+  [ testPropertyNamed "assoc" "prop_mat4_assoc" prop_mat4_assoc
+  , testPropertyNamed "order" "prop_mat4_order" prop_mat4_order
+  , testPropertyNamed "eq" "prop_mat4_eq" prop_mat4_eq
+  ]
+
+prop_mat4_assoc :: Property
+prop_mat4_assoc = withDiscards 1000 . withTests PROP_TESTS $ property do
+  (p, p_) <- forAllTransform
+  (v, v_) <- forAllTransform
+  (m, m_) <- forAllTransform
+
+  let
+    pv'm = (p <> v) <> m
+    p'vm = p <> (v <> m)
+    pv'mBall = Ref.Mat4.compose (Ref.Mat4.compose (balls44 p_) (balls44 v_)) (balls44 m_)
+    p'vmBall = Ref.Mat4.compose (balls44 p_) (Ref.Mat4.compose (balls44 v_) (balls44 m_))
+  replicate 16 Nothing === enclosed (entries pv'mBall) (entries (toM44 pv'm))
+  replicate 16 Nothing === enclosed (entries p'vmBall) (entries (toM44 p'vm))
+
+  let
+    mv_p = (m_ !*! v_) !*! p_
+    m_vp = m_ !*! (v_ !*! p_)
+    mv_pBall = (balls44 m_ !*! balls44 v_) !*! balls44 p_
+    m_vpBall = balls44 m_ !*! (balls44 v_ !*! balls44 p_)
+  replicate 16 Nothing === enclosed (entries mv_pBall) (entries mv_p)
+  replicate 16 Nothing === enclosed (entries m_vpBall) (entries m_vp)
+
+  replicate 16 Nothing === consistent (entries pv'mBall) (entries p'vmBall)
+  replicate 16 Nothing === consistent (entries mv_pBall) (entries m_vpBall)
+  replicate 16 Nothing === consistent (entries pv'mBall) (entries mv_pBall)
+
+prop_mat4_order :: Property
+prop_mat4_order = withTests 1 $ property do
+  let
+    cm = Geomancy.Mat4.colMajor @Geomancy.Mat4.Mat4
+      0 1 2 3
+      4 5 6 7
+      8 9 0 1
+      2 3 4 5
+    rm = Geomancy.Mat4.rowMajor @Geomancy.Mat4.Mat4
+      0 4 8 2
+      1 5 9 3
+      2 6 0 4
+      3 7 1 5
+  Geomancy.Mat4.toListColMajor2d cm === Geomancy.Mat4.toListColMajor2d rm
+
+  let
+    cmT = Geomancy.Mat4.transpose cm
+    rmT = Geomancy.Mat4.transpose rm
+  Geomancy.Mat4.toListColMajor2d cmT === Geomancy.Mat4.toListColMajor2d rmT
+
+prop_mat4_eq :: Property
+prop_mat4_eq = withTests PROP_TESTS $ property do
+  let
+    four = Gen.list (Range.singleton 4)
+    fromRows = evalMaybe . Geomancy.Mat4.fromRowMajor2d @[] @Geomancy.Mat4.Mat4
+  rowsA <- forAll $ four (four genEdgeScalar)
+  rowsB <- forAll $ traverse (traverse (genMostlySame 8)) rowsA
+  a <- fromRows rowsA
+  b <- fromRows rowsB
+  label $ if rowsA == rowsB then "equal" else "different"
+  (a == b) === (rowsA == rowsB)
+  (a /= b) === (rowsA /= rowsB)
diff --git a/test/Spec/Point.hs b/test/Spec/Point.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Point.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Spec.Point (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy.Point qualified
+
+tests :: TestTree
+tests = testGroup "Point"
+  [ testPropertyNamed "dpoint" "prop_dpoint" prop_dpoint
+  ]
+
+prop_dpoint :: Property
+prop_dpoint = withTests 1 $ property do
+  let
+    far = 1e9
+    a = Point (dvec3 far 0 0) :: DPoint3
+    b = Point (dvec3 (far + 0.5) 0 0)
+  0.5 === Geomancy.Point.distance a b
+  b === a .+^ dvec3 0.5 0 0
+  dvec3 0.5 0 0 === b .-. a
+  Point (dvec3 (far + 0.25) 0 0) === Geomancy.Point.lerp a b 0.5
+
+  5 === Geomancy.Point.distance (Point (vec3 0 0 0)) (Point (vec3 3 4 0))
diff --git a/test/Spec/Quaternion.hs b/test/Spec/Quaternion.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Quaternion.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Spec.Quaternion (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Hedgehog.Gen qualified as Gen
+import Hedgehog.Range qualified as Range
+import Linear.Quaternion qualified
+
+import Geomancy.Quaternion qualified
+import Geomancy.Transform ((!.))
+import Geomancy.Transform qualified as Transform
+
+import Support.Ball (balls, consistent, enclosed, exactly)
+import Support.Fixtures
+  (intrinsicComposed, intrinsicComposedRef, quarterTurn, rotationsMatch, xNeg, xPos, yNeg, yPos, zNeg, zPos)
+import Support.Gen (genAngle, genSmallVec3, genVec3)
+import Support.Linear (toQ, toV3)
+import Support.Reference.Linear qualified as Ref.Linear
+import Support.Reference.Quaternion qualified as Ref.Quaternion
+import Support.Reference.Transform qualified as Ref.Transform
+
+tests :: TestTree
+tests = testGroup "Quaternion"
+  [ testPropertyNamed "ref" "prop_quaternion_ref" prop_quaternion_ref
+  , testPropertyNamed "rotate_matrix" "prop_quaternion_rotate_matrix" prop_quaternion_rotate_matrix
+  , testPropertyNamed "associativity" "prop_quaternion_associativity" prop_quaternion_associativity
+  , testPropertyNamed "intrinsic" "prop_quaternion_intrinsic" prop_quaternion_intrinsic
+  , testPropertyNamed "extrinsic" "prop_quaternion_extrinsic" prop_quaternion_extrinsic
+  , testPropertyNamed "intrinsic_ref" "prop_quaternion_intrinsic_ref" prop_quaternion_intrinsic_ref
+  ]
+
+prop_quaternion_ref :: Property
+prop_quaternion_ref = property do
+  annotate "Construction"
+  (axis, angle) <- forAll $ (,) <$> genVec3 <*> genAngle
+  let qg = Geomancy.Quaternion.axisAngle axis angle
+  let ql = Linear.Quaternion.axisAngle (toV3 axis) angle
+  show (toQ qg) === show ql
+
+  annotate "Rotation"
+  p <- forAll genSmallVec3
+  let
+    rpg = Geomancy.Quaternion.rotate qg p
+    rpl = Linear.Quaternion.rotate ql (toV3 p)
+    rpgBall =
+      Ref.Quaternion.rotate
+        (Ref.Quaternion.axisAngle (balls (toV3 axis)) (exactly angle))
+        (balls (toV3 p))
+    rplBall =
+      Ref.Linear.rotate
+        (Linear.Quaternion.axisAngle (balls (toV3 axis)) (exactly angle))
+        (balls (toV3 p))
+  replicate 3 Nothing === enclosed rpgBall (toV3 rpg)
+  replicate 3 Nothing === enclosed rplBall rpl
+  replicate 3 Nothing === consistent rpgBall rplBall
+
+  annotate "Multiplication"
+  (axisB, angleB) <- forAll $ (,) <$> genVec3 <*> genAngle
+  let qgB = Geomancy.Quaternion.axisAngle axisB angleB
+  let qlB = Linear.Quaternion.axisAngle (toV3 axisB) angleB
+  show (toQ (qg * qgB)) === show (ql * qlB)
+
+prop_quaternion_rotate_matrix :: Property
+prop_quaternion_rotate_matrix = property do
+  q <- forAll $ quaternion <$> genUnitish <*> genUnitish <*> genUnitish <*> genUnitish
+  p <- forAll genSmallVec3
+  let
+    viaRotate = Geomancy.Quaternion.rotate q p
+    viaMatrix = Transform.rotateQ q !. p
+    viaRotateBall = Ref.Quaternion.rotate (balls (toQ q)) (balls (toV3 p))
+    viaMatrixBall = Ref.Transform.rotateQ (balls (toQ q)) Ref.Transform.!. balls (toV3 p)
+  replicate 3 Nothing === enclosed viaRotateBall (toV3 viaRotate)
+  replicate 3 Nothing === enclosed viaMatrixBall (toV3 viaMatrix)
+  replicate 3 Nothing === consistent viaRotateBall viaMatrixBall
+  where
+    genUnitish = Gen.float (Range.linearFracFrom 0.0 (-1) 1)
+
+prop_quaternion_associativity :: Property
+prop_quaternion_associativity = property do
+  (a, b, c) <- forAll $ (,,)
+    <$> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
+    <*> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
+    <*> (Geomancy.Quaternion.axisAngle <$> genVec3 <*> genAngle)
+  let ab'c = (a * b) * c
+  annotateShow ab'c
+  let a'bc = a * (b * c)
+  annotateShow a'bc
+  let
+    aBall = balls (toQ a)
+    bBall = balls (toQ b)
+    cBall = balls (toQ c)
+    ab'cBall = (aBall `Ref.Quaternion.multiply` bBall) `Ref.Quaternion.multiply` cBall
+    a'bcBall = aBall `Ref.Quaternion.multiply` (bBall `Ref.Quaternion.multiply` cBall)
+  replicate 4 Nothing === enclosed ab'cBall (toQ ab'c)
+  replicate 4 Nothing === enclosed a'bcBall (toQ a'bc)
+  replicate 4 Nothing === consistent ab'cBall a'bcBall
+
+prop_quaternion_intrinsic :: Property
+prop_quaternion_intrinsic = withTests 1 $ property do
+  let
+    q = Geomancy.Quaternion.intrinsic 0 quarterTurn quarterTurn
+    qBall = Ref.Quaternion.intrinsic 0 quarterTurn quarterTurn
+  rotationsMatch toV3
+    (Geomancy.Quaternion.rotate q)
+    (Ref.Quaternion.rotate qBall)
+    [(zPos, yNeg), (xPos, zNeg), (yNeg, xNeg)]
+
+prop_quaternion_extrinsic :: Property
+prop_quaternion_extrinsic = withTests 1 $ property do
+  let
+    q = Geomancy.Quaternion.extrinsic quarterTurn quarterTurn 0
+    qBall = Ref.Quaternion.extrinsic quarterTurn quarterTurn 0
+  rotationsMatch toV3
+    (Geomancy.Quaternion.rotate q)
+    (Ref.Quaternion.rotate qBall)
+    [(zPos, xPos), (xPos, yPos), (yNeg, zNeg)]
+
+prop_quaternion_intrinsic_ref :: Property
+prop_quaternion_intrinsic_ref = property do
+  (roll, pitch, yaw) <- forAll $ (,,) <$> genAngle <*> genAngle <*> genAngle
+  let fused = Geomancy.Quaternion.intrinsic roll pitch yaw
+  annotateShow fused
+  let composed = intrinsicComposed roll pitch yaw
+  annotateShow composed
+  let viaFused = Geomancy.Quaternion.rotate fused zPos
+  annotateShow viaFused
+  let viaComposed = Geomancy.Quaternion.rotate composed zPos
+  let
+    zPosBall = balls (toV3 zPos)
+    viaFusedBall =
+      Ref.Quaternion.rotate (Ref.Quaternion.intrinsic (exactly roll) (exactly pitch) (exactly yaw)) zPosBall
+    viaComposedBall =
+      Ref.Quaternion.rotate (intrinsicComposedRef (exactly roll) (exactly pitch) (exactly yaw)) zPosBall
+  replicate 3 Nothing === enclosed viaFusedBall (toV3 viaFused)
+  replicate 3 Nothing === enclosed viaComposedBall (toV3 viaComposed)
+  replicate 3 Nothing === consistent viaFusedBall viaComposedBall
diff --git a/test/Spec/Storable.hs b/test/Spec/Storable.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Storable.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Spec.Storable (tests) where
+
+import Data.Proxy (Proxy(..))
+import Data.Vector.Storable qualified as Storable
+import Foreign (Storable)
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy.DVec3 qualified
+import Geomancy.IVec3 qualified
+import Geomancy.UVec3 qualified
+import Geomancy.Vec3 qualified
+
+import Support.Gen (forAllDTransform, forAllTransform, genDVec4, genVec4)
+import Support.Property (pattern PROP_TESTS, layout140)
+
+tests :: TestTree
+tests = testGroup "Storable"
+  [ testPropertyNamed "vec4_strict_reads" "prop_vec4_strict_reads" prop_vec4_strict_reads
+  , testPropertyNamed "dvec4_strict_reads" "prop_dvec4_strict_reads" prop_dvec4_strict_reads
+  , testPropertyNamed "mat4_strict_reads" "prop_mat4_strict_reads" prop_mat4_strict_reads
+  , testPropertyNamed "dmat4_strict_reads" "prop_dmat4_strict_reads" prop_dmat4_strict_reads
+  , testPropertyNamed "block_layout" "prop_block_layout" prop_block_layout
+  ]
+
+prop_vec4_strict_reads :: Property
+prop_vec4_strict_reads = withTests PROP_TESTS $ property do
+  a <- forAll genVec4
+  b <- forAll genVec4
+  strictReads (Storable.fromList [a, b]) === (a, b)
+
+prop_dvec4_strict_reads :: Property
+prop_dvec4_strict_reads = withTests PROP_TESTS $ property do
+  a <- forAll genDVec4
+  b <- forAll genDVec4
+  strictReads (Storable.fromList [a, b]) === (a, b)
+
+prop_mat4_strict_reads :: Property
+prop_mat4_strict_reads = withTests PROP_TESTS $ property do
+  (a, _) <- forAllTransform
+  (b, _) <- forAllTransform
+  strictReads (Storable.fromList [a, b]) === (a, b)
+
+prop_dmat4_strict_reads :: Property
+prop_dmat4_strict_reads = withTests PROP_TESTS $ property do
+  (a, _) <- forAllDTransform
+  (b, _) <- forAllDTransform
+  strictReads (Storable.fromList [a, b]) === (a, b)
+
+prop_block_layout :: Property
+prop_block_layout = withTests 1 $ property do
+  (8, 8) === layout140 (Proxy @Vec2)
+  (16, 16) === layout140 (Proxy @Vec3)
+  (16, 12) === layout140 (Proxy @Geomancy.Vec3.Packed)
+  (16, 16) === layout140 (Proxy @Vec4)
+  (8, 8) === layout140 (Proxy @IVec2)
+  (16, 16) === layout140 (Proxy @IVec3)
+  (16, 12) === layout140 (Proxy @Geomancy.IVec3.Packed)
+  (16, 16) === layout140 (Proxy @IVec4)
+  (8, 8) === layout140 (Proxy @UVec2)
+  (16, 16) === layout140 (Proxy @UVec3)
+  (16, 12) === layout140 (Proxy @Geomancy.UVec3.Packed)
+  (16, 16) === layout140 (Proxy @UVec4)
+  (16, 16) === layout140 (Proxy @DVec2)
+  (32, 32) === layout140 (Proxy @DVec3)
+  (32, 24) === layout140 (Proxy @Geomancy.DVec3.Packed)
+  (32, 32) === layout140 (Proxy @DVec4)
+  (16, 16) === layout140 (Proxy @Quaternion)
+  (32, 32) === layout140 (Proxy @DQuaternion)
+  (16, 64) === layout140 (Proxy @Transform)
+  (32, 128) === layout140 (Proxy @DTransform)
+
+data Both a = Both !a !a
+
+{-# INLINE strictReads #-}
+strictReads :: Storable a => Storable.Vector a -> (a, a)
+strictReads v =
+  case Both (Storable.unsafeIndex v 0) (Storable.unsafeIndex v 1) of
+    Both a b -> (a, b)
diff --git a/test/Spec/Swizzle.hs b/test/Spec/Swizzle.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Swizzle.hs
@@ -0,0 +1,3114 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Spec.Swizzle (tests) where
+
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy
+import Geomancy.Swizzle ()
+
+import Support.Gen (genDouble, genFloat, genInt32, genInt64, genWord32, genWord64)
+import Support.Swizzle (Mismatch, swizzled, swizzles)
+
+tests :: TestTree
+tests = testGroup "Swizzle"
+  [ testPropertyNamed "vec2" "prop_vec2_swizzles" $
+      swizzles (vec2 <$> genFloat <*> genFloat) vec2Swizzles
+  , testPropertyNamed "vec3" "prop_vec3_swizzles" $
+      swizzles (vec3 <$> genFloat <*> genFloat <*> genFloat) vec3Swizzles
+  , testPropertyNamed "vec4" "prop_vec4_swizzles" $
+      swizzles (vec4 <$> genFloat <*> genFloat <*> genFloat <*> genFloat) vec4Swizzles
+  , testPropertyNamed "dvec2" "prop_dvec2_swizzles" $
+      swizzles (dvec2 <$> genDouble <*> genDouble) dvec2Swizzles
+  , testPropertyNamed "dvec3" "prop_dvec3_swizzles" $
+      swizzles (dvec3 <$> genDouble <*> genDouble <*> genDouble) dvec3Swizzles
+  , testPropertyNamed "dvec4" "prop_dvec4_swizzles" $
+      swizzles (dvec4 <$> genDouble <*> genDouble <*> genDouble <*> genDouble) dvec4Swizzles
+  , testPropertyNamed "ivec2" "prop_ivec2_swizzles" $
+      swizzles (ivec2 <$> genInt32 <*> genInt32) ivec2Swizzles
+  , testPropertyNamed "ivec3" "prop_ivec3_swizzles" $
+      swizzles (ivec3 <$> genInt32 <*> genInt32 <*> genInt32) ivec3Swizzles
+  , testPropertyNamed "ivec4" "prop_ivec4_swizzles" $
+      swizzles (ivec4 <$> genInt32 <*> genInt32 <*> genInt32 <*> genInt32) ivec4Swizzles
+  , testPropertyNamed "uvec2" "prop_uvec2_swizzles" $
+      swizzles (uvec2 <$> genWord32 <*> genWord32) uvec2Swizzles
+  , testPropertyNamed "uvec3" "prop_uvec3_swizzles" $
+      swizzles (uvec3 <$> genWord32 <*> genWord32 <*> genWord32) uvec3Swizzles
+  , testPropertyNamed "uvec4" "prop_uvec4_swizzles" $
+      swizzles (uvec4 <$> genWord32 <*> genWord32 <*> genWord32 <*> genWord32) uvec4Swizzles
+  , testPropertyNamed "i64vec2" "prop_i64vec2_swizzles" $
+      swizzles (i64vec2 <$> genInt64 <*> genInt64) i64vec2Swizzles
+  , testPropertyNamed "i64vec3" "prop_i64vec3_swizzles" $
+      swizzles (i64vec3 <$> genInt64 <*> genInt64 <*> genInt64) i64vec3Swizzles
+  , testPropertyNamed "i64vec4" "prop_i64vec4_swizzles" $
+      swizzles (i64vec4 <$> genInt64 <*> genInt64 <*> genInt64 <*> genInt64) i64vec4Swizzles
+  , testPropertyNamed "u64vec2" "prop_u64vec2_swizzles" $
+      swizzles (u64vec2 <$> genWord64 <*> genWord64) u64vec2Swizzles
+  , testPropertyNamed "u64vec3" "prop_u64vec3_swizzles" $
+      swizzles (u64vec3 <$> genWord64 <*> genWord64 <*> genWord64) u64vec3Swizzles
+  , testPropertyNamed "u64vec4" "prop_u64vec4_swizzles" $
+      swizzles (u64vec4 <$> genWord64 <*> genWord64 <*> genWord64 <*> genWord64) u64vec4Swizzles
+  ]
+
+vec2Swizzles :: Vec2 -> [Maybe Mismatch]
+vec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+vec3Swizzles :: Vec3 -> [Maybe Mismatch]
+vec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+vec4Swizzles :: Vec4 -> [Maybe Mismatch]
+vec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
+
+dvec2Swizzles :: DVec2 -> [Maybe Mismatch]
+dvec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+dvec3Swizzles :: DVec3 -> [Maybe Mismatch]
+dvec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+dvec4Swizzles :: DVec4 -> [Maybe Mismatch]
+dvec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
+
+ivec2Swizzles :: IVec2 -> [Maybe Mismatch]
+ivec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+ivec3Swizzles :: IVec3 -> [Maybe Mismatch]
+ivec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+ivec4Swizzles :: IVec4 -> [Maybe Mismatch]
+ivec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
+
+uvec2Swizzles :: UVec2 -> [Maybe Mismatch]
+uvec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+uvec3Swizzles :: UVec3 -> [Maybe Mismatch]
+uvec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+uvec4Swizzles :: UVec4 -> [Maybe Mismatch]
+uvec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
+
+i64vec2Swizzles :: I64Vec2 -> [Maybe Mismatch]
+i64vec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+i64vec3Swizzles :: I64Vec3 -> [Maybe Mismatch]
+i64vec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+i64vec4Swizzles :: I64Vec4 -> [Maybe Mismatch]
+i64vec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
+
+u64vec2Swizzles :: U64Vec2 -> [Maybe Mismatch]
+u64vec2Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"xy0" v
+  , swizzled @"xy1" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"xy00" v
+  , swizzled @"xy01" v
+  , swizzled @"xy10" v
+  , swizzled @"xy11" v
+  ]
+
+u64vec3Swizzles :: U64Vec3 -> [Maybe Mismatch]
+u64vec3Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"xyz0" v
+  , swizzled @"xyz1" v
+  ]
+
+u64vec4Swizzles :: U64Vec4 -> [Maybe Mismatch]
+u64vec4Swizzles v =
+  [ swizzled @"x" v
+  , swizzled @"y" v
+  , swizzled @"z" v
+  , swizzled @"w" v
+  , swizzled @"xx" v
+  , swizzled @"xy" v
+  , swizzled @"xz" v
+  , swizzled @"xw" v
+  , swizzled @"yx" v
+  , swizzled @"yy" v
+  , swizzled @"yz" v
+  , swizzled @"yw" v
+  , swizzled @"zx" v
+  , swizzled @"zy" v
+  , swizzled @"zz" v
+  , swizzled @"zw" v
+  , swizzled @"wx" v
+  , swizzled @"wy" v
+  , swizzled @"wz" v
+  , swizzled @"ww" v
+  , swizzled @"xxx" v
+  , swizzled @"xxy" v
+  , swizzled @"xxz" v
+  , swizzled @"xxw" v
+  , swizzled @"xyx" v
+  , swizzled @"xyy" v
+  , swizzled @"xyz" v
+  , swizzled @"xyw" v
+  , swizzled @"xzx" v
+  , swizzled @"xzy" v
+  , swizzled @"xzz" v
+  , swizzled @"xzw" v
+  , swizzled @"xwx" v
+  , swizzled @"xwy" v
+  , swizzled @"xwz" v
+  , swizzled @"xww" v
+  , swizzled @"yxx" v
+  , swizzled @"yxy" v
+  , swizzled @"yxz" v
+  , swizzled @"yxw" v
+  , swizzled @"yyx" v
+  , swizzled @"yyy" v
+  , swizzled @"yyz" v
+  , swizzled @"yyw" v
+  , swizzled @"yzx" v
+  , swizzled @"yzy" v
+  , swizzled @"yzz" v
+  , swizzled @"yzw" v
+  , swizzled @"ywx" v
+  , swizzled @"ywy" v
+  , swizzled @"ywz" v
+  , swizzled @"yww" v
+  , swizzled @"zxx" v
+  , swizzled @"zxy" v
+  , swizzled @"zxz" v
+  , swizzled @"zxw" v
+  , swizzled @"zyx" v
+  , swizzled @"zyy" v
+  , swizzled @"zyz" v
+  , swizzled @"zyw" v
+  , swizzled @"zzx" v
+  , swizzled @"zzy" v
+  , swizzled @"zzz" v
+  , swizzled @"zzw" v
+  , swizzled @"zwx" v
+  , swizzled @"zwy" v
+  , swizzled @"zwz" v
+  , swizzled @"zww" v
+  , swizzled @"wxx" v
+  , swizzled @"wxy" v
+  , swizzled @"wxz" v
+  , swizzled @"wxw" v
+  , swizzled @"wyx" v
+  , swizzled @"wyy" v
+  , swizzled @"wyz" v
+  , swizzled @"wyw" v
+  , swizzled @"wzx" v
+  , swizzled @"wzy" v
+  , swizzled @"wzz" v
+  , swizzled @"wzw" v
+  , swizzled @"wwx" v
+  , swizzled @"wwy" v
+  , swizzled @"wwz" v
+  , swizzled @"www" v
+  , swizzled @"xxxx" v
+  , swizzled @"xxxy" v
+  , swizzled @"xxxz" v
+  , swizzled @"xxxw" v
+  , swizzled @"xxyx" v
+  , swizzled @"xxyy" v
+  , swizzled @"xxyz" v
+  , swizzled @"xxyw" v
+  , swizzled @"xxzx" v
+  , swizzled @"xxzy" v
+  , swizzled @"xxzz" v
+  , swizzled @"xxzw" v
+  , swizzled @"xxwx" v
+  , swizzled @"xxwy" v
+  , swizzled @"xxwz" v
+  , swizzled @"xxww" v
+  , swizzled @"xyxx" v
+  , swizzled @"xyxy" v
+  , swizzled @"xyxz" v
+  , swizzled @"xyxw" v
+  , swizzled @"xyyx" v
+  , swizzled @"xyyy" v
+  , swizzled @"xyyz" v
+  , swizzled @"xyyw" v
+  , swizzled @"xyzx" v
+  , swizzled @"xyzy" v
+  , swizzled @"xyzz" v
+  , swizzled @"xyzw" v
+  , swizzled @"xywx" v
+  , swizzled @"xywy" v
+  , swizzled @"xywz" v
+  , swizzled @"xyww" v
+  , swizzled @"xzxx" v
+  , swizzled @"xzxy" v
+  , swizzled @"xzxz" v
+  , swizzled @"xzxw" v
+  , swizzled @"xzyx" v
+  , swizzled @"xzyy" v
+  , swizzled @"xzyz" v
+  , swizzled @"xzyw" v
+  , swizzled @"xzzx" v
+  , swizzled @"xzzy" v
+  , swizzled @"xzzz" v
+  , swizzled @"xzzw" v
+  , swizzled @"xzwx" v
+  , swizzled @"xzwy" v
+  , swizzled @"xzwz" v
+  , swizzled @"xzww" v
+  , swizzled @"xwxx" v
+  , swizzled @"xwxy" v
+  , swizzled @"xwxz" v
+  , swizzled @"xwxw" v
+  , swizzled @"xwyx" v
+  , swizzled @"xwyy" v
+  , swizzled @"xwyz" v
+  , swizzled @"xwyw" v
+  , swizzled @"xwzx" v
+  , swizzled @"xwzy" v
+  , swizzled @"xwzz" v
+  , swizzled @"xwzw" v
+  , swizzled @"xwwx" v
+  , swizzled @"xwwy" v
+  , swizzled @"xwwz" v
+  , swizzled @"xwww" v
+  , swizzled @"yxxx" v
+  , swizzled @"yxxy" v
+  , swizzled @"yxxz" v
+  , swizzled @"yxxw" v
+  , swizzled @"yxyx" v
+  , swizzled @"yxyy" v
+  , swizzled @"yxyz" v
+  , swizzled @"yxyw" v
+  , swizzled @"yxzx" v
+  , swizzled @"yxzy" v
+  , swizzled @"yxzz" v
+  , swizzled @"yxzw" v
+  , swizzled @"yxwx" v
+  , swizzled @"yxwy" v
+  , swizzled @"yxwz" v
+  , swizzled @"yxww" v
+  , swizzled @"yyxx" v
+  , swizzled @"yyxy" v
+  , swizzled @"yyxz" v
+  , swizzled @"yyxw" v
+  , swizzled @"yyyx" v
+  , swizzled @"yyyy" v
+  , swizzled @"yyyz" v
+  , swizzled @"yyyw" v
+  , swizzled @"yyzx" v
+  , swizzled @"yyzy" v
+  , swizzled @"yyzz" v
+  , swizzled @"yyzw" v
+  , swizzled @"yywx" v
+  , swizzled @"yywy" v
+  , swizzled @"yywz" v
+  , swizzled @"yyww" v
+  , swizzled @"yzxx" v
+  , swizzled @"yzxy" v
+  , swizzled @"yzxz" v
+  , swizzled @"yzxw" v
+  , swizzled @"yzyx" v
+  , swizzled @"yzyy" v
+  , swizzled @"yzyz" v
+  , swizzled @"yzyw" v
+  , swizzled @"yzzx" v
+  , swizzled @"yzzy" v
+  , swizzled @"yzzz" v
+  , swizzled @"yzzw" v
+  , swizzled @"yzwx" v
+  , swizzled @"yzwy" v
+  , swizzled @"yzwz" v
+  , swizzled @"yzww" v
+  , swizzled @"ywxx" v
+  , swizzled @"ywxy" v
+  , swizzled @"ywxz" v
+  , swizzled @"ywxw" v
+  , swizzled @"ywyx" v
+  , swizzled @"ywyy" v
+  , swizzled @"ywyz" v
+  , swizzled @"ywyw" v
+  , swizzled @"ywzx" v
+  , swizzled @"ywzy" v
+  , swizzled @"ywzz" v
+  , swizzled @"ywzw" v
+  , swizzled @"ywwx" v
+  , swizzled @"ywwy" v
+  , swizzled @"ywwz" v
+  , swizzled @"ywww" v
+  , swizzled @"zxxx" v
+  , swizzled @"zxxy" v
+  , swizzled @"zxxz" v
+  , swizzled @"zxxw" v
+  , swizzled @"zxyx" v
+  , swizzled @"zxyy" v
+  , swizzled @"zxyz" v
+  , swizzled @"zxyw" v
+  , swizzled @"zxzx" v
+  , swizzled @"zxzy" v
+  , swizzled @"zxzz" v
+  , swizzled @"zxzw" v
+  , swizzled @"zxwx" v
+  , swizzled @"zxwy" v
+  , swizzled @"zxwz" v
+  , swizzled @"zxww" v
+  , swizzled @"zyxx" v
+  , swizzled @"zyxy" v
+  , swizzled @"zyxz" v
+  , swizzled @"zyxw" v
+  , swizzled @"zyyx" v
+  , swizzled @"zyyy" v
+  , swizzled @"zyyz" v
+  , swizzled @"zyyw" v
+  , swizzled @"zyzx" v
+  , swizzled @"zyzy" v
+  , swizzled @"zyzz" v
+  , swizzled @"zyzw" v
+  , swizzled @"zywx" v
+  , swizzled @"zywy" v
+  , swizzled @"zywz" v
+  , swizzled @"zyww" v
+  , swizzled @"zzxx" v
+  , swizzled @"zzxy" v
+  , swizzled @"zzxz" v
+  , swizzled @"zzxw" v
+  , swizzled @"zzyx" v
+  , swizzled @"zzyy" v
+  , swizzled @"zzyz" v
+  , swizzled @"zzyw" v
+  , swizzled @"zzzx" v
+  , swizzled @"zzzy" v
+  , swizzled @"zzzz" v
+  , swizzled @"zzzw" v
+  , swizzled @"zzwx" v
+  , swizzled @"zzwy" v
+  , swizzled @"zzwz" v
+  , swizzled @"zzww" v
+  , swizzled @"zwxx" v
+  , swizzled @"zwxy" v
+  , swizzled @"zwxz" v
+  , swizzled @"zwxw" v
+  , swizzled @"zwyx" v
+  , swizzled @"zwyy" v
+  , swizzled @"zwyz" v
+  , swizzled @"zwyw" v
+  , swizzled @"zwzx" v
+  , swizzled @"zwzy" v
+  , swizzled @"zwzz" v
+  , swizzled @"zwzw" v
+  , swizzled @"zwwx" v
+  , swizzled @"zwwy" v
+  , swizzled @"zwwz" v
+  , swizzled @"zwww" v
+  , swizzled @"wxxx" v
+  , swizzled @"wxxy" v
+  , swizzled @"wxxz" v
+  , swizzled @"wxxw" v
+  , swizzled @"wxyx" v
+  , swizzled @"wxyy" v
+  , swizzled @"wxyz" v
+  , swizzled @"wxyw" v
+  , swizzled @"wxzx" v
+  , swizzled @"wxzy" v
+  , swizzled @"wxzz" v
+  , swizzled @"wxzw" v
+  , swizzled @"wxwx" v
+  , swizzled @"wxwy" v
+  , swizzled @"wxwz" v
+  , swizzled @"wxww" v
+  , swizzled @"wyxx" v
+  , swizzled @"wyxy" v
+  , swizzled @"wyxz" v
+  , swizzled @"wyxw" v
+  , swizzled @"wyyx" v
+  , swizzled @"wyyy" v
+  , swizzled @"wyyz" v
+  , swizzled @"wyyw" v
+  , swizzled @"wyzx" v
+  , swizzled @"wyzy" v
+  , swizzled @"wyzz" v
+  , swizzled @"wyzw" v
+  , swizzled @"wywx" v
+  , swizzled @"wywy" v
+  , swizzled @"wywz" v
+  , swizzled @"wyww" v
+  , swizzled @"wzxx" v
+  , swizzled @"wzxy" v
+  , swizzled @"wzxz" v
+  , swizzled @"wzxw" v
+  , swizzled @"wzyx" v
+  , swizzled @"wzyy" v
+  , swizzled @"wzyz" v
+  , swizzled @"wzyw" v
+  , swizzled @"wzzx" v
+  , swizzled @"wzzy" v
+  , swizzled @"wzzz" v
+  , swizzled @"wzzw" v
+  , swizzled @"wzwx" v
+  , swizzled @"wzwy" v
+  , swizzled @"wzwz" v
+  , swizzled @"wzww" v
+  , swizzled @"wwxx" v
+  , swizzled @"wwxy" v
+  , swizzled @"wwxz" v
+  , swizzled @"wwxw" v
+  , swizzled @"wwyx" v
+  , swizzled @"wwyy" v
+  , swizzled @"wwyz" v
+  , swizzled @"wwyw" v
+  , swizzled @"wwzx" v
+  , swizzled @"wwzy" v
+  , swizzled @"wwzz" v
+  , swizzled @"wwzw" v
+  , swizzled @"wwwx" v
+  , swizzled @"wwwy" v
+  , swizzled @"wwwz" v
+  , swizzled @"wwww" v
+  ]
diff --git a/test/Spec/Transform.hs b/test/Spec/Transform.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Transform.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Spec.Transform (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Linear (M44, V3(..))
+
+import Geomancy.Mat4 qualified
+import Geomancy.Quaternion qualified
+import Geomancy.Transform ((!.))
+import Geomancy.Transform qualified as Transform
+
+import Support.Ball (Ball, balls, consistent, enclosed)
+import Support.Fixtures
+  (intrinsicComposed, intrinsicComposedRef, quarterTurn, rotationsMatch, trs, trsRef, xPos, yNeg, yPos, zPos)
+import Support.Linear (toV3)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+import Support.Reference.Quaternion qualified as Ref.Quaternion
+import Support.Reference.Transform qualified as Ref.Transform
+
+tests :: TestTree
+tests = testGroup "Transform"
+  [ testPropertyNamed "det" "prop_transform_det" prop_transform_det
+  , testPropertyNamed "rotateX" "prop_transform_rotateX" prop_transform_rotateX
+  , testPropertyNamed "rotateY" "prop_transform_rotateY" prop_transform_rotateY
+  , testPropertyNamed "rotateZ" "prop_transform_rotateZ" prop_transform_rotateZ
+  , testPropertyNamed "node" "prop_transform_node" prop_transform_node
+  , testPropertyNamed "order" "prop_transform_order" prop_transform_order
+  ]
+
+prop_transform_det :: Property
+prop_transform_det = withTests 1 $ property do
+  1     === Geomancy.Mat4.det Geomancy.Mat4.identity
+  1     === Geomancy.Mat4.det (Transform.rotateY (pi/6))  -- area-preserving
+  1     === Geomancy.Mat4.det (Transform.translate 1 2 3) -- area-preserving too
+  0     === Geomancy.Mat4.det (Transform.scaleX 0)        -- space collapse, no inverse
+  -1    === Geomancy.Mat4.det (Transform.scaleZ (-1))     -- flips the space
+  8     === Geomancy.Mat4.det (Transform.scale 2)         -- stretches a little
+  (1/8) === Geomancy.Mat4.det (Transform.scale (1/2))     -- stretches backwards
+
+prop_transform_rotateX :: Property
+prop_transform_rotateX = withTests 1 $ property do
+  rotationMatches xPos Transform.rotateX Ref.Transform.rotateX zPos yNeg
+
+prop_transform_rotateY :: Property
+prop_transform_rotateY = withTests 1 $ property do
+  rotationMatches yPos Transform.rotateY Ref.Transform.rotateY zPos xPos
+
+prop_transform_rotateZ :: Property
+prop_transform_rotateZ = withTests 1 $ property do
+  rotationMatches zPos Transform.rotateZ Ref.Transform.rotateZ xPos yPos
+
+rotationMatches
+  :: Vec3
+  -> (Float -> Transform)
+  -> (Ball Float -> M44 (Ball Float))
+  -> Vec3
+  -> Vec3
+  -> PropertyT IO ()
+rotationMatches axis rotate rotateRef input expected = do
+  rotationsMatch toV3
+    (rotate quarterTurn !.)
+    (rotateRef quarterTurn Ref.Transform.!.)
+    [(input, expected)]
+  rotationsMatch toV3
+    (Transform.rotateQ (Geomancy.Quaternion.axisAngle axis quarterTurn) !.)
+    (Ref.Transform.rotateQ (Ref.Quaternion.axisAngle (balls (toV3 axis)) quarterTurn) Ref.Transform.!.)
+    [(input, expected)]
+
+prop_transform_node :: Property
+prop_transform_node = withTests 1 $ property do
+  let
+    r = intrinsicComposed 0 0 (pi/7)
+    dps = Transform.node (vec3 2 3 5) r 11
+    node = trs (vec3 2 3 5) r 11
+    v = vec3 0 0 1
+    rBall = intrinsicComposedRef 0 0 (pi/7)
+    dpsBall = Ref.Transform.node (V3 2 3 5) rBall 11
+    nodeBall = trsRef (V3 2 3 5) rBall 11
+    viaDpsBall = dpsBall Ref.Transform.!. V3 0 0 1
+    viaNodeBall = nodeBall Ref.Transform.!. V3 0 0 1
+  replicate 3 Nothing === enclosed viaDpsBall (toV3 (dps !. v))
+  replicate 3 Nothing === enclosed viaNodeBall (toV3 (node !. v))
+  replicate 3 Nothing === consistent viaDpsBall viaNodeBall
+
+prop_transform_order :: Property
+prop_transform_order = withTests 1 $ property do
+  let
+    parent = Transform.node (vec3 4 5 6) (intrinsicComposed 0 0 (pi/6)) 2
+    local = Transform.node (vec3 7 8 9) (intrinsicComposed 0 (pi/6) 0) (1/3)
+    precomp = parent <> local !. vec3 0 0 1
+    nocomp = parent !. local !. vec3 0 0 1
+    parentBall = Ref.Transform.node (V3 4 5 6) (intrinsicComposedRef 0 0 (pi/6)) 2
+    localBall = Ref.Transform.node (V3 7 8 9) (intrinsicComposedRef 0 (pi/6) 0) (1/3)
+    precompBall = Ref.Mat4.compose parentBall localBall Ref.Transform.!. V3 0 0 1
+    nocompBall = parentBall Ref.Transform.!. localBall Ref.Transform.!. V3 0 0 1
+  replicate 3 Nothing === enclosed precompBall (toV3 precomp)
+  replicate 3 Nothing === enclosed nocompBall (toV3 nocomp)
+  replicate 3 Nothing === consistent precompBall nocompBall
diff --git a/test/Spec/Vec4.hs b/test/Spec/Vec4.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Vec4.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Spec.Vec4 (tests) where
+
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Geomancy.DVec4 qualified
+import Geomancy.Vec4 qualified
+
+import Support.Gen (genEdgeScalar, genMostlySame)
+import Support.Property (pattern PROP_TESTS)
+
+tests :: TestTree
+tests = testGroup "Vec4"
+  [ testPropertyNamed "eq_ord" "prop_vec4_eq_ord" prop_vec4_eq_ord
+  , testPropertyNamed "dvec4_eq_ord" "prop_dvec4_eq_ord" prop_dvec4_eq_ord
+  ]
+
+prop_vec4_eq_ord :: Property
+prop_vec4_eq_ord = withTests PROP_TESTS $ property do
+  (xsA, xsB) <- forAll nearbyTuples
+  matchesTuple (Geomancy.Vec4.fromTuple xsA, xsA) (Geomancy.Vec4.fromTuple xsB, xsB)
+
+prop_dvec4_eq_ord :: Property
+prop_dvec4_eq_ord = withTests PROP_TESTS $ property do
+  (xsA, xsB) <- forAll nearbyTuples
+  matchesTuple (Geomancy.DVec4.fromTuple xsA, xsA) (Geomancy.DVec4.fromTuple xsB, xsB)
+
+type Tuple4 a = (a, a, a, a)
+
+nearbyTuples :: Fractional a => Gen (Tuple4 a, Tuple4 a)
+nearbyTuples = do
+  a <- (,,,) <$> genEdgeScalar <*> genEdgeScalar <*> genEdgeScalar <*> genEdgeScalar
+  b <- traverse4 (genMostlySame 4) a
+  pure (a, b)
+  where
+    traverse4 f (x, y, z, w) = (,,,) <$> f x <*> f y <*> f z <*> f w
+
+matchesTuple
+  :: (Ord v, Show v, Ord a)
+  => (v, Tuple4 a)
+  -> (v, Tuple4 a)
+  -> PropertyT IO ()
+matchesTuple (a, xsA) (b, xsB) = do
+  label $ if xsA == xsB then "equal" else "different"
+  (a == b) === (xsA == xsB)
+  (a /= b) === (xsA /= xsB)
+  compare a b === compare xsA xsB
+  (a < b) === (xsA < xsB)
+  (a <= b) === (xsA <= xsB)
+  (a > b) === (xsA > xsB)
+  (a >= b) === (xsA >= xsB)
diff --git a/test/Spec/Vec64.hs b/test/Spec/Vec64.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Vec64.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Spec.Vec64 (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Data.Proxy (Proxy(..))
+import Data.Word (Word64)
+import Foreign (allocaBytes, peekByteOff, pokeByteOff)
+import Graphics.Gl.Block qualified as Block
+
+import Geomancy.I64Vec3 qualified
+import Geomancy.U64Vec3 qualified
+
+import Support.Gen (genInt64, genWord64)
+import Support.Property (pattern PROP_TESTS, layout140, storableRoundtrip)
+
+tests :: TestTree
+tests = testGroup "Vec64"
+  [ testPropertyNamed "storable_roundtrip" "prop_vec64_storable_roundtrip" prop_vec64_storable_roundtrip
+  , testPropertyNamed "packed_write_bounds" "prop_vec64_packed_write_bounds" prop_vec64_packed_write_bounds
+  , testPropertyNamed "abs" "prop_vec64_abs" prop_vec64_abs
+  , testPropertyNamed "block_layout" "prop_vec64_block_layout" prop_vec64_block_layout
+  ]
+
+prop_vec64_storable_roundtrip :: Property
+prop_vec64_storable_roundtrip = withTests PROP_TESTS $ property do
+  i2 <- forAll $ i64vec2 <$> genInt64 <*> genInt64
+  storableRoundtrip i2 >>= (i2 ===)
+
+  i3 <- forAll $ i64vec3 <$> genInt64 <*> genInt64 <*> genInt64
+  storableRoundtrip i3 >>= (i3 ===)
+
+  let i3p = Geomancy.I64Vec3.Packed i3
+  storableRoundtrip i3p >>= (i3p ===)
+
+  i4 <- forAll $ i64vec4 <$> genInt64 <*> genInt64 <*> genInt64 <*> genInt64
+  storableRoundtrip i4 >>= (i4 ===)
+
+  u2 <- forAll $ u64vec2 <$> genWord64 <*> genWord64
+  storableRoundtrip u2 >>= (u2 ===)
+
+  u3 <- forAll $ u64vec3 <$> genWord64 <*> genWord64 <*> genWord64
+  storableRoundtrip u3 >>= (u3 ===)
+
+  let u3p = Geomancy.U64Vec3.Packed u3
+  storableRoundtrip u3p >>= (u3p ===)
+
+  u4 <- forAll $ u64vec4 <$> genWord64 <*> genWord64 <*> genWord64 <*> genWord64
+  storableRoundtrip u4 >>= (u4 ===)
+
+prop_vec64_packed_write_bounds :: Property
+prop_vec64_packed_write_bounds = withTests PROP_TESTS $ property do
+  i3 <- forAll $ i64vec3 <$> genInt64 <*> genInt64 <*> genInt64
+  u3 <- forAll $ u64vec3 <$> genWord64 <*> genWord64 <*> genWord64
+  let sentinel = 0x5EAF00D :: Word64
+  (i3', u3', afterI, afterU) <- evalIO $ allocaBytes 64 \ptr -> do
+    pokeByteOff ptr 24 sentinel
+    pokeByteOff ptr 56 sentinel
+    pokeByteOff ptr 0 (Block.Packed i3)
+    pokeByteOff ptr 32 (Block.Packed u3)
+    (,,,)
+      <$> fmap Block.getPacked (peekByteOff ptr 0)
+      <*> fmap Block.getPacked (peekByteOff ptr 32)
+      <*> peekByteOff ptr 24
+      <*> peekByteOff ptr 56
+  i3 === i3'
+  u3 === u3'
+  sentinel === afterI
+  sentinel === afterU
+
+prop_vec64_abs :: Property
+prop_vec64_abs = withTests 1 $ property do
+  i64vec2 1 2 === abs (i64vec2 (-1) 2)
+  i64vec3 1 2 3 === abs (i64vec3 (-1) 2 (-3))
+  i64vec4 1 2 3 4 === abs (i64vec4 (-1) 2 (-3) 4)
+
+prop_vec64_block_layout :: Property
+prop_vec64_block_layout = withTests 1 $ property do
+  (16, 16) === layout140 (Proxy @I64Vec2)
+  (32, 32) === layout140 (Proxy @I64Vec3)
+  (32, 24) === layout140 (Proxy @Geomancy.I64Vec3.Packed)
+  (32, 32) === layout140 (Proxy @I64Vec4)
+  (16, 16) === layout140 (Proxy @U64Vec2)
+  (32, 32) === layout140 (Proxy @U64Vec3)
+  (32, 24) === layout140 (Proxy @Geomancy.U64Vec3.Packed)
+  (32, 32) === layout140 (Proxy @U64Vec4)
diff --git a/test/Spec/Vulkan.hs b/test/Spec/Vulkan.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec/Vulkan.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Spec.Vulkan (tests) where
+
+import Geomancy
+import Hedgehog
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.Hedgehog (testPropertyNamed)
+
+import Linear (M44, V3(..), V4(..))
+
+import Geomancy.DMat4 qualified
+import Geomancy.DTransform qualified as DTransform
+import Geomancy.Mat4 qualified
+import Geomancy.Mat4 ((!*))
+import Geomancy.Transform qualified as Transform
+import Geomancy.Vulkan.DProjection qualified as DProjection
+import Geomancy.Vulkan.DView qualified as DView
+import Geomancy.Vulkan.Projection qualified as Projection
+import Geomancy.Vulkan.View qualified as View
+
+import Support.Ball (Ball, enclosed, exactly)
+import Support.Fixtures (quarterTurn, toNDC)
+import Support.Gen (genDVec3, genVec3)
+import Support.Linear (entries, toM44, toM44D)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+import Support.Reference.Vulkan qualified as Ref.Vulkan
+
+tests :: TestTree
+tests = testGroup "Vulkan"
+  [ testGroup "Projection"
+      [ testPropertyNamed "reverseDepthRH" "prop_projection_reverseDepthRH" prop_projection_reverseDepthRH
+      , testPropertyNamed "orthoRH_identity" "prop_projection_orthoRH_identity" prop_projection_orthoRH_identity
+      , testPropertyNamed "reverseDepthOrthoRH" "prop_projection_reverseDepthOrthoRH" prop_projection_reverseDepthOrthoRH
+      ]
+  , testGroup "View"
+      [ testPropertyNamed "lookAtRH_identity" "prop_view_lookAtRH_identity" prop_view_lookAtRH_identity
+      ]
+  , testGroup "DProjection"
+      [ testPropertyNamed "dprojection" "prop_dprojection" prop_dprojection
+      ]
+  , testGroup "DView"
+      [ testPropertyNamed "lookAtRH_identity" "prop_dview_lookAtRH_identity" prop_dview_lookAtRH_identity
+      ]
+  ]
+
+prop_projection_reverseDepthRH :: Property
+prop_projection_reverseDepthRH = withTests 1 $ property do
+  let
+    zNear = 0.1
+    Transform p = Projection.reverseDepthRH quarterTurn zNear 800 600
+    pBall = Ref.Vulkan.reverseDepthRH quarterTurn (exactly zNear) 800 600
+  annotateShow p
+  let
+    -- stating the expected in transposed order for testing
+    Transform expected = Geomancy.Mat4.rowMajor
+      0.7500 0.0000 0.0000 0.0000
+      0.0000 1.0000 0.0000 0.0000
+      0.0000 0.0000 0.0000 1.0000
+      0.0000 0.0000  zNear 0.0000
+  annotateShow expected
+  replicate 16 Nothing === enclosed (entries pBall) (entries (toM44 p))
+  replicate 16 Nothing === enclosed (entries pBall) (entries (toM44 expected))
+
+  let
+    centerNearIn = vec4 0 0 zNear 1
+    centerNearOut = p !* centerNearIn
+    centerNearNDC = toNDC centerNearOut
+  annotateShow (centerNearIn, centerNearOut)
+  vec3 0 0 1 === centerNearNDC
+
+prop_projection_orthoRH_identity :: Property
+prop_projection_orthoRH_identity = withTests 1 $ property do
+  let Transform pNative = Projection.orthoRH 0 1 2 2
+  annotateShow pNative
+  let pBall = Ref.Vulkan.orthoRH 0 1 2 2 :: M44 (Ball Float)
+  replicate 16 Nothing === enclosed (entries pBall) (entries (toM44 pNative))
+  replicate 16 Nothing === enclosed (entries pBall) (entries (toM44 mempty))
+
+prop_projection_reverseDepthOrthoRH :: Property
+prop_projection_reverseDepthOrthoRH = withTests 1 $ property do
+  let t = Projection.reverseDepthOrthoRH 1 10 800 600
+  annotateShow t
+
+  vec4 0 0 1 1 === t !* vec4 0 0 1 1 -- center/near
+  vec4 0 0 0 1 === t !* vec4 0 0 10 1 -- center/far
+  vec4 1 1 0 1 === t !* vec4 400 300 10 1 -- edge/far
+  vec4 (-1/400) (-1/300) 1 1 === t !* vec4 (-1) (-1) 1 1 -- step/near
+  vec4 (1/400) (1/300) 0 1 === t !* vec4 1 1 10 1 -- step/far
+
+prop_view_lookAtRH_identity :: Property
+prop_view_lookAtRH_identity = property do
+  let alreadyThere = View.lookAtRH_ (vec3 0 0 0) (vec3 0 0 1)
+  annotateShow alreadyThere
+
+  p <- forAll genVec3
+
+  p === Transform.apply p alreadyThere
+
+prop_dprojection :: Property
+prop_dprojection = withTests 1 $ property do
+  let
+    zNear = 0.1
+    DTransform p = DProjection.reverseDepthRH quarterTurn zNear 800 600
+    centerNear = p Geomancy.DMat4.!* dvec4 0 0 zNear 1
+    pBall = Ref.Vulkan.reverseDepthRH quarterTurn (exactly zNear) 800 600
+    V4 xBall yBall zBall wBall = Ref.Mat4.apply pBall (V4 0 0 (exactly zNear) 1)
+    centerNearNDCBall = V3 (xBall / wBall) (yBall / wBall) (zBall / wBall)
+  withDVec4 centerNear \x y z w -> do
+    replicate 3 Nothing === enclosed centerNearNDCBall (V3 (x/w) (y/w) (z/w))
+    replicate 3 Nothing === enclosed centerNearNDCBall (V3 0 0 1 :: V3 Double)
+
+  let
+    DTransform o = DProjection.orthoRH 0 1 2 2
+    oBall = Ref.Vulkan.orthoRH 0 1 2 2 :: M44 (Ball Double)
+  replicate 16 Nothing === enclosed (entries oBall) (entries (toM44D o))
+  replicate 16 Nothing === enclosed (entries oBall) (entries (toM44D mempty))
+
+  let t = DProjection.reverseDepthOrthoRH 1 10 800 600
+  dvec4 0 0 1 1 === t Geomancy.DMat4.!* dvec4 0 0 1 1
+  dvec4 0 0 0 1 === t Geomancy.DMat4.!* dvec4 0 0 10 1
+  dvec4 1 1 0 1 === t Geomancy.DMat4.!* dvec4 400 300 10 1
+
+prop_dview_lookAtRH_identity :: Property
+prop_dview_lookAtRH_identity = property do
+  let alreadyThere = DView.lookAtRH_ (dvec3 0 0 0) (dvec3 0 0 1)
+  p <- forAll genDVec3
+  p === DTransform.apply p alreadyThere
diff --git a/test/Support/Ball.hs b/test/Support/Ball.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Ball.hs
@@ -0,0 +1,265 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+{- | Ball arithmetic
+
+Also known as mid-rad interval arithmetic, is an extension of floating-point arithmetic
+in which an error bound is attached to each variable.
+-}
+
+module Support.Ball
+  ( Ball(..)
+  , exactly
+  , balls
+  , balls44
+  , widen
+  , narrow
+  , isExactly
+  , sumAnyOrder
+  , libmUlps
+  , Outside(..)
+  , outside
+  , enclosed
+  , Disjoint(..)
+  , disjoint
+  , consistent
+  ) where
+
+import Data.Foldable (toList)
+import Linear (M44)
+import Linear.Epsilon (Epsilon(..))
+
+data Ball p = Ball
+  { center :: {-# UNPACK #-} !Double
+  , radius :: {-# UNPACK #-} !Double
+  }
+  deriving (Eq, Show)
+
+exactly :: Real p => p -> Ball p
+exactly x = Ball (realToFrac x) 0
+
+balls :: (Functor f, Real p) => f p -> f (Ball p)
+balls = fmap exactly
+
+balls44 :: Real p => M44 p -> M44 (Ball p)
+balls44 = fmap balls
+
+widen :: Ball p -> Ball Double
+widen (Ball m r) = Ball m r
+
+narrow :: Ball Double -> Ball Float
+narrow (Ball m r)
+  | r == 0, representable @Float m = Ball m 0
+  | otherwise = rounded m r
+
+isExactly :: Double -> Ball p -> Bool
+isExactly x (Ball m r) = r == 0 && m == x
+
+-- | Assume `sin`, `cos` and `tan` are accurate to 1 ulp.
+libmUlps :: Double
+libmUlps = 1
+
+unitRoundoff :: forall p. RealFloat p => Double
+unitRoundoff = 2 ^^ negate (floatDigits (0 :: p))
+
+smallestSubnormal :: forall p. RealFloat p => Double
+smallestSubnormal = encodeFloat 1 (fst (floatRange (0 :: p)) - floatDigits (0 :: p))
+
+representable :: forall p. RealFloat p => Double -> Bool
+representable x = realToFrac (realToFrac x :: p) == x
+
+gamma :: Int -> Double -> Double
+gamma n u = nu / (1 - nu)
+  where
+    nu = fromIntegral n * u
+
+radiusSlack :: Double -> Double
+radiusSlack r = r * (1 + 16 * unitRoundoff @Double)
+
+rounded :: forall p. RealFloat p => Double -> Double -> Ball p
+rounded m propagated =
+  Ball m $ radiusSlack (propagated + midpointRounding + simulatedRounding)
+  where
+    midpointRounding = unitRoundoff @Double * abs m + smallestSubnormal @Double
+    simulatedRounding =
+      unitRoundoff @p * (abs m + propagated + midpointRounding) + smallestSubnormal @p
+
+libmRounded :: forall p. RealFloat p => Double -> Double -> Ball p
+libmRounded m propagated =
+  Ball m $ radiusSlack (propagated + midpointError + simulatedError)
+  where
+    midpointError = libmError @Double (abs m)
+    simulatedError = libmError @p (abs m + propagated + midpointError)
+
+libmError :: forall p. RealFloat p => Double -> Double
+libmError magnitude = libmUlps * (2 * unitRoundoff @p * magnitude + smallestSubnormal @p)
+
+twoSum :: Double -> Double -> (Double, Double)
+twoSum a b = (s, (a - (s - b')) + (b - b'))
+  where
+    s = a + b
+    b' = s - a
+
+exactProduct :: Double -> Double -> Double -> Bool
+exactProduct a b prod =
+  snd (twoProduct a b) == 0 && toRational a * toRational b == toRational prod
+
+twoProduct :: Double -> Double -> (Double, Double)
+twoProduct a b = (p, ((ah * bh - p) + ah * bl + al * bh) + al * bl)
+  where
+    p = a * b
+    (ah, al) = split a
+    (bh, bl) = split b
+    split x = (hi, x - hi)
+      where
+        c = 134217729 * x
+        hi = c - (c - x)
+
+plus :: forall p. RealFloat p => Ball p -> Ball p -> Ball p
+plus a@(Ball ma ra) b@(Ball mb rb)
+  | isExactly 0 a = b
+  | isExactly 0 b = a
+  | ra == 0, rb == 0, roundoff == 0, representable @p s = Ball s 0
+  | otherwise = rounded s (ra + rb)
+  where
+    (s, roundoff) = twoSum ma mb
+
+times :: forall p. RealFloat p => Ball p -> Ball p -> Ball p
+times a@(Ball ma ra) b@(Ball mb rb)
+  | isExactly 0 a || isExactly 0 b = Ball 0 0
+  | isExactly 1 a = b
+  | isExactly 1 b = a
+  | isExactly (-1) a = negate b
+  | isExactly (-1) b = negate a
+  | ra == 0, rb == 0, exactProduct ma mb prod, representable @p prod = Ball prod 0
+  | otherwise = rounded prod (abs ma * rb + abs mb * ra + ra * rb)
+  where
+    prod = ma * mb
+
+sumAnyOrder :: forall p. RealFloat p => [Ball p] -> Ball p
+sumAnyOrder summands =
+  case filter (not . isExactly 0) summands of
+    [] -> Ball 0 0
+    [single] -> single
+    nonZero -> anyOrder nonZero
+  where
+    anyOrder xs = Ball m $ radiusSlack (propagated + midpointRounding + simulatedRounding)
+      where
+        m = sum $ map center xs
+        propagated = (1 + gamma additions (unitRoundoff @Double)) * sum (map radius xs)
+        magnitudes = sum $ map (abs . center) xs
+        additions = length xs - 1
+        midpointRounding =
+          gamma additions (unitRoundoff @Double) * magnitudes +
+          fromIntegral additions * smallestSubnormal @Double
+        simulatedRounding =
+          gamma additions (unitRoundoff @p) * (magnitudes + propagated + midpointRounding) +
+          fromIntegral additions * smallestSubnormal @p
+
+literal :: forall p. RealFloat p => Rational -> Ball p
+literal q
+  | exact = Ball m 0
+  | otherwise = roundedLiteral m (realToFrac (fromRational q :: p))
+  where
+    m = fromRational q
+    exact = toRational m == q && toRational (fromRational q :: p) == q
+
+roundedLiteral :: Double -> Double -> Ball p
+roundedLiteral m simulated =
+  Ball m $ radiusSlack (max (abs (simulated - m)) midpointRounding)
+  where
+    midpointRounding = unitRoundoff @Double * abs m + smallestSubnormal @Double
+
+instance RealFloat p => Num (Ball p) where
+  (+) = plus
+  a - b = plus a (negate b)
+  (*) = times
+  negate (Ball m r) = Ball (negate m) r
+  abs (Ball m r) = Ball (abs m) r
+  signum = error "Ball.signum: no enclosure for a discontinuous function"
+  fromInteger = literal . fromInteger
+
+instance RealFloat p => Fractional (Ball p) where
+  a@(Ball ma ra) / b@(Ball mb rb)
+    | isExactly 1 b = a
+    | abs mb <= 2 * rb = error "Ball./: divisor is too close to zero to bound the quotient"
+    | ra == 0, rb == 0, exactQuotient = Ball quotient 0
+    | otherwise = rounded quotient (((abs quotient + smallestSubnormal @Double) * rb + ra) / (abs mb - rb))
+    where
+      quotient = ma / mb
+      exactQuotient =
+        toRational quotient == toRational ma / toRational mb && representable @p quotient
+  fromRational = literal
+
+instance RealFloat p => Floating (Ball p) where
+  pi = roundedLiteral pi (realToFrac (pi :: p))
+
+  sqrt (Ball m r)
+    | r == 0, exactProduct root root m, representable @p root = Ball root 0
+    | m > 2 * r = rounded root (r / root)
+    | m + r < 0 = error "Ball.sqrt: negative argument"
+    | otherwise = rounded (upper / 2) (upper / 2)
+    where
+      root = sqrt m
+      upper = sqrt (m + r)
+
+  sin x@(Ball m r)
+    | isExactly 0 x = Ball 0 0
+    | otherwise = libmRounded (sin m) r
+  cos x@(Ball m r)
+    | isExactly 0 x = Ball 1 0
+    | otherwise = libmRounded (cos m) r
+  tan x
+    | isExactly 0 x = Ball 0 0
+    | otherwise = Ball m $ radiusSlack (r + libmError @p (abs m + r))
+    where
+      Ball m r = sin (widen x) / cos (widen x)
+
+  exp = unsupported "exp"
+  log = unsupported "log"
+  asin = unsupported "asin"
+  acos = unsupported "acos"
+  atan = unsupported "atan"
+  sinh = unsupported "sinh"
+  cosh = unsupported "cosh"
+  asinh = unsupported "asinh"
+  acosh = unsupported "acosh"
+  atanh = unsupported "atanh"
+
+unsupported :: String -> a
+unsupported name = error $ "Ball." <> name <> ": no enclosure implemented"
+
+instance (RealFloat p, Epsilon p) => Epsilon (Ball p) where
+  nearZero (Ball m r)
+    | nearest == farthest = nearest
+    | otherwise = error "Ball.nearZero: the ball straddles the threshold"
+    where
+      nearest = nearZero (realToFrac (max 0 (abs m - r)) :: p)
+      farthest = nearZero (realToFrac (abs m + r) :: p)
+
+data Outside p = Outside
+  { actual :: p
+  , enclosure :: Ball p
+  }
+  deriving (Eq, Show)
+
+outside :: RealFloat p => Ball p -> p -> Maybe (Outside p)
+outside ball@(Ball m r) x
+  | isNaN x || isInfinite x = Just $ Outside x ball
+  | abs (realToFrac x - m) <= r = Nothing
+  | otherwise = Just $ Outside x ball
+
+enclosed :: (Foldable f, Foldable g, RealFloat p) => f (Ball p) -> g p -> [Maybe (Outside p)]
+enclosed bs xs = zipWith outside (toList bs) (toList xs)
+
+data Disjoint p = Disjoint (Ball p) (Ball p)
+  deriving (Eq, Show)
+
+disjoint :: Ball p -> Ball p -> Maybe (Disjoint p)
+disjoint a b
+  | abs (center a - center b) <= radius a + radius b = Nothing
+  | otherwise = Just $ Disjoint a b
+
+consistent :: (Foldable f, Foldable g) => f (Ball p) -> g (Ball p) -> [Maybe (Disjoint p)]
+consistent as bs = zipWith disjoint (toList as) (toList bs)
diff --git a/test/Support/Fixtures.hs b/test/Support/Fixtures.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Fixtures.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Fixtures
+  ( xPos
+  , xNeg
+  , yPos
+  , yNeg
+  , zPos
+  , zNeg
+  , intrinsicComposed
+  , intrinsicComposedD
+  , trs
+  , toNDC
+  , intrinsicComposedRef
+  , trsRef
+  , quarterTurn
+  , twelfthTurn
+  , fourteenthTurn
+  , rotationsMatch
+  ) where
+
+import Geomancy
+import Hedgehog
+
+import Data.Foldable (for_)
+import Linear (M44, V3(..))
+import Linear qualified
+import Linear.Epsilon (Epsilon)
+
+import Geomancy.DQuaternion qualified
+import Geomancy.Quaternion qualified
+import Geomancy.Transform qualified as Transform
+
+import Support.Ball (Ball, balls, enclosed)
+import Support.Reference.Mat4 qualified as Ref.Mat4
+import Support.Reference.Quaternion qualified as Ref.Quaternion
+import Support.Reference.Transform qualified as Ref.Transform
+
+xPos :: Vec3
+xPos = vec3 1 0 0
+
+xNeg :: Vec3
+xNeg = vec3 (-1) 0 0
+
+yPos :: Vec3
+yPos = vec3 0 1 0
+
+yNeg :: Vec3
+yNeg = vec3 0 (-1) 0
+
+zPos :: Vec3
+zPos = vec3 0 0 1
+
+zNeg :: Vec3
+zNeg = vec3 0 0 (-1)
+
+intrinsicComposed :: Float -> Float -> Float -> Quaternion
+intrinsicComposed roll pitch yaw =
+  Geomancy.Quaternion.axisAngle (vec3 0 1 0) yaw *
+  Geomancy.Quaternion.axisAngle (vec3 1 0 0) pitch *
+  Geomancy.Quaternion.axisAngle (vec3 0 0 1) roll
+
+intrinsicComposedD :: Double -> Double -> Double -> DQuaternion
+intrinsicComposedD roll pitch yaw =
+  Geomancy.DQuaternion.axisAngle (dvec3 0 1 0) yaw *
+  Geomancy.DQuaternion.axisAngle (dvec3 1 0 0) pitch *
+  Geomancy.DQuaternion.axisAngle (dvec3 0 0 1) roll
+
+trs :: Vec3 -> Quaternion -> Vec3 -> Transform
+trs t r s = mconcat
+  [ Transform.translateV t
+  , Transform.rotateQ r
+  , Transform.scaleV s
+  ]
+
+toNDC :: Vec4 -> Vec3
+toNDC v = withVec4 v \x y z w -> vec3 (x/w) (y/w) (z/w)
+
+intrinsicComposedRef :: (Floating a, Epsilon a) => a -> a -> a -> Linear.Quaternion a
+intrinsicComposedRef roll pitch yaw =
+  Ref.Quaternion.axisAngle (V3 0 1 0) yaw `Ref.Quaternion.multiply`
+  Ref.Quaternion.axisAngle (V3 1 0 0) pitch `Ref.Quaternion.multiply`
+  Ref.Quaternion.axisAngle (V3 0 0 1) roll
+
+trsRef :: RealFloat p => V3 (Ball p) -> Linear.Quaternion (Ball p) -> V3 (Ball p) -> M44 (Ball p)
+trsRef t r s = foldr Ref.Mat4.compose Ref.Mat4.identity
+  [ Ref.Transform.translateV t
+  , Ref.Transform.rotateQ r
+  , Ref.Transform.scaleV s
+  ]
+
+quarterTurn :: Floating a => a
+quarterTurn = pi / 2
+
+twelfthTurn :: Floating a => a
+twelfthTurn = pi / 6
+
+fourteenthTurn :: Floating a => a
+fourteenthTurn = pi / 7
+
+rotationsMatch
+  :: (Show v, Show p, RealFloat p)
+  => (v -> V3 p)
+  -> (v -> v)
+  -> (V3 (Ball p) -> V3 (Ball p))
+  -> [(v, v)]
+  -> PropertyT IO ()
+rotationsMatch toV rotate rotateBall cases =
+  for_ cases \(input, expected) -> do
+    let
+      rotated = rotate input
+      rotatedBall = rotateBall (balls (toV input))
+    annotateShow rotated
+    replicate 3 Nothing === enclosed rotatedBall (toV rotated)
+    replicate 3 Nothing === enclosed rotatedBall (toV expected)
diff --git a/test/Support/Gen.hs b/test/Support/Gen.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Gen.hs
@@ -0,0 +1,168 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Gen
+  ( genFloat
+  , genDouble
+  , genAngle
+  , genAngleD
+  , genVec2
+  , genVec3
+  , genVec4
+  , genSmallVec3
+  , genDVec2
+  , genDVec3
+  , genDVec4
+  , genSmallDVec3
+  , genDQuaternion
+  , genInt32
+  , genWord32
+  , genInt64
+  , genWord64
+  , genEdgeScalar
+  , genMostlySame
+  , genTransform
+  , forAllTransform
+  , forAllDTransform
+  ) where
+
+import Geomancy
+import Hedgehog
+
+import Control.Monad (when)
+import Data.Int (Int32, Int64)
+import Data.Word (Word32, Word64)
+import GHC.Stack (withFrozenCallStack)
+import Hedgehog.Gen qualified as Gen
+import Hedgehog.Range qualified as Range
+import Linear qualified
+import Text.Printf (printf)
+
+import Geomancy.DMat4 qualified
+import Geomancy.Mat4 qualified
+import Geomancy.Transform qualified as Transform
+
+import Support.Linear (toM44, toM44D)
+
+forAllTransform :: PropertyT IO (Geomancy.Mat4.Mat4, Linear.M44 Float)
+forAllTransform = withFrozenCallStack do
+  (_name, Transform g) <- forAllWith fst genTransform
+  pure (g, toM44 g)
+
+forAllDTransform :: PropertyT IO (Geomancy.DMat4.DMat4, Linear.M44 Double)
+forAllDTransform = withFrozenCallStack do
+  (_name, t) <- forAllWith fst genTransform
+  let g = Geomancy.DMat4.fromMat4 t
+  pure (g, toM44D g)
+
+genInt32 :: Gen Int32
+genInt32 = Gen.int32 Range.linearBounded
+
+genWord32 :: Gen Word32
+genWord32 = Gen.word32 Range.linearBounded
+
+genInt64 :: Gen Int64
+genInt64 = Gen.int64 Range.linearBounded
+
+genWord64 :: Gen Word64
+genWord64 = Gen.word64 Range.linearBounded
+
+genEdgeScalar :: Fractional a => Gen a
+genEdgeScalar = Gen.frequency [(4, pure 0), (4, pure (-0)), (4, pure 1), (4, pure (-1)), (1, pure (0 / 0))]
+
+genMostlySame :: Fractional a => Int -> a -> Gen a
+genMostlySame sameWeight x = Gen.frequency [(sameWeight, pure x), (1, genEdgeScalar)]
+
+genFloat :: Gen Float
+genFloat = Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+
+genDouble :: Gen Double
+genDouble = Gen.double (Range.linearFracFrom 0.0 (-1e6) 1e6)
+
+genVec2 :: Gen Vec2
+genVec2 = vec2 <$> genFloat <*> genFloat
+
+genVec4 :: Gen Vec4
+genVec4 = vec4 <$> genFloat <*> genFloat <*> genFloat <*> genFloat
+
+genDVec2 :: Gen DVec2
+genDVec2 = dvec2 <$> genDouble <*> genDouble
+
+genDVec3 :: Gen DVec3
+genDVec3 = dvec3 <$> genDouble <*> genDouble <*> genDouble
+
+genDVec4 :: Gen DVec4
+genDVec4 = dvec4 <$> genDouble <*> genDouble <*> genDouble <*> genDouble
+
+genSmallVec3 :: Gen Vec3
+genSmallVec3 =
+  vec3
+    <$> Gen.float (Range.linearFracFrom 0.0 (-10) 10)
+    <*> Gen.float (Range.linearFracFrom 0.0 (-10) 10)
+    <*> Gen.float (Range.linearFracFrom 0.0 (-10) 10)
+
+genSmallDVec3 :: Gen DVec3
+genSmallDVec3 =
+  dvec3
+    <$> Gen.double (Range.linearFracFrom 0.0 (-10) 10)
+    <*> Gen.double (Range.linearFracFrom 0.0 (-10) 10)
+    <*> Gen.double (Range.linearFracFrom 0.0 (-10) 10)
+
+genDQuaternion :: Gen DQuaternion
+genDQuaternion = dquaternion <$> genDouble <*> genDouble <*> genDouble <*> genDouble
+
+genAngleD :: Gen Double
+genAngleD = Gen.double (Range.linearFracFrom 0.0 (-8*pi) (8*pi))
+
+genVec3 :: Gen Vec3
+genVec3 =
+  vec3
+    <$> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+    <*> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+    <*> Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+
+genAngle :: Gen Float
+genAngle = Gen.float (Range.linearFracFrom 0.0 (-8*pi) (8*pi))
+
+genTransform :: Gen ([Char], Transform) -- TODO: cross-check with Linear
+genTransform = Gen.choice
+  [ genIdentity
+  , genTranslate
+  , genRotate
+  , genScale
+  ]
+  where
+    genIdentity = pure ("identity", mempty)
+
+    genTranslate = do
+      x <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+      y <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+      z <- Gen.float (Range.linearFracFrom 0.0 (-1e6) 1e6)
+      when (abs x == 0 && abs y == 0 && abs z == 0) Gen.discard
+      pure
+        ( printf "translate %0.4f %0.4f %0.4f" x y z
+        , Transform.translate x y z
+        )
+
+    genRotate = do
+      (name, axis) <- Gen.element
+        [ ("rotate/x", Transform.rotateX)
+        , ("rotate/y", Transform.rotateY)
+        , ("rotate/z", Transform.rotateZ)
+        ]
+      angle <- genAngle
+      when (abs angle == 0) Gen.discard
+      pure
+        ( printf "%s %0.4f" name angle
+        , axis angle
+        )
+
+    genScale = do
+      x <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
+      y <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
+      z <- Gen.float (Range.linearFracFrom 1.0 1e-6 1e6)
+      when (abs x == 1 && abs y == 1 && abs z == 1) Gen.discard
+      pure
+        ( printf "scale %0.4f %0.4f %0.4f" x y z
+        , Transform.scale3 x y z
+        )
diff --git a/test/Support/Linear.hs b/test/Support/Linear.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Linear.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Linear
+  ( toM44
+  , toM44D
+  , toV3
+  , toV3D
+  , toV4
+  , toV4D
+  , toQ
+  , toQD
+  , entries
+  ) where
+
+import Geomancy
+
+import Data.Foldable (toList)
+import Linear qualified
+
+import Geomancy.DMat4 qualified
+import Geomancy.Mat4 (withRowMajor)
+
+toM44 :: Geomancy.Mat4 -> Linear.M44 Float
+toM44 mat4 =
+  withRowMajor mat4
+    \ m00 m10 m20 m30
+      m01 m11 m21 m31
+      m02 m12 m22 m32
+      m03 m13 m23 m33 ->
+        Linear.V4
+          (Linear.V4 m00 m10 m20 m30)
+          (Linear.V4 m01 m11 m21 m31)
+          (Linear.V4 m02 m12 m22 m32)
+          (Linear.V4 m03 m13 m23 m33)
+
+toM44D :: Geomancy.DMat4.DMat4 -> Linear.M44 Double
+toM44D dmat4 =
+  Geomancy.DMat4.withRowMajor dmat4
+    \ m00 m10 m20 m30
+      m01 m11 m21 m31
+      m02 m12 m22 m32
+      m03 m13 m23 m33 ->
+        Linear.V4
+          (Linear.V4 m00 m10 m20 m30)
+          (Linear.V4 m01 m11 m21 m31)
+          (Linear.V4 m02 m12 m22 m32)
+          (Linear.V4 m03 m13 m23 m33)
+
+toV3 :: Vec3 -> Linear.V3 Float
+toV3 v = withVec3 v Linear.V3
+
+toV3D :: DVec3 -> Linear.V3 Double
+toV3D v = withDVec3 v Linear.V3
+
+toV4 :: Vec4 -> Linear.V4 Float
+toV4 v = withVec4 v Linear.V4
+
+toV4D :: DVec4 -> Linear.V4 Double
+toV4D v = withDVec4 v Linear.V4
+
+toQ :: Geomancy.Quaternion -> Linear.Quaternion Float
+toQ q = withQuaternion q \s x y z -> Linear.Quaternion s (Linear.V3 x y z)
+
+toQD :: DQuaternion -> Linear.Quaternion Double
+toQD q = withDQuaternion q \s x y z -> Linear.Quaternion s (Linear.V3 x y z)
+
+entries :: (Foldable f, Foldable g) => f (g a) -> [a]
+entries = concatMap toList
diff --git a/test/Support/Property.hs b/test/Support/Property.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Property.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE NumericUnderscores #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Support.Property
+  ( pattern PROP_TESTS
+  , pattern PROP_TESTS_BRUTAL
+  , storableRoundtrip
+  , layout140
+  ) where
+
+import Hedgehog
+
+import Data.Proxy (Proxy)
+import Foreign (Storable, peek, with)
+import Graphics.Gl.Block qualified as Block
+
+-- | Enough tests to cover the principles
+pattern PROP_TESTS :: TestLimit
+pattern PROP_TESTS = 10_000
+
+-- | Try harder to catch FP precision errors
+pattern PROP_TESTS_BRUTAL :: TestLimit
+pattern PROP_TESTS_BRUTAL = 10_000_000
+
+storableRoundtrip :: Storable a => a -> PropertyT IO a
+storableRoundtrip x = evalIO $ with x peek
+
+layout140 :: Block.Block a => Proxy a -> (Int, Int)
+layout140 p = (Block.alignment140 p, Block.sizeOf140 p)
diff --git a/test/Support/Reference/Linear.hs b/test/Support/Reference/Linear.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Linear.hs
@@ -0,0 +1,20 @@
+module Support.Reference.Linear
+  ( multiply
+  , conjugate
+  , rotate
+  ) where
+
+import Linear (Quaternion(..), V3, cross, dot, (*^))
+
+multiply :: Num a => Quaternion a -> Quaternion a -> Quaternion a
+multiply (Quaternion s1 v1) (Quaternion s2 v2) =
+  Quaternion (s1 * s2 - (v1 `dot` v2)) $
+    (v1 `cross` v2) + s1 *^ v2 + s2 *^ v1
+
+conjugate :: Num a => Quaternion a -> Quaternion a
+conjugate (Quaternion e v) = Quaternion e (negate v)
+
+rotate :: Num a => Quaternion a -> V3 a -> V3 a
+rotate q v = ijk
+  where
+    Quaternion _ ijk = q `multiply` Quaternion 0 v `multiply` conjugate q
diff --git a/test/Support/Reference/Mat4.hs b/test/Support/Reference/Mat4.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Mat4.hs
@@ -0,0 +1,140 @@
+{-# LANGUAGE RecordWildCards #-}
+
+module Support.Reference.Mat4
+  ( rowMajor
+  , colMajor
+  , identity
+  , compose
+  , apply
+  , det
+  , inverse
+  ) where
+
+import Data.Foldable (toList)
+import Linear (M44, V4(..), transpose)
+
+import Support.Ball (Ball, sumAnyOrder)
+
+rowMajor
+  :: a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> M44 a
+rowMajor
+  m00 m01 m02 m03
+  m10 m11 m12 m13
+  m20 m21 m22 m23
+  m30 m31 m32 m33 =
+    V4
+      (V4 m00 m01 m02 m03)
+      (V4 m10 m11 m12 m13)
+      (V4 m20 m21 m22 m23)
+      (V4 m30 m31 m32 m33)
+
+colMajor
+  :: a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> a -> a -> a -> a
+  -> M44 a
+colMajor
+  m00 m01 m02 m03
+  m10 m11 m12 m13
+  m20 m21 m22 m23
+  m30 m31 m32 m33 =
+    transpose $ rowMajor
+      m00 m01 m02 m03
+      m10 m11 m12 m13
+      m20 m21 m22 m23
+      m30 m31 m32 m33
+
+identity :: Num a => M44 a
+identity = rowMajor
+  1 0 0 0
+  0 1 0 0
+  0 0 1 0
+  0 0 0 1
+
+compose :: RealFloat p => M44 (Ball p) -> M44 (Ball p) -> M44 (Ball p)
+compose a b = fmap (\row -> fmap (dotAnyOrder row) (transpose a)) b
+
+apply :: RealFloat p => M44 (Ball p) -> V4 (Ball p) -> V4 (Ball p)
+apply m v = fmap (dotAnyOrder v) (transpose m)
+
+dotAnyOrder :: RealFloat p => V4 (Ball p) -> V4 (Ball p) -> Ball p
+dotAnyOrder a b = sumAnyOrder $ zipWith (*) (toList a) (toList b)
+
+det :: Num a => M44 a -> a
+det m =
+    s0 * c5
+  - s1 * c4
+  + s2 * c3
+  + s3 * c2
+  - s4 * c1
+  + s5 * c0
+  where
+    Cofactors{..} = cofactors m
+
+inverse :: Fractional a => M44 a -> M44 a
+inverse m@(V4
+  (V4 m00 m01 m02 m03)
+  (V4 m10 m11 m12 m13)
+  (V4 m20 m21 m22 m23)
+  (V4 m30 m31 m32 m33)) =
+    rowMajor
+      i00 i01 i02 i03
+      i10 i11 i12 i13
+      i20 i21 i22 i23
+      i30 i31 i32 i33
+  where
+    Cofactors{..} = cofactors m
+
+    invDet = recip (det m)
+
+    i00 = ( m11 * c5 - m12 * c4 + m13 * c3) * invDet
+    i01 = (-m01 * c5 + m02 * c4 - m03 * c3) * invDet
+    i02 = ( m31 * s5 - m32 * s4 + m33 * s3) * invDet
+    i03 = (-m21 * s5 + m22 * s4 - m23 * s3) * invDet
+
+    i10 = (-m10 * c5 + m12 * c2 - m13 * c1) * invDet
+    i11 = ( m00 * c5 - m02 * c2 + m03 * c1) * invDet
+    i12 = (-m30 * s5 + m32 * s2 - m33 * s1) * invDet
+    i13 = ( m20 * s5 - m22 * s2 + m23 * s1) * invDet
+
+    i20 = ( m10 * c4 - m11 * c2 + m13 * c0) * invDet
+    i21 = (-m00 * c4 + m01 * c2 - m03 * c0) * invDet
+    i22 = ( m30 * s4 - m31 * s2 + m33 * s0) * invDet
+    i23 = (-m20 * s4 + m21 * s2 - m23 * s0) * invDet
+
+    i30 = (-m10 * c3 + m11 * c1 - m12 * c0) * invDet
+    i31 = ( m00 * c3 - m01 * c1 + m02 * c0) * invDet
+    i32 = (-m30 * s3 + m31 * s1 - m32 * s0) * invDet
+    i33 = ( m20 * s3 - m21 * s1 + m22 * s0) * invDet
+
+data Cofactors a = Cofactors
+  { s0, s1, s2, s3, s4, s5 :: a
+  , c0, c1, c2, c3, c4, c5 :: a
+  }
+
+cofactors :: Num a => M44 a -> Cofactors a
+cofactors (V4
+  (V4 m00 m01 m02 m03)
+  (V4 m10 m11 m12 m13)
+  (V4 m20 m21 m22 m23)
+  (V4 m30 m31 m32 m33)) =
+    Cofactors
+      { s0 = m00 * m11 - m10 * m01
+      , s1 = m00 * m12 - m10 * m02
+      , s2 = m00 * m13 - m10 * m03
+      , s3 = m01 * m12 - m11 * m02
+      , s4 = m01 * m13 - m11 * m03
+      , s5 = m02 * m13 - m12 * m03
+
+      , c5 = m22 * m33 - m32 * m23
+      , c4 = m21 * m33 - m31 * m23
+      , c3 = m21 * m32 - m31 * m22
+      , c2 = m20 * m33 - m30 * m23
+      , c1 = m20 * m32 - m30 * m22
+      , c0 = m20 * m31 - m30 * m21
+      }
diff --git a/test/Support/Reference/Quaternion.hs b/test/Support/Reference/Quaternion.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Quaternion.hs
@@ -0,0 +1,62 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Reference.Quaternion
+  ( multiply
+  , axisAngle
+  , intrinsic
+  , extrinsic
+  , rotate
+  ) where
+
+import Linear (Quaternion(..), V3(..))
+import Linear.Epsilon (Epsilon)
+
+import Support.Reference.Vec3 qualified as Vec3
+
+multiply :: Num a => Quaternion a -> Quaternion a -> Quaternion a
+multiply (Quaternion as v1) (Quaternion bs v2) = Quaternion s v
+  where
+    s = as * bs - Vec3.dot v1 v2
+    v = Vec3.cross v1 v2 + fmap (* as) v2 + fmap (* bs) v1
+
+axisAngle :: (Floating a, Epsilon a) => V3 a -> a -> Quaternion a
+axisAngle axis rads =
+  Quaternion (cos half) (fmap (* sin half) (Vec3.normalize axis))
+  where
+    half = rads / 2
+
+intrinsic :: Floating a => a -> a -> a -> Quaternion a
+intrinsic roll pitch yaw =
+  Quaternion
+    (cx * cy * cz + sx * sy * sz)
+    (V3
+      (sx * cy * cz + cx * sy * sz)
+      (cx * sy * cz - sx * cy * sz)
+      (cx * cy * sz - sx * sy * cz))
+  where
+    cx = cos (pitch * 0.5)
+    sx = sin (pitch * 0.5)
+    cy = cos (yaw * 0.5)
+    sy = sin (yaw * 0.5)
+    cz = cos (roll * 0.5)
+    sz = sin (roll * 0.5)
+
+extrinsic :: (Floating a, Epsilon a) => a -> a -> a -> Quaternion a
+extrinsic heading elevation tilt =
+  axisAngle (V3 0 0 1) tilt `multiply`
+  axisAngle (V3 1 0 0) elevation `multiply`
+  axisAngle (V3 0 1 0) heading
+
+rotate :: Num a => Quaternion a -> V3 a -> V3 a
+rotate (Quaternion w (V3 x y z)) (V3 vx vy vz) =
+  V3
+    (vx + w * tx + y * tz - z * ty)
+    (vy + w * ty + z * tx - x * tz)
+    (vz + w * tz + x * ty - y * tx)
+  where
+    x2 = x + x
+    y2 = y + y
+    z2 = z + z
+    tx = y2 * vz - z2 * vy
+    ty = z2 * vx - x2 * vz
+    tz = x2 * vy - y2 * vx
diff --git a/test/Support/Reference/Transform.hs b/test/Support/Reference/Transform.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Transform.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Reference.Transform
+  ( (!.)
+  , translate
+  , translateV
+  , scale3
+  , scaleV
+  , rotateX
+  , rotateY
+  , rotateZ
+  , rotateQ
+  , dirPos
+  , node
+  ) where
+
+import Linear (M44, Quaternion(..), V3(..), V4(..))
+
+import Support.Ball (Ball, isExactly)
+import Support.Reference.Mat4 (colMajor)
+import Support.Reference.Mat4 qualified as Mat4
+
+(!.) :: RealFloat p => M44 (Ball p) -> V3 (Ball p) -> V3 (Ball p)
+(!.) mat (V3 vx vy vz) = V3 (x / w) (y / w) (z / w)
+  where
+    V4 x y z w = Mat4.apply mat (V4 vx vy vz 1)
+
+infixr 5 !.
+
+translate :: Num a => a -> a -> a -> M44 a
+translate x y z = colMajor
+  1 0 0 x
+  0 1 0 y
+  0 0 1 z
+  0 0 0 1
+
+translateV :: Num a => V3 a -> M44 a
+translateV (V3 x y z) = translate x y z
+
+scale3 :: Num a => a -> a -> a -> M44 a
+scale3 x y z = colMajor
+  x 0 0 0
+  0 y 0 0
+  0 0 z 0
+  0 0 0 1
+
+scaleV :: Num a => V3 a -> M44 a
+scaleV (V3 x y z) = scale3 x y z
+
+rotateX :: Floating a => a -> M44 a
+rotateX rads =
+  colMajor
+    1 0   0  0
+    0 c (-s) 0
+    0 s   c  0
+    0 0   0  1
+  where
+    c = cos rads
+    s = sin rads
+
+rotateY :: Floating a => a -> M44 a
+rotateY rads =
+  colMajor
+    c  0 s 0
+    0  1 0 0
+  (-s) 0 c 0
+    0  0 0 1
+  where
+    c = cos rads
+    s = sin rads
+
+rotateZ :: Floating a => a -> M44 a
+rotateZ rads =
+  colMajor
+    c (-s) 0 0
+    s   c  0 0
+    0   0  1 0
+    0   0  0 1
+  where
+    c = cos rads
+    s = sin rads
+
+rotateQ :: Num a => Quaternion a -> M44 a
+rotateQ dir = dirPos dir 0
+
+dirPos :: Num a => Quaternion a -> V3 a -> M44 a
+dirPos (Quaternion w (V3 x y z)) (V3 tx ty tz) =
+  colMajor
+    (1 - 2 * (y2 + z2)) (    2 * (xy - zw)) (    2 * (xz + yw)) tx
+    (    2 * (xy + zw)) (1 - 2 * (x2 + z2)) (    2 * (yz - xw)) ty
+    (    2 * (xz - yw)) (    2 * (yz + xw)) (1 - 2 * (x2 + y2)) tz
+    0                   0                   0                    1
+  where
+    x2 = x * x
+    y2 = y * y
+    z2 = z * z
+    xy = x * y
+    xz = x * z
+    xw = x * w
+    yz = y * z
+    yw = y * w
+    zw = z * w
+
+node :: RealFloat p => V3 (Ball p) -> Quaternion (Ball p) -> V3 (Ball p) -> M44 (Ball p)
+node t r s
+  | all (isExactly 1) s = dirPos r t
+  | otherwise = dirPos r t `Mat4.compose` scaleV s
diff --git a/test/Support/Reference/Vec3.hs b/test/Support/Reference/Vec3.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Vec3.hs
@@ -0,0 +1,31 @@
+module Support.Reference.Vec3
+  ( dot
+  , cross
+  , normalize
+  ) where
+
+import Linear (V3(..))
+import Linear.Epsilon (Epsilon(..))
+
+dot :: Num a => V3 a -> V3 a -> a
+dot (V3 a b c) (V3 d e f) =
+  a * d +
+  b * e +
+  c * f
+
+cross :: Num a => V3 a -> V3 a -> V3 a
+cross (V3 a b c) (V3 d e f) =
+  V3
+    (b * f - c * e)
+    (c * d - a * f)
+    (a * e - b * d)
+
+normalize :: (Floating a, Epsilon a) => V3 a -> V3 a
+normalize v =
+  if nearZero q || nearZero (1 - q) then
+    v
+  else
+    fmap (/ l) v
+  where
+    q = dot v v
+    l = sqrt q
diff --git a/test/Support/Reference/Vulkan.hs b/test/Support/Reference/Vulkan.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Reference/Vulkan.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+
+module Support.Reference.Vulkan
+  ( reverseDepthRH
+  , orthoRH
+  , lookAtRH
+  , lookAtRH_
+  ) where
+
+import Linear (M44, V3(..))
+import Linear.Epsilon (Epsilon)
+
+import Support.Reference.Mat4 (colMajor)
+import Support.Reference.Vec3 (cross, dot, normalize)
+
+reverseDepthRH :: Floating a => a -> a -> a -> a -> M44 a
+reverseDepthRH fovRads zn width height =
+  colMajor
+    sx  0 0  0
+    0  sy 0  0
+    0   0 0 zn
+    0   0 1  0
+  where
+    sx = sy * recipAspect
+      where
+        recipAspect = height / width
+    sy = 1 / tan (fovRads / 2)
+
+orthoRH :: Fractional a => a -> a -> a -> a -> M44 a
+orthoRH near far width height =
+  colMajor
+    sx 0 0 0
+    0 sy 0 0
+    0  0 z w
+    0  0 0 1
+  where
+    sx = 2 / width
+    sy = 2 / height
+    z = 1 / (far - near)
+    w = near / (near - far)
+
+lookAtRH :: (Floating a, Epsilon a) => V3 a -> V3 a -> V3 a -> M44 a
+lookAtRH eye target up =
+  colMajor
+    rx ry rz (-er)
+    ux uy uz (-eu)
+    fx fy fz (-ef)
+     0  0  0    1
+  where
+    fwd@(V3 fx fy fz) = normalize (target - eye)
+    rgt@(V3 rx ry rz) = normalize (cross fwd up)
+    up'@(V3 ux uy uz) = normalize (cross fwd rgt)
+    er = dot eye rgt
+    eu = dot eye up'
+    ef = dot eye fwd
+
+lookAtRH_ :: (Floating a, Epsilon a) => V3 a -> V3 a -> M44 a
+lookAtRH_ eye target = lookAtRH eye target (V3 0 (-1) 0)
diff --git a/test/Support/Swizzle.hs b/test/Support/Swizzle.hs
new file mode 100644
--- /dev/null
+++ b/test/Support/Swizzle.hs
@@ -0,0 +1,127 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Support.Swizzle
+  ( Lanes(..)
+  , Mismatch
+  , swizzled
+  , swizzles
+  ) where
+
+import Data.Int (Int32, Int64)
+import Data.Maybe (catMaybes, fromMaybe)
+import Data.Proxy (Proxy(..))
+import Data.Word (Word32, Word64)
+import GHC.Float (castDoubleToWord64, castFloatToWord32)
+import GHC.Records (HasField(..))
+import GHC.TypeLits (KnownSymbol, symbolVal)
+import Hedgehog
+
+import Geomancy
+
+import Support.Property (pattern PROP_TESTS)
+
+class Lanes v where
+  lanes :: v -> [Word64]
+
+instance Lanes Float where
+  lanes x = [fromIntegral (castFloatToWord32 x)]
+
+instance Lanes Double where
+  lanes x = [castDoubleToWord64 x]
+
+instance Lanes Int32 where
+  lanes x = [fromIntegral x]
+
+instance Lanes Word32 where
+  lanes x = [fromIntegral x]
+
+instance Lanes Int64 where
+  lanes x = [fromIntegral x]
+
+instance Lanes Word64 where
+  lanes x = [x]
+
+instance Lanes Vec2 where
+  lanes v = withVec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes Vec3 where
+  lanes v = withVec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes Vec4 where
+  lanes v = withVec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+instance Lanes DVec2 where
+  lanes v = withDVec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes DVec3 where
+  lanes v = withDVec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes DVec4 where
+  lanes v = withDVec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+instance Lanes IVec2 where
+  lanes v = withIVec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes IVec3 where
+  lanes v = withIVec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes IVec4 where
+  lanes v = withIVec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+instance Lanes UVec2 where
+  lanes v = withUVec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes UVec3 where
+  lanes v = withUVec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes UVec4 where
+  lanes v = withUVec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+instance Lanes I64Vec2 where
+  lanes v = withI64Vec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes I64Vec3 where
+  lanes v = withI64Vec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes I64Vec4 where
+  lanes v = withI64Vec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+instance Lanes U64Vec2 where
+  lanes v = withU64Vec2 v \x y -> concatMap lanes [x, y]
+
+instance Lanes U64Vec3 where
+  lanes v = withU64Vec3 v \x y z -> concatMap lanes [x, y, z]
+
+instance Lanes U64Vec4 where
+  lanes v = withU64Vec4 v \x y z w -> concatMap lanes [x, y, z, w]
+
+data Mismatch = Mismatch String [Word64] [Word64]
+  deriving (Eq, Show)
+
+swizzles :: Show v => Gen v -> (v -> [Maybe Mismatch]) -> Property
+swizzles gen checks = withTests PROP_TESTS $ property do
+  v <- forAll gen
+  catMaybes (checks v) === []
+
+swizzled
+  :: forall s v r
+  .  (KnownSymbol s, HasField s v r, Lanes v, Lanes r, Num r)
+  => v
+  -> Maybe Mismatch
+swizzled v =
+  if expected == actual then
+    Nothing
+  else
+    Just (Mismatch name expected actual)
+  where
+    name = symbolVal (Proxy @s)
+    expected = concatMap lane name
+    actual = lanes (getField @s v)
+    lane c = fromMaybe (error $ "no lane " <> [c]) $ lookup c (zip "xyzw" (map pure (lanes v)) <> constants)
+    constants = [('0', splat 0), ('1', splat 1)]
+    splat x = take 1 (lanes (x :: r))
