ramap.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. /* Copyright (C) 1996,1998,2000,2001,2004,2005, 2006, 2008 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public License
  5. * as published by the Free Software Foundation; either version 3 of
  6. * the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301 USA
  17. */
  18. /*
  19. HWN:FIXME::
  20. Someone should rename this to arraymap.c; that would reflect the
  21. contents better. */
  22. #ifdef HAVE_CONFIG_H
  23. # include <config.h>
  24. #endif
  25. #include "libguile/_scm.h"
  26. #include "libguile/strings.h"
  27. #include "libguile/unif.h"
  28. #include "libguile/smob.h"
  29. #include "libguile/chars.h"
  30. #include "libguile/eq.h"
  31. #include "libguile/eval.h"
  32. #include "libguile/feature.h"
  33. #include "libguile/root.h"
  34. #include "libguile/vectors.h"
  35. #include "libguile/srfi-4.h"
  36. #include "libguile/dynwind.h"
  37. #include "libguile/validate.h"
  38. #include "libguile/ramap.h"
  39. typedef struct
  40. {
  41. char *name;
  42. SCM sproc;
  43. int (*vproc) ();
  44. } ra_iproc;
  45. /* These tables are a kluge that will not scale well when more
  46. * vectorized subrs are added. It is tempting to steal some bits from
  47. * the SCM_CAR of all subrs (like those selected by SCM_SMOBNUM) to hold an
  48. * offset into a table of vectorized subrs.
  49. */
  50. static ra_iproc ra_rpsubrs[] =
  51. {
  52. {"=", SCM_UNDEFINED, scm_ra_eqp},
  53. {"<", SCM_UNDEFINED, scm_ra_lessp},
  54. {"<=", SCM_UNDEFINED, scm_ra_leqp},
  55. {">", SCM_UNDEFINED, scm_ra_grp},
  56. {">=", SCM_UNDEFINED, scm_ra_greqp},
  57. {0, 0, 0}
  58. };
  59. static ra_iproc ra_asubrs[] =
  60. {
  61. {"+", SCM_UNDEFINED, scm_ra_sum},
  62. {"-", SCM_UNDEFINED, scm_ra_difference},
  63. {"*", SCM_UNDEFINED, scm_ra_product},
  64. {"/", SCM_UNDEFINED, scm_ra_divide},
  65. {0, 0, 0}
  66. };
  67. #define GVREF scm_c_generalized_vector_ref
  68. #define GVSET scm_c_generalized_vector_set_x
  69. static unsigned long
  70. cind (SCM ra, long *ve)
  71. {
  72. unsigned long i;
  73. int k;
  74. if (!SCM_I_ARRAYP (ra))
  75. return *ve;
  76. i = SCM_I_ARRAY_BASE (ra);
  77. for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
  78. i += (ve[k] - SCM_I_ARRAY_DIMS (ra)[k].lbnd) * SCM_I_ARRAY_DIMS (ra)[k].inc;
  79. return i;
  80. }
  81. /* Checker for scm_array mapping functions:
  82. return values: 4 --> shapes, increments, and bases are the same;
  83. 3 --> shapes and increments are the same;
  84. 2 --> shapes are the same;
  85. 1 --> ras are at least as big as ra0;
  86. 0 --> no match.
  87. */
  88. int
  89. scm_ra_matchp (SCM ra0, SCM ras)
  90. {
  91. SCM ra1;
  92. scm_t_array_dim dims;
  93. scm_t_array_dim *s0 = &dims;
  94. scm_t_array_dim *s1;
  95. unsigned long bas0 = 0;
  96. int i, ndim = 1;
  97. int exact = 2 /* 4 */ ; /* Don't care about values >2 (yet?) */
  98. if (scm_is_generalized_vector (ra0))
  99. {
  100. s0->lbnd = 0;
  101. s0->inc = 1;
  102. s0->ubnd = scm_c_generalized_vector_length (ra0) - 1;
  103. }
  104. else if (SCM_I_ARRAYP (ra0))
  105. {
  106. ndim = SCM_I_ARRAY_NDIM (ra0);
  107. s0 = SCM_I_ARRAY_DIMS (ra0);
  108. bas0 = SCM_I_ARRAY_BASE (ra0);
  109. }
  110. else
  111. return 0;
  112. while (SCM_NIMP (ras))
  113. {
  114. ra1 = SCM_CAR (ras);
  115. if (scm_is_generalized_vector (ra1))
  116. {
  117. size_t length;
  118. if (1 != ndim)
  119. return 0;
  120. length = scm_c_generalized_vector_length (ra1);
  121. switch (exact)
  122. {
  123. case 4:
  124. if (0 != bas0)
  125. exact = 3;
  126. case 3:
  127. if (1 != s0->inc)
  128. exact = 2;
  129. case 2:
  130. if ((0 == s0->lbnd) && (s0->ubnd == length - 1))
  131. break;
  132. exact = 1;
  133. case 1:
  134. if (s0->lbnd < 0 || s0->ubnd >= length)
  135. return 0;
  136. }
  137. }
  138. else if (SCM_I_ARRAYP (ra1) && ndim == SCM_I_ARRAY_NDIM (ra1))
  139. {
  140. s1 = SCM_I_ARRAY_DIMS (ra1);
  141. if (bas0 != SCM_I_ARRAY_BASE (ra1))
  142. exact = 3;
  143. for (i = 0; i < ndim; i++)
  144. switch (exact)
  145. {
  146. case 4:
  147. case 3:
  148. if (s0[i].inc != s1[i].inc)
  149. exact = 2;
  150. case 2:
  151. if (s0[i].lbnd == s1[i].lbnd && s0[i].ubnd == s1[i].ubnd)
  152. break;
  153. exact = 1;
  154. default:
  155. if (s0[i].lbnd < s1[i].lbnd || s0[i].ubnd > s1[i].ubnd)
  156. return (s0[i].lbnd <= s0[i].ubnd ? 0 : 1);
  157. }
  158. }
  159. else
  160. return 0;
  161. ras = SCM_CDR (ras);
  162. }
  163. return exact;
  164. }
  165. /* array mapper: apply cproc to each dimension of the given arrays?.
  166. int (*cproc) (); procedure to call on unrolled arrays?
  167. cproc (dest, source list) or
  168. cproc (dest, data, source list).
  169. SCM data; data to give to cproc or unbound.
  170. SCM ra0; destination array.
  171. SCM lra; list of source arrays.
  172. const char *what; caller, for error reporting. */
  173. int
  174. scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
  175. {
  176. SCM z;
  177. SCM vra0, ra1, vra1;
  178. SCM lvra, *plvra;
  179. long *vinds;
  180. int k, kmax;
  181. switch (scm_ra_matchp (ra0, lra))
  182. {
  183. default:
  184. case 0:
  185. scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
  186. case 2:
  187. case 3:
  188. case 4: /* Try unrolling arrays */
  189. kmax = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_NDIM (ra0) - 1 : 0);
  190. if (kmax < 0)
  191. goto gencase;
  192. vra0 = scm_array_contents (ra0, SCM_UNDEFINED);
  193. if (SCM_IMP (vra0)) goto gencase;
  194. if (!SCM_I_ARRAYP (vra0))
  195. {
  196. size_t length = scm_c_generalized_vector_length (vra0);
  197. vra1 = scm_i_make_ra (1, 0);
  198. SCM_I_ARRAY_BASE (vra1) = 0;
  199. SCM_I_ARRAY_DIMS (vra1)->lbnd = 0;
  200. SCM_I_ARRAY_DIMS (vra1)->ubnd = length - 1;
  201. SCM_I_ARRAY_DIMS (vra1)->inc = 1;
  202. SCM_I_ARRAY_V (vra1) = vra0;
  203. vra0 = vra1;
  204. }
  205. lvra = SCM_EOL;
  206. plvra = &lvra;
  207. for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
  208. {
  209. ra1 = SCM_CAR (z);
  210. vra1 = scm_i_make_ra (1, 0);
  211. SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
  212. SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
  213. if (!SCM_I_ARRAYP (ra1))
  214. {
  215. SCM_I_ARRAY_BASE (vra1) = 0;
  216. SCM_I_ARRAY_DIMS (vra1)->inc = 1;
  217. SCM_I_ARRAY_V (vra1) = ra1;
  218. }
  219. else if (!SCM_I_ARRAY_CONTP (ra1))
  220. goto gencase;
  221. else
  222. {
  223. SCM_I_ARRAY_BASE (vra1) = SCM_I_ARRAY_BASE (ra1);
  224. SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
  225. SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
  226. }
  227. *plvra = scm_cons (vra1, SCM_EOL);
  228. plvra = SCM_CDRLOC (*plvra);
  229. }
  230. return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
  231. case 1:
  232. gencase: /* Have to loop over all dimensions. */
  233. vra0 = scm_i_make_ra (1, 0);
  234. if (SCM_I_ARRAYP (ra0))
  235. {
  236. kmax = SCM_I_ARRAY_NDIM (ra0) - 1;
  237. if (kmax < 0)
  238. {
  239. SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
  240. SCM_I_ARRAY_DIMS (vra0)->ubnd = 0;
  241. SCM_I_ARRAY_DIMS (vra0)->inc = 1;
  242. }
  243. else
  244. {
  245. SCM_I_ARRAY_DIMS (vra0)->lbnd = SCM_I_ARRAY_DIMS (ra0)[kmax].lbnd;
  246. SCM_I_ARRAY_DIMS (vra0)->ubnd = SCM_I_ARRAY_DIMS (ra0)[kmax].ubnd;
  247. SCM_I_ARRAY_DIMS (vra0)->inc = SCM_I_ARRAY_DIMS (ra0)[kmax].inc;
  248. }
  249. SCM_I_ARRAY_BASE (vra0) = SCM_I_ARRAY_BASE (ra0);
  250. SCM_I_ARRAY_V (vra0) = SCM_I_ARRAY_V (ra0);
  251. }
  252. else
  253. {
  254. size_t length = scm_c_generalized_vector_length (ra0);
  255. kmax = 0;
  256. SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
  257. SCM_I_ARRAY_DIMS (vra0)->ubnd = length - 1;
  258. SCM_I_ARRAY_DIMS (vra0)->inc = 1;
  259. SCM_I_ARRAY_BASE (vra0) = 0;
  260. SCM_I_ARRAY_V (vra0) = ra0;
  261. ra0 = vra0;
  262. }
  263. lvra = SCM_EOL;
  264. plvra = &lvra;
  265. for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
  266. {
  267. ra1 = SCM_CAR (z);
  268. vra1 = scm_i_make_ra (1, 0);
  269. SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
  270. SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
  271. if (SCM_I_ARRAYP (ra1))
  272. {
  273. if (kmax >= 0)
  274. SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
  275. SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
  276. }
  277. else
  278. {
  279. SCM_I_ARRAY_DIMS (vra1)->inc = 1;
  280. SCM_I_ARRAY_V (vra1) = ra1;
  281. }
  282. *plvra = scm_cons (vra1, SCM_EOL);
  283. plvra = SCM_CDRLOC (*plvra);
  284. }
  285. scm_dynwind_begin (0);
  286. vinds = scm_malloc (sizeof(long) * SCM_I_ARRAY_NDIM (ra0));
  287. scm_dynwind_free (vinds);
  288. for (k = 0; k <= kmax; k++)
  289. vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd;
  290. k = kmax;
  291. do
  292. {
  293. if (k == kmax)
  294. {
  295. SCM y = lra;
  296. SCM_I_ARRAY_BASE (vra0) = cind (ra0, vinds);
  297. for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
  298. SCM_I_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), vinds);
  299. if (0 == (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)))
  300. return 0;
  301. k--;
  302. continue;
  303. }
  304. if (vinds[k] < SCM_I_ARRAY_DIMS (ra0)[k].ubnd)
  305. {
  306. vinds[k]++;
  307. k++;
  308. continue;
  309. }
  310. vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd - 1;
  311. k--;
  312. }
  313. while (k >= 0);
  314. scm_dynwind_end ();
  315. return 1;
  316. }
  317. }
  318. SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
  319. (SCM ra, SCM fill),
  320. "Store @var{fill} in every element of @var{array}. The value returned\n"
  321. "is unspecified.")
  322. #define FUNC_NAME s_scm_array_fill_x
  323. {
  324. scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
  325. return SCM_UNSPECIFIED;
  326. }
  327. #undef FUNC_NAME
  328. /* to be used as cproc in scm_ramapc to fill an array dimension with
  329. "fill". */
  330. int
  331. scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
  332. #define FUNC_NAME s_scm_array_fill_x
  333. {
  334. unsigned long i;
  335. unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
  336. long inc = SCM_I_ARRAY_DIMS (ra)->inc;
  337. unsigned long base = SCM_I_ARRAY_BASE (ra);
  338. ra = SCM_I_ARRAY_V (ra);
  339. for (i = base; n--; i += inc)
  340. GVSET (ra, i, fill);
  341. return 1;
  342. }
  343. #undef FUNC_NAME
  344. static int
  345. racp (SCM src, SCM dst)
  346. {
  347. long n = (SCM_I_ARRAY_DIMS (src)->ubnd - SCM_I_ARRAY_DIMS (src)->lbnd + 1);
  348. long inc_d, inc_s = SCM_I_ARRAY_DIMS (src)->inc;
  349. unsigned long i_d, i_s = SCM_I_ARRAY_BASE (src);
  350. dst = SCM_CAR (dst);
  351. inc_d = SCM_I_ARRAY_DIMS (dst)->inc;
  352. i_d = SCM_I_ARRAY_BASE (dst);
  353. src = SCM_I_ARRAY_V (src);
  354. dst = SCM_I_ARRAY_V (dst);
  355. for (; n-- > 0; i_s += inc_s, i_d += inc_d)
  356. GVSET (dst, i_d, GVREF (src, i_s));
  357. return 1;
  358. }
  359. SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
  360. SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
  361. (SCM src, SCM dst),
  362. "@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
  363. "Copy every element from vector or array @var{source} to the\n"
  364. "corresponding element of @var{destination}. @var{destination} must have\n"
  365. "the same rank as @var{source}, and be at least as large in each\n"
  366. "dimension. The order is unspecified.")
  367. #define FUNC_NAME s_scm_array_copy_x
  368. {
  369. scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
  370. return SCM_UNSPECIFIED;
  371. }
  372. #undef FUNC_NAME
  373. /* Functions callable by ARRAY-MAP! */
  374. int
  375. scm_ra_eqp (SCM ra0, SCM ras)
  376. {
  377. SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
  378. scm_t_array_handle ra0_handle;
  379. scm_t_array_dim *ra0_dims;
  380. size_t n;
  381. ssize_t inc0;
  382. size_t i0 = 0;
  383. unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
  384. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  385. long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
  386. ra1 = SCM_I_ARRAY_V (ra1);
  387. ra2 = SCM_I_ARRAY_V (ra2);
  388. scm_array_get_handle (ra0, &ra0_handle);
  389. ra0_dims = scm_array_handle_dims (&ra0_handle);
  390. n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
  391. inc0 = ra0_dims[0].inc;
  392. {
  393. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  394. if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
  395. if (!scm_is_eq (GVREF (ra1, i1), GVREF (ra2, i2)))
  396. scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
  397. }
  398. scm_array_handle_release (&ra0_handle);
  399. return 1;
  400. }
  401. /* opt 0 means <, nonzero means >= */
  402. static int
  403. ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
  404. {
  405. scm_t_array_handle ra0_handle;
  406. scm_t_array_dim *ra0_dims;
  407. size_t n;
  408. ssize_t inc0;
  409. size_t i0 = 0;
  410. unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
  411. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  412. long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
  413. ra1 = SCM_I_ARRAY_V (ra1);
  414. ra2 = SCM_I_ARRAY_V (ra2);
  415. scm_array_get_handle (ra0, &ra0_handle);
  416. ra0_dims = scm_array_handle_dims (&ra0_handle);
  417. n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
  418. inc0 = ra0_dims[0].inc;
  419. {
  420. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  421. if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
  422. if (opt ?
  423. scm_is_true (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))) :
  424. scm_is_false (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))))
  425. scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
  426. }
  427. scm_array_handle_release (&ra0_handle);
  428. return 1;
  429. }
  430. int
  431. scm_ra_lessp (SCM ra0, SCM ras)
  432. {
  433. return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
  434. }
  435. int
  436. scm_ra_leqp (SCM ra0, SCM ras)
  437. {
  438. return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
  439. }
  440. int
  441. scm_ra_grp (SCM ra0, SCM ras)
  442. {
  443. return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
  444. }
  445. int
  446. scm_ra_greqp (SCM ra0, SCM ras)
  447. {
  448. return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
  449. }
  450. int
  451. scm_ra_sum (SCM ra0, SCM ras)
  452. {
  453. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  454. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  455. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  456. ra0 = SCM_I_ARRAY_V (ra0);
  457. if (!scm_is_null(ras))
  458. {
  459. SCM ra1 = SCM_CAR (ras);
  460. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  461. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  462. ra1 = SCM_I_ARRAY_V (ra1);
  463. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  464. {
  465. default:
  466. {
  467. for (; n-- > 0; i0 += inc0, i1 += inc1)
  468. GVSET (ra0, i0, scm_sum (GVREF(ra0, i0), GVREF(ra1, i1)));
  469. break;
  470. }
  471. }
  472. }
  473. return 1;
  474. }
  475. int
  476. scm_ra_difference (SCM ra0, SCM ras)
  477. {
  478. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  479. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  480. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  481. ra0 = SCM_I_ARRAY_V (ra0);
  482. if (scm_is_null (ras))
  483. {
  484. switch (SCM_TYP7 (ra0))
  485. {
  486. default:
  487. {
  488. for (; n-- > 0; i0 += inc0)
  489. GVSET (ra0, i0, scm_difference (GVREF(ra0, i0), SCM_UNDEFINED));
  490. break;
  491. }
  492. }
  493. }
  494. else
  495. {
  496. SCM ra1 = SCM_CAR (ras);
  497. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  498. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  499. ra1 = SCM_I_ARRAY_V (ra1);
  500. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  501. {
  502. default:
  503. {
  504. for (; n-- > 0; i0 += inc0, i1 += inc1)
  505. GVSET (ra0, i0, scm_difference (GVREF (ra0, i0),
  506. GVREF (ra1, i1)));
  507. break;
  508. }
  509. }
  510. }
  511. return 1;
  512. }
  513. int
  514. scm_ra_product (SCM ra0, SCM ras)
  515. {
  516. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  517. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  518. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  519. ra0 = SCM_I_ARRAY_V (ra0);
  520. if (!scm_is_null (ras))
  521. {
  522. SCM ra1 = SCM_CAR (ras);
  523. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  524. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  525. ra1 = SCM_I_ARRAY_V (ra1);
  526. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  527. {
  528. default:
  529. {
  530. for (; n-- > 0; i0 += inc0, i1 += inc1)
  531. GVSET (ra0, i0, scm_product (GVREF (ra0, i0),
  532. GVREF (ra1, i1)));
  533. }
  534. }
  535. }
  536. return 1;
  537. }
  538. int
  539. scm_ra_divide (SCM ra0, SCM ras)
  540. {
  541. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  542. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  543. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  544. ra0 = SCM_I_ARRAY_V (ra0);
  545. if (scm_is_null (ras))
  546. {
  547. switch (SCM_TYP7 (ra0))
  548. {
  549. default:
  550. {
  551. for (; n-- > 0; i0 += inc0)
  552. GVSET (ra0, i0, scm_divide (GVREF (ra0, i0), SCM_UNDEFINED));
  553. break;
  554. }
  555. }
  556. }
  557. else
  558. {
  559. SCM ra1 = SCM_CAR (ras);
  560. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  561. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  562. ra1 = SCM_I_ARRAY_V (ra1);
  563. switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
  564. {
  565. default:
  566. {
  567. for (; n-- > 0; i0 += inc0, i1 += inc1)
  568. {
  569. SCM res = scm_divide (GVREF (ra0, i0),
  570. GVREF (ra1, i1));
  571. GVSET (ra0, i0, res);
  572. }
  573. break;
  574. }
  575. }
  576. }
  577. return 1;
  578. }
  579. int
  580. scm_array_identity (SCM dst, SCM src)
  581. {
  582. return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
  583. }
  584. static int
  585. ramap (SCM ra0, SCM proc, SCM ras)
  586. {
  587. long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
  588. long inc = SCM_I_ARRAY_DIMS (ra0)->inc;
  589. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
  590. long base = SCM_I_ARRAY_BASE (ra0) - i * inc;
  591. ra0 = SCM_I_ARRAY_V (ra0);
  592. if (scm_is_null (ras))
  593. for (; i <= n; i++)
  594. GVSET (ra0, i*inc+base, scm_call_0 (proc));
  595. else
  596. {
  597. SCM ra1 = SCM_CAR (ras);
  598. SCM args;
  599. unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
  600. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  601. ra1 = SCM_I_ARRAY_V (ra1);
  602. ras = SCM_CDR (ras);
  603. if (scm_is_null(ras))
  604. ras = scm_nullvect;
  605. else
  606. ras = scm_vector (ras);
  607. for (; i <= n; i++, i1 += inc1)
  608. {
  609. args = SCM_EOL;
  610. for (k = scm_c_vector_length (ras); k--;)
  611. args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
  612. args = scm_cons (GVREF (ra1, i1), args);
  613. GVSET (ra0, i*inc+base, scm_apply_0 (proc, args));
  614. }
  615. }
  616. return 1;
  617. }
  618. static int
  619. ramap_dsubr (SCM ra0, SCM proc, SCM ras)
  620. {
  621. SCM ra1 = SCM_CAR (ras);
  622. unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
  623. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  624. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra1)->lbnd + 1;
  625. ra0 = SCM_I_ARRAY_V (ra0);
  626. ra1 = SCM_I_ARRAY_V (ra1);
  627. switch (SCM_TYP7 (ra0))
  628. {
  629. default:
  630. for (; n-- > 0; i0 += inc0, i1 += inc1)
  631. GVSET (ra0, i0, scm_call_1 (proc, GVREF (ra1, i1)));
  632. break;
  633. }
  634. return 1;
  635. }
  636. static int
  637. ramap_rp (SCM ra0, SCM proc, SCM ras)
  638. {
  639. SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
  640. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  641. unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
  642. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  643. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  644. long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
  645. ra0 = SCM_I_ARRAY_V (ra0);
  646. ra1 = SCM_I_ARRAY_V (ra1);
  647. ra2 = SCM_I_ARRAY_V (ra2);
  648. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  649. if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
  650. if (scm_is_false (SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2))))
  651. scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
  652. return 1;
  653. }
  654. static int
  655. ramap_1 (SCM ra0, SCM proc, SCM ras)
  656. {
  657. SCM ra1 = SCM_CAR (ras);
  658. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  659. unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
  660. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  661. ra0 = SCM_I_ARRAY_V (ra0);
  662. ra1 = SCM_I_ARRAY_V (ra1);
  663. if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
  664. for (; n-- > 0; i0 += inc0, i1 += inc1)
  665. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
  666. else
  667. for (; n-- > 0; i0 += inc0, i1 += inc1)
  668. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
  669. return 1;
  670. }
  671. static int
  672. ramap_2o (SCM ra0, SCM proc, SCM ras)
  673. {
  674. SCM ra1 = SCM_CAR (ras);
  675. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  676. unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
  677. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  678. ra0 = SCM_I_ARRAY_V (ra0);
  679. ra1 = SCM_I_ARRAY_V (ra1);
  680. ras = SCM_CDR (ras);
  681. if (scm_is_null (ras))
  682. {
  683. for (; n-- > 0; i0 += inc0, i1 += inc1)
  684. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), SCM_UNDEFINED));
  685. }
  686. else
  687. {
  688. SCM ra2 = SCM_CAR (ras);
  689. unsigned long i2 = SCM_I_ARRAY_BASE (ra2);
  690. long inc2 = SCM_I_ARRAY_DIMS (ra2)->inc;
  691. ra2 = SCM_I_ARRAY_V (ra2);
  692. for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
  693. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2)));
  694. }
  695. return 1;
  696. }
  697. static int
  698. ramap_a (SCM ra0, SCM proc, SCM ras)
  699. {
  700. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  701. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  702. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  703. ra0 = SCM_I_ARRAY_V (ra0);
  704. if (scm_is_null (ras))
  705. for (; n-- > 0; i0 += inc0)
  706. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), SCM_UNDEFINED));
  707. else
  708. {
  709. SCM ra1 = SCM_CAR (ras);
  710. unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
  711. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  712. ra1 = SCM_I_ARRAY_V (ra1);
  713. for (; n-- > 0; i0 += inc0, i1 += inc1)
  714. GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), GVREF (ra1, i1)));
  715. }
  716. return 1;
  717. }
  718. SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
  719. SCM_SYMBOL (sym_b, "b");
  720. SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
  721. (SCM ra0, SCM proc, SCM lra),
  722. "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
  723. "@var{array1}, @dots{} must have the same number of dimensions as\n"
  724. "@var{array0} and have a range for each index which includes the range\n"
  725. "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
  726. "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
  727. "as the corresponding element in @var{array0}. The value returned is\n"
  728. "unspecified. The order of application is unspecified.")
  729. #define FUNC_NAME s_scm_array_map_x
  730. {
  731. SCM_VALIDATE_PROC (2, proc);
  732. SCM_VALIDATE_REST_ARGUMENT (lra);
  733. switch (SCM_TYP7 (proc))
  734. {
  735. default:
  736. gencase:
  737. scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
  738. return SCM_UNSPECIFIED;
  739. case scm_tc7_subr_1:
  740. if (! scm_is_pair (lra))
  741. SCM_WRONG_NUM_ARGS (); /* need 1 source */
  742. scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
  743. return SCM_UNSPECIFIED;
  744. case scm_tc7_subr_2:
  745. if (! (scm_is_pair (lra) && scm_is_pair (SCM_CDR (lra))))
  746. SCM_WRONG_NUM_ARGS (); /* need 2 sources */
  747. goto subr_2o;
  748. case scm_tc7_subr_2o:
  749. if (! scm_is_pair (lra))
  750. SCM_WRONG_NUM_ARGS (); /* need 1 source */
  751. subr_2o:
  752. scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
  753. return SCM_UNSPECIFIED;
  754. case scm_tc7_dsubr:
  755. if (! scm_is_pair (lra))
  756. SCM_WRONG_NUM_ARGS (); /* need 1 source */
  757. scm_ramapc (ramap_dsubr, proc, ra0, lra, FUNC_NAME);
  758. return SCM_UNSPECIFIED;
  759. case scm_tc7_rpsubr:
  760. {
  761. ra_iproc *p;
  762. if (!scm_is_typed_array (ra0, sym_b))
  763. goto gencase;
  764. scm_array_fill_x (ra0, SCM_BOOL_T);
  765. for (p = ra_rpsubrs; p->name; p++)
  766. if (scm_is_eq (proc, p->sproc))
  767. {
  768. while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
  769. {
  770. scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
  771. lra = SCM_CDR (lra);
  772. }
  773. return SCM_UNSPECIFIED;
  774. }
  775. while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
  776. {
  777. scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
  778. lra = SCM_CDR (lra);
  779. }
  780. return SCM_UNSPECIFIED;
  781. }
  782. case scm_tc7_asubr:
  783. if (scm_is_null (lra))
  784. {
  785. SCM fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
  786. scm_array_fill_x (ra0, fill);
  787. }
  788. else
  789. {
  790. SCM tail, ra1 = SCM_CAR (lra);
  791. SCM v0 = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_V (ra0) : ra0);
  792. ra_iproc *p;
  793. /* Check to see if order might matter.
  794. This might be an argument for a separate
  795. SERIAL-ARRAY-MAP! */
  796. if (scm_is_eq (v0, ra1)
  797. || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
  798. if (!scm_is_eq (ra0, ra1)
  799. || (SCM_I_ARRAYP(ra0) && !SCM_I_ARRAY_CONTP(ra0)))
  800. goto gencase;
  801. for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
  802. {
  803. ra1 = SCM_CAR (tail);
  804. if (scm_is_eq (v0, ra1)
  805. || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
  806. goto gencase;
  807. }
  808. for (p = ra_asubrs; p->name; p++)
  809. if (scm_is_eq (proc, p->sproc))
  810. {
  811. if (!scm_is_eq (ra0, SCM_CAR (lra)))
  812. scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
  813. lra = SCM_CDR (lra);
  814. while (1)
  815. {
  816. scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
  817. if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
  818. return SCM_UNSPECIFIED;
  819. lra = SCM_CDR (lra);
  820. }
  821. }
  822. scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
  823. lra = SCM_CDR (lra);
  824. if (SCM_NIMP (lra))
  825. for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
  826. scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
  827. }
  828. return SCM_UNSPECIFIED;
  829. }
  830. }
  831. #undef FUNC_NAME
  832. static int
  833. rafe (SCM ra0, SCM proc, SCM ras)
  834. {
  835. long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
  836. unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
  837. long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  838. long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
  839. ra0 = SCM_I_ARRAY_V (ra0);
  840. if (scm_is_null (ras))
  841. for (; i <= n; i++, i0 += inc0)
  842. scm_call_1 (proc, GVREF (ra0, i0));
  843. else
  844. {
  845. SCM ra1 = SCM_CAR (ras);
  846. SCM args;
  847. unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
  848. long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  849. ra1 = SCM_I_ARRAY_V (ra1);
  850. ras = SCM_CDR (ras);
  851. if (scm_is_null(ras))
  852. ras = scm_nullvect;
  853. else
  854. ras = scm_vector (ras);
  855. for (; i <= n; i++, i0 += inc0, i1 += inc1)
  856. {
  857. args = SCM_EOL;
  858. for (k = scm_c_vector_length (ras); k--;)
  859. args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
  860. args = scm_cons2 (GVREF (ra0, i0), GVREF (ra1, i1), args);
  861. scm_apply_0 (proc, args);
  862. }
  863. }
  864. return 1;
  865. }
  866. SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
  867. (SCM proc, SCM ra0, SCM lra),
  868. "Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
  869. "in row-major order. The value returned is unspecified.")
  870. #define FUNC_NAME s_scm_array_for_each
  871. {
  872. SCM_VALIDATE_PROC (1, proc);
  873. SCM_VALIDATE_REST_ARGUMENT (lra);
  874. scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
  875. return SCM_UNSPECIFIED;
  876. }
  877. #undef FUNC_NAME
  878. SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
  879. (SCM ra, SCM proc),
  880. "Apply @var{proc} to the indices of each element of @var{array} in\n"
  881. "turn, storing the result in the corresponding element. The value\n"
  882. "returned and the order of application are unspecified.\n\n"
  883. "One can implement @var{array-indexes} as\n"
  884. "@lisp\n"
  885. "(define (array-indexes array)\n"
  886. " (let ((ra (apply make-array #f (array-shape array))))\n"
  887. " (array-index-map! ra (lambda x x))\n"
  888. " ra))\n"
  889. "@end lisp\n"
  890. "Another example:\n"
  891. "@lisp\n"
  892. "(define (apl:index-generator n)\n"
  893. " (let ((v (make-uniform-vector n 1)))\n"
  894. " (array-index-map! v (lambda (i) i))\n"
  895. " v))\n"
  896. "@end lisp")
  897. #define FUNC_NAME s_scm_array_index_map_x
  898. {
  899. unsigned long i;
  900. SCM_VALIDATE_PROC (2, proc);
  901. if (SCM_I_ARRAYP (ra))
  902. {
  903. SCM args = SCM_EOL;
  904. int j, k, kmax = SCM_I_ARRAY_NDIM (ra) - 1;
  905. long *vinds;
  906. if (kmax < 0)
  907. return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
  908. scm_dynwind_begin (0);
  909. vinds = scm_malloc (sizeof(long) * SCM_I_ARRAY_NDIM (ra));
  910. scm_dynwind_free (vinds);
  911. for (k = 0; k <= kmax; k++)
  912. vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
  913. k = kmax;
  914. do
  915. {
  916. if (k == kmax)
  917. {
  918. vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
  919. i = cind (ra, vinds);
  920. for (; vinds[k] <= SCM_I_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
  921. {
  922. for (j = kmax + 1, args = SCM_EOL; j--;)
  923. args = scm_cons (scm_from_long (vinds[j]), args);
  924. GVSET (SCM_I_ARRAY_V (ra), i, scm_apply_0 (proc, args));
  925. i += SCM_I_ARRAY_DIMS (ra)[k].inc;
  926. }
  927. k--;
  928. continue;
  929. }
  930. if (vinds[k] < SCM_I_ARRAY_DIMS (ra)[k].ubnd)
  931. {
  932. vinds[k]++;
  933. k++;
  934. continue;
  935. }
  936. vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd - 1;
  937. k--;
  938. }
  939. while (k >= 0);
  940. scm_dynwind_end ();
  941. return SCM_UNSPECIFIED;
  942. }
  943. else if (scm_is_generalized_vector (ra))
  944. {
  945. size_t length = scm_c_generalized_vector_length (ra);
  946. for (i = 0; i < length; i++)
  947. GVSET (ra, i, scm_call_1 (proc, scm_from_ulong (i)));
  948. return SCM_UNSPECIFIED;
  949. }
  950. else
  951. scm_wrong_type_arg_msg (NULL, 0, ra, "array");
  952. }
  953. #undef FUNC_NAME
  954. static int
  955. raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
  956. {
  957. unsigned long i0 = 0, i1 = 0;
  958. long inc0 = 1, inc1 = 1;
  959. unsigned long n;
  960. ra1 = SCM_CAR (ra1);
  961. if (SCM_I_ARRAYP(ra0))
  962. {
  963. n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
  964. i0 = SCM_I_ARRAY_BASE (ra0);
  965. inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
  966. ra0 = SCM_I_ARRAY_V (ra0);
  967. }
  968. else
  969. n = scm_c_generalized_vector_length (ra0);
  970. if (SCM_I_ARRAYP (ra1))
  971. {
  972. i1 = SCM_I_ARRAY_BASE (ra1);
  973. inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
  974. ra1 = SCM_I_ARRAY_V (ra1);
  975. }
  976. if (scm_is_generalized_vector (ra0))
  977. {
  978. for (; n--; i0 += inc0, i1 += inc1)
  979. {
  980. if (scm_is_false (as_equal))
  981. {
  982. if (scm_is_false (scm_array_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
  983. return 0;
  984. }
  985. else if (scm_is_false (scm_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
  986. return 0;
  987. }
  988. return 1;
  989. }
  990. else
  991. return 0;
  992. }
  993. static int
  994. raeql (SCM ra0, SCM as_equal, SCM ra1)
  995. {
  996. SCM v0 = ra0, v1 = ra1;
  997. scm_t_array_dim dim0, dim1;
  998. scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
  999. unsigned long bas0 = 0, bas1 = 0;
  1000. int k, unroll = 1, vlen = 1, ndim = 1;
  1001. if (SCM_I_ARRAYP (ra0))
  1002. {
  1003. ndim = SCM_I_ARRAY_NDIM (ra0);
  1004. s0 = SCM_I_ARRAY_DIMS (ra0);
  1005. bas0 = SCM_I_ARRAY_BASE (ra0);
  1006. v0 = SCM_I_ARRAY_V (ra0);
  1007. }
  1008. else
  1009. {
  1010. s0->inc = 1;
  1011. s0->lbnd = 0;
  1012. s0->ubnd = scm_c_generalized_vector_length (v0) - 1;
  1013. unroll = 0;
  1014. }
  1015. if (SCM_I_ARRAYP (ra1))
  1016. {
  1017. if (ndim != SCM_I_ARRAY_NDIM (ra1))
  1018. return 0;
  1019. s1 = SCM_I_ARRAY_DIMS (ra1);
  1020. bas1 = SCM_I_ARRAY_BASE (ra1);
  1021. v1 = SCM_I_ARRAY_V (ra1);
  1022. }
  1023. else
  1024. {
  1025. /*
  1026. Huh ? Schizophrenic return type. --hwn
  1027. */
  1028. if (1 != ndim)
  1029. return 0;
  1030. s1->inc = 1;
  1031. s1->lbnd = 0;
  1032. s1->ubnd = scm_c_generalized_vector_length (v1) - 1;
  1033. unroll = 0;
  1034. }
  1035. if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
  1036. return 0;
  1037. for (k = ndim; k--;)
  1038. {
  1039. if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
  1040. return 0;
  1041. if (unroll)
  1042. {
  1043. unroll = (s0[k].inc == s1[k].inc);
  1044. vlen *= s0[k].ubnd - s1[k].lbnd + 1;
  1045. }
  1046. }
  1047. if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
  1048. return 1;
  1049. return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
  1050. }
  1051. SCM
  1052. scm_raequal (SCM ra0, SCM ra1)
  1053. {
  1054. return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
  1055. }
  1056. #if 0
  1057. /* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
  1058. SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
  1059. (SCM ra0, SCM ra1),
  1060. "Return @code{#t} iff all arguments are arrays with the same\n"
  1061. "shape, the same type, and have corresponding elements which are\n"
  1062. "either @code{equal?} or @code{array-equal?}. This function\n"
  1063. "differs from @code{equal?} in that a one dimensional shared\n"
  1064. "array may be @var{array-equal?} but not @var{equal?} to a\n"
  1065. "vector or uniform vector.")
  1066. #define FUNC_NAME s_scm_array_equal_p
  1067. {
  1068. }
  1069. #undef FUNC_NAME
  1070. #endif
  1071. static char s_array_equal_p[] = "array-equal?";
  1072. SCM
  1073. scm_array_equal_p (SCM ra0, SCM ra1)
  1074. {
  1075. if (SCM_I_ARRAYP (ra0) || SCM_I_ARRAYP (ra1))
  1076. return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
  1077. return scm_equal_p (ra0, ra1);
  1078. }
  1079. static void
  1080. init_raprocs (ra_iproc *subra)
  1081. {
  1082. for (; subra->name; subra++)
  1083. {
  1084. SCM sym = scm_from_locale_symbol (subra->name);
  1085. SCM var =
  1086. scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
  1087. if (var != SCM_BOOL_F)
  1088. subra->sproc = SCM_VARIABLE_REF (var);
  1089. else
  1090. subra->sproc = SCM_BOOL_F;
  1091. }
  1092. }
  1093. void
  1094. scm_init_ramap ()
  1095. {
  1096. init_raprocs (ra_rpsubrs);
  1097. init_raprocs (ra_asubrs);
  1098. scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
  1099. scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal;
  1100. #include "libguile/ramap.x"
  1101. scm_add_feature (s_scm_array_for_each);
  1102. }
  1103. /*
  1104. Local Variables:
  1105. c-file-style: "gnu"
  1106. End:
  1107. */