ramap.c 32 KB

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