(module gl-vectors mzscheme (require mzlib/foreign (only racket/base for/list in-list in-naturals) "gl-types.rkt") (define-syntax gl-vector-binop (syntax-rules () ((_ op name make-res) (case-lambda ((v) (unless (gl-vector? v) (raise-argument-error name "gl-vector?" v)) (let* ((l (cvector-length v)) (res (make-res l))) (let loop ((i 0)) (when (< i l) (cvector-set! res i (op (cvector-ref v i))) (loop (add1 i))) res))) ((v1 v2) (unless (gl-vector? v1) (raise-argument-error name "gl-vector?" 0 v1 v2)) (unless (gl-vector? v2) (raise-argument-error name "gl-vector?" 1 v1 v2)) (unless (= (cvector-length v1) (cvector-length v2)) (raise-arguments-error name "given gl-vector arguments of unequal lengths" "first argument length" (cvector-length v1) "second argument length" (cvector-length v2))) (let* ((l (cvector-length v1)) (t (cvector-type v1)) (res (make-res l))) (let loop ((i 0)) (when (< i l) (cvector-set! res i (op (cvector-ref v1 i) (cvector-ref v2 i))) (loop (add1 i)))) res)) ((v . vs) (let ((all-v (cons v vs))) (unless (andmap gl-vector? all-v) (let loop ((i 0) (to-check all-v)) (unless (null? to-check) (unless (gl-vector? (car to-check)) (apply raise-argument-error (list* name "gl-vector?" i all-v))) (loop (add1 i) (cdr to-check))))) (let ((l (cvector-length v))) (unless (andmap (lambda (x) (= l (cvector-length x))) vs) (apply raise-arguments-error name "given gl-vector arguments of unequal lengths" (apply append (for/list ([v (in-list all-v)] [i (in-naturals 1)]) (list (format "argument ~a" i) v))))) (let ((res (make-res l))) (let loop ((i 0)) (when (< i l) (cvector-set! res i (apply op (map (lambda (x) (cvector-ref x i)) all-v))) (loop (add1 i)))) res)))))))) (define-for-syntax (d->so stx str) (datum->syntax-object stx (string->symbol str))) (define-syntax (define-gl-vector stx) (syntax-case stx () ((_ type) (let ((t (syntax-object->datum #'type))) (with-syntax (((v? make-v v vector->v list->v v+ v- v*) (map (lambda (fmt) (d->so #'type (format fmt t))) '("gl-~a-vector?" "make-gl-~a-vector" "gl-~a-vector" "vector->gl-~a-vector" "list->gl-~a-vector" "gl-~a-vector+" "gl-~a-vector-" "gl-~a-vector*"))) (gl-type (d->so #'type (format "_gl-~a" t))) (gl-vtype (d->so #'type (format "_gl-~av" t)))) #'(begin (provide v? make-v v vector->v list->v v+ v- v*) (define (v? v) (and (cvector? v) (eq? (cvector-type v) gl-type))) (define (make-v len) (make-cvector gl-type len)) (define (v . args) (apply cvector (cons gl-type args))) (define (vector->v v) (unless (vector? v) (raise-argument-error 'vector->v "vector?" v)) (list->cvector (vector->list v) gl-type)) (define (list->v l) (list->cvector l gl-type)) (define v+ (gl-vector-binop + 'v+ make-v)) (define v- (gl-vector-binop - 'v- make-v)) (define (v* n v) (unless (real? n) (raise-argument-error 'gl-vector* "real?" 0 n v)) (unless (gl-vector? v) (raise-argument-error 'gl-vector* "gl-vector?" 1 n v)) (let* ((l (cvector-length v)) (t (cvector-type v)) (res (make-v l))) (let loop ((i 0)) (when (< i l) (cvector-set! res i (* n (cvector-ref v i))) (loop (add1 i)))) res)))))))) (define-syntax define-gl-vectors (syntax-rules () ((_ type) (define-gl-vector type)) ((_ type rest ...) (begin (define-gl-vector type) (define-gl-vectors rest ...))))) (define-gl-vectors byte ubyte short ushort int uint float double boolean) (provide gl-vector->vector gl-vector->list gl-vector-length gl-vector-ref gl-vector-set! gl-vector? gl-vector-norm) (define (gl-vector->vector v) (list->vector (cvector->list v))) (define gl-vector->list cvector->list) (define gl-vector-length cvector-length) (define gl-vector-ref cvector-ref) (define gl-vector-set! cvector-set!) (define gl-vector? cvector?) (define (gl-vector-norm v) (unless (gl-vector? v) (raise-argument-error 'gl-vector-norm "gl-vector?" v)) (let ((l (gl-vector-length v))) (let loop ((i 0) (res 0)) (cond ((< i l) (loop (add1 i) (+ (expt (gl-vector-ref v i) 2) res))) (else (sqrt res)))))) )