ashinn / chibi-scheme

Official chibi-scheme repository
Other
1.2k stars 142 forks source link

SRFI 231: no array-fold-{left|right} #973

Closed gambiteer closed 2 months ago

gambiteer commented 2 months ago

Perhaps unfortunately, array-fold-left and array-fold-right in SRFI 231 differ from array-foldl and array-foldr in SRFI 179. So SRFI 231 as no conforming implementations of array-fold-left and array-fold-right.

Right now I don't know how to proceed with this.

Brad

ashinn commented 2 months ago

Sorry, what's the difference apart from supporting zero-dimensional arrays?

gambiteer commented 2 months ago

I started by reviewing the document, but you can do that as well as I.

Here's an implementation that does no error checking and which, for the sake of speed, should be specialized for a single array argument. My tests pass with this.

heine:~/programs/chibi-scheme> git diff
diff --git a/lib/srfi/231.sld b/lib/srfi/231.sld
index fbb1101c..d54ba006 100644
--- a/lib/srfi/231.sld
+++ b/lib/srfi/231.sld
@@ -45,8 +45,8 @@
    array-safe? array-packed? specialized-array-share
    array-copy array-curry array-extract array-tile array-translate
    array-permute array-reverse array-sample
-   array-outer-product array-map array-for-each array-foldl
-   array-foldr array-reduce array-any array-every
+   array-outer-product array-map array-for-each array-foldl array-fold-left
+   array-foldr array-fold-right array-reduce array-any array-every
    array-inner-product array-stack array-append array-block
    array->list list->array array->vector vector->array
    array->list* list*->array array->vector* vector*->array
diff --git a/lib/srfi/231/transforms.scm b/lib/srfi/231/transforms.scm
index 4903f990..e3efbb64 100644
--- a/lib/srfi/231/transforms.scm
+++ b/lib/srfi/231/transforms.scm
@@ -388,6 +388,22 @@
 (define (array-foldr kons knil array)
   (fold-right kons knil (array->list array)))

+
+(define (array-fold-left operator identity array . arrays)
+  (interval-fold-left (array-getter (apply array-map list array arrays))
+                      (lambda (accumulator array-elements)
+                        (apply operator accumulator array-elements))
+                      identity
+                      (array-domain array)))
+
+(define (array-fold-right operator identity array . arrays)
+  (interval-fold-right (array-getter (apply array-map list array arrays))
+                       (lambda (array-elements accumulator)
+                         (apply operator (append array-elements (list accumulator))))
+                       identity
+                       (array-domain array)))
+
+
gambiteer commented 2 months ago

After this addition and your fix to array-append, I had the test program run 10,000 iterations with random data per test:

     ..........................................................................
     ............................
    50052 out of 50052 (100.0%) tests passed in 617.9135191440582 seconds.
764639 out of 764639 (100.0%) tests passed in 2816.5676140785217 seconds.
36 out of 36 (100.0%) subgroups passed.

I'm not saying I've tested everything, but this is pretty good!

gambiteer commented 2 months ago

Array-fold-left has the accumulated value as the left argument of the operator, array-foldl has the accumulated value as the right argument.