array-helpers.scm 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 variable number of arguments,
  123. depending on how many dimensions the array has (what its
  124. rank is). However, apply works with lists as last arguments,
  125. not with vectors. To avoid having to convert vectors of
  126. indices to lists of indices every time such a vector of
  127. indices is used with an array, array-cell-ref-vec can be
  128. used."
  129. (let ([vec-len (vector-length indices-vec)])
  130. (let iter ([index-into-indices-vec° 0] [result arr])
  131. (cond
  132. [(< index-into-indices-vec° vec-len)
  133. (let ([cell-index (vector-ref indices-vec index-into-indices-vec°)])
  134. (iter (+ index-into-indices-vec° 1)
  135. (array-cell-ref result cell-index)))]
  136. [else result])))))
  137. (define array-index-of
  138. (lambda* (arr pred #:optional (start-indices #f))
  139. "Return the index of the first element in ARR which
  140. satisfies the predicate PRED."
  141. (let* ([shape (array-shape arr)]
  142. [shape-vec (list->vector shape)]
  143. [rank (array-rank arr)]
  144. [initial-indices
  145. (if start-indices
  146. start-indices
  147. (vector-map (λ (_i elem) (car elem)) shape-vec))])
  148. (let iter ([indices° initial-indices])
  149. (cond
  150. [indices°
  151. (cond
  152. ;; If the array element satisfies the
  153. ;; predicate, return the indices of the
  154. ;; element.
  155. [(pred (array-cell-ref-vec arr indices°))
  156. indices°]
  157. [else
  158. ;; Potential optimization: Make better use of
  159. ;; the rank argument, so that array-next-index
  160. ;; does not have to search unnecessarily for
  161. ;; the index to increment.
  162. (iter (array-next-index shape-vec indices° (- rank 1)))])]
  163. ;; No index found at which the predicate would be
  164. ;; satisfied.
  165. [else #f])))))
  166. (define array-indices-of
  167. (λ (arr pred)
  168. (let* ([shape (array-shape arr)]
  169. [shape-vec (list->vector shape)]
  170. [rank (array-rank arr)]
  171. [initial-indices (vector-map (λ (_i elem) (car elem)) shape-vec)])
  172. (let iter ([indices° initial-indices])
  173. (cond
  174. [indices°
  175. (cond
  176. [(pred (array-cell-ref-vec arr indices°))
  177. (cons indices°
  178. (iter (array-next-index shape-vec indices° (- rank 1))))]
  179. [else (iter (array-next-index shape-vec indices° (- rank 1)))])]
  180. [else '()]))))))