array-helpers.scm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. (library (array-helpers)
  2. (export array-len-in-dim
  3. arrays->hash-table
  4. array-display
  5. array-map
  6. array-next-index
  7. array-cell-ref-vec
  8. array-index-of
  9. array-indices-of)
  10. (import
  11. (except (rnrs base)
  12. let-values
  13. map
  14. error
  15. vector-map)
  16. (only (guile)
  17. lambda* λ
  18. current-output-port
  19. ;; arrays
  20. array-shape
  21. array-ref
  22. array-cell-ref
  23. array-map!
  24. array-rank
  25. ;; display
  26. display
  27. simple-format
  28. current-output-port)
  29. ;; lists
  30. (srfi srfi-1)
  31. ;; vectors
  32. (srfi srfi-43)
  33. ;; hash tables
  34. (srfi srfi-69)
  35. (ice-9 arrays))
  36. (define array-len-in-dim
  37. (λ (arr dim)
  38. (let* ([shape (array-shape arr)]
  39. [dim-min-max (list-ref shape dim)])
  40. (+ (- (second dim-min-max)
  41. (first dim-min-max))
  42. 1))))
  43. (define arrays->hash-table
  44. (lambda* (keys-arr vals-arrs #:optional (equal-func equal?))
  45. (let ([rows (array-len-in-dim keys-arr 0)]
  46. [cols (array-len-in-dim keys-arr 1)]
  47. [table (make-hash-table equal-func)])
  48. (let iter-rows ([row-ind 0])
  49. (let iter-cols ([col-ind 0])
  50. (cond
  51. [(< row-ind rows)
  52. (cond
  53. [(< col-ind cols)
  54. (hash-table-set! table
  55. (array-ref keys-arr row-ind col-ind)
  56. (array-ref vals-arrs row-ind col-ind))
  57. (iter-cols (+ col-ind 1))]
  58. [else (iter-rows (+ row-ind 1))])]
  59. [else table]))))))
  60. (define array-display
  61. (lambda* (landscape
  62. #:optional (port (current-output-port))
  63. #:key (formatter (λ (elem) elem)))
  64. (let ([rows (array-len-in-dim landscape 0)]
  65. [cols (array-len-in-dim landscape 1)])
  66. (let iter-rows ([row-ind 0])
  67. (let iter-cols ([col-ind 0])
  68. (cond
  69. [(>= row-ind rows) 'done]
  70. [(>= col-ind cols)
  71. (display "\n" (current-output-port))
  72. (iter-rows (+ row-ind 1))]
  73. [else
  74. (display (formatter (array-cell-ref landscape row-ind col-ind)) port)
  75. (iter-cols (+ col-ind 1))]))))))
  76. (define array-map
  77. (λ (proc src-arr)
  78. (define target-arr (array-copy src-arr))
  79. (array-map! target-arr proc src-arr)
  80. target-arr))
  81. (define array-next-index
  82. (λ (shape-vec indices-vec max-dim)
  83. "Increment one of indices in INDICES-VEC for which the
  84. following conditions are true:
  85. 1. There is no index in INDICES-VEC that sits at a later
  86. position (higher index) than MAX-DIM of INDICES-VEC and is
  87. not yet at its maximum. The maximum is specified by the
  88. SHAPE-VEC. Each index in INDICES-VEC has a corresponding
  89. minimum and maximum in SHAPE-VEC at the same position.
  90. After incrementing the index in INDICES-VEC, all later
  91. indices (at a higher index of INDICES-VEC) are set to their
  92. corresponding minimum to get a correct indices vector."
  93. (cond
  94. [(>= max-dim 0)
  95. (let ([index (vector-ref indices-vec max-dim)]
  96. [max-for-index (second (vector-ref shape-vec max-dim))])
  97. (cond
  98. [(< index max-for-index)
  99. ;; Copy the vector to not mutate argument.
  100. (let ([updated-indices-vec (vector-copy indices-vec)])
  101. ;; Increase index at position.
  102. (vector-set! updated-indices-vec
  103. max-dim
  104. (+ (vector-ref updated-indices-vec max-dim) 1))
  105. ;; Set later indices to their corresponding minimum.
  106. (let ([indices-vec-len (vector-length indices-vec)])
  107. (let iter ([dim° (+ max-dim 1)])
  108. (cond
  109. [(< dim° indices-vec-len)
  110. (let ([minimum-ind-val (first (vector-ref shape-vec dim°))])
  111. (vector-set! updated-indices-vec dim° minimum-ind-val)
  112. (iter (+ dim° 1)))]
  113. [else updated-indices-vec]))))]
  114. [else
  115. ;; Increment next higher dimension.
  116. (array-next-index shape-vec
  117. indices-vec
  118. (- max-dim 1))]))]
  119. [else #f])))
  120. (define array-cell-ref-vec
  121. (λ (arr indices-vec)
  122. "array-cell-ref takes a vector of indices INDICES-VEC, whose
  123. length depends on how many dimensions the array ARR
  124. has (what its rank is)."
  125. (let ([vec-len (vector-length indices-vec)])
  126. (let iter ([index-into-indices-vec° 0] [result arr])
  127. (cond
  128. [(< index-into-indices-vec° vec-len)
  129. (let ([cell-index (vector-ref indices-vec index-into-indices-vec°)])
  130. (iter (+ index-into-indices-vec° 1)
  131. (array-cell-ref result cell-index)))]
  132. [else result])))))
  133. (define array-index-of
  134. (lambda* (arr pred #:optional (start-indices #f))
  135. "Return the index of the first element in ARR which
  136. satisfies the predicate PRED."
  137. (let* ([shape (array-shape arr)]
  138. [shape-vec (list->vector shape)]
  139. [rank (array-rank arr)]
  140. [initial-indices
  141. (if start-indices
  142. start-indices
  143. (vector-map (λ (_i elem) (car elem)) shape-vec))])
  144. (let iter ([indices° initial-indices])
  145. (cond
  146. [indices°
  147. (cond
  148. ;; If the array element satisfies the
  149. ;; predicate, return the indices of the
  150. ;; element.
  151. [(pred (array-cell-ref-vec arr indices°))
  152. indices°]
  153. [else
  154. ;; Potential optimization: Make better use of
  155. ;; the rank argument, so that array-next-index
  156. ;; does not have to search unnecessarily for
  157. ;; the index to increment.
  158. (iter (array-next-index shape-vec indices° (- rank 1)))])]
  159. ;; No index found at which the predicate would be
  160. ;; satisfied.
  161. [else #f])))))
  162. (define array-indices-of
  163. (λ (arr pred)
  164. "Return a list of vectors of indices into the given array ARR which
  165. satisfy the given predicate PRED, for an array of arbitrary rank."
  166. (let* ([shape (array-shape arr)]
  167. [shape-vec (list->vector shape)]
  168. [rank (array-rank arr)]
  169. [initial-indices (vector-map (λ (_i elem) (car elem)) shape-vec)])
  170. (let iter ([indices° initial-indices])
  171. (cond
  172. [indices°
  173. (cond
  174. [(pred (array-cell-ref-vec arr indices°))
  175. (cons indices°
  176. (iter (array-next-index shape-vec indices° (- rank 1))))]
  177. [else (iter (array-next-index shape-vec indices° (- rank 1)))])]
  178. [else '()]))))))