array-map.c 23 KB

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