From 03aa7ea2e61b419d38c6ca8de75ee34e5b55d28a Mon Sep 17 00:00:00 2001
From: Daniel Llorens <daniel.llorens@bluewin.ch>
Date: Wed, 3 Apr 2013 16:19:17 +0200
Subject: [PATCH 5/5] Remove double indirection in array-fill!

* libguile/array-map.c, libguile/array-map.c: deprecate scm_array_fill_int.
* libguile/array-map.c: new function rafill, like scm_array_fill_int, but
  factors GVSET out of loop. Use this in scm_array_fill_x instead of
  scm_array_fill_int.
* test-suite/tests/arrays.test: test array-fill! with noncompact array.
* doc/guile-api.alist: unlist scm_array_fill_int.
---
 doc/guile-api.alist          |    1 -
 libguile/array-map.c         |   57 ++++++++++++++++++++++++++----------------
 libguile/array-map.h         |    2 +-
 test-suite/tests/arrays.test |   10 +++++++-
 4 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/doc/guile-api.alist b/doc/guile-api.alist
index 5830c91..78d3a5c 100644
--- a/doc/guile-api.alist
+++ b/doc/guile-api.alist
@@ -1359,7 +1359,6 @@
 (scm_array_copy_x (groups scm C) (scan-data T))
 (scm_array_dimensions (groups scm C) (scan-data T))
 (scm_array_equal_p (groups scm C) (scan-data T))
-(scm_array_fill_int (groups scm C) (scan-data T))
 (scm_array_fill_x (groups scm C) (scan-data T))
 (scm_array_for_each (groups scm C) (scan-data T))
 (scm_array_identity (groups scm C) (scan-data T))
diff --git a/libguile/array-map.c b/libguile/array-map.c
index b5b8cec..517c9cb 100644
--- a/libguile/array-map.c
+++ b/libguile/array-map.c
@@ -318,6 +318,23 @@ scm_ramapc (void *cproc_ptr, SCM data, SCM ra0, SCM lra, const char *what)
     }
 }
 
+static int
+rafill (SCM dst, SCM fill)
+{
+  long n = (SCM_I_ARRAY_DIMS (dst)->ubnd - SCM_I_ARRAY_DIMS (dst)->lbnd + 1);
+  scm_t_array_handle h;
+  size_t i;
+  ssize_t inc;
+  scm_generalized_vector_get_handle (SCM_I_ARRAY_V (dst), &h);
+  i = h.base + h.dims[0].lbnd + SCM_I_ARRAY_BASE (dst)*h.dims[0].inc;
+  inc = SCM_I_ARRAY_DIMS (dst)->inc * h.dims[0].inc;
+
+  for (; n-- > 0; i += inc)
+    h.impl->vset (&h, i, fill);
+
+  scm_array_handle_release (&h);
+  return 1;
+}
 
 SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
 	    (SCM ra, SCM fill),
@@ -325,31 +342,11 @@ SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
 	    "returned is unspecified.")
 #define FUNC_NAME s_scm_array_fill_x
 {
-  scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
+  scm_ramapc (rafill, fill, ra, SCM_EOL, FUNC_NAME);
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
-/* to be used as cproc in scm_ramapc to fill an array dimension with
-   "fill". */
-int 
-scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
-#define FUNC_NAME s_scm_array_fill_x
-{
-  unsigned long i;
-  unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
-  long inc = SCM_I_ARRAY_DIMS (ra)->inc;
-  unsigned long base = SCM_I_ARRAY_BASE (ra);
-
-  ra = SCM_I_ARRAY_V (ra);
-
-  for (i = base; n--; i += inc)
-    GVSET (ra, i, fill);
-
-  return 1;
-}
-#undef FUNC_NAME
-
 
 static int
 racp (SCM src, SCM dst)
@@ -398,6 +395,24 @@ SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
 
 #if SCM_ENABLE_DEPRECATED == 1
 
+/* to be used as cproc in scm_ramapc to fill an array dimension with
+   "fill". */
+int
+scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
+{
+  unsigned long i;
+  unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
+  long inc = SCM_I_ARRAY_DIMS (ra)->inc;
+  unsigned long base = SCM_I_ARRAY_BASE (ra);
+
+  ra = SCM_I_ARRAY_V (ra);
+
+  for (i = base; n--; i += inc)
+    GVSET (ra, i, fill);
+
+  return 1;
+}
+
 int
 scm_ra_eqp (SCM ra0, SCM ras)
 {
diff --git a/libguile/array-map.h b/libguile/array-map.h
index 9785666..c328d8d 100644
--- a/libguile/array-map.h
+++ b/libguile/array-map.h
@@ -31,7 +31,7 @@
 SCM_API int scm_ra_matchp (SCM ra0, SCM ras);
 SCM_API int scm_ramapc (void *cproc, SCM data, SCM ra0, SCM lra,
 			const char *what);
-SCM_API int scm_array_fill_int (SCM ra, SCM fill, SCM ignore);
+SCM_DEPRECATED int scm_array_fill_int (SCM ra, SCM fill, SCM ignore);
 SCM_API SCM scm_array_fill_x (SCM ra, SCM fill);
 SCM_API SCM scm_array_copy_x (SCM src, SCM dst);
 SCM_DEPRECATED int scm_ra_eqp (SCM ra0, SCM ras);
diff --git a/test-suite/tests/arrays.test b/test-suite/tests/arrays.test
index d88a1cb..0791783 100644
--- a/test-suite/tests/arrays.test
+++ b/test-suite/tests/arrays.test
@@ -291,7 +291,15 @@
       (pass-if "0"      (array-fill! a 0)      #t)
       (pass-if "123"    (array-fill! a 123)    #t)
       (pass-if "-123"   (array-fill! a -123)   #t)
-      (pass-if "5/8"    (array-fill! a 5/8)    #t))))
+      (pass-if "5/8"    (array-fill! a 5/8)    #t)))
+
+  (with-test-prefix "noncompact"
+    (let* ((a (make-array 0 3 3))
+           (b (make-shared-array a (lambda (i) (list i i)) 3)))
+      (array-fill! b 9)
+      (pass-if
+        (and (equal? b #(9 9 9))
+             (equal? a #2((9 0 0) (0 9 0) (0 0 9))))))))
 
 ;;;
 ;;; array-in-bounds?
-- 
1.7.9.5

