array-map.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. /* Copyright (C) 1996, 1998, 2000, 2001, 2004, 2005, 2006, 2008, 2009,
  2. * 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public License
  6. * as published by the Free Software Foundation; either version 3 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301 USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22. #include "libguile/_scm.h"
  23. #include "libguile/strings.h"
  24. #include "libguile/arrays.h"
  25. #include "libguile/smob.h"
  26. #include "libguile/chars.h"
  27. #include "libguile/eq.h"
  28. #include "libguile/eval.h"
  29. #include "libguile/feature.h"
  30. #include "libguile/root.h"
  31. #include "libguile/vectors.h"
  32. #include "libguile/bitvectors.h"
  33. #include "libguile/srfi-4.h"
  34. #include "libguile/generalized-arrays.h"
  35. #include "libguile/validate.h"
  36. #include "libguile/array-map.h"
  37. /* The WHAT argument for `scm_gc_malloc ()' et al. */
  38. static const char vi_gc_hint[] = "array-indices";
  39. /* This is only every used wit v = SCM_I_ARRAY_V () or with the vra from
  40. scm_ramapc, where lbnd is always 0. */
  41. static SCM
  42. AREF (SCM v, size_t pos)
  43. {
  44. scm_t_array_handle h;
  45. SCM ret;
  46. scm_array_get_handle (v, &h);
  47. ret = h.impl->vref (h.root, h.base + pos * h.dims[0].inc);
  48. scm_array_handle_release (&h);
  49. return ret;
  50. }
  51. /* This is only ever used with v = SCM_I_ARRAY_V () */
  52. static void
  53. ASET (SCM v, size_t pos, SCM val)
  54. {
  55. scm_t_array_handle h;
  56. scm_array_get_handle (v, &h);
  57. h.impl->vset (h.root, pos, val);
  58. scm_array_handle_release (&h);
  59. }
  60. static SCM
  61. make1array (SCM v, ssize_t inc)
  62. {
  63. SCM a = scm_i_make_array (1);
  64. SCM_I_ARRAY_BASE (a) = 0;
  65. SCM_I_ARRAY_DIMS (a)->lbnd = 0;
  66. SCM_I_ARRAY_DIMS (a)->ubnd = scm_c_array_length (v) - 1;
  67. SCM_I_ARRAY_DIMS (a)->inc = inc;
  68. SCM_I_ARRAY_V (a) = v;
  69. return a;
  70. }
  71. /* Linear index of not-unrolled index set. */
  72. static size_t
  73. cindk (SCM ra, ssize_t *ve, int kend)
  74. {
  75. if (SCM_I_ARRAYP (ra))
  76. {
  77. int k;
  78. size_t i = SCM_I_ARRAY_BASE (ra);
  79. for (k = 0; k < kend; ++k)
  80. i += (ve[k] - SCM_I_ARRAY_DIMS (ra)[k].lbnd) * SCM_I_ARRAY_DIMS (ra)[k].inc;
  81. return i;
  82. }
  83. else
  84. return 0; /* this is BASE */
  85. }
  86. /* array mapper: apply cproc to each dimension of the given arrays?.
  87. int (*cproc) (); procedure to call on unrolled arrays?
  88. cproc (dest, source list) or
  89. cproc (dest, data, source list).
  90. SCM data; data to give to cproc or unbound.
  91. SCM ra0; destination array.
  92. SCM lra; list of source arrays.
  93. const char *what; caller, for error reporting. */
  94. #define LBND(ra, k) SCM_I_ARRAY_DIMS (ra)[k].lbnd
  95. #define UBND(ra, k) SCM_I_ARRAY_DIMS (ra)[k].ubnd
  96. int
  97. scm_ramapc (void *cproc_ptr, SCM data, SCM ra0, SCM lra, const char *what)
  98. {
  99. int (*cproc) () = cproc_ptr;
  100. SCM z, va0, lva, *plva;
  101. int k, kmax, kroll;
  102. ssize_t *vi, inc;
  103. size_t len;
  104. /* Prepare reference argument. */
  105. if (SCM_I_ARRAYP (ra0))
  106. {
  107. kmax = SCM_I_ARRAY_NDIM (ra0)-1;
  108. inc = kmax < 0 ? 0 : SCM_I_ARRAY_DIMS (ra0)[kmax].inc;
  109. va0 = make1array (SCM_I_ARRAY_V (ra0), inc);
  110. /* Find unroll depth */
  111. for (kroll = max(0, kmax); kroll > 0; --kroll)
  112. {
  113. inc *= (UBND (ra0, kroll) - LBND (ra0, kroll) + 1);
  114. if (inc != SCM_I_ARRAY_DIMS (ra0)[kroll-1].inc)
  115. break;
  116. }
  117. }
  118. else
  119. {
  120. kroll = kmax = 0;
  121. va0 = ra0 = make1array (ra0, 1);
  122. }
  123. /* Prepare rest arguments. */
  124. lva = SCM_EOL;
  125. plva = &lva;
  126. for (z = lra; !scm_is_null (z); z = SCM_CDR (z))
  127. {
  128. SCM va1, ra1 = SCM_CAR (z);
  129. if (SCM_I_ARRAYP (ra1))
  130. {
  131. if (kmax != SCM_I_ARRAY_NDIM (ra1) - 1)
  132. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  133. inc = kmax < 0 ? 0 : SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
  134. va1 = make1array (SCM_I_ARRAY_V (ra1), inc);
  135. /* Check unroll depth. */
  136. for (k = kmax; k > kroll; --k)
  137. {
  138. ssize_t l0 = LBND (ra0, k), u0 = UBND (ra0, k);
  139. if (l0 < LBND (ra1, k) || u0 > UBND (ra1, k))
  140. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  141. inc *= (u0 - l0 + 1);
  142. if (inc != SCM_I_ARRAY_DIMS (ra1)[k-1].inc)
  143. {
  144. kroll = k;
  145. break;
  146. }
  147. }
  148. /* Check matching of not-unrolled axes. */
  149. for (; k>=0; --k)
  150. if (LBND (ra0, k) < LBND (ra1, k) || UBND (ra0, k) > UBND (ra1, k))
  151. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  152. }
  153. else
  154. {
  155. if (kmax != 0)
  156. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  157. va1 = make1array (ra1, 1);
  158. if (LBND (ra0, 0) < LBND (va1, 0) || UBND (ra0, 0) > UBND (va1, 0))
  159. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  160. }
  161. *plva = scm_cons (va1, SCM_EOL);
  162. plva = SCM_CDRLOC (*plva);
  163. }
  164. /* Check emptiness of not-unrolled axes. */
  165. for (k = 0; k < kroll; ++k)
  166. if (0 == (UBND (ra0, k) - LBND (ra0, k) + 1))
  167. return 1;
  168. /* Set unrolled size. */
  169. for (len = 1; k <= kmax; ++k)
  170. len *= (UBND (ra0, k) - LBND (ra0, k) + 1);
  171. UBND (va0, 0) = len - 1;
  172. for (z = lva; !scm_is_null (z); z = SCM_CDR (z))
  173. UBND (SCM_CAR (z), 0) = len - 1;
  174. /* Set starting indices and go. */
  175. vi = scm_gc_malloc_pointerless (sizeof(ssize_t) * kroll, vi_gc_hint);
  176. for (k = 0; k < kroll; ++k)
  177. vi[k] = LBND (ra0, k);
  178. do
  179. {
  180. if (k == kroll)
  181. {
  182. SCM y = lra;
  183. SCM_I_ARRAY_BASE (va0) = cindk (ra0, vi, kroll);
  184. for (z = lva; !scm_is_null (z); z = SCM_CDR (z), y = SCM_CDR (y))
  185. SCM_I_ARRAY_BASE (SCM_CAR (z)) = cindk (SCM_CAR (y), vi, kroll);
  186. if (! (SCM_UNBNDP (data) ? cproc (va0, lva) : cproc (va0, data, lva)))
  187. return 0;
  188. --k;
  189. }
  190. else if (vi[k] < UBND (ra0, k))
  191. {
  192. ++vi[k];
  193. ++k;
  194. }
  195. else
  196. {
  197. vi[k] = LBND (ra0, k) - 1;
  198. --k;
  199. }
  200. }
  201. while (k >= 0);
  202. return 1;
  203. }
  204. #undef UBND
  205. #undef LBND
  206. static int
  207. rafill (SCM dst, SCM fill)
  208. {
  209. scm_t_array_handle h;
  210. size_t n, i;
  211. ssize_t inc;
  212. scm_array_get_handle (SCM_I_ARRAY_V (dst), &h);
  213. i = SCM_I_ARRAY_BASE (dst);
  214. inc = SCM_I_ARRAY_DIMS (dst)->inc;
  215. n = (SCM_I_ARRAY_DIMS (dst)->ubnd - SCM_I_ARRAY_DIMS (dst)->lbnd + 1);
  216. dst = SCM_I_ARRAY_V (dst);
  217. for (; n-- > 0; i += inc)
  218. h.impl->vset (dst, i, fill);
  219. scm_array_handle_release (&h);
  220. return 1;
  221. }
  222. SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
  223. (SCM ra, SCM fill),
  224. "Store @var{fill} in every element of array @var{ra}. The value\n"
  225. "returned is unspecified.")
  226. #define FUNC_NAME s_scm_array_fill_x
  227. {
  228. scm_ramapc (rafill, fill, ra, SCM_EOL, FUNC_NAME);
  229. return SCM_UNSPECIFIED;
  230. }
  231. #undef FUNC_NAME
  232. static int
  233. racp (SCM src, SCM dst)
  234. {
  235. scm_t_array_handle h_s, h_d;
  236. size_t n, i_s, i_d;
  237. ssize_t inc_s, inc_d;
  238. dst = SCM_CAR (dst);
  239. i_s = SCM_I_ARRAY_BASE (src);
  240. i_d = SCM_I_ARRAY_BASE (dst);
  241. inc_s = SCM_I_ARRAY_DIMS (src)->inc;
  242. inc_d = SCM_I_ARRAY_DIMS (dst)->inc;
  243. n = (SCM_I_ARRAY_DIMS (src)->ubnd - SCM_I_ARRAY_DIMS (src)->lbnd + 1);
  244. src = SCM_I_ARRAY_V (src);
  245. dst = SCM_I_ARRAY_V (dst);
  246. scm_array_get_handle (src, &h_s);
  247. scm_array_get_handle (dst, &h_d);
  248. if (scm_is_vector (src) && scm_is_vector (dst))
  249. {
  250. SCM const * el_s = h_s.elements;
  251. SCM * el_d = h_d.writable_elements;
  252. for (; n-- > 0; i_s += inc_s, i_d += inc_d)
  253. el_d[i_d] = el_s[i_s];
  254. }
  255. else
  256. for (; n-- > 0; i_s += inc_s, i_d += inc_d)
  257. h_d.impl->vset (dst, i_d, h_s.impl->vref (src, i_s));
  258. scm_array_handle_release (&h_d);
  259. scm_array_handle_release (&h_s);
  260. return 1;
  261. }
  262. SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
  263. SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
  264. (SCM src, SCM dst),
  265. "@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
  266. "Copy every element from vector or array @var{src} to the\n"
  267. "corresponding element of @var{dst}. @var{dst} must have the\n"
  268. "same rank as @var{src}, and be at least as large in each\n"
  269. "dimension. The order is unspecified.")
  270. #define FUNC_NAME s_scm_array_copy_x
  271. {
  272. scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
  273. return SCM_UNSPECIFIED;
  274. }
  275. #undef FUNC_NAME
  276. #if SCM_ENABLE_DEPRECATED == 1
  277. /* to be used as cproc in scm_ramapc to fill an array dimension with
  278. "fill". */
  279. int
  280. scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
  281. {
  282. unsigned long i;
  283. unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
  284. long inc = SCM_I_ARRAY_DIMS (ra)->inc;
  285. unsigned long base = SCM_I_ARRAY_BASE (ra);
  286. ra = SCM_I_ARRAY_V (ra);
  287. for (i = base; n--; i += inc)
  288. ASET (ra, i, fill);
  289. return 1;
  290. }
  291. /* Functions callable by ARRAY-MAP! */
  292. int
  293. scm_ra_eqp (SCM ra0, SCM ras)
  294. {
  295. SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
  296. scm_t_array_handle ra0_handle;
  297. scm_t_array_dim *ra0_dims;
  298. size_t n;
  299. ssize_t inc0;
  300. size_t i0 = 0;
  301. unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
  302. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  303. long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
  304. ra1 = SCM_I_ARRAY_V (ra1);
  305. ra2 = SCM_I_ARRAY_V (ra2);
  306. scm_array_get_handle (ra0, &ra0_handle);
  307. ra0_dims = scm_array_handle_dims (&ra0_handle);
  308. n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
  309. inc0 = ra0_dims[0].inc;
  310. {
  311. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  312. if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
  313. if (!scm_is_eq (AREF (ra1, i1), AREF (ra2, i2)))
  314. scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
  315. }
  316. scm_array_handle_release (&ra0_handle);
  317. return 1;
  318. }
  319. /* opt 0 means <, nonzero means >= */
  320. static int
  321. ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
  322. {
  323. scm_t_array_handle ra0_handle;
  324. scm_t_array_dim *ra0_dims;
  325. size_t n;
  326. ssize_t inc0;
  327. size_t i0 = 0;
  328. unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
  329. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  330. long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
  331. ra1 = SCM_I_ARRAY_V (ra1);
  332. ra2 = SCM_I_ARRAY_V (ra2);
  333. scm_array_get_handle (ra0, &ra0_handle);
  334. ra0_dims = scm_array_handle_dims (&ra0_handle);
  335. n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
  336. inc0 = ra0_dims[0].inc;
  337. {
  338. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  339. if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
  340. if (opt ?
  341. scm_is_true (scm_less_p (AREF (ra1, i1), AREF (ra2, i2))) :
  342. scm_is_false (scm_less_p (AREF (ra1, i1), AREF (ra2, i2))))
  343. scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
  344. }
  345. scm_array_handle_release (&ra0_handle);
  346. return 1;
  347. }
  348. int
  349. scm_ra_lessp (SCM ra0, SCM ras)
  350. {
  351. return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
  352. }
  353. int
  354. scm_ra_leqp (SCM ra0, SCM ras)
  355. {
  356. return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
  357. }
  358. int
  359. scm_ra_grp (SCM ra0, SCM ras)
  360. {
  361. return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
  362. }
  363. int
  364. scm_ra_greqp (SCM ra0, SCM ras)
  365. {
  366. return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
  367. }
  368. int
  369. scm_ra_sum (SCM ra0, SCM ras)
  370. {
  371. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  372. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  373. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  374. ra0 = SCM_I_ARRAY_V (ra0);
  375. if (!scm_is_null(ras))
  376. {
  377. SCM ra1 = SCM_CAR (ras);
  378. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  379. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  380. ra1 = SCM_I_ARRAY_V (ra1);
  381. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  382. {
  383. default:
  384. {
  385. for (; n-- > 0; i0 += inc0, i1 += inc1)
  386. ASET (ra0, i0, scm_sum (AREF(ra0, i0), AREF(ra1, i1)));
  387. break;
  388. }
  389. }
  390. }
  391. return 1;
  392. }
  393. int
  394. scm_ra_difference (SCM ra0, SCM ras)
  395. {
  396. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  397. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  398. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  399. ra0 = SCM_I_ARRAY_V (ra0);
  400. if (scm_is_null (ras))
  401. {
  402. switch (SCM_TYP7 (ra0))
  403. {
  404. default:
  405. {
  406. for (; n-- > 0; i0 += inc0)
  407. ASET (ra0, i0, scm_difference (AREF(ra0, i0), SCM_UNDEFINED));
  408. break;
  409. }
  410. }
  411. }
  412. else
  413. {
  414. SCM ra1 = SCM_CAR (ras);
  415. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  416. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  417. ra1 = SCM_I_ARRAY_V (ra1);
  418. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  419. {
  420. default:
  421. {
  422. for (; n-- > 0; i0 += inc0, i1 += inc1)
  423. ASET (ra0, i0, scm_difference (AREF (ra0, i0), AREF (ra1, i1)));
  424. break;
  425. }
  426. }
  427. }
  428. return 1;
  429. }
  430. int
  431. scm_ra_product (SCM ra0, SCM ras)
  432. {
  433. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  434. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  435. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  436. ra0 = SCM_I_ARRAY_V (ra0);
  437. if (!scm_is_null (ras))
  438. {
  439. SCM ra1 = SCM_CAR (ras);
  440. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  441. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  442. ra1 = SCM_I_ARRAY_V (ra1);
  443. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  444. {
  445. default:
  446. {
  447. for (; n-- > 0; i0 += inc0, i1 += inc1)
  448. ASET (ra0, i0, scm_product (AREF (ra0, i0), AREF (ra1, i1)));
  449. }
  450. }
  451. }
  452. return 1;
  453. }
  454. int
  455. scm_ra_divide (SCM ra0, SCM ras)
  456. {
  457. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  458. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  459. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  460. ra0 = SCM_I_ARRAY_V (ra0);
  461. if (scm_is_null (ras))
  462. {
  463. switch (SCM_TYP7 (ra0))
  464. {
  465. default:
  466. {
  467. for (; n-- > 0; i0 += inc0)
  468. ASET (ra0, i0, scm_divide (AREF (ra0, i0), SCM_UNDEFINED));
  469. break;
  470. }
  471. }
  472. }
  473. else
  474. {
  475. SCM ra1 = SCM_CAR (ras);
  476. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  477. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  478. ra1 = SCM_I_ARRAY_V (ra1);
  479. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  480. {
  481. default:
  482. {
  483. for (; n-- > 0; i0 += inc0, i1 += inc1)
  484. {
  485. SCM res = scm_divide (AREF (ra0, i0), AREF (ra1, i1));
  486. ASET (ra0, i0, res);
  487. }
  488. break;
  489. }
  490. }
  491. }
  492. return 1;
  493. }
  494. int
  495. scm_array_identity (SCM dst, SCM src)
  496. {
  497. return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
  498. }
  499. #endif /* SCM_ENABLE_DEPRECATED */
  500. static int
  501. ramap (SCM ra0, SCM proc, SCM ras)
  502. {
  503. scm_t_array_handle h0;
  504. size_t n, i0;
  505. ssize_t i, inc0;
  506. i0 = SCM_I_ARRAY_BASE (ra0);
  507. inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  508. i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
  509. n = SCM_I_ARRAY_DIMS (ra0)->ubnd - i + 1;
  510. ra0 = SCM_I_ARRAY_V (ra0);
  511. scm_array_get_handle (ra0, &h0);
  512. if (scm_is_null (ras))
  513. for (; n--; i0 += inc0)
  514. h0.impl->vset (ra0, i0, scm_call_0 (proc));
  515. else
  516. {
  517. SCM ra1 = SCM_CAR (ras);
  518. scm_t_array_handle h1;
  519. size_t i1;
  520. ssize_t inc1;
  521. i1 = SCM_I_ARRAY_BASE (ra1);
  522. inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  523. ras = SCM_CDR (ras);
  524. ra1 = SCM_I_ARRAY_V (ra1);
  525. scm_array_get_handle (ra1, &h1);
  526. if (scm_is_null (ras))
  527. for (; n--; i0 += inc0, i1 += inc1)
  528. h0.impl->vset (ra0, i0, scm_call_1 (proc, h1.impl->vref (ra1, i1)));
  529. else
  530. {
  531. ras = scm_vector (ras);
  532. for (; n--; i0 += inc0, i1 += inc1, ++i)
  533. {
  534. SCM args = SCM_EOL;
  535. unsigned long k;
  536. for (k = scm_c_vector_length (ras); k--;)
  537. args = scm_cons (AREF (scm_c_vector_ref (ras, k), i), args);
  538. h0.impl->vset (ra0, i0, scm_apply_1 (proc, h1.impl->vref (ra1, i1), args));
  539. }
  540. }
  541. scm_array_handle_release (&h1);
  542. }
  543. scm_array_handle_release (&h0);
  544. return 1;
  545. }
  546. SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
  547. SCM_SYMBOL (sym_b, "b");
  548. SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
  549. (SCM ra0, SCM proc, SCM lra),
  550. "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
  551. "@var{array1}, @dots{} must have the same number of dimensions\n"
  552. "as @var{ra0} and have a range for each index which includes the\n"
  553. "range for the corresponding index in @var{ra0}. @var{proc} is\n"
  554. "applied to each tuple of elements of @var{array1}, @dots{} and\n"
  555. "the result is stored as the corresponding element in @var{ra0}.\n"
  556. "The value returned is unspecified. The order of application is\n"
  557. "unspecified.")
  558. #define FUNC_NAME s_scm_array_map_x
  559. {
  560. SCM_VALIDATE_PROC (2, proc);
  561. SCM_VALIDATE_REST_ARGUMENT (lra);
  562. scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
  563. return SCM_UNSPECIFIED;
  564. }
  565. #undef FUNC_NAME
  566. static int
  567. rafe (SCM ra0, SCM proc, SCM ras)
  568. {
  569. ssize_t i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
  570. size_t n = SCM_I_ARRAY_DIMS (ra0)->ubnd - i + 1;
  571. scm_t_array_handle h0;
  572. size_t i0;
  573. ssize_t inc0;
  574. i0 = SCM_I_ARRAY_BASE (ra0);
  575. inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  576. ra0 = SCM_I_ARRAY_V (ra0);
  577. scm_array_get_handle (ra0, &h0);
  578. if (scm_is_null (ras))
  579. for (; n--; i0 += inc0)
  580. scm_call_1 (proc, h0.impl->vref (ra0, i0));
  581. else
  582. {
  583. ras = scm_vector (ras);
  584. for (; n--; i0 += inc0, ++i)
  585. {
  586. SCM args = SCM_EOL;
  587. unsigned long k;
  588. for (k = scm_c_vector_length (ras); k--;)
  589. args = scm_cons (AREF (scm_c_vector_ref (ras, k), i), args);
  590. scm_apply_1 (proc, h0.impl->vref (ra0, i0), args);
  591. }
  592. }
  593. scm_array_handle_release (&h0);
  594. return 1;
  595. }
  596. SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
  597. (SCM proc, SCM ra0, SCM lra),
  598. "Apply @var{proc} to each tuple of elements of @var{ra0} @dots{}\n"
  599. "in row-major order. The value returned is unspecified.")
  600. #define FUNC_NAME s_scm_array_for_each
  601. {
  602. SCM_VALIDATE_PROC (1, proc);
  603. SCM_VALIDATE_REST_ARGUMENT (lra);
  604. scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
  605. return SCM_UNSPECIFIED;
  606. }
  607. #undef FUNC_NAME
  608. SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
  609. (SCM ra, SCM proc),
  610. "Apply @var{proc} to the indices of each element of @var{ra} in\n"
  611. "turn, storing the result in the corresponding element. The value\n"
  612. "returned and the order of application are unspecified.\n\n"
  613. "One can implement @var{array-indexes} as\n"
  614. "@lisp\n"
  615. "(define (array-indexes array)\n"
  616. " (let ((ra (apply make-array #f (array-shape array))))\n"
  617. " (array-index-map! ra (lambda x x))\n"
  618. " ra))\n"
  619. "@end lisp\n"
  620. "Another example:\n"
  621. "@lisp\n"
  622. "(define (apl:index-generator n)\n"
  623. " (let ((v (make-uniform-vector n 1)))\n"
  624. " (array-index-map! v (lambda (i) i))\n"
  625. " v))\n"
  626. "@end lisp")
  627. #define FUNC_NAME s_scm_array_index_map_x
  628. {
  629. scm_t_array_handle h;
  630. SCM_VALIDATE_PROC (2, proc);
  631. if (!scm_is_array (ra))
  632. scm_wrong_type_arg_msg (NULL, 0, ra, "array");
  633. /* This also covers the not-SCM_I_ARRAYP case */
  634. else if (1 == scm_c_array_rank(ra))
  635. {
  636. ssize_t i, inc;
  637. size_t p;
  638. scm_array_get_handle (ra, &h);
  639. inc = h.dims[0].inc;
  640. for (i = h.dims[0].lbnd, p = h.base; i <= h.dims[0].ubnd; ++i, p += inc)
  641. h.impl->vset (h.root, p, scm_call_1 (proc, scm_from_ssize_t (i)));
  642. scm_array_handle_release (&h);
  643. }
  644. else
  645. {
  646. size_t i;
  647. int k, kmax = SCM_I_ARRAY_NDIM (ra) - 1;
  648. ssize_t *vi;
  649. SCM **si;
  650. SCM args = SCM_EOL;
  651. SCM *p = &args;
  652. if (kmax < 0)
  653. return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
  654. vi = scm_gc_malloc_pointerless (sizeof(ssize_t) * (kmax + 1), vi_gc_hint);
  655. si = scm_gc_malloc_pointerless (sizeof(SCM *) * (kmax + 1), vi_gc_hint);
  656. for (k = 0; k <= kmax; k++)
  657. {
  658. vi[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
  659. if (vi[k] > SCM_I_ARRAY_DIMS (ra)[k].ubnd)
  660. return SCM_UNSPECIFIED;
  661. *p = scm_cons (scm_from_ssize_t (vi[k]), SCM_EOL);
  662. si[k] = SCM_CARLOC (*p);
  663. p = SCM_CDRLOC (*p);
  664. }
  665. scm_array_get_handle (ra, &h);
  666. k = kmax;
  667. do
  668. {
  669. if (k == kmax)
  670. {
  671. vi[kmax] = SCM_I_ARRAY_DIMS (ra)[kmax].lbnd;
  672. i = cindk (ra, vi, kmax+1);
  673. for (; vi[kmax] <= SCM_I_ARRAY_DIMS (ra)[kmax].ubnd; ++vi[kmax])
  674. {
  675. *(si[kmax]) = scm_from_ssize_t (vi[kmax]);
  676. h.impl->vset (h.root, i, scm_apply_0 (proc, args));
  677. i += SCM_I_ARRAY_DIMS (ra)[kmax].inc;
  678. }
  679. k--;
  680. }
  681. else if (vi[k] < SCM_I_ARRAY_DIMS (ra)[k].ubnd)
  682. {
  683. *(si[k]) = scm_from_ssize_t (++vi[k]);
  684. k++;
  685. }
  686. else
  687. {
  688. vi[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd - 1;
  689. k--;
  690. }
  691. }
  692. while (k >= 0);
  693. scm_array_handle_release (&h);
  694. }
  695. return SCM_UNSPECIFIED;
  696. }
  697. #undef FUNC_NAME
  698. static int
  699. array_compare (scm_t_array_handle *hx, scm_t_array_handle *hy,
  700. size_t dim, unsigned long posx, unsigned long posy)
  701. {
  702. if (dim == scm_array_handle_rank (hx))
  703. return scm_is_true (scm_equal_p (scm_array_handle_ref (hx, posx),
  704. scm_array_handle_ref (hy, posy)));
  705. else
  706. {
  707. long incx, incy;
  708. size_t i;
  709. if (hx->dims[dim].lbnd != hy->dims[dim].lbnd
  710. || hx->dims[dim].ubnd != hy->dims[dim].ubnd)
  711. return 0;
  712. i = hx->dims[dim].ubnd - hx->dims[dim].lbnd + 1;
  713. incx = hx->dims[dim].inc;
  714. incy = hy->dims[dim].inc;
  715. posx += (i - 1) * incx;
  716. posy += (i - 1) * incy;
  717. for (; i > 0; i--, posx -= incx, posy -= incy)
  718. if (!array_compare (hx, hy, dim + 1, posx, posy))
  719. return 0;
  720. return 1;
  721. }
  722. }
  723. SCM
  724. scm_array_equal_p (SCM x, SCM y)
  725. {
  726. scm_t_array_handle hx, hy;
  727. SCM res;
  728. scm_array_get_handle (x, &hx);
  729. scm_array_get_handle (y, &hy);
  730. res = scm_from_bool (hx.ndims == hy.ndims
  731. && hx.element_type == hy.element_type);
  732. if (scm_is_true (res))
  733. res = scm_from_bool (array_compare (&hx, &hy, 0, 0, 0));
  734. scm_array_handle_release (&hy);
  735. scm_array_handle_release (&hx);
  736. return res;
  737. }
  738. static SCM scm_i_array_equal_p (SCM, SCM, SCM);
  739. SCM_DEFINE (scm_i_array_equal_p, "array-equal?", 0, 2, 1,
  740. (SCM ra0, SCM ra1, SCM rest),
  741. "Return @code{#t} iff all arguments are arrays with the same\n"
  742. "shape, the same type, and have corresponding elements which are\n"
  743. "either @code{equal?} or @code{array-equal?}. This function\n"
  744. "differs from @code{equal?} in that all arguments must be arrays.")
  745. #define FUNC_NAME s_scm_i_array_equal_p
  746. {
  747. if (SCM_UNBNDP (ra0) || SCM_UNBNDP (ra1))
  748. return SCM_BOOL_T;
  749. while (!scm_is_null (rest))
  750. { if (scm_is_false (scm_array_equal_p (ra0, ra1)))
  751. return SCM_BOOL_F;
  752. ra0 = ra1;
  753. ra1 = scm_car (rest);
  754. rest = scm_cdr (rest);
  755. }
  756. return scm_array_equal_p (ra0, ra1);
  757. }
  758. #undef FUNC_NAME
  759. void
  760. scm_init_array_map (void)
  761. {
  762. #include "libguile/array-map.x"
  763. scm_add_feature (s_scm_array_for_each);
  764. }
  765. /*
  766. Local Variables:
  767. c-file-style: "gnu"
  768. End:
  769. */