;; ;; ;; A collection of utility functions for manipulating SRFI-4 vectors. ;; ;; ;; Copyright 2007-2012 Ivan Raikov and the Okinawa Institute of Science and Technology. ;; ;; ;; This program is free software: you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; A full copy of the GPL license can be found at ;; . ;; ;; (module srfi-4-utils (f64vector-fold f32vector-fold s32vector-fold u32vector-fold s16vector-fold u16vector-fold s8vector-fold u8vector-fold f64vector-map f32vector-map s32vector-map u32vector-map s16vector-map u16vector-map s8vector-map u8vector-map f64vector-foldi f32vector-foldi s32vector-foldi u32vector-foldi s16vector-foldi u16vector-foldi s8vector-foldi u8vector-foldi f64vector-mapi f32vector-mapi s32vector-mapi u32vector-mapi s16vector-mapi u16vector-mapi s8vector-mapi u8vector-mapi f64vector-quick-sort! f32vector-quick-sort! s32vector-quick-sort! u32vector-quick-sort! s16vector-quick-sort! u16vector-quick-sort! s8vector-quick-sort! u8vector-quick-sort! f64vector-repmat f64vector-meshgrid) (import scheme chicken foreign) (require-library srfi-1) (import (only srfi-1 fold every)) (require-extension srfi-4 srfi-42 srfi-4-comprehensions) (define (make-vector-fold vector-length vector-ref) (lambda (f x0 v . rest) (let ((n (vector-length v)) (vs (cons v rest))) (fold-ec x0 (:range i 0 n) (map (lambda (v) (vector-ref v i)) vs) (lambda (x ax) (apply f (append x (list ax)))))))) (define f64vector-fold (make-vector-fold f64vector-length f64vector-ref)) (define f32vector-fold (make-vector-fold f32vector-length f32vector-ref)) (define s32vector-fold (make-vector-fold s32vector-length s32vector-ref)) (define u32vector-fold (make-vector-fold u32vector-length u32vector-ref)) (define s16vector-fold (make-vector-fold s16vector-length s16vector-ref)) (define u16vector-fold (make-vector-fold u16vector-length u16vector-ref)) (define s8vector-fold (make-vector-fold s8vector-length s8vector-ref)) (define u8vector-fold (make-vector-fold u8vector-length u8vector-ref)) (define (make-vector-foldi vector-length vector-ref) (lambda (f x0 v . rest) (let ((n (vector-length v)) (vs (cons v rest))) (fold-ec x0 (:range i 0 n) (cons i (map (lambda (v) (vector-ref v i)) vs)) (lambda (x ax) (apply f (append x (list ax)))))))) (define f64vector-foldi (make-vector-foldi f64vector-length f64vector-ref)) (define f32vector-foldi (make-vector-foldi f32vector-length f32vector-ref)) (define s32vector-foldi (make-vector-foldi s32vector-length s32vector-ref)) (define u32vector-foldi (make-vector-foldi u32vector-length u32vector-ref)) (define s16vector-foldi (make-vector-foldi s16vector-length s16vector-ref)) (define u16vector-foldi (make-vector-foldi u16vector-length u16vector-ref)) (define s8vector-foldi (make-vector-foldi s8vector-length s8vector-ref)) (define u8vector-foldi (make-vector-foldi u8vector-length u8vector-ref)) (define (f64vector-map f v . rest) (let ((n (f64vector-length v))) (f64vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (f64vector-ref v i)) (cons v rest)))))) (define (f32vector-map f v . rest) (let ((n (f32vector-length v))) (f32vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (f32vector-ref v i)) (cons v rest)))))) (define (s32vector-map f v . rest) (let ((n (s32vector-length v))) (s32vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (s32vector-ref v i)) (cons v rest)))))) (define (u32vector-map f v . rest) (let ((n (u32vector-length v))) (u32vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (u32vector-ref v i)) (cons v rest)))))) (define (s16vector-map f v . rest) (let ((n (s16vector-length v))) (s16vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (s16vector-ref v i)) (cons v rest)))))) (define (u16vector-map f v . rest) (let ((n (u16vector-length v))) (u16vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (u16vector-ref v i)) (cons v rest)))))) (define (s8vector-map f v . rest) (let ((n (s8vector-length v))) (s8vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (s8vector-ref v i)) (cons v rest)))))) (define (u8vector-map f v . rest) (let ((n (u8vector-length v))) (u8vector-of-length-ec n (:range i 0 n) (apply f (map (lambda (v) (u8vector-ref v i)) (cons v rest)))))) (define (f64vector-mapi f v . rest) (let ((n (f64vector-length v))) (f64vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (f64vector-ref v i)) (cons v rest))))))) (define (f32vector-mapi f v . rest) (let ((n (f32vector-length v))) (f32vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (f32vector-ref v i)) (cons v rest))))))) (define (s32vector-mapi f v . rest) (let ((n (s32vector-length v))) (s32vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (s32vector-ref v i)) (cons v rest))))))) (define (u32vector-mapi f v . rest) (let ((n (u32vector-length v))) (u32vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (u32vector-ref v i)) (cons v rest))))))) (define (s16vector-mapi f v . rest) (let ((n (s16vector-length v))) (s16vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (s16vector-ref v i)) (cons v rest))))))) (define (u16vector-mapi f v . rest) (let ((n (u16vector-length v))) (u16vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (u16vector-ref v i)) (cons v rest))))))) (define (s8vector-mapi f v . rest) (let ((n (s8vector-length v))) (s8vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (s8vector-ref v i)) (cons v rest))))))) (define (u8vector-mapi f v . rest) (let ((n (u8vector-length v))) (u8vector-of-length-ec n (:range i 0 n) (apply f (cons i (map (lambda (v) (u8vector-ref v i)) (cons v rest))))))) ;; ;; In-place quick sort from SRFI-32 reference implementation. ;; Modified so that the comparison function uses element indices as ;; well as element values: ;; ;; elt< :: i1 v1 i2 v2 -> boolean ;; ;; Copyright (c) 1998 by Olin Shivers. You may do as you please with ;; this code, as long as you do not delete this notice or hold me ;; responsible for any outcome related to its use. ;; (define (srfi-4-vector-quick-sort! vector-ref vector-set! vector-length) (lambda (v elt< . rest) (let-optionals rest ((start 0) (end (vector-length v))) (let recur ((l start) (r end)) ; Sort the range [l,r). (if (fx< 1 (fx- r l)) ;; Choose the median of V[l], V[r], and V[middle] for the pivot. (let ((median (lambda (i1 i2 i3) (let ((v1 (vector-ref v i1)) (v2 (vector-ref v i2)) (v3 (vector-ref v i3))) (receive (ilittle little ibig big) (if (elt< i1 v1 i2 v2) (values i1 v1 i2 v2) (values i2 v2 i1 v1)) (if (elt< ibig big i3 v3) (values ibig big) (if (elt< ilittle little i3 v3) (values i3 v3) (values ilittle little)))))))) (let-values (((ipivot pivot) (median l (quotient (fx+ l r) 2) (fx- r 1)))) (let loop ((i l) (j (fx- r 1))) (let ((i (let scan ((i i)) (if (elt< i (vector-ref v i) ipivot pivot) (scan (fx+ i 1)) i))) (j (let scan ((j j)) (if (elt< ipivot pivot j (vector-ref v j)) (scan (fx- j 1)) j)))) (if (fx< i j) (let ((tmp (vector-ref v j))) (vector-set! v j (vector-ref v i)) ; Swap V[I] (vector-set! v i tmp) ; and V[J]. (loop (fx+ i 1) (fx- j 1))) (begin (recur l i) (recur (fx+ j 1) r))))))) v))))) (define f64vector-quick-sort! (srfi-4-vector-quick-sort! f64vector-ref f64vector-set! f64vector-length)) (define f32vector-quick-sort! (srfi-4-vector-quick-sort! f32vector-ref f32vector-set! f32vector-length)) (define s32vector-quick-sort! (srfi-4-vector-quick-sort! s32vector-ref s32vector-set! s32vector-length)) (define u32vector-quick-sort! (srfi-4-vector-quick-sort! u32vector-ref u32vector-set! u32vector-length)) (define s16vector-quick-sort! (srfi-4-vector-quick-sort! s16vector-ref s16vector-set! s16vector-length)) (define u16vector-quick-sort! (srfi-4-vector-quick-sort! u16vector-ref u16vector-set! u16vector-length)) (define s8vector-quick-sort! (srfi-4-vector-quick-sort! s8vector-ref s8vector-set! s8vector-length)) (define u8vector-quick-sort! (srfi-4-vector-quick-sort! u8vector-ref u8vector-set! u8vector-length)) #> /* repeat a block of memory rep times */ void cmemrep(double *dest, size_t chunk, int rep) { if(rep == 1) return; memcpy(dest + chunk, dest, sizeof(double)*chunk); if(rep & 1) { dest += chunk; memcpy(dest + chunk, dest, sizeof(double)*chunk); } /* now repeat using a block twice as big */ cmemrep(dest, chunk<<1, rep>>1); } void crepmat(double *dest, const double *src, int ndim, int *destdimsize, int *dimsize, const int *dims, int *rep) { int i, chunk; int d = ndim-1; /* copy the first repetition into dest */ if(d == 0) { chunk = dimsize[0]; memcpy(dest,src,sizeof(double)*chunk); } else { /* recursively repeat each slice of src */ for(i=0; is32vector dims))) (assert (every positive? reps)) ;; compute dimension sizes (s32vector-set! dimsize 0 (car dims)) (let recur ((i 1) (dims (cdr dims))) (if (< i ndim) (begin (s32vector-set! dimsize i (* (car dims) (s32vector-ref dimsize (- i 1)))) (recur (+ 1 i) (cdr dims))) )) ;; determine repetition vector (let* ((nrep (length reps)) (ndimdest (if (> nrep ndim) nrep ndim)) (rep (make-s32vector ndimdest))) (let recur ((i 0) (reps reps)) (if (< i nrep) (let ((repv (car reps))) (s32vector-set! rep i repv) (recur (+ 1 i) (cdr reps))))) ;; compute output size (let ((destdims (make-s32vector ndimdest 0))) (let recur ((i 0)) (if (< i ndim) (begin (s32vector-set! destdims i (* (s32vector-ref vdims i) (s32vector-ref rep i ))) (recur (+ 1 i))))) (let ((extrarep (let recur ((i ndim) (extrarep 1)) (if (< i ndimdest) (let ((ri (s32vector-ref rep i))) (s32vector-set! destdims i ri) (recur (+ 1 i) (* extrarep ri))) extrarep )))) (let ((destdimsize (make-s32vector ndimdest))) (s32vector-set! destdimsize 0 (s32vector-ref destdims 0)) (let recur ((i 1)) (if (< i ndimdest) (begin (s32vector-set! destdimsize i (* (s32vector-ref destdimsize (- i 1)) (s32vector-ref destdims i))) (recur (+ 1 i))))) ;; return array (let* ((destlen (s32vector-ref destdimsize (- ndimdest 1))) (dest (make-f64vector destlen))) #| (print "destlen = " destlen) (print "dimsize = " dimsize) (print "destdimsize = " destdimsize) (print "rep = " rep) |# (crepmat dest src ndim destdimsize dimsize vdims rep) (if (> ndimdest ndim) (let ((n (s32vector-ref destdimsize (- ndim 1)))) ; (print "extrarep = " extrarep) ; (print "n = " n) (cmemrep dest n extrarep))) dest )) )) ))) (define (f64vector-meshgrid x y z) (let ((lenx (f64vector-length x)) (leny (f64vector-length y)) (lenz (f64vector-length z))) (let ((dimx (list 1 lenx)) (dimy (list 1 leny)) (dimz (list 1 lenz))) (let ((xx (f64vector-repmat (f64vector-repmat x dimx (list leny 1)) (list leny lenx) (list 1 1 lenz))) (yy (f64vector-repmat (f64vector-repmat y dimy (list 1 lenx)) (list lenx leny) (list 1 1 lenz))) (zz (f64vector-repmat z dimz (list (* lenx leny) 1)))) (list xx yy zz)) ))) )