preserves/_includes/intbytes.rkt

130 lines
3.7 KiB
Racket

#lang racket
(define (base-bytes v)
(define byte-count (cond [(zero? v) 0]
[else (define raw-bit-count (+ (integer-length v) 1))
(quotient (+ raw-bit-count 7) 8)]))
(for/list [(shift (in-range (* byte-count 8) 0 -8))]
(bitwise-bit-field v (- shift 8) shift)))
(define (mod n d) (modulo n d)) ;; sign equal to sign of d
(define (div n d) (/ (- n (mod n d)) d)) ;; sign equal to sign of n, or zero
;;---------------------------------------------------------------------------
;; One
;;
;; (define (intbytes* v)
;; (cond [(zero? v) '()]
;; [(= v -1) '()]
;; [else (append (intbytes* (div v 256)) (list (mod v 256)))]))
;;
;; (define (intbytes v)
;; (define bs (intbytes* v))
;; (define looks-negative (and (pair? bs) (>= (car bs) 128)))
;; (if (xor (negative? v) looks-negative)
;; (cons (if (negative? v) 255 0) bs)
;; bs))
;;---------------------------------------------------------------------------
;; Two
;;
;; (define (intbytes** v)
;; (cond [(zero? v) '()]
;; [else (append (intbytes** (quotient v 256)) (list (remainder v 256)))]))
;;
;; (define (intbytes* v)
;; (define bs (intbytes** v))
;; (if (and (pair? bs) (>= (car bs) 128))
;; (cons 0 bs)
;; bs))
;;
;; (define (intbytes v)
;; (if (negative? v)
;; (map (lambda (n) (- 255 n)) (intbytes* (- (+ v 1))))
;; (intbytes* v)))
;;---------------------------------------------------------------------------
;; Three
;;
;; (define (intbytes+ v)
;; (cond [(>= v 128) (append (intbytes+ (div v 256)) (list (mod v 256)))]
;; [else (list (mod v 256))]))
;;
;; (define (intbytes- v)
;; (cond [(< v -128) (append (intbytes- (div v 256)) (list (mod v 256)))]
;; [else (list (mod v 256))]))
;;
;; (define (intbytes v)
;; (cond [(negative? v) (intbytes- v)]
;; [(zero? v) '()]
;; [(positive? v) (intbytes+ v)]))
;;---------------------------------------------------------------------------
;; Four
;;
;; (define (intbytes* v)
;; (append (if (<= -128 v 127)
;; '()
;; (intbytes* (div v 256)))
;; (list (mod v 256))))
;;
;; (define (intbytes v)
;; (if (zero? v)
;; '()
;; (intbytes* v)))
;;---------------------------------------------------------------------------
;; Five
;;
;; (define (intbytes* v)
;; (if (<= -128 v 127)
;; (list (mod v 256))
;; (append (intbytes* (div v 256)) (list (mod v 256)))))
;;
;; (define (intbytes v)
;; (if (zero? v)
;; '()
;; (intbytes* v)))
;;---------------------------------------------------------------------------
;; Six
(define (intbytes* v)
(if (<= -128 v 127)
(list (bitwise-and v 255))
(append (intbytes* (arithmetic-shift v -8)) (list (bitwise-and v 255)))))
(define (intbytes v)
(if (zero? v)
'()
(intbytes* v)))
(define cases `(
(-257 (#xfe #xff))
(-256 (#xff #x00))
(-255 (#xff #x01))
(-129 (#xff #x7f))
(-128 (#x80))
(-127 (#x81))
(-2 (#xfe))
(-1 (#xff))
(0 ())
(1 (#x01))
(127 (#x7f))
(128 (#x00 #x80))
(255 (#x00 #xff))
(256 (#x01 #x00))
(32767 (#x7f #xff))
(32768 (#x00 #x80 #x00))
(65535 (#x00 #xff #xff))
(65536 (#x01 #x00 #x00))
))
(module+ test
(require rackunit)
(for [(c (in-list cases))]
(match-define (list input output) c)
(writeln (list input output (base-bytes input) (intbytes input)))
(check-equal? output (base-bytes input))
(check-equal? output (intbytes input))))