| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929 |
- (in-package :cl-user)
- (defpackage #:ocm.s2
- (:use :cl))
- (in-package :ocm.s2)
- ;; In the process of converting a latitude-longitude pair to a 64-bit cell
- ;; id, the following coordinate systems are used:
- ;;
- ;; (id)
- ;; An S2CellId is a 64-bit encoding of a face and a Hilbert curve position
- ;; on that face. The Hilbert curve position implicitly encodes both the
- ;; position of a cell and its subdivision level (see s2cell_id.h).
- ;;
- ;; (face, i, j)
- ;; Leaf-cell coordinates. "i" and "j" are integers in the range
- ;; [0,(2**30)-1] that identify a particular leaf cell on the given face.
- ;; The (i, j) coordinate system is right-handed on each face, and the
- ;; faces are oriented such that Hilbert curves connect continuously from
- ;; one face to the next.
- ;;
- ;; (face, s, t)
- ;; Cell-space coordinates. "s" and "t" are real numbers in the range
- ;; [0,1] that identify a point on the given face. For example, the point
- ;; (s, t) = (0.5, 0.5) corresponds to the center of the top-level face
- ;; cell. This point is also a vertex of exactly four cells at each
- ;; subdivision level greater than zero.
- ;;
- ;; (face, si, ti)
- ;; Discrete cell-space coordinates. These are obtained by multiplying
- ;; "s" and "t" by 2**31 and rounding to the nearest unsigned integer.
- ;; Discrete coordinates lie in the range [0,2**31]. This coordinate
- ;; system can represent the edge and center positions of all cells with
- ;; no loss of precision (including non-leaf cells). In binary, each
- ;; coordinate of a level-k cell center ends with a 1 followed by
- ;; (30 - k) 0s. The coordinates of its edges end with (at least)
- ;; (31 - k) 0s.
- ;;
- ;; (face, u, v)
- ;; Cube-space coordinates in the range [-1,1]. To make the cells at each
- ;; level more uniform in size after they are projected onto the sphere,
- ;; we apply a nonlinear transformation of the form u=f(s), v=f(t).
- ;; The (u, v) coordinates after this transformation give the actual
- ;; coordinates on the cube face (modulo some 90 degree rotations) before
- ;; it is projected onto the unit sphere.
- ;;
- ;; (face, u, v, w)
- ;; Per-face coordinate frame. This is an extension of the (face, u, v)
- ;; cube-space coordinates that adds a third axis "w" in the direction of
- ;; the face normal. It is always a right-handed 3D coordinate system.
- ;; Cube-space coordinates can be converted to this frame by setting w=1,
- ;; while (u,v,w) coordinates can be projected onto the cube face by
- ;; dividing by w, i.e. (face, u/w, v/w).
- ;;
- ;; (x, y, z)
- ;; Direction vector (S2Point). Direction vectors are not necessarily unit
- ;; length, and are often chosen to be points on the biunit cube
- ;; [-1,+1]x[-1,+1]x[-1,+1]. They can be be normalized to obtain the
- ;; corresponding point on the unit sphere.
- ;;
- ;; (lat, lng)
- ;; Latitude and longitude (S2LatLng). Latitudes must be between -90 and
- ;; 90 degrees inclusive, and longitudes must be between -180 and 180
- ;; degrees inclusive.
- ;;
- ;; Note that the (i, j), (s, t), (si, ti), and (u, v) coordinate systems are
- ;; right-handed on all six faces.
- (defparameter +swap-mask+ 1)
- (defparameter +invert-mask+ 2)
- (defparameter +max-cell-level+ 30 "This is the number of levels needed to specify a leaf cell.")
- (defparameter +limit-ij+ (ash 1 +max-cell-level+) "The maximum index of a valid leaf cell plus one. The range of valid leaf cell indices is [0..+limit-ij+-1].")
- (defparameter +max-si-ti+ (ash 1 (+ 1 +max-cell-level+)) "The maximum value of an si- or ti-coordinate. The range of valid (si,ti) values is [0..+max-si-ti+].")
- ;; An S2CellId is a 64-bit unsigned integer that uniquely identifies a
- ;; cell in the S2 cell decomposition. It has the following format:
- ;;
- ;; id = [face][face_pos]
- ;;
- ;; face: a 3-bit number (range 0..5) encoding the cube face.
- ;;
- ;; face_pos: a 61-bit number encoding the position of the center of this
- ;; cell along the Hilbert curve over this face (see the Wiki
- ;; pages for details).
- ;;
- ;; Sequentially increasing cell ids follow a continuous space-filling curve
- ;; over the entire sphere. They have the following properties:
- ;;
- ;; - The id of a cell at level k consists of a 3-bit face number followed
- ;; by k bit pairs that recursively select one of the four children of
- ;; each cell. The next bit is always 1, and all other bits are 0.
- ;; Therefore, the level of a cell is determined by the position of its
- ;; lowest-numbered bit that is turned on (for a cell at level k, this
- ;; position is 2 * (kMaxLevel - k).)
- ;;
- ;; - The id of a parent cell is at the midpoint of the range of ids spanned
- ;; by its children (or by its descendants at any level).
- (defparameter +face-bits+ 3)
- (defparameter +num-faces+ 6)
- (defparameter +max-level+ +max-cell-level+)
- (defparameter +pos-bits+ (1+ (* 2 +max-level+)))
- (defparameter +max-size+ (ash 1 +max-level+))
- (defun st-to-ij (s)
- (max 0 (min (- +limit-ij+ 1) (round (- (* s +limit-ij+) 0.5d0)))))
- ;; Use quadratic (s,t) -> (u,v) projection. See S2 sources for explanation.
- (defun st-to-uv (s)
- (* (/ 1 3)
- (if (>= s 0.5d0)
- (- (* 4 s s) 1)
- (- 1 (* 4 (- s 1) (- s 1))))))
- (defun uv-to-st (u)
- (if (>= u 0)
- (* 0.5d0 (sqrt (+ 1 (* 3 u))))
- (- 1 (* 0.5d0 (sqrt (- 1 (* 3 u)))))))
- (defstruct point
- (x 0.0d0 :type double-float)
- (y 0.0d0 :type double-float)
- (z 0.0d0 :type double-float))
- (defstruct latlng
- (lat 0d0 :type double-float)
- (lng 0d0 :type double-float))
- (defun deg-to-rad (deg)
- (* (/ pi 180d0) deg))
- (defun rad-to-deg (rad)
- (* (/ 180d0 pi) rad))
- (defun from-radians (lat-rad lng-rad)
- (make-latlng :lat lat-rad :lng lng-rad))
- (defun from-degrees (lat-deg lng-deg)
- (make-latlng :lat (deg-to-rad lat-deg) :lng (deg-to-rad lng-deg)))
- (defun to-degrees (latlng)
- (declare (type latlng latlng))
- (with-slots (lat lng) latlng
- (cons (rad-to-deg lat) (rad-to-deg lng))))
- (defun latlng-to-point (latlng)
- (declare (type latlng latlng))
- (with-slots (lat lng) latlng
- (let* ((phi lat)
- (theta lng)
- (cos-phi (cos phi)))
- (make-point :x (* (cos theta) cos-phi)
- :y (* (sin theta) cos-phi)
- :z (sin phi)))))
- (defun point-lat (p)
- (declare (type point p))
- (with-slots (x y z) p
- (atan z (sqrt (+ (* x x) (* y y))))))
- (defun point-lng (p)
- (declare (type point p))
- (with-slots (x y z) p
- (atan y x)))
- (defun point-to-lat-lng (p)
- (declare (type point p))
- (from-radians (point-lat p) (point-lng p)))
- (defun dot (p1 p2)
- (declare (type point p1 p2))
- (+ (* (point-x p1) (point-x p2))
- (* (point-y p1) (point-y p2))
- (* (point-z p1) (point-z p2))))
- (defparameter +face-uvw-axes+
- (make-array '(6 3) :element-type 'point :initial-contents
- (list
- (list (make-point :y 1d0) (make-point :z 1d0) (make-point :x 1d0))
- (list (make-point :x -1d0) (make-point :z 1d0) (make-point :y 1d0))
- (list (make-point :x -1d0) (make-point :y -1d0) (make-point :z 1d0))
- (list (make-point :z -1d0) (make-point :y -1d0) (make-point :x -1d0))
- (list (make-point :z -1d0) (make-point :x 1d0) (make-point :y -1d0))
- (list (make-point :y 1d0) (make-point :x 1d0) (make-point :z -1d0))))
- "The U,V,W axes for each face.")
- (defun get-xyz-face (p)
- (declare (type point p))
- (with-slots (x y z) p
- (cond
- ((and (> (abs x) (abs y))
- (> (abs x) (abs z)))
- (if (>= x 0) 0 3))
- ((and (> (abs y) (abs x))
- (> (abs y) (abs z)))
- (if (>= y 0) 1 4))
- (t
- (if (>= z 0) 2 5)))))
- (defun get-uvw-axis (face axis)
- (aref +face-uvw-axes+ face axis))
- (defun get-norm (face)
- (get-uvw-axis face 2))
- (defun valid-face-xyz-to-uv (face p)
- (declare (type point p))
- (assert (> (dot (get-norm face) p) 0))
- (with-slots (x y z) p
- (ecase face
- (0 (values (/ y x) (/ z x)))
- (1 (values (/ (- x) y) (/ z y)))
- (2 (values (/ (- x) z) (/ (- y) z)))
- (3 (values (/ z x) (/ y x)))
- (4 (values (/ z y) (/ (- x) y)))
- (5 (values (/ (- y) z) (/ (- x) z))))))
- (defun xyz-to-face-uv (p)
- (declare (type point p))
- (let ((face (get-xyz-face p)))
- (multiple-value-bind (u v)
- (valid-face-xyz-to-uv face p)
- (values face u v))))
- (defparameter +lookup-bits+ 4)
- (defvar *lookup-pos* (make-array (ash 1 (+ 2 (* +lookup-bits+ 2))) :element-type '(unsigned-byte 16)))
- (defvar *lookup-ij* (make-array (ash 1 (+ 2 (* +lookup-bits+ 2))) :element-type '(unsigned-byte 16)))
- (defparameter +ij-to-pos+
- #(#(0 1 3 2) ; canonical order
- #(0 3 1 2) ; axes swapped
- #(2 3 1 0) ; bits inverted
- #(2 1 3 0)); swapped & inverted
- "IJtoPos[orientation][ij] -> pos")
- (defparameter +pos-to-ij+
- #(#(0 1 3 2) ; canonical order: (0,0), (0,1), (1,1), (1,0)
- #(0 2 3 1) ; axes swapped: (0,0), (1,0), (1,1), (0,1)
- #(3 2 0 1) ; bits inverted: (1,1), (1,0), (0,0), (0,1)
- #(3 1 0 2)); swapped & inverted: (1,1), (0,1), (0,0), (1,0)
- "PosToIJ[orientation][pos] -> ij")
- (defparameter +pos-to-orient+
- (make-array 4 :element-type '(unsigned-byte 8)
- :initial-contents (list +swap-mask+ 0 0 (logior +swap-mask+ +invert-mask+)))
- "PosToOrientation[pos] -> orientation_modifier")
- (defun init-lookup ()
- (labels ((init-lookup-cell (level i j orig-orient pos orient)
- (if (= level +lookup-bits+)
- (let ((ij (+ (ash i +lookup-bits+) j)))
- (setf (aref *lookup-pos* (+ (ash ij 2) orig-orient)) (+ (ash pos 2) orient))
- (setf (aref *lookup-ij* (+ (ash pos 2) orig-orient)) (+ (ash ij 2) orient)))
- (let ((level (1+ level))
- (i (ash i 1))
- (j (ash j 1))
- (pos (ash pos 2))
- (r (aref +pos-to-ij+ orient)))
- (init-lookup-cell level (+ i (ash (aref r 0) -1)) (+ j (logand (aref r 0) 1))
- orig-orient pos (logxor orient (aref +pos-to-orient+ 0)))
- (init-lookup-cell level (+ i (ash (aref r 1) -1)) (+ j (logand (aref r 1) 1))
- orig-orient (+ pos 1) (logxor orient (aref +pos-to-orient+ 1)))
- (init-lookup-cell level (+ i (ash (aref r 2) -1)) (+ j (logand (aref r 2) 1))
- orig-orient (+ pos 2) (logxor orient (aref +pos-to-orient+ 2)))
- (init-lookup-cell level (+ i (ash (aref r 3) -1)) (+ j (logand (aref r 3) 1))
- orig-orient (+ pos 3) (logxor orient (aref +pos-to-orient+ 3)))))))
- (init-lookup-cell 0 0 0 0 0 0)
- (init-lookup-cell 0 0 0 +swap-mask+ 0 +swap-mask+)
- (init-lookup-cell 0 0 0 +invert-mask+ 0 +invert-mask+)
- (init-lookup-cell 0 0 0 (logior +swap-mask+ +invert-mask+) 0 (logior +swap-mask+ +invert-mask+))))
- (eval-when (:execute :compile-toplevel :load-toplevel)
- (init-lookup))
- (defun from-face-ij (face i j)
- (let ((n (ash face (1- +pos-bits+)))
- (bits (logand face +swap-mask+)))
- (macrolet ((get-bits (k)
- `(let ((mask (1- (ash 1 +lookup-bits+))))
- (setf bits
- (aref *lookup-pos*
- (+ bits
- (ash (logand mask (ash i (- (* ,k +lookup-bits+)))) (+ +lookup-bits+ 2))
- (ash (logand mask (ash j (- (* ,k +lookup-bits+)))) 2))))
- (setf n (logior n (ash (ash bits -2)
- (* ,k 2 +lookup-bits+)))
- bits (logand bits (logior +swap-mask+ +invert-mask+))))))
- (get-bits 7)
- (get-bits 6)
- (get-bits 5)
- (get-bits 4)
- (get-bits 3)
- (get-bits 2)
- (get-bits 1)
- (get-bits 0))
- (1+ (* 2 n))))
- (defun point-to-cell (p)
- (multiple-value-bind (face u v)
- (xyz-to-face-uv p)
- (from-face-ij face
- (st-to-ij (uv-to-st u))
- (st-to-ij (uv-to-st v)))))
- (defun cell-to-face-ij-orientation (id)
- (let* ((i 0)
- (j 0)
- (face (cell-face id))
- (bits (logand face +swap-mask+)))
- (macrolet ((get-bits (k)
- `(let ((nbits (if (= ,k 7) (- +max-level+ (* 7 +lookup-bits+)) +lookup-bits+)))
- (setf bits (aref *lookup-ij*
- (+ bits
- (ash (logand (ash id (- (1+ (* ,k 2 +lookup-bits+))))
- (1- (ash 1 (* 2 nbits)))) 2))))
- (setf i (+ i (ash (ash bits (- (+ +lookup-bits+ 2)))
- (* ,k +lookup-bits+)))
- j (+ j (ash (logand (ash bits -2)
- (1- (ash 1 +lookup-bits+)))
- (* ,k +lookup-bits+)))
- bits (logand bits (logior +swap-mask+ +invert-mask+))))))
- (get-bits 7)
- (get-bits 6)
- (get-bits 5)
- (get-bits 4)
- (get-bits 3)
- (get-bits 2)
- (get-bits 1)
- (get-bits 0)
- (values face i j (logxor bits (if (zerop (logand (cell-lsb id) #x1111111111111110)) 0 +swap-mask+))))))
- (defun cell-get-center-face-si-ti (id)
- (multiple-value-bind (face i j orient) (cell-to-face-ij-orientation id)
- (declare (ignore orient))
- (let ((delta (if (cell-is-leaf id) 1 (if (zerop (logand 1 (logxor i (ash id -2)))) 0 2))))
- (values face (+ delta (* 2 i)) (+ delta (* 2 j))))))
- (defun face-si-ti-to-xyz (face si ti)
- (face-uv-ti-xyz face
- (st-to-uv (si-ti-to-st si))
- (st-to-uv (si-ti-to-st ti))))
- (defun face-uv-ti-xyz (face u v)
- (declare (type double-float u v))
- (ecase face
- (0 (make-point :x 1d0 :y u :z v))
- (1 (make-point :x (- u) :y 1d0 :z v))
- (2 (make-point :x (- u) :y (- v) :z 1d0))
- (3 (make-point :x -1d0 :y (- v) :z (- u)))
- (4 (make-point :x v :y -1d0 :z (- u)))
- (5 (make-point :x v :y u :z -1d0))))
- (defun si-ti-to-st (si)
- (assert (<= si +max-si-ti+))
- (* si (/ 1d0 +max-si-ti+)))
- (defun cell-to-point-raw (id)
- (apply #'face-si-ti-to-xyz (multiple-value-list (cell-get-center-face-si-ti id))))
- (defun find-lsb-set (num)
- (loop for i upto 63 when (logbitp i num) return i))
- (defun find-msb-set (num)
- (loop for i from 63 downto 0 when (logbitp i num) return i))
- (defun lsb-for-level (level)
- (ash 1 (* 2 (- +max-level+ level))))
- (defun cell-face (id)
- (ash id (- +pos-bits+)))
- (defun cell-lsb (id)
- (logand id (1+ (lognot id))))
- (defun cell-level (id)
- (assert (not (zerop id)))
- (- +max-level+ (ash (find-lsb-set id) -1)))
- (defun cell-pos (id)
- (logand id (lognot 0)))
- (defun cell-is-valid (id)
- (and (< (cell-face id) +num-faces+)
- (not (zerop (logand (cell-lsb id) #x1555555555555555)))))
- (defun cell-child-position (id &optional level)
- (unless level (setf level (cell-level id)))
- (assert (cell-is-valid id))
- (assert (>= level 1))
- (assert (<= level (cell-level id)))
- (logand 3 (ash id (- (1+ (* 2 (- +max-level+ level)))))))
- (defun cell-range-min (id)
- (- id (1- (cell-lsb id)) ))
- (defun cell-range-max (id)
- (+ id (1- (cell-lsb id))))
- (defun cell-is-leaf (id)
- (not (zerop (logand id 1))))
- (defun cell-is-face (id)
- (zerop (logand id (1- (lsb-for-level 0)))))
- (defun cell-parent (id &optional level)
- (assert (cell-is-valid id))
- (if level (progn
- (assert (>= level 0))
- (assert (<= level (cell-level id))))
- (progn (assert (not (cell-is-face id)))))
- (let ((new-lsb (if level (lsb-for-level level) (ash (cell-lsb id) 2))))
- (logior new-lsb (logand id (1+ (lognot new-lsb))))))
- (defun cell-child (id pos)
- (assert (cell-is-valid id))
- (assert (not (cell-is-leaf id)))
- (+ id (* (+ (* 2 pos) 1 -4) (ash (cell-lsb id) -2))))
- (defun cell-to-string (id)
- (format nil "~a/~{~a~}" (cell-face id)
- (loop for level from 1 to (cell-level id)
- collect (cell-child-position id level))))
- ;;;;;;;;;
- ;;;
- (defun make-span (vector offset &optional size)
- (declare (type vector vector))
- (let ((length (length vector)))
- (assert (< offset length))
- (when size (assert (< (+ offset size) length)))
- (make-array (if size size (- length offset))
- :element-type (or (cadr (type-of vector)) t)
- :displaced-to vector
- :displaced-index-offset offset)))
- (deftype byte-vector () `(vector (unsigned-byte 8)))
- (defun make-encoder (size)
- (make-array size :element-type '(unsigned-byte 8) :fill-pointer 0 :adjustable t))
- (defun encoder-avail (encoder)
- (declare (type byte-vector encoder))
- (- (array-total-size encoder)
- (fill-pointer encoder)))
- (defun encoder-ensure (encoder size)
- (declare (type byte-vector encoder))
- (when (< (encoder-avail encoder) size)
- (adjust-array encoder (+ (fill-pointer encoder) size))))
- (defun encoder-put8 (encoder value)
- (declare (type byte-vector encoder)
- (type (unsigned-byte 8) value))
- (assert (> (encoder-avail encoder) 1))
- (vector-push value encoder)
- encoder)
- (defun encoder-putn (encoder vector)
- (declare (type byte-vector encoder)
- (type byte-vector vector))
- (loop for value across vector do (vector-push value encoder))
- encoder)
- (defun encoder-length (encoder)
- (declare (type byte-vector encoder))
- (fill-pointer encoder))
- (defparameter +varint-max32+ 5 "Maximum varint encoding length for uint32")
- (defun encoder-put-varint32 (encoder v)
- (declare (type byte-vector encoder)
- (type (unsigned-byte 32) v))
- (let ((b 128))
- (cond
- ((< v (ash 1 7)) (encoder-put8 encoder v))
- ((< v (ash 1 14))
- (encoder-put8 encoder (logand 255 (logior v b)))
- (encoder-put8 encoder (logand 255 (ash v -7))))
- ((< v (ash 1 21))
- (encoder-put8 encoder (logand 255 (logior v b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -7) b)))
- (encoder-put8 encoder (logand 255 (ash v -14))))
- ((< v (ash 1 28))
- (encoder-put8 encoder (logand 255 (logior v b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -7) b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -14) b)))
- (encoder-put8 encoder (logand 255 (ash v -21))))
- (t
- (encoder-put8 encoder (logand 255 (logior v b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -7) b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -14) b)))
- (encoder-put8 encoder (logand 255 (logior (ash v -21) b)))
- (encoder-put8 encoder (logand 255 (ash v -28))))))
- encoder)
- (defparameter +varint-max64+ 10 "Maximum varint encoding length for uint64")
- (defun encoder-put-varint64 (encoder v)
- (declare (type byte-vector encoder)
- (type (unsigned-byte 64) v))
- (if (< v (ash 1 28))
- (encoder-put-varint32 encoder v)
- (let ((x32 (logand (1- (ash 1 32)) (logior v (ash 1 7) (ash 1 21))))
- (y32 (logand (1- (ash 1 32)) (logior v (ash 1 14) (ash 1 28)))))
- (encoder-put8 encoder (logand 255 x32))
- (encoder-put8 encoder (logand 255 (ash y32 -7)))
- (encoder-put8 encoder (logand 255 (ash x32 -14)))
- (encoder-put8 encoder (logand 255 (ash y32 -21)))
- (if (< v (ash 1 35))
- (encoder-put8 encoder (logand 255 (ash v -28)))
- (progn
- (encoder-put8 encoder (logand 255 (logior (ash v -28) (ash 1 7))))
- (encoder-put-varint32 encoder (ash v -35)))))))
- ;;; decoder ;;;
- (defun make-decoder (size &key (fill-pointer 0) initial-contents initial-element displaced-to)
- (apply #'make-array size
- :element-type '(unsigned-byte 8)
- :fill-pointer fill-pointer
- (append
- (when initial-contents `(:initial-contents ,initial-contents))
- (when initial-element `(:initial-element ,initial-element))
- (when displaced-to `(:displaced-to ,displaced-to :displaced-index-offset ,(fill-pointer displaced-to))))))
- (defun decoder-avail (decoder)
- (declare (type byte-vector decoder))
- (- (array-total-size decoder)
- (fill-pointer decoder)))
- (defun decoder-skip (decoder &optional (count 1))
- (declare (type byte-vector decoder)
- (type (unsigned-byte 32) count))
- (incf (fill-pointer decoder) count))
- (defun decoder-reset (decoder)
- (declare (type byte-vector decoder))
- (setf (fill-pointer decoder) 0)
- decoder)
- (defun make-sub-decoder (decoder size &optional will-decode)
- (when (>= (decoder-avail decoder) size)
- (prog1 (make-decoder size :fill-pointer (if will-decode 0 size) :displaced-to decoder)
- (decoder-skip decoder size))))
- (defmacro with-decoder-reset ((decoder &optional (offset 0)) &body body)
- (let ((fp (gensym "FP"))
- (dc (gensym "DC")))
- `(let* ((,dc ,decoder)
- (,fp (fill-pointer ,dc)))
- (unwind-protect
- (progn
- (setf (fill-pointer ,dc) ,offset)
- ,@body)
- (setf (fill-pointer ,dc) ,fp)))))
- (defun decoder-get8 (decoder)
- (declare (type byte-vector decoder))
- (prog1 (aref decoder (fill-pointer decoder))
- (decoder-skip decoder)))
- (defun decoder-peek (decoder &optional (offset 0))
- (declare (type byte-vector decoder)
- (type (unsigned-byte 32) offset))
- (aref decoder (+ (fill-pointer decoder) offset)))
- (defun decoder-get-varint64 (decoder)
- (declare (type byte-vector decoder))
- (loop
- for b = (decoder-get8 decoder) then (decoder-get8 decoder)
- for i from 0
- with result = 0
- do (incf result (ash (if (zerop i) b (1- b)) (* i 7)))
- until (< b 128)
- finally (return result)))
- ;;;
- ;;; encoded-uint-vector ;;;
- ;;;
- (defun encode-uint-with-length (value length encoder)
- (declare (type integer value)
- (type (integer 0 8) length)
- (type byte-vector encoder))
- (assert (>= (encoder-avail encoder) length))
- (loop repeat length
- do (encoder-put8 encoder (logand value 255))
- do (setf value (ash value -8)))
- (assert (zerop value))
- (values))
- (defun get-uint-with-length (decoder length)
- (declare (type byte-vector decoder)
- (type (integer 0 8) length))
- (let ((value 0))
- (loop for i from (1- length) downto 0
- do (setf value (+ (ash value 8)
- (decoder-peek decoder i))))
- (decoder-skip decoder length)
- value))
- (defun get-type-byte-size (v-type)
- (values
- (typecase v-type
- (list (case (car v-type)
- ((array simple-array vector) (get-type-byte-size (cadr v-type)))
- ((unsigned-byte signed-byte) (ceiling (cadr v-type) 8))
- (integer (when (cadr v-type) (ceiling (log (cadr v-type) 2) 8)))
- (t nil)))
- (symbol (when (eql v-type 'fixnum) 8))
- (t nil))))
- (defun encode-uint-vector (v encoder)
- (declare (type vector v)
- (type byte-vector encoder))
- (let ((length (1+ (ash (find-msb-set
- (loop
- for value across v
- with bits = 1
- do (setf bits (logior bits value))
- finally (return bits)))
- -3))))
- (assert (<= 1 length 8))
- (encoder-ensure encoder (+ (* (length v) length)
- +varint-max64+))
- (encoder-put-varint64 encoder
- (logior (* (length v) (get-type-byte-size (type-of v)))
- (1- length)))
- (loop for value across v
- do (encode-uint-with-length value length encoder))
- encoder))
- (defstruct encoded-uint-vector
- (size 0 :type (unsigned-byte 32))
- (length 1 :type (integer 1 8))
- (bytes 8 :type (member 1 2 4 8))
- (data nil :type byte-vector))
- (defun encoded-uint-vector-init (decoder &optional (bytes 8))
- (declare (type byte-vector decoder)
- (type (member 1 2 4 8) bytes))
- (let ((size-len (decoder-get-varint64 decoder)))
- (when size-len
- (let* ((size (floor size-len bytes))
- (length (1+ (logand size-len (1- bytes))))
- (bytes-length (* size length))
- (data (make-sub-decoder decoder bytes-length)))
- (when data
- (make-encoded-uint-vector :size size :length length :bytes bytes
- :data data))))))
- (defun encoded-uint-vector-get (euv pos)
- (declare (type encoded-uint-vector euv)
- (type (unsigned-byte 32) pos))
- (with-slots (size data length) euv
- (assert (< pos size))
- (with-decoder-reset (data (* pos length))
- (get-uint-with-length data length))))
- (defun encoded-uint-vector-decode (euv)
- (declare (type encoded-uint-vector euv))
- (let* ((size (encoded-uint-vector-size euv))
- (result (make-array size :element-type '(unsigned-byte 64))))
- (dotimes (i size result)
- (setf (aref result i) (encoded-uint-vector-get euv i)))))
- ;; encoded-string-vector
- (defstruct string-vector-encoder
- (offsets (make-array 0 :element-type '(unsigned-byte 64) :adjustable t :fill-pointer 0)
- :type (vector (unsigned-byte 64)))
- (data (make-encoder 0) :type byte-vector))
- (defun string-vector-encoder-add-via-encoder (sve)
- (declare (type string-vector-encoder sve))
- (with-slots (offsets data) sve
- (vector-push-extend (length data) offsets)
- data))
- (defun string-vector-encoder-size (sve)
- (declare (type string-vector-encoder sve))
- (length (string-vector-encoder-offsets sve)))
- (defun string-vector-encoder-encode (sve encoder)
- (declare (type string-vector-encoder sve)
- (type byte-vector encoder))
- (with-slots (offsets data) sve
- (vector-push-extend (length data) offsets)
- (encode-uint-vector (make-span offsets 1) encoder)
- (encoder-ensure encoder (encoder-length data))
- (encoder-putn encoder data)
- encoder))
- (defstruct encoded-string-vector
- (offsets nil :type encoded-uint-vector)
- (data nil :type byte-vector))
- (defun encoded-string-vector-init (decoder)
- (declare (type byte-vector decoder))
- (let ((offsets (encoded-uint-vector-init decoder 8)))
- (when offsets
- (let* ((size (encoded-uint-vector-size offsets))
- (length (if (zerop size) 0 (encoded-uint-vector-get offsets (1- size))))
- (data (make-sub-decoder decoder length)))
- (when data
- (make-encoded-string-vector :offsets offsets :data data))))))
- (defun encoded-string-vector-size (esv)
- (declare (type encoded-string-vector esv))
- (encoded-uint-vector-size (encoded-string-vector-offsets esv)))
- (defun encoded-string-vector-get (esv index &optional fill-pointer)
- (declare (type encoded-string-vector esv)
- (type (unsigned-byte 32) index))
- (with-slots (offsets data) esv
- (let* ((start (if (zerop index) 0 (encoded-uint-vector-get offsets (1- index))))
- (length (- (encoded-uint-vector-get offsets index) start)))
- (with-decoder-reset (data start)
- (make-decoder length :displaced-to data :fill-pointer fill-pointer)))))
- (defun encoded-string-vector-decode (esv)
- (declare (type encoded-string-vector esv))
- (let* ((size (encoded-string-vector-size esv))
- (result (make-array size :element-type '(vector (unsigned-byte 8)))))
- (dotimes (i size result)
- (setf (aref result i) (encoded-string-vector-get esv i)))))
- ;; encoded-cell-id-vector
- (defstruct encoded-cell-id-vector
- (deltas nil :type encoded-uint-vector)
- (base 0 :type (unsigned-byte 64))
- (shift 0 :type (unsigned-byte 8)))
- (defun encoded-cell-id-vector-size (ecv)
- (declare (type encoded-cell-id-vector ecv))
- (with-slots (deltas) ecv
- (when deltas
- (encoded-uint-vector-size deltas))))
- (defun encoded-cell-id-vector-get (ecv i)
- (declare (type encoded-cell-id-vector ecv)
- (type (unsigned-byte 32) i))
- (with-slots (deltas base shift) ecv
- (+ base
- (ash (encoded-uint-vector-get deltas i) shift))))
- (defun encoded-cell-id-vector-init (decoder)
- (declare (type byte-vector decoder))
- (when (>= (decoder-avail decoder) 2)
- (let* ((code+len (decoder-get8 decoder))
- (shift-code (ash code+len -3)))
- (when (= shift-code 31)
- (setf shift-code (+ 29 (decoder-get8 decoder))))
- (let* ((base-len (logand code+len 7))
- (base (get-uint-with-length decoder base-len))
- shift)
- (when base
- (setf base (ash base (- 64 (* 8 (max 1 base-len)))))
- (if (>= shift-code 29)
- (setf shift (1+ (* 2 (- shift-code 29)))
- base (logior base (ash 1 (1- shift))))
- (setf shift (* 2 shift-code)))
- (make-encoded-cell-id-vector
- :deltas (encoded-uint-vector-init decoder 8)
- :base base
- :shift shift))))))
- (defun encoded-cell-id-vector-decode (eciv)
- (declare (type encoded-cell-id-vector eciv))
- (let* ((size (encoded-cell-id-vector-size eciv))
- (result (make-array size :element-type '(unsigned-byte 64))))
- (dotimes (i size result)
- (setf (aref result i) (encoded-cell-id-vector-get eciv i)))))
- (defun encode-cell-id-vector (v encoder)
- (declare (type (vector (unsigned-byte 64)) v)
- (type byte-vector encoder))
- (destructuring-bind (v-or v-and v-min v-max)
- (loop for cell-id across v
- with v-or = 0
- with v-and = -1
- do (setf v-or (logior v-or cell-id)
- v-and (logand v-and cell-id))
- maximizing cell-id into v-max
- minimizing cell-id into v-min
- finally (return (list v-or v-and v-min v-max)))
- (let ((e-base 0)
- (e-base-len 0)
- (e-shift 0)
- (e-max-delta-msb 0))
- (when (> v-or 0)
- (setf e-shift (min 56 (dpb 0 (byte 1 0) (find-lsb-set v-or))))
- (unless (zerop (logand v-and (ash 1 e-shift)))
- (incf e-shift))
- (let ((e-bytes (1- (ash 1 65))))
- (dotimes (len 8)
- (let* ((t-base (mask-field (byte (* 8 len) (- 64 (* 8 len))) v-min))
- (t-max-delta-msb (max 0 (1- (integer-length (ash (- v-max t-base)
- (- e-shift))))))
- (t-bytes (+ len (* (length v) (1+ (ash t-max-delta-msb -3))))))
- (when (< t-bytes e-bytes)
- (setf e-base t-base
- e-base-len len
- e-max-delta-msb t-max-delta-msb
- e-bytes t-bytes)))))
- (when (and (logbitp 0 e-shift)
- (not (= (logand e-max-delta-msb 7) 7)))
- (decf e-shift)))
- (assert (<= e-base-len 7))
- (assert (<= e-shift 56))
- (encoder-ensure encoder (+ 2 e-base-len))
- (let ((shift-code (ash e-shift -1)))
- (when (logbitp 0 e-shift)
- (setf shift-code (min 31 (+ shift-code 29))))
- (encoder-put8 encoder (logior (ash shift-code 3)
- e-base-len))
- (when (= shift-code 31)
- (encoder-put8 encoder (ash e-shift -1))))
- (encode-uint-with-length
- (ash e-base (- (- 64 (* 8 (max 1 e-base-len))))) e-base-len encoder)
- (let ((deltas (make-array (length v) :element-type '(unsigned-byte 64))))
- (loop for cell-id across v
- for i from 0
- do (setf (aref deltas i)
- (ash (- cell-id e-base) (- e-shift))))
- (encode-uint-vector deltas encoder)))))
- ;; encoded-point-vector
- (defstruct encoded-point-vector
- (size 0 :type (unsigned-byte 32))
- (blocks nil :type encoded-string-vector)
- (base 0 :type (unsigned-byte 64))
- (level 0 :type (unsigned-byte 8))
- (have-exceptions nil :type boolean))
- (defstruct cell-point
- (level 0 :type (unsigned-byte 8))
- (face 0 :type (unsigned-byte 8))
- (si 0 :type (unsigned-byte 32))
- (ti 0 :type (unsigned-byte 32)))
- (defparameter +block-shift+ 4)
- (defparameter +block-size+ (ash 1 +block-shift+))
- (defparameter +exception+ -1)
- (defstruct block-code
- (delta-bits 0 :type (signed-byte 32))
- (offset-bits 0 :type (signed-byte 32))
- (overlap-bits 0 :type (signed-byte 32)))
- (defun bit-mask (n)
- (declare (type (integer 0 64) n))
- (if (zerop n) 0
- (dpb -1 (byte n 0) 0)))
- (defun max-bits-for-level (level)
- (declare (type (integer 0 30) level))
- (+ (* 2 level) 3))
- (defun base-shift (level base-bits)
- (declare (type (integer 0 30) level)
- (type (integer 0 64) base-bits))
- (max 0 (- (max-bits-for-level level) base-bits)))
- (defun encode-point-vector-compact (points encoder)
- (declare (type (vector point) points)
- (type byte-vector encoder))
- (multiple-value-bind (level cell-points)
- (choose-best-level points)
- (when (< level 0)
- (return (encode-point-vector-fast points encoder)))
- (multiple-value-bind (values have-exceptions) (convert-cells-to-values cell-points level)
- (multiple-value-bind (base base-bits) (choose-base values level have-exceptions)
- (let ((num-blocks (ash (+ (length values) +block-size+ -1) (- +block-shift+)))
- (base-bytes (ash base-bits -3)))
- (encoder-ensure encoder (+ 2 base-bytes))
- (let ((last-block-count (- (length values) (* +block-size+ (1- num-blocks))))
- (blocks (make-string-vector-encoder))
- (exceptions (make-array 0 :element-type point :adjustable t)))
- (assert (>= last-block-count 0))
- (assert (<= last-block-count +block-size+))
- (assert (<= base-bytes 7))
- (assert (<= level 30))
- (encoder-put8 (logior +encoded-point-vector-cell-ids+
- (ash have-exceptions 3)
- (ash (1- last-block-count) 4)))
- (encoder-put8 (logior base-bytes
- (ash level 3)))
- (encode-uint-with-length (ash base (- (base-shift level base-bits))) base-bytes encoder)
- (loop for i from 0 to (length values) step +block-size+
- for block-size = (min +block-size+ (- (length values) i))
- for code = (get-block-code values i block-size base have-exceptions)
- do (let ((block (string-vector-encoder-add-via-encoder blocks))
- (offset-bytes (ash (block-code-offset-bits code) -3))
- (delta-nibbles (ash (block-code-delta-bits code) -2))
- (overlap-nibbles (ash (block-code-overlap-bits code) -2)))
- (encoder-ensure block (+ 1 offset-bytes (* delta-nibbles (ash +block-size+ -1))))
- (assert (<= (- offset-bytes overlap-nibbles) 7))
- (assert (<= overlap-nibbles 1))
- (assert (<= delta-nibbles 16))
- (encoder-put8 block (logior (- offset-bytes overlap-nibbles)
- (ash overlap-nibbles 3)
- (ash (1- delta-nibbles) 4)))
- (let ((offset (1- (ash 1 65)))
- (num-exceptions 0))
- (dotimes (i block-size)
- (let ((value (aref values (+ i j))))
- (if (equalp value +exception+)
- (incf num-exceptions)
- (progn
- (assert (>= value base))
- (setf offset (min offset (- value base)))))))
- (when (= num-exceptions block-size)
- (setf offset))
- (let ((offset-shift (- (block-code-delta-bits code)
- (block-code-overlap-bits code))))
- (setf offset (logand offset (lognot (bit-mask offset-shift))))
- (assert (= (zerop offset) (zerop offset-bytes)))
- (when (> offset 0)
- (encode-uint-with-length (ash offset (- offset-shift)) offset-bytes block))
- (let ((delta-bytes (ash (1+ delta-nibbles) -1)))
- (setf (fill-pointer exceptions) 0)
- (dotimes (j block-size)
- (let ((delta 0)
- (value (arerf values (+ i j))))
- (if (equalp value +exception+)
- (progn
- (setf delta (length exceptions))
- (vector-push-extend (aref points (+ i j)) exceptions))
- (progn
- (assert (>= value (+ offset base)))
- (setf delta (- value (+ offset base)))
- (when have-exceptions
- (assert (<= delta (- (1- (ash 1 65)) +block-size+)))
- (incf delta +block-size+))))
- (assert (<= delta (bit-mask (block-code-delta-bits delta))))
- (when (and (logbitp delta-nibbles 0)
- (logbitp j 0))
- ())
- )))
- ))))
- ))))))
|