Finished with C-ing the code, it's now 2.5 times faster than it was,
and spending only 7% of the GC time it used to spend. svn: r2915
This commit is contained in:
parent
1e760c0546
commit
fd96a129f3
|
@ -93,48 +93,55 @@
|
||||||
;; performance.
|
;; performance.
|
||||||
|
|
||||||
;; (word c) turns into a quoted pair '(hi . lo) if c is a literal number.
|
;; (word c) turns into a quoted pair '(hi . lo) if c is a literal number.
|
||||||
|
;; can create a new word, compute one at compile-time etc
|
||||||
(define-syntax (word stx)
|
(define-syntax (word stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(word c)
|
;; normal version
|
||||||
(let ([n (syntax-e #'c)])
|
[(word #:new c)
|
||||||
(if (integer? n)
|
|
||||||
(datum->syntax-object
|
|
||||||
#'c `(quote ,(cons (quotient n 65536) (remainder n 65536))) #'c)
|
|
||||||
#'(let ([n c])
|
#'(let ([n c])
|
||||||
(if (<= 0 n 4294967296)
|
(if (<= 0 n 4294967296)
|
||||||
(cons (quotient n 65536) (remainder n 65536))
|
(cons (quotient n 65536) (remainder n 65536))
|
||||||
(error 'word "out of range: ~e" n)))))]))
|
(error 'word "out of range: ~e" n)))]
|
||||||
|
;; to use when the number is known to be in range
|
||||||
|
[(word #:safe #:new c) #'(word #:new #:safe c)]
|
||||||
|
[(word #:new #:safe c)
|
||||||
|
#'(let ([n c]) (cons (quotient n 65536) (remainder n 65536)))]
|
||||||
|
;; default form: compute at compile-time if possible
|
||||||
|
[(word c)
|
||||||
|
(let ([n (syntax-e #'c)])
|
||||||
|
(if (integer? n)
|
||||||
|
(if (<= 0 n 4294967295)
|
||||||
|
(datum->syntax-object
|
||||||
|
#'c `(quote ,(cons (quotient n 65536) (remainder n 65536))) #'c)
|
||||||
|
(raise-syntax-error #f "constant number out of range" stx))
|
||||||
|
#'(word #:new c)))]))
|
||||||
|
|
||||||
(define (word+ a b)
|
;; destructive operations to save on consing
|
||||||
|
|
||||||
|
;; destructive cons
|
||||||
|
(define (cons! p x y)
|
||||||
|
(set-car! p x)
|
||||||
|
(set-cdr! p y))
|
||||||
|
|
||||||
|
;; a := b
|
||||||
|
(define (word=! a b)
|
||||||
|
(cons! a (car b) (cdr b)))
|
||||||
|
|
||||||
|
;; a := a + b
|
||||||
|
(define (word+=! a b)
|
||||||
(let ([t1 (+ (car a) (car b))]
|
(let ([t1 (+ (car a) (car b))]
|
||||||
[t2 (+ (cdr a) (cdr b))])
|
[t2 (+ (cdr a) (cdr b))])
|
||||||
(cons (bitwise-and (+ t1 (arithmetic-shift t2 -16)) 65535)
|
(set-car! a (bitwise-and (+ t1 (arithmetic-shift t2 -16)) 65535))
|
||||||
(bitwise-and t2 65535))))
|
(set-cdr! a (bitwise-and t2 65535))
|
||||||
|
a))
|
||||||
|
|
||||||
(define (word-or a b)
|
(define word<<<!
|
||||||
(cons (bitwise-ior (car a) (car b))
|
|
||||||
(bitwise-ior (cdr a) (cdr b))))
|
|
||||||
|
|
||||||
(define (word-not a)
|
|
||||||
(cons (bitwise-and (bitwise-not (car a)) 65535)
|
|
||||||
(bitwise-and (bitwise-not (cdr a)) 65535)))
|
|
||||||
|
|
||||||
(define (word-xor a b)
|
|
||||||
(cons (bitwise-xor (car a) (car b))
|
|
||||||
(bitwise-xor (cdr a) (cdr b))))
|
|
||||||
(define (word-xor3 a b c)
|
|
||||||
(cons (bitwise-xor (car a) (car b) (car c))
|
|
||||||
(bitwise-xor (cdr a) (cdr b) (cdr c))))
|
|
||||||
|
|
||||||
(define (word-and a b)
|
|
||||||
(cons (bitwise-and (car a) (car b))
|
|
||||||
(bitwise-and (cdr a) (cdr b))))
|
|
||||||
|
|
||||||
(define word<<<
|
|
||||||
(let* ([masks '#(#x0 #x1 #x3 #x7 #xF #x1F #x3F #x7F #xFF #x1FF #x3FF #x7FF
|
(let* ([masks '#(#x0 #x1 #x3 #x7 #xF #x1F #x3F #x7F #xFF #x1FF #x3FF #x7FF
|
||||||
#xFFF #x1FFF #x3FFF #x7FFF #xFFFF)]
|
#xFFF #x1FFF #x3FFF #x7FFF #xFFFF)])
|
||||||
[rot (lambda (hi lo s)
|
(lambda (a s)
|
||||||
(cons (bitwise-ior
|
(let ([rot (lambda (hi lo s)
|
||||||
|
(cons! a
|
||||||
|
(bitwise-ior
|
||||||
(arithmetic-shift
|
(arithmetic-shift
|
||||||
(bitwise-and hi (vector-ref masks (- 16 s)))
|
(bitwise-and hi (vector-ref masks (- 16 s)))
|
||||||
s)
|
s)
|
||||||
|
@ -146,10 +153,9 @@
|
||||||
s)
|
s)
|
||||||
(bitwise-and (arithmetic-shift hi (- s 16))
|
(bitwise-and (arithmetic-shift hi (- s 16))
|
||||||
(vector-ref masks s)))))])
|
(vector-ref masks s)))))])
|
||||||
(lambda (a s)
|
|
||||||
(cond [(< 0 s 16) (rot (car a) (cdr a) s)]
|
(cond [(< 0 s 16) (rot (car a) (cdr a) s)]
|
||||||
[(< s 32) (rot (cdr a) (car a) (- s 16))]
|
[(< s 32) (rot (cdr a) (car a) (- s 16))]
|
||||||
[else (error "word<<<: shift out of range: " s)]))))
|
[else (error 'word<<< "shift out of range: ~e" s)])))))
|
||||||
|
|
||||||
;; word->bytesl : word -> (list byte byte byte byte), little endian!
|
;; word->bytesl : word -> (list byte byte byte byte), little endian!
|
||||||
(define (word->bytesl w)
|
(define (word->bytesl w)
|
||||||
|
@ -277,23 +283,36 @@
|
||||||
(vector (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)
|
(vector (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)
|
||||||
(cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)
|
(cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)
|
||||||
(cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)))
|
(cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0)))
|
||||||
(let loop ([A (word #x67452301)]
|
(define A (word #:new #:safe #x67452301))
|
||||||
[B (word #xefcdab89)]
|
(define B (word #:new #:safe #xefcdab89))
|
||||||
[C (word #x98badcfe)]
|
(define C (word #:new #:safe #x98badcfe))
|
||||||
[D (word #x10325476)]
|
(define D (word #:new #:safe #x10325476))
|
||||||
[a-port a-port]
|
(define AA (cons 0 0))
|
||||||
[done 0])
|
(define BB (cons 0 0))
|
||||||
|
(define CC (cons 0 0))
|
||||||
|
(define DD (cons 0 0))
|
||||||
|
(define tmp (cons 0 0))
|
||||||
|
(let loop ([a-port a-port] [done 0])
|
||||||
(if (not a-port)
|
(if (not a-port)
|
||||||
(list A B C D)
|
(list A B C D)
|
||||||
(let-values ([(b-port done) (read-block! a-port done X)]
|
(let-values ([(b-port done) (read-block! a-port done X)])
|
||||||
[(AA) A] [(BB) B] [(CC) C] [(DD) D])
|
|
||||||
(define-syntax step
|
(define-syntax step
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(_ a b c d e f g h)
|
[(_ a b c d e f g h)
|
||||||
|
#| This is the `no GC version' (aka C-in-Scheme) of this:
|
||||||
(set! a (word+ b (word<<< (word+ (word+ a (e b c d))
|
(set! a (word+ b (word<<< (word+ (word+ a (e b c d))
|
||||||
(word+ (vector-ref X f)
|
(word+ (vector-ref X f)
|
||||||
(word g)))
|
(word g)))
|
||||||
h)))]))
|
h)))
|
||||||
|
|#
|
||||||
|
(begin (e tmp b c d)
|
||||||
|
(word+=! a tmp)
|
||||||
|
(word+=! a (vector-ref X f))
|
||||||
|
(word+=! a (word g))
|
||||||
|
(word<<<! a h)
|
||||||
|
(word+=! a b))]))
|
||||||
|
;;---
|
||||||
|
(word=! AA A) (word=! BB B) (word=! CC C) (word=! DD D)
|
||||||
;;---
|
;;---
|
||||||
(step A B C D F 0 3614090360 7)
|
(step A B C D F 0 3614090360 7)
|
||||||
(step D A B C F 1 3905402710 12)
|
(step D A B C F 1 3905402710 12)
|
||||||
|
@ -363,8 +382,9 @@
|
||||||
(step C D A B II 2 718787259 15)
|
(step C D A B II 2 718787259 15)
|
||||||
(step B C D A II 9 3951481745 21)
|
(step B C D A II 9 3951481745 21)
|
||||||
;;---
|
;;---
|
||||||
(loop (word+ A AA) (word+ B BB) (word+ C CC) (word+ D DD)
|
(word+=! A AA) (word+=! B BB) (word+=! C CC) (word+=! D DD)
|
||||||
b-port done)))))
|
;;---
|
||||||
|
(loop b-port done)))))
|
||||||
|
|
||||||
;; Each round consists of the application of the following
|
;; Each round consists of the application of the following
|
||||||
;; basic functions. They functions on a word bitwise, as follows.
|
;; basic functions. They functions on a word bitwise, as follows.
|
||||||
|
@ -373,10 +393,43 @@
|
||||||
;; H(X,Y,Z) = X xor Y xor Z
|
;; H(X,Y,Z) = X xor Y xor Z
|
||||||
;; I(X,Y,Z) = Y xor (X v not(Z))
|
;; I(X,Y,Z) = Y xor (X v not(Z))
|
||||||
|
|
||||||
(define (F x y z) (word-or (word-and x y) (word-and (word-not x) z)))
|
#| These functions used to be simple, for example:
|
||||||
(define (G x y z) (word-or (word-and x z) (word-and y (word-not z))))
|
(define (F x y z)
|
||||||
(define (H x y z) (word-xor3 x y z))
|
(word-or (word-and x y) (word-and (word-not x) z)))
|
||||||
(define (II x y z) (word-xor y (word-or x (word-not z))))
|
but we don't want to allocate stuff for each operation, so we add an
|
||||||
|
output pair for each of these functions (the `t' argument). However, this
|
||||||
|
means that if we want to avoid consing, we need either a few such
|
||||||
|
pre-allocated `register' values... The solution is to use a macro that
|
||||||
|
will perform an operation on the cars, cdrs, and set the result into the
|
||||||
|
target pair. Works only because these operations are symmetrical in their
|
||||||
|
use of the two halves.
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
(define-syntax cons-op!
|
||||||
|
(syntax-rules ()
|
||||||
|
[(cons-op! t (x ...) body)
|
||||||
|
(cons! t (let ([x (car x)] ...) body) (let ([x (cdr x)] ...) body))]))
|
||||||
|
|
||||||
|
(define (F t x y z)
|
||||||
|
(cons-op! t (x y z)
|
||||||
|
(bitwise-and (bitwise-ior (bitwise-and x y)
|
||||||
|
(bitwise-and (bitwise-not x) z))
|
||||||
|
65535)))
|
||||||
|
|
||||||
|
(define (G t x y z)
|
||||||
|
(cons-op! t (x y z)
|
||||||
|
(bitwise-and (bitwise-ior (bitwise-and x z)
|
||||||
|
(bitwise-and y (bitwise-not z)))
|
||||||
|
65535)))
|
||||||
|
|
||||||
|
(define (H t x y z)
|
||||||
|
(cons-op! t (x y z) (bitwise-xor x y z)))
|
||||||
|
|
||||||
|
(define (II t x y z)
|
||||||
|
(cons-op! t (x y z)
|
||||||
|
(bitwise-and (bitwise-xor y (bitwise-ior x (bitwise-not z)))
|
||||||
|
65535)))
|
||||||
|
|
||||||
;; Step 5 - Output
|
;; Step 5 - Output
|
||||||
;; To finish up, we convert the word to hexadecimal string
|
;; To finish up, we convert the word to hexadecimal string
|
||||||
|
|
Loading…
Reference in New Issue
Block a user