I've got an interesting problem. The user enters a minimum value, which I represent as a 64bit signed number. But I want to store it as a 64 bit unsigned number relative to the lowest possible value that a 64bit signed can represent. Heres what I mean demonstrated with 3 bit numbers

- Code: Select all
`;; SIGNED UNSIGNED RELATIVE TO -4`

;; 000 = 0 --- goal --> 4 100

;; 001 = 1 5 101

;; 010 = 2 6 110

;; 011 = 3 7 111

;; 100 = -4 0 000

;; 101 = -3 1 001

;; 110 = -2 2 010

;; 111 = -1 3 011

;; Thus

;; 000 -> 100

;; 001 -> 101

;; 010 -> 110

;; 011 -> 111

;; 100 -> 000

;; 101 -> 001

;; 110 -> 010

;; 111 -> 011

From this ready pattern emerges; To convert a signed 64 bit number to an unsigned 64 bit number where 0 represents the smallest representable 64bit signed number I just need to add the smallest 64bit signed number and treat the result as an unsigned number.

So far, I've written this:

- Code: Select all
`(defconstant +smallest-64s+ (the (signed-byte 64) #x8000000000000000))`

(defun 64s->_64us (64s)

nil)

But I already have problems. Lisp won't let me define +smallest-64s+, because it thinks it has a positive number (although I could evaluate (- 0 (expt 2 63))), but I suspect I'll have a bigger problem: How will I coerce the answer to a unsigned? (coerce n '(unsigned-byte 64)) gives an error if N is negative.

Basically, what I'm asking is how can I get Lisp out of the way so I can do precisely what I want with raw bits? And when I'm done, how can I tell Lisp that the answer was unsigned?

I'm using SBCL. Thanks for your help!