unif.c 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634
  1. /* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2004 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program 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
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. * Boston, MA 02110-1301 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. /*
  42. This file has code for arrays in lots of variants (double, integer,
  43. unsigned etc. ). It suffers from hugely repetitive code because
  44. there is similar (but different) code for every variant included. (urg.)
  45. --hwn
  46. */
  47. #include <stdio.h>
  48. #include <errno.h>
  49. #include <string.h>
  50. #include "libguile/_scm.h"
  51. #include "libguile/chars.h"
  52. #include "libguile/eval.h"
  53. #include "libguile/fports.h"
  54. #include "libguile/smob.h"
  55. #include "libguile/strop.h"
  56. #include "libguile/feature.h"
  57. #include "libguile/root.h"
  58. #include "libguile/strings.h"
  59. #include "libguile/vectors.h"
  60. #include "libguile/validate.h"
  61. #include "libguile/unif.h"
  62. #include "libguile/ramap.h"
  63. #ifdef HAVE_UNISTD_H
  64. #include <unistd.h>
  65. #endif
  66. #ifdef HAVE_IO_H
  67. #include <io.h>
  68. #endif
  69. /* The set of uniform scm_vector types is:
  70. * Vector of: Called:
  71. * unsigned char string
  72. * char byvect
  73. * boolean bvect
  74. * signed long ivect
  75. * unsigned long uvect
  76. * float fvect
  77. * double dvect
  78. * complex double cvect
  79. * short svect
  80. * long long llvect
  81. */
  82. scm_t_bits scm_tc16_array;
  83. /* return the size of an element in a uniform array or 0 if type not
  84. found. */
  85. size_t
  86. scm_uniform_element_size (SCM obj)
  87. {
  88. size_t result;
  89. switch (SCM_TYP7 (obj))
  90. {
  91. case scm_tc7_bvect:
  92. case scm_tc7_uvect:
  93. case scm_tc7_ivect:
  94. result = sizeof (long);
  95. break;
  96. case scm_tc7_byvect:
  97. result = sizeof (char);
  98. break;
  99. case scm_tc7_svect:
  100. result = sizeof (short);
  101. break;
  102. #ifdef HAVE_LONG_LONGS
  103. case scm_tc7_llvect:
  104. result = sizeof (long long);
  105. break;
  106. #endif
  107. case scm_tc7_fvect:
  108. result = sizeof (float);
  109. break;
  110. case scm_tc7_dvect:
  111. result = sizeof (double);
  112. break;
  113. case scm_tc7_cvect:
  114. result = 2 * sizeof (double);
  115. break;
  116. default:
  117. result = 0;
  118. }
  119. return result;
  120. }
  121. /* Silly function used not to modify the semantics of the silly
  122. * prototype system in order to be backward compatible.
  123. */
  124. static int
  125. singp (SCM obj)
  126. {
  127. if (!SCM_SLOPPY_REALP (obj))
  128. return 0;
  129. else
  130. {
  131. double x = SCM_REAL_VALUE (obj);
  132. float fx = x;
  133. return (- SCM_FLTMAX < x) && (x < SCM_FLTMAX) && (fx == x);
  134. }
  135. }
  136. SCM
  137. scm_make_uve (long k, SCM prot)
  138. #define FUNC_NAME "scm_make_uve"
  139. {
  140. SCM v;
  141. long i, type;
  142. if (SCM_EQ_P (prot, SCM_BOOL_T))
  143. {
  144. SCM_NEWCELL (v);
  145. if (k > 0)
  146. {
  147. SCM_ASSERT_RANGE (1, scm_long2num (k), k <= SCM_BITVECTOR_MAX_LENGTH);
  148. i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
  149. SCM_SET_BITVECTOR_BASE (v, (char *) scm_must_malloc (i, "vector"));
  150. SCM_SET_BITVECTOR_LENGTH (v, k);
  151. }
  152. else
  153. {
  154. SCM_SET_BITVECTOR_BASE (v, 0);
  155. SCM_SET_BITVECTOR_LENGTH (v, 0);
  156. }
  157. return v;
  158. }
  159. else if (SCM_CHARP (prot) && (SCM_CHAR (prot) == '\0'))
  160. {
  161. i = sizeof (char) * k;
  162. type = scm_tc7_byvect;
  163. }
  164. else if (SCM_CHARP (prot))
  165. {
  166. i = sizeof (char) * k;
  167. return scm_allocate_string (i);
  168. }
  169. else if (SCM_INUMP (prot))
  170. {
  171. i = sizeof (long) * k;
  172. if (SCM_INUM (prot) > 0)
  173. type = scm_tc7_uvect;
  174. else
  175. type = scm_tc7_ivect;
  176. }
  177. else if (SCM_SYMBOLP (prot) && (1 == SCM_SYMBOL_LENGTH (prot)))
  178. {
  179. char s;
  180. s = SCM_SYMBOL_CHARS (prot)[0];
  181. if (s == 's')
  182. {
  183. i = sizeof (short) * k;
  184. type = scm_tc7_svect;
  185. }
  186. #ifdef HAVE_LONG_LONGS
  187. else if (s == 'l')
  188. {
  189. i = sizeof (long long) * k;
  190. type = scm_tc7_llvect;
  191. }
  192. #endif
  193. else
  194. {
  195. return scm_c_make_vector (k, SCM_UNDEFINED);
  196. }
  197. }
  198. else if (!SCM_INEXACTP (prot))
  199. /* Huge non-unif vectors are NOT supported. */
  200. /* no special scm_vector */
  201. return scm_c_make_vector (k, SCM_UNDEFINED);
  202. else if (singp (prot))
  203. {
  204. i = sizeof (float) * k;
  205. type = scm_tc7_fvect;
  206. }
  207. else if (SCM_COMPLEXP (prot))
  208. {
  209. i = 2 * sizeof (double) * k;
  210. type = scm_tc7_cvect;
  211. }
  212. else
  213. {
  214. i = sizeof (double) * k;
  215. type = scm_tc7_dvect;
  216. }
  217. SCM_ASSERT_RANGE (1, scm_long2num (k), k <= SCM_UVECTOR_MAX_LENGTH);
  218. SCM_NEWCELL (v);
  219. SCM_DEFER_INTS;
  220. SCM_SET_UVECTOR_BASE (v, (char *) scm_must_malloc (i ? i : 1, "vector"));
  221. SCM_SET_UVECTOR_LENGTH (v, k, type);
  222. SCM_ALLOW_INTS;
  223. return v;
  224. }
  225. #undef FUNC_NAME
  226. SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
  227. (SCM v),
  228. "Return the number of elements in @var{uve}.")
  229. #define FUNC_NAME s_scm_uniform_vector_length
  230. {
  231. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  232. switch SCM_TYP7 (v)
  233. {
  234. default:
  235. badarg1:SCM_WRONG_TYPE_ARG (1, v);
  236. case scm_tc7_vector:
  237. case scm_tc7_wvect:
  238. return SCM_MAKINUM (SCM_VECTOR_LENGTH (v));
  239. case scm_tc7_string:
  240. return SCM_MAKINUM (SCM_STRING_LENGTH (v));
  241. case scm_tc7_bvect:
  242. return SCM_MAKINUM (SCM_BITVECTOR_LENGTH (v));
  243. case scm_tc7_byvect:
  244. case scm_tc7_uvect:
  245. case scm_tc7_ivect:
  246. case scm_tc7_fvect:
  247. case scm_tc7_dvect:
  248. case scm_tc7_cvect:
  249. case scm_tc7_svect:
  250. #ifdef HAVE_LONG_LONGS
  251. case scm_tc7_llvect:
  252. #endif
  253. return SCM_MAKINUM (SCM_UVECTOR_LENGTH (v));
  254. }
  255. }
  256. #undef FUNC_NAME
  257. SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
  258. (SCM v, SCM prot),
  259. "Return @code{#t} if the @var{obj} is an array, and @code{#f} if\n"
  260. "not. The @var{prototype} argument is used with uniform arrays\n"
  261. "and is described elsewhere.")
  262. #define FUNC_NAME s_scm_array_p
  263. {
  264. int nprot;
  265. int enclosed;
  266. nprot = SCM_UNBNDP (prot);
  267. enclosed = 0;
  268. if (SCM_IMP (v))
  269. return SCM_BOOL_F;
  270. while (SCM_TYP7 (v) == scm_tc7_smob)
  271. {
  272. if (!SCM_ARRAYP (v))
  273. return SCM_BOOL_F;
  274. if (nprot)
  275. return SCM_BOOL_T;
  276. if (enclosed++)
  277. return SCM_BOOL_F;
  278. v = SCM_ARRAY_V (v);
  279. }
  280. if (nprot)
  281. return SCM_BOOL(nprot);
  282. else
  283. {
  284. int protp = 0;
  285. switch (SCM_TYP7 (v))
  286. {
  287. case scm_tc7_bvect:
  288. protp = (SCM_EQ_P (prot, SCM_BOOL_T));
  289. break;
  290. case scm_tc7_string:
  291. protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
  292. break;
  293. case scm_tc7_byvect:
  294. protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
  295. break;
  296. case scm_tc7_uvect:
  297. protp = SCM_INUMP(prot) && SCM_INUM(prot)>0;
  298. break;
  299. case scm_tc7_ivect:
  300. protp = SCM_INUMP(prot) && SCM_INUM(prot)<=0;
  301. break;
  302. case scm_tc7_svect:
  303. protp = SCM_SYMBOLP (prot)
  304. && (1 == SCM_SYMBOL_LENGTH (prot))
  305. && ('s' == SCM_SYMBOL_CHARS (prot)[0]);
  306. break;
  307. #ifdef HAVE_LONG_LONGS
  308. case scm_tc7_llvect:
  309. protp = SCM_SYMBOLP (prot)
  310. && (1 == SCM_SYMBOL_LENGTH (prot))
  311. && ('l' == SCM_SYMBOL_CHARS (prot)[0]);
  312. break;
  313. #endif
  314. case scm_tc7_fvect:
  315. protp = (SCM_NIMP (prot) && singp (prot));
  316. break;
  317. case scm_tc7_dvect:
  318. protp = (SCM_REALP (prot) && ! singp (prot));
  319. break;
  320. case scm_tc7_cvect:
  321. protp = SCM_COMPLEXP(prot);
  322. break;
  323. case scm_tc7_vector:
  324. case scm_tc7_wvect:
  325. protp = SCM_NULLP(prot);
  326. break;
  327. default:
  328. /* no default */
  329. ;
  330. }
  331. return SCM_BOOL(protp);
  332. }
  333. }
  334. #undef FUNC_NAME
  335. SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
  336. (SCM ra),
  337. "Return the number of dimensions of @var{obj}. If @var{obj} is\n"
  338. "not an array, @code{0} is returned.")
  339. #define FUNC_NAME s_scm_array_rank
  340. {
  341. if (SCM_IMP (ra))
  342. return SCM_INUM0;
  343. switch (SCM_TYP7 (ra))
  344. {
  345. default:
  346. return SCM_INUM0;
  347. case scm_tc7_string:
  348. case scm_tc7_vector:
  349. case scm_tc7_wvect:
  350. case scm_tc7_byvect:
  351. case scm_tc7_uvect:
  352. case scm_tc7_ivect:
  353. case scm_tc7_fvect:
  354. case scm_tc7_cvect:
  355. case scm_tc7_dvect:
  356. #ifdef HAVE_LONG_LONGS
  357. case scm_tc7_llvect:
  358. #endif
  359. case scm_tc7_svect:
  360. return SCM_MAKINUM (1L);
  361. case scm_tc7_smob:
  362. if (SCM_ARRAYP (ra))
  363. return SCM_MAKINUM (SCM_ARRAY_NDIM (ra));
  364. return SCM_INUM0;
  365. }
  366. }
  367. #undef FUNC_NAME
  368. SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
  369. (SCM ra),
  370. "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
  371. "elements with a @code{0} minimum with one greater than the maximum. So:\n"
  372. "@lisp\n"
  373. "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
  374. "@end lisp")
  375. #define FUNC_NAME s_scm_array_dimensions
  376. {
  377. SCM res = SCM_EOL;
  378. size_t k;
  379. scm_t_array_dim *s;
  380. if (SCM_IMP (ra))
  381. return SCM_BOOL_F;
  382. switch (SCM_TYP7 (ra))
  383. {
  384. default:
  385. return SCM_BOOL_F;
  386. case scm_tc7_string:
  387. case scm_tc7_vector:
  388. case scm_tc7_wvect:
  389. case scm_tc7_bvect:
  390. case scm_tc7_byvect:
  391. case scm_tc7_uvect:
  392. case scm_tc7_ivect:
  393. case scm_tc7_fvect:
  394. case scm_tc7_cvect:
  395. case scm_tc7_dvect:
  396. case scm_tc7_svect:
  397. #ifdef HAVE_LONG_LONGS
  398. case scm_tc7_llvect:
  399. #endif
  400. return scm_cons (scm_uniform_vector_length (ra), SCM_EOL);
  401. case scm_tc7_smob:
  402. if (!SCM_ARRAYP (ra))
  403. return SCM_BOOL_F;
  404. k = SCM_ARRAY_NDIM (ra);
  405. s = SCM_ARRAY_DIMS (ra);
  406. while (k--)
  407. res = scm_cons (s[k].lbnd
  408. ? scm_cons2 (SCM_MAKINUM (s[k].lbnd),
  409. SCM_MAKINUM (s[k].ubnd),
  410. SCM_EOL)
  411. : SCM_MAKINUM (1 + s[k].ubnd),
  412. res);
  413. return res;
  414. }
  415. }
  416. #undef FUNC_NAME
  417. SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
  418. (SCM ra),
  419. "Return the root vector of a shared array.")
  420. #define FUNC_NAME s_scm_shared_array_root
  421. {
  422. SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
  423. return SCM_ARRAY_V (ra);
  424. }
  425. #undef FUNC_NAME
  426. SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
  427. (SCM ra),
  428. "Return the root vector index of the first element in the array.")
  429. #define FUNC_NAME s_scm_shared_array_offset
  430. {
  431. SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
  432. return SCM_MAKINUM (SCM_ARRAY_BASE (ra));
  433. }
  434. #undef FUNC_NAME
  435. SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
  436. (SCM ra),
  437. "For each dimension, return the distance between elements in the root vector.")
  438. #define FUNC_NAME s_scm_shared_array_increments
  439. {
  440. SCM res = SCM_EOL;
  441. size_t k;
  442. scm_t_array_dim *s;
  443. SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
  444. k = SCM_ARRAY_NDIM (ra);
  445. s = SCM_ARRAY_DIMS (ra);
  446. while (k--)
  447. res = scm_cons (SCM_MAKINUM (s[k].inc), res);
  448. return res;
  449. }
  450. #undef FUNC_NAME
  451. static char s_bad_ind[] = "Bad scm_array index";
  452. long
  453. scm_aind (SCM ra, SCM args, const char *what)
  454. #define FUNC_NAME what
  455. {
  456. SCM ind;
  457. register long j;
  458. register unsigned long pos = SCM_ARRAY_BASE (ra);
  459. register unsigned long k = SCM_ARRAY_NDIM (ra);
  460. scm_t_array_dim *s = SCM_ARRAY_DIMS (ra);
  461. if (SCM_INUMP (args))
  462. {
  463. if (k != 1)
  464. scm_error_num_args_subr (what);
  465. return pos + (SCM_INUM (args) - s->lbnd) * (s->inc);
  466. }
  467. while (k && SCM_CONSP (args))
  468. {
  469. ind = SCM_CAR (args);
  470. args = SCM_CDR (args);
  471. if (!SCM_INUMP (ind))
  472. scm_misc_error (what, s_bad_ind, SCM_EOL);
  473. j = SCM_INUM (ind);
  474. if (j < s->lbnd || j > s->ubnd)
  475. scm_out_of_range (what, ind);
  476. pos += (j - s->lbnd) * (s->inc);
  477. k--;
  478. s++;
  479. }
  480. if (k != 0 || !SCM_NULLP (args))
  481. scm_error_num_args_subr (what);
  482. return pos;
  483. }
  484. #undef FUNC_NAME
  485. SCM
  486. scm_make_ra (int ndim)
  487. {
  488. SCM ra;
  489. SCM_NEWCELL (ra);
  490. SCM_DEFER_INTS;
  491. SCM_NEWSMOB(ra, ((scm_t_bits) ndim << 17) + scm_tc16_array,
  492. scm_must_malloc ((sizeof (scm_t_array) +
  493. ndim * sizeof (scm_t_array_dim)),
  494. "array"));
  495. SCM_ARRAY_V (ra) = scm_nullvect;
  496. SCM_ALLOW_INTS;
  497. return ra;
  498. }
  499. static char s_bad_spec[] = "Bad scm_array dimension";
  500. /* Increments will still need to be set. */
  501. SCM
  502. scm_shap2ra (SCM args, const char *what)
  503. {
  504. scm_t_array_dim *s;
  505. SCM ra, spec, sp;
  506. int ndim = scm_ilength (args);
  507. if (ndim < 0)
  508. scm_misc_error (what, s_bad_spec, SCM_EOL);
  509. ra = scm_make_ra (ndim);
  510. SCM_ARRAY_BASE (ra) = 0;
  511. s = SCM_ARRAY_DIMS (ra);
  512. for (; !SCM_NULLP (args); s++, args = SCM_CDR (args))
  513. {
  514. spec = SCM_CAR (args);
  515. if (SCM_INUMP (spec))
  516. {
  517. if (SCM_INUM (spec) < 0)
  518. scm_misc_error (what, s_bad_spec, SCM_EOL);
  519. s->lbnd = 0;
  520. s->ubnd = SCM_INUM (spec) - 1;
  521. s->inc = 1;
  522. }
  523. else
  524. {
  525. if (!SCM_CONSP (spec) || !SCM_INUMP (SCM_CAR (spec)))
  526. scm_misc_error (what, s_bad_spec, SCM_EOL);
  527. s->lbnd = SCM_INUM (SCM_CAR (spec));
  528. sp = SCM_CDR (spec);
  529. if (!SCM_CONSP (sp)
  530. || !SCM_INUMP (SCM_CAR (sp))
  531. || !SCM_NULLP (SCM_CDR (sp)))
  532. scm_misc_error (what, s_bad_spec, SCM_EOL);
  533. s->ubnd = SCM_INUM (SCM_CAR (sp));
  534. s->inc = 1;
  535. }
  536. }
  537. return ra;
  538. }
  539. SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
  540. (SCM dims, SCM prot, SCM fill),
  541. "@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]\n"
  542. "Create and return a uniform array or vector of type\n"
  543. "corresponding to @var{prototype} with dimensions @var{dims} or\n"
  544. "length @var{length}. If @var{fill} is supplied, it's used to\n"
  545. "fill the array, otherwise @var{prototype} is used.")
  546. #define FUNC_NAME s_scm_dimensions_to_uniform_array
  547. {
  548. size_t k;
  549. unsigned long rlen = 1;
  550. scm_t_array_dim *s;
  551. SCM ra;
  552. if (SCM_INUMP (dims))
  553. {
  554. SCM answer = scm_make_uve (SCM_INUM (dims), prot);
  555. if (!SCM_UNBNDP (fill))
  556. scm_array_fill_x (answer, fill);
  557. else if (SCM_SYMBOLP (prot))
  558. scm_array_fill_x (answer, SCM_MAKINUM (0));
  559. else
  560. scm_array_fill_x (answer, prot);
  561. return answer;
  562. }
  563. SCM_ASSERT (SCM_NULLP (dims) || SCM_CONSP (dims),
  564. dims, SCM_ARG1, FUNC_NAME);
  565. ra = scm_shap2ra (dims, FUNC_NAME);
  566. SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
  567. s = SCM_ARRAY_DIMS (ra);
  568. k = SCM_ARRAY_NDIM (ra);
  569. while (k--)
  570. {
  571. s[k].inc = rlen;
  572. SCM_ASSERT_RANGE (1, dims, s[k].lbnd <= s[k].ubnd);
  573. rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
  574. }
  575. SCM_ARRAY_V (ra) = scm_make_uve (rlen, prot);
  576. if (!SCM_UNBNDP (fill))
  577. scm_array_fill_x (ra, fill);
  578. else if (SCM_SYMBOLP (prot))
  579. scm_array_fill_x (ra, SCM_MAKINUM (0));
  580. else
  581. scm_array_fill_x (ra, prot);
  582. if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
  583. if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
  584. return SCM_ARRAY_V (ra);
  585. return ra;
  586. }
  587. #undef FUNC_NAME
  588. void
  589. scm_ra_set_contp (SCM ra)
  590. {
  591. size_t k = SCM_ARRAY_NDIM (ra);
  592. if (k)
  593. {
  594. long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
  595. while (k--)
  596. {
  597. if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
  598. {
  599. SCM_CLR_ARRAY_CONTIGUOUS_FLAG (ra);
  600. return;
  601. }
  602. inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
  603. - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
  604. }
  605. }
  606. SCM_SET_ARRAY_CONTIGUOUS_FLAG (ra);
  607. }
  608. SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
  609. (SCM oldra, SCM mapfunc, SCM dims),
  610. "@code{make-shared-array} can be used to create shared subarrays of other\n"
  611. "arrays. The @var{mapper} is a function that translates coordinates in\n"
  612. "the new array into coordinates in the old array. A @var{mapper} must be\n"
  613. "linear, and its range must stay within the bounds of the old array, but\n"
  614. "it can be otherwise arbitrary. A simple example:\n"
  615. "@lisp\n"
  616. "(define fred (make-array #f 8 8))\n"
  617. "(define freds-diagonal\n"
  618. " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
  619. "(array-set! freds-diagonal 'foo 3)\n"
  620. "(array-ref fred 3 3) @result{} foo\n"
  621. "(define freds-center\n"
  622. " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
  623. "(array-ref freds-center 0 0) @result{} foo\n"
  624. "@end lisp")
  625. #define FUNC_NAME s_scm_make_shared_array
  626. {
  627. SCM ra;
  628. SCM inds, indptr;
  629. SCM imap;
  630. size_t k, i;
  631. long old_min, new_min, old_max, new_max;
  632. scm_t_array_dim *s;
  633. SCM_VALIDATE_REST_ARGUMENT (dims);
  634. SCM_VALIDATE_ARRAY (1,oldra);
  635. SCM_VALIDATE_PROC (2,mapfunc);
  636. ra = scm_shap2ra (dims, FUNC_NAME);
  637. if (SCM_ARRAYP (oldra))
  638. {
  639. SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
  640. old_min = old_max = SCM_ARRAY_BASE (oldra);
  641. s = SCM_ARRAY_DIMS (oldra);
  642. k = SCM_ARRAY_NDIM (oldra);
  643. while (k--)
  644. {
  645. if (s[k].inc > 0)
  646. old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
  647. else
  648. old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
  649. }
  650. }
  651. else
  652. {
  653. SCM_ARRAY_V (ra) = oldra;
  654. old_min = 0;
  655. old_max = SCM_INUM (scm_uniform_vector_length (oldra)) - 1;
  656. }
  657. inds = SCM_EOL;
  658. s = SCM_ARRAY_DIMS (ra);
  659. for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
  660. {
  661. inds = scm_cons (SCM_MAKINUM (s[k].lbnd), inds);
  662. if (s[k].ubnd < s[k].lbnd)
  663. {
  664. if (1 == SCM_ARRAY_NDIM (ra))
  665. ra = scm_make_uve (0L, scm_array_prototype (ra));
  666. else
  667. SCM_ARRAY_V (ra) = scm_make_uve (0L, scm_array_prototype (ra));
  668. return ra;
  669. }
  670. }
  671. imap = scm_apply_0 (mapfunc, scm_reverse (inds));
  672. if (SCM_ARRAYP (oldra))
  673. i = (size_t) scm_aind (oldra, imap, FUNC_NAME);
  674. else
  675. {
  676. if (SCM_NINUMP (imap))
  677. {
  678. if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
  679. SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
  680. imap = SCM_CAR (imap);
  681. }
  682. i = SCM_INUM (imap);
  683. }
  684. SCM_ARRAY_BASE (ra) = new_min = new_max = i;
  685. indptr = inds;
  686. k = SCM_ARRAY_NDIM (ra);
  687. while (k--)
  688. {
  689. if (s[k].ubnd > s[k].lbnd)
  690. {
  691. SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
  692. imap = scm_apply_0 (mapfunc, scm_reverse (inds));
  693. if (SCM_ARRAYP (oldra))
  694. s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
  695. else
  696. {
  697. if (SCM_NINUMP (imap))
  698. {
  699. if (scm_ilength (imap) != 1 || !SCM_INUMP (SCM_CAR (imap)))
  700. SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
  701. imap = SCM_CAR (imap);
  702. }
  703. s[k].inc = (long) SCM_INUM (imap) - i;
  704. }
  705. i += s[k].inc;
  706. if (s[k].inc > 0)
  707. new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
  708. else
  709. new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
  710. }
  711. else
  712. s[k].inc = new_max - new_min + 1; /* contiguous by default */
  713. indptr = SCM_CDR (indptr);
  714. }
  715. if (old_min > new_min || old_max < new_max)
  716. SCM_MISC_ERROR ("mapping out of range", SCM_EOL);
  717. if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
  718. {
  719. SCM v = SCM_ARRAY_V (ra);
  720. unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
  721. if (1 == s->inc && 0 == s->lbnd && length == 1 + s->ubnd)
  722. return v;
  723. if (s->ubnd < s->lbnd)
  724. return scm_make_uve (0L, scm_array_prototype (ra));
  725. }
  726. scm_ra_set_contp (ra);
  727. return ra;
  728. }
  729. #undef FUNC_NAME
  730. /* args are RA . DIMS */
  731. SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
  732. (SCM ra, SCM args),
  733. "Return an array sharing contents with @var{array}, but with\n"
  734. "dimensions arranged in a different order. There must be one\n"
  735. "@var{dim} argument for each dimension of @var{array}.\n"
  736. "@var{dim0}, @var{dim1}, @dots{} should be integers between 0\n"
  737. "and the rank of the array to be returned. Each integer in that\n"
  738. "range must appear at least once in the argument list.\n"
  739. "\n"
  740. "The values of @var{dim0}, @var{dim1}, @dots{} correspond to\n"
  741. "dimensions in the array to be returned, their positions in the\n"
  742. "argument list to dimensions of @var{array}. Several @var{dim}s\n"
  743. "may have the same value, in which case the returned array will\n"
  744. "have smaller rank than @var{array}.\n"
  745. "\n"
  746. "@lisp\n"
  747. "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
  748. "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
  749. "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
  750. " #2((a 4) (b 5) (c 6))\n"
  751. "@end lisp")
  752. #define FUNC_NAME s_scm_transpose_array
  753. {
  754. SCM res, vargs, *ve = &vargs;
  755. scm_t_array_dim *s, *r;
  756. int ndim, i, k;
  757. SCM_VALIDATE_REST_ARGUMENT (args);
  758. SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
  759. switch (SCM_TYP7 (ra))
  760. {
  761. default:
  762. badarg:SCM_WRONG_TYPE_ARG (1, ra);
  763. case scm_tc7_bvect:
  764. case scm_tc7_string:
  765. case scm_tc7_byvect:
  766. case scm_tc7_uvect:
  767. case scm_tc7_ivect:
  768. case scm_tc7_fvect:
  769. case scm_tc7_dvect:
  770. case scm_tc7_cvect:
  771. case scm_tc7_svect:
  772. #ifdef HAVE_LONG_LONGS
  773. case scm_tc7_llvect:
  774. #endif
  775. if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
  776. SCM_WRONG_NUM_ARGS ();
  777. SCM_VALIDATE_INUM (SCM_ARG2, SCM_CAR (args));
  778. SCM_ASSERT_RANGE (SCM_ARG2, SCM_CAR (args),
  779. SCM_EQ_P (SCM_INUM0, SCM_CAR (args)));
  780. return ra;
  781. case scm_tc7_smob:
  782. SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
  783. vargs = scm_vector (args);
  784. if (SCM_VECTOR_LENGTH (vargs) != SCM_ARRAY_NDIM (ra))
  785. SCM_WRONG_NUM_ARGS ();
  786. ve = SCM_VELTS (vargs);
  787. ndim = 0;
  788. for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
  789. {
  790. SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
  791. FUNC_NAME);
  792. i = SCM_INUM (ve[k]);
  793. if (i < 0 || i >= SCM_ARRAY_NDIM (ra))
  794. scm_out_of_range (FUNC_NAME, ve[k]);
  795. if (ndim < i)
  796. ndim = i;
  797. }
  798. ndim++;
  799. res = scm_make_ra (ndim);
  800. SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
  801. SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
  802. for (k = ndim; k--;)
  803. {
  804. SCM_ARRAY_DIMS (res)[k].lbnd = 0;
  805. SCM_ARRAY_DIMS (res)[k].ubnd = -1;
  806. }
  807. for (k = SCM_ARRAY_NDIM (ra); k--;)
  808. {
  809. i = SCM_INUM (ve[k]);
  810. s = &(SCM_ARRAY_DIMS (ra)[k]);
  811. r = &(SCM_ARRAY_DIMS (res)[i]);
  812. if (r->ubnd < r->lbnd)
  813. {
  814. r->lbnd = s->lbnd;
  815. r->ubnd = s->ubnd;
  816. r->inc = s->inc;
  817. ndim--;
  818. }
  819. else
  820. {
  821. if (r->ubnd > s->ubnd)
  822. r->ubnd = s->ubnd;
  823. if (r->lbnd < s->lbnd)
  824. {
  825. SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
  826. r->lbnd = s->lbnd;
  827. }
  828. r->inc += s->inc;
  829. }
  830. }
  831. if (ndim > 0)
  832. SCM_MISC_ERROR ("bad argument list", SCM_EOL);
  833. scm_ra_set_contp (res);
  834. return res;
  835. }
  836. }
  837. #undef FUNC_NAME
  838. /* args are RA . AXES */
  839. SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
  840. (SCM ra, SCM axes),
  841. "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
  842. "the rank of @var{array}. @var{enclose-array} returns an array\n"
  843. "resembling an array of shared arrays. The dimensions of each shared\n"
  844. "array are the same as the @var{dim}th dimensions of the original array,\n"
  845. "the dimensions of the outer array are the same as those of the original\n"
  846. "array that did not match a @var{dim}.\n\n"
  847. "An enclosed array is not a general Scheme array. Its elements may not\n"
  848. "be set using @code{array-set!}. Two references to the same element of\n"
  849. "an enclosed array will be @code{equal?} but will not in general be\n"
  850. "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
  851. "enclosed array is unspecified.\n\n"
  852. "examples:\n"
  853. "@lisp\n"
  854. "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
  855. " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
  856. "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
  857. " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
  858. "@end lisp")
  859. #define FUNC_NAME s_scm_enclose_array
  860. {
  861. SCM axv, res, ra_inr;
  862. scm_t_array_dim vdim, *s = &vdim;
  863. int ndim, j, k, ninr, noutr;
  864. SCM_VALIDATE_REST_ARGUMENT (axes);
  865. if (SCM_NULLP (axes))
  866. axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
  867. ninr = scm_ilength (axes);
  868. if (ninr < 0)
  869. SCM_WRONG_NUM_ARGS ();
  870. ra_inr = scm_make_ra (ninr);
  871. SCM_ASRTGO (SCM_NIMP (ra), badarg1);
  872. switch SCM_TYP7 (ra)
  873. {
  874. default:
  875. badarg1:SCM_WRONG_TYPE_ARG (1, ra);
  876. case scm_tc7_string:
  877. case scm_tc7_bvect:
  878. case scm_tc7_byvect:
  879. case scm_tc7_uvect:
  880. case scm_tc7_ivect:
  881. case scm_tc7_fvect:
  882. case scm_tc7_dvect:
  883. case scm_tc7_cvect:
  884. case scm_tc7_vector:
  885. case scm_tc7_wvect:
  886. case scm_tc7_svect:
  887. #ifdef HAVE_LONG_LONGS
  888. case scm_tc7_llvect:
  889. #endif
  890. s->lbnd = 0;
  891. s->ubnd = SCM_INUM (scm_uniform_vector_length (ra)) - 1;
  892. s->inc = 1;
  893. SCM_ARRAY_V (ra_inr) = ra;
  894. SCM_ARRAY_BASE (ra_inr) = 0;
  895. ndim = 1;
  896. break;
  897. case scm_tc7_smob:
  898. SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
  899. s = SCM_ARRAY_DIMS (ra);
  900. SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
  901. SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
  902. ndim = SCM_ARRAY_NDIM (ra);
  903. break;
  904. }
  905. noutr = ndim - ninr;
  906. if (noutr < 0)
  907. SCM_WRONG_NUM_ARGS ();
  908. axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
  909. res = scm_make_ra (noutr);
  910. SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
  911. SCM_ARRAY_V (res) = ra_inr;
  912. for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
  913. {
  914. if (!SCM_INUMP (SCM_CAR (axes)))
  915. SCM_MISC_ERROR ("bad axis", SCM_EOL);
  916. j = SCM_INUM (SCM_CAR (axes));
  917. SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
  918. SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
  919. SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
  920. SCM_STRING_CHARS (axv)[j] = 1;
  921. }
  922. for (j = 0, k = 0; k < noutr; k++, j++)
  923. {
  924. while (SCM_STRING_CHARS (axv)[j])
  925. j++;
  926. SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
  927. SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
  928. SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
  929. }
  930. scm_ra_set_contp (ra_inr);
  931. scm_ra_set_contp (res);
  932. return res;
  933. }
  934. #undef FUNC_NAME
  935. SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
  936. (SCM v, SCM args),
  937. "Return @code{#t} if its arguments would be acceptable to\n"
  938. "@code{array-ref}.")
  939. #define FUNC_NAME s_scm_array_in_bounds_p
  940. {
  941. SCM ind = SCM_EOL;
  942. long pos = 0;
  943. register size_t k;
  944. register long j;
  945. scm_t_array_dim *s;
  946. SCM_VALIDATE_REST_ARGUMENT (args);
  947. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  948. if (SCM_NIMP (args))
  949. {
  950. ind = SCM_CAR (args);
  951. args = SCM_CDR (args);
  952. SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
  953. pos = SCM_INUM (ind);
  954. }
  955. tail:
  956. switch SCM_TYP7 (v)
  957. {
  958. default:
  959. badarg1:SCM_WRONG_TYPE_ARG (1, v);
  960. wna: SCM_WRONG_NUM_ARGS ();
  961. case scm_tc7_smob:
  962. k = SCM_ARRAY_NDIM (v);
  963. s = SCM_ARRAY_DIMS (v);
  964. pos = SCM_ARRAY_BASE (v);
  965. if (!k)
  966. {
  967. SCM_ASRTGO (SCM_NULLP (ind), wna);
  968. ind = SCM_INUM0;
  969. }
  970. else
  971. while (!0)
  972. {
  973. j = SCM_INUM (ind);
  974. if (!(j >= (s->lbnd) && j <= (s->ubnd)))
  975. {
  976. SCM_ASRTGO (--k == scm_ilength (args), wna);
  977. return SCM_BOOL_F;
  978. }
  979. pos += (j - s->lbnd) * (s->inc);
  980. if (!(--k && SCM_NIMP (args)))
  981. break;
  982. ind = SCM_CAR (args);
  983. args = SCM_CDR (args);
  984. s++;
  985. if (!SCM_INUMP (ind))
  986. SCM_MISC_ERROR (s_bad_ind, SCM_EOL);
  987. }
  988. SCM_ASRTGO (0 == k, wna);
  989. v = SCM_ARRAY_V (v);
  990. goto tail;
  991. case scm_tc7_bvect:
  992. case scm_tc7_string:
  993. case scm_tc7_byvect:
  994. case scm_tc7_uvect:
  995. case scm_tc7_ivect:
  996. case scm_tc7_fvect:
  997. case scm_tc7_dvect:
  998. case scm_tc7_cvect:
  999. case scm_tc7_svect:
  1000. #ifdef HAVE_LONG_LONGS
  1001. case scm_tc7_llvect:
  1002. #endif
  1003. case scm_tc7_vector:
  1004. case scm_tc7_wvect:
  1005. {
  1006. unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
  1007. SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
  1008. return SCM_BOOL(pos >= 0 && pos < length);
  1009. }
  1010. }
  1011. }
  1012. #undef FUNC_NAME
  1013. SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
  1014. SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
  1015. (SCM v, SCM args),
  1016. "@deffnx {Scheme Procedure} array-ref v . args\n"
  1017. "Return the element at the @code{(index1, index2)} element in\n"
  1018. "@var{array}.")
  1019. #define FUNC_NAME s_scm_uniform_vector_ref
  1020. {
  1021. long pos;
  1022. if (SCM_IMP (v))
  1023. {
  1024. SCM_ASRTGO (SCM_NULLP (args), badarg);
  1025. return v;
  1026. }
  1027. else if (SCM_ARRAYP (v))
  1028. {
  1029. pos = scm_aind (v, args, FUNC_NAME);
  1030. v = SCM_ARRAY_V (v);
  1031. }
  1032. else
  1033. {
  1034. unsigned long int length;
  1035. if (SCM_NIMP (args))
  1036. {
  1037. SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
  1038. pos = SCM_INUM (SCM_CAR (args));
  1039. SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
  1040. }
  1041. else
  1042. {
  1043. SCM_VALIDATE_INUM (2,args);
  1044. pos = SCM_INUM (args);
  1045. }
  1046. length = SCM_INUM (scm_uniform_vector_length (v));
  1047. SCM_ASRTGO (pos >= 0 && pos < length, outrng);
  1048. }
  1049. switch SCM_TYP7 (v)
  1050. {
  1051. default:
  1052. if (SCM_NULLP (args))
  1053. return v;
  1054. badarg:
  1055. SCM_WRONG_TYPE_ARG (1, v);
  1056. /* not reached */
  1057. outrng:
  1058. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
  1059. wna:
  1060. SCM_WRONG_NUM_ARGS ();
  1061. case scm_tc7_smob:
  1062. { /* enclosed */
  1063. int k = SCM_ARRAY_NDIM (v);
  1064. SCM res = scm_make_ra (k);
  1065. SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
  1066. SCM_ARRAY_BASE (res) = pos;
  1067. while (k--)
  1068. {
  1069. SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
  1070. SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
  1071. SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
  1072. }
  1073. return res;
  1074. }
  1075. case scm_tc7_bvect:
  1076. if (SCM_BITVEC_REF (v, pos))
  1077. return SCM_BOOL_T;
  1078. else
  1079. return SCM_BOOL_F;
  1080. case scm_tc7_string:
  1081. return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
  1082. case scm_tc7_byvect:
  1083. return SCM_MAKINUM (((signed char *) SCM_UVECTOR_BASE (v))[pos]);
  1084. case scm_tc7_uvect:
  1085. return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
  1086. case scm_tc7_ivect:
  1087. return scm_long2num (((signed long *) SCM_VELTS (v))[pos]);
  1088. case scm_tc7_svect:
  1089. return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
  1090. #ifdef HAVE_LONG_LONGS
  1091. case scm_tc7_llvect:
  1092. return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
  1093. #endif
  1094. case scm_tc7_fvect:
  1095. return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
  1096. case scm_tc7_dvect:
  1097. return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
  1098. case scm_tc7_cvect:
  1099. return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
  1100. ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
  1101. case scm_tc7_vector:
  1102. case scm_tc7_wvect:
  1103. return SCM_VELTS (v)[pos];
  1104. }
  1105. }
  1106. #undef FUNC_NAME
  1107. /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
  1108. tries to recycle conses. (Make *sure* you want them recycled.) */
  1109. SCM
  1110. scm_cvref (SCM v, unsigned long pos, SCM last)
  1111. #define FUNC_NAME "scm_cvref"
  1112. {
  1113. switch SCM_TYP7 (v)
  1114. {
  1115. default:
  1116. SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
  1117. case scm_tc7_bvect:
  1118. if (SCM_BITVEC_REF(v,pos))
  1119. return SCM_BOOL_T;
  1120. else
  1121. return SCM_BOOL_F;
  1122. case scm_tc7_string:
  1123. return SCM_MAKE_CHAR (SCM_STRING_UCHARS (v)[pos]);
  1124. case scm_tc7_byvect:
  1125. return SCM_MAKINUM (((char *) SCM_UVECTOR_BASE (v))[pos]);
  1126. case scm_tc7_uvect:
  1127. return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
  1128. case scm_tc7_ivect:
  1129. return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
  1130. case scm_tc7_svect:
  1131. return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
  1132. #ifdef HAVE_LONG_LONGS
  1133. case scm_tc7_llvect:
  1134. return scm_long_long2num (((long long *) SCM_CELL_WORD_1 (v))[pos]);
  1135. #endif
  1136. case scm_tc7_fvect:
  1137. if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
  1138. {
  1139. SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
  1140. return last;
  1141. }
  1142. return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
  1143. case scm_tc7_dvect:
  1144. if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
  1145. {
  1146. SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
  1147. return last;
  1148. }
  1149. return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
  1150. case scm_tc7_cvect:
  1151. if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
  1152. {
  1153. SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
  1154. SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
  1155. return last;
  1156. }
  1157. return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
  1158. ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
  1159. case scm_tc7_vector:
  1160. case scm_tc7_wvect:
  1161. return SCM_VELTS (v)[pos];
  1162. case scm_tc7_smob:
  1163. { /* enclosed scm_array */
  1164. int k = SCM_ARRAY_NDIM (v);
  1165. SCM res = scm_make_ra (k);
  1166. SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
  1167. SCM_ARRAY_BASE (res) = pos;
  1168. while (k--)
  1169. {
  1170. SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
  1171. SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
  1172. SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
  1173. }
  1174. return res;
  1175. }
  1176. }
  1177. }
  1178. #undef FUNC_NAME
  1179. SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
  1180. /* Note that args may be a list or an immediate object, depending which
  1181. PROC is used (and it's called from C too). */
  1182. SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
  1183. (SCM v, SCM obj, SCM args),
  1184. "@deffnx {Scheme Procedure} uniform-array-set1! v obj args\n"
  1185. "Set the element at the @code{(index1, index2)} element in @var{array} to\n"
  1186. "@var{new-value}. The value returned by array-set! is unspecified.")
  1187. #define FUNC_NAME s_scm_array_set_x
  1188. {
  1189. long pos = 0;
  1190. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  1191. if (SCM_ARRAYP (v))
  1192. {
  1193. pos = scm_aind (v, args, FUNC_NAME);
  1194. v = SCM_ARRAY_V (v);
  1195. }
  1196. else
  1197. {
  1198. unsigned long int length;
  1199. if (SCM_CONSP (args))
  1200. {
  1201. SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), args, SCM_ARG3, FUNC_NAME);
  1202. SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
  1203. pos = SCM_INUM (SCM_CAR (args));
  1204. }
  1205. else
  1206. {
  1207. SCM_VALIDATE_INUM_COPY (3,args,pos);
  1208. }
  1209. length = SCM_INUM (scm_uniform_vector_length (v));
  1210. SCM_ASRTGO (pos >= 0 && pos < length, outrng);
  1211. }
  1212. switch (SCM_TYP7 (v))
  1213. {
  1214. default: badarg1:
  1215. SCM_WRONG_TYPE_ARG (1, v);
  1216. /* not reached */
  1217. outrng:
  1218. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
  1219. wna:
  1220. SCM_WRONG_NUM_ARGS ();
  1221. case scm_tc7_smob: /* enclosed */
  1222. goto badarg1;
  1223. case scm_tc7_bvect:
  1224. if (SCM_FALSEP (obj))
  1225. SCM_BITVEC_CLR(v,pos);
  1226. else if (SCM_EQ_P (obj, SCM_BOOL_T))
  1227. SCM_BITVEC_SET(v,pos);
  1228. else
  1229. badobj:SCM_WRONG_TYPE_ARG (2, obj);
  1230. break;
  1231. case scm_tc7_string:
  1232. SCM_ASRTGO (SCM_CHARP (obj), badobj);
  1233. SCM_STRING_UCHARS (v)[pos] = SCM_CHAR (obj);
  1234. break;
  1235. case scm_tc7_byvect:
  1236. if (SCM_CHARP (obj))
  1237. obj = SCM_MAKINUM ((signed char) SCM_CHAR (obj));
  1238. SCM_ASRTGO (SCM_INUMP (obj), badobj);
  1239. SCM_ASSERT_RANGE (SCM_ARG2, obj,
  1240. -128 <= SCM_INUM (obj) && SCM_INUM (obj) < 128);
  1241. ((char *) SCM_UVECTOR_BASE (v))[pos] = SCM_INUM (obj);
  1242. break;
  1243. case scm_tc7_uvect:
  1244. ((unsigned long *) SCM_UVECTOR_BASE (v))[pos]
  1245. = scm_num2ulong (obj, SCM_ARG2, FUNC_NAME);
  1246. break;
  1247. case scm_tc7_ivect:
  1248. ((long *) SCM_UVECTOR_BASE (v))[pos]
  1249. = scm_num2long (obj, SCM_ARG2, FUNC_NAME);
  1250. break;
  1251. case scm_tc7_svect:
  1252. ((short *) SCM_UVECTOR_BASE (v))[pos]
  1253. = scm_num2short (obj, SCM_ARG2, FUNC_NAME);
  1254. break;
  1255. #ifdef HAVE_LONG_LONGS
  1256. case scm_tc7_llvect:
  1257. ((long long *) SCM_UVECTOR_BASE (v))[pos]
  1258. = scm_num2long_long (obj, SCM_ARG2, FUNC_NAME);
  1259. break;
  1260. #endif
  1261. case scm_tc7_fvect:
  1262. ((float *) SCM_UVECTOR_BASE (v))[pos]
  1263. = (float) scm_num2dbl (obj, FUNC_NAME);
  1264. break;
  1265. case scm_tc7_dvect:
  1266. ((double *) SCM_UVECTOR_BASE (v))[pos]
  1267. = scm_num2dbl (obj, FUNC_NAME);
  1268. break;
  1269. case scm_tc7_cvect:
  1270. SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
  1271. if (SCM_REALP (obj)) {
  1272. ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_REAL_VALUE (obj);
  1273. ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = 0.0;
  1274. } else {
  1275. ((double *) SCM_UVECTOR_BASE (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
  1276. ((double *) SCM_UVECTOR_BASE (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
  1277. }
  1278. break;
  1279. case scm_tc7_vector:
  1280. case scm_tc7_wvect:
  1281. SCM_VELTS (v)[pos] = obj;
  1282. break;
  1283. }
  1284. return SCM_UNSPECIFIED;
  1285. }
  1286. #undef FUNC_NAME
  1287. /* attempts to unroll an array into a one-dimensional array.
  1288. returns the unrolled array or #f if it can't be done. */
  1289. /* if strict is not SCM_UNDEFINED, return #f if returned array
  1290. wouldn't have contiguous elements. */
  1291. SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
  1292. (SCM ra, SCM strict),
  1293. "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
  1294. "without changing their order (last subscript changing fastest), then\n"
  1295. "@code{array-contents} returns that shared array, otherwise it returns\n"
  1296. "@code{#f}. All arrays made by @var{make-array} and\n"
  1297. "@var{make-uniform-array} may be unrolled, some arrays made by\n"
  1298. "@var{make-shared-array} may not be.\n\n"
  1299. "If the optional argument @var{strict} is provided, a shared array will\n"
  1300. "be returned only if its elements are stored internally contiguous in\n"
  1301. "memory.")
  1302. #define FUNC_NAME s_scm_array_contents
  1303. {
  1304. SCM sra;
  1305. if (SCM_IMP (ra))
  1306. return SCM_BOOL_F;
  1307. switch SCM_TYP7 (ra)
  1308. {
  1309. default:
  1310. return SCM_BOOL_F;
  1311. case scm_tc7_vector:
  1312. case scm_tc7_wvect:
  1313. case scm_tc7_string:
  1314. case scm_tc7_bvect:
  1315. case scm_tc7_byvect:
  1316. case scm_tc7_uvect:
  1317. case scm_tc7_ivect:
  1318. case scm_tc7_fvect:
  1319. case scm_tc7_dvect:
  1320. case scm_tc7_cvect:
  1321. case scm_tc7_svect:
  1322. #ifdef HAVE_LONG_LONGS
  1323. case scm_tc7_llvect:
  1324. #endif
  1325. return ra;
  1326. case scm_tc7_smob:
  1327. {
  1328. size_t k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
  1329. if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
  1330. return SCM_BOOL_F;
  1331. for (k = 0; k < ndim; k++)
  1332. len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
  1333. if (!SCM_UNBNDP (strict))
  1334. {
  1335. if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
  1336. return SCM_BOOL_F;
  1337. if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
  1338. {
  1339. if (len != SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) ||
  1340. SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
  1341. len % SCM_LONG_BIT)
  1342. return SCM_BOOL_F;
  1343. }
  1344. }
  1345. {
  1346. SCM v = SCM_ARRAY_V (ra);
  1347. unsigned long int length = SCM_INUM (scm_uniform_vector_length (v));
  1348. if ((len == length) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
  1349. return v;
  1350. }
  1351. sra = scm_make_ra (1);
  1352. SCM_ARRAY_DIMS (sra)->lbnd = 0;
  1353. SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
  1354. SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
  1355. SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
  1356. SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
  1357. return sra;
  1358. }
  1359. }
  1360. }
  1361. #undef FUNC_NAME
  1362. SCM
  1363. scm_ra2contig (SCM ra, int copy)
  1364. {
  1365. SCM ret;
  1366. long inc = 1;
  1367. size_t k, len = 1;
  1368. for (k = SCM_ARRAY_NDIM (ra); k--;)
  1369. len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
  1370. k = SCM_ARRAY_NDIM (ra);
  1371. if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
  1372. {
  1373. if (scm_tc7_bvect != SCM_TYP7 (SCM_ARRAY_V (ra)))
  1374. return ra;
  1375. if ((len == SCM_BITVECTOR_LENGTH (SCM_ARRAY_V (ra)) &&
  1376. 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
  1377. 0 == len % SCM_LONG_BIT))
  1378. return ra;
  1379. }
  1380. ret = scm_make_ra (k);
  1381. SCM_ARRAY_BASE (ret) = 0;
  1382. while (k--)
  1383. {
  1384. SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
  1385. SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
  1386. SCM_ARRAY_DIMS (ret)[k].inc = inc;
  1387. inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
  1388. }
  1389. SCM_ARRAY_V (ret) = scm_make_uve (inc, scm_array_prototype (ra));
  1390. if (copy)
  1391. scm_array_copy_x (ra, ret);
  1392. return ret;
  1393. }
  1394. SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
  1395. (SCM ra, SCM port_or_fd, SCM start, SCM end),
  1396. "@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
  1397. "Attempt to read all elements of @var{ura}, in lexicographic order, as\n"
  1398. "binary objects from @var{port-or-fdes}.\n"
  1399. "If an end of file is encountered during\n"
  1400. "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
  1401. "(starting at the beginning) and the remainder of the array is\n"
  1402. "unchanged.\n\n"
  1403. "The optional arguments @var{start} and @var{end} allow\n"
  1404. "a specified region of a vector (or linearized array) to be read,\n"
  1405. "leaving the remainder of the vector unchanged.\n\n"
  1406. "@code{uniform-array-read!} returns the number of objects read.\n"
  1407. "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
  1408. "returned by @code{(current-input-port)}.")
  1409. #define FUNC_NAME s_scm_uniform_array_read_x
  1410. {
  1411. SCM cra = SCM_UNDEFINED, v = ra;
  1412. long sz, vlen, ans;
  1413. long cstart = 0;
  1414. long cend;
  1415. long offset = 0;
  1416. char *base;
  1417. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  1418. if (SCM_UNBNDP (port_or_fd))
  1419. port_or_fd = scm_cur_inp;
  1420. else
  1421. SCM_ASSERT (SCM_INUMP (port_or_fd)
  1422. || (SCM_OPINPORTP (port_or_fd)),
  1423. port_or_fd, SCM_ARG2, FUNC_NAME);
  1424. vlen = (SCM_TYP7 (v) == scm_tc7_smob
  1425. ? 0
  1426. : SCM_INUM (scm_uniform_vector_length (v)));
  1427. loop:
  1428. switch SCM_TYP7 (v)
  1429. {
  1430. default:
  1431. badarg1:SCM_WRONG_TYPE_ARG (SCM_ARG1, v);
  1432. case scm_tc7_smob:
  1433. SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
  1434. cra = scm_ra2contig (ra, 0);
  1435. cstart += SCM_ARRAY_BASE (cra);
  1436. vlen = SCM_ARRAY_DIMS (cra)->inc *
  1437. (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
  1438. v = SCM_ARRAY_V (cra);
  1439. goto loop;
  1440. case scm_tc7_string:
  1441. base = SCM_STRING_CHARS (v);
  1442. sz = sizeof (char);
  1443. break;
  1444. case scm_tc7_bvect:
  1445. base = (char *) SCM_BITVECTOR_BASE (v);
  1446. vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
  1447. cstart /= SCM_LONG_BIT;
  1448. sz = sizeof (long);
  1449. break;
  1450. case scm_tc7_byvect:
  1451. base = (char *) SCM_UVECTOR_BASE (v);
  1452. sz = sizeof (char);
  1453. break;
  1454. case scm_tc7_uvect:
  1455. case scm_tc7_ivect:
  1456. base = (char *) SCM_UVECTOR_BASE (v);
  1457. sz = sizeof (long);
  1458. break;
  1459. case scm_tc7_svect:
  1460. base = (char *) SCM_UVECTOR_BASE (v);
  1461. sz = sizeof (short);
  1462. break;
  1463. #ifdef HAVE_LONG_LONGS
  1464. case scm_tc7_llvect:
  1465. base = (char *) SCM_UVECTOR_BASE (v);
  1466. sz = sizeof (long long);
  1467. break;
  1468. #endif
  1469. case scm_tc7_fvect:
  1470. base = (char *) SCM_UVECTOR_BASE (v);
  1471. sz = sizeof (float);
  1472. break;
  1473. case scm_tc7_dvect:
  1474. base = (char *) SCM_UVECTOR_BASE (v);
  1475. sz = sizeof (double);
  1476. break;
  1477. case scm_tc7_cvect:
  1478. base = (char *) SCM_UVECTOR_BASE (v);
  1479. sz = 2 * sizeof (double);
  1480. break;
  1481. }
  1482. cend = vlen;
  1483. if (!SCM_UNBNDP (start))
  1484. {
  1485. offset =
  1486. SCM_NUM2LONG (3, start);
  1487. if (offset < 0 || offset >= cend)
  1488. scm_out_of_range (FUNC_NAME, start);
  1489. if (!SCM_UNBNDP (end))
  1490. {
  1491. long tend =
  1492. SCM_NUM2LONG (4, end);
  1493. if (tend <= offset || tend > cend)
  1494. scm_out_of_range (FUNC_NAME, end);
  1495. cend = tend;
  1496. }
  1497. }
  1498. if (SCM_NIMP (port_or_fd))
  1499. {
  1500. scm_t_port *pt = SCM_PTAB_ENTRY (port_or_fd);
  1501. int remaining = (cend - offset) * sz;
  1502. char *dest = base + (cstart + offset) * sz;
  1503. if (pt->rw_active == SCM_PORT_WRITE)
  1504. scm_flush (port_or_fd);
  1505. ans = cend - offset;
  1506. while (remaining > 0)
  1507. {
  1508. if (pt->read_pos < pt->read_end)
  1509. {
  1510. int to_copy = min (pt->read_end - pt->read_pos,
  1511. remaining);
  1512. memcpy (dest, pt->read_pos, to_copy);
  1513. pt->read_pos += to_copy;
  1514. remaining -= to_copy;
  1515. dest += to_copy;
  1516. }
  1517. else
  1518. {
  1519. if (scm_fill_input (port_or_fd) == EOF)
  1520. {
  1521. if (remaining % sz != 0)
  1522. {
  1523. SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
  1524. }
  1525. ans -= remaining / sz;
  1526. break;
  1527. }
  1528. }
  1529. }
  1530. if (pt->rw_random)
  1531. pt->rw_active = SCM_PORT_READ;
  1532. }
  1533. else /* file descriptor. */
  1534. {
  1535. SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
  1536. base + (cstart + offset) * sz,
  1537. (sz * (cend - offset))));
  1538. if (ans == -1)
  1539. SCM_SYSERROR;
  1540. }
  1541. if (SCM_TYP7 (v) == scm_tc7_bvect)
  1542. ans *= SCM_LONG_BIT;
  1543. if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
  1544. scm_array_copy_x (cra, ra);
  1545. return SCM_MAKINUM (ans);
  1546. }
  1547. #undef FUNC_NAME
  1548. SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
  1549. (SCM v, SCM port_or_fd, SCM start, SCM end),
  1550. "@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]\n"
  1551. "Writes all elements of @var{ura} as binary objects to\n"
  1552. "@var{port-or-fdes}.\n\n"
  1553. "The optional arguments @var{start}\n"
  1554. "and @var{end} allow\n"
  1555. "a specified region of a vector (or linearized array) to be written.\n\n"
  1556. "The number of objects actually written is returned.\n"
  1557. "@var{port-or-fdes} may be\n"
  1558. "omitted, in which case it defaults to the value returned by\n"
  1559. "@code{(current-output-port)}.")
  1560. #define FUNC_NAME s_scm_uniform_array_write
  1561. {
  1562. long sz, vlen, ans;
  1563. long offset = 0;
  1564. long cstart = 0;
  1565. long cend;
  1566. char *base;
  1567. port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
  1568. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  1569. if (SCM_UNBNDP (port_or_fd))
  1570. port_or_fd = scm_cur_outp;
  1571. else
  1572. SCM_ASSERT (SCM_INUMP (port_or_fd)
  1573. || (SCM_OPOUTPORTP (port_or_fd)),
  1574. port_or_fd, SCM_ARG2, FUNC_NAME);
  1575. vlen = (SCM_TYP7 (v) == scm_tc7_smob
  1576. ? 0
  1577. : SCM_INUM (scm_uniform_vector_length (v)));
  1578. loop:
  1579. switch SCM_TYP7 (v)
  1580. {
  1581. default:
  1582. badarg1:SCM_WRONG_TYPE_ARG (1, v);
  1583. case scm_tc7_smob:
  1584. SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
  1585. v = scm_ra2contig (v, 1);
  1586. cstart = SCM_ARRAY_BASE (v);
  1587. vlen = (SCM_ARRAY_DIMS (v)->inc
  1588. * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1));
  1589. v = SCM_ARRAY_V (v);
  1590. goto loop;
  1591. case scm_tc7_string:
  1592. base = SCM_STRING_CHARS (v);
  1593. sz = sizeof (char);
  1594. break;
  1595. case scm_tc7_bvect:
  1596. base = (char *) SCM_BITVECTOR_BASE (v);
  1597. vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
  1598. cstart /= SCM_LONG_BIT;
  1599. sz = sizeof (long);
  1600. break;
  1601. case scm_tc7_byvect:
  1602. base = (char *) SCM_UVECTOR_BASE (v);
  1603. sz = sizeof (char);
  1604. break;
  1605. case scm_tc7_uvect:
  1606. case scm_tc7_ivect:
  1607. base = (char *) SCM_UVECTOR_BASE (v);
  1608. sz = sizeof (long);
  1609. break;
  1610. case scm_tc7_svect:
  1611. base = (char *) SCM_UVECTOR_BASE (v);
  1612. sz = sizeof (short);
  1613. break;
  1614. #ifdef HAVE_LONG_LONGS
  1615. case scm_tc7_llvect:
  1616. base = (char *) SCM_UVECTOR_BASE (v);
  1617. sz = sizeof (long long);
  1618. break;
  1619. #endif
  1620. case scm_tc7_fvect:
  1621. base = (char *) SCM_UVECTOR_BASE (v);
  1622. sz = sizeof (float);
  1623. break;
  1624. case scm_tc7_dvect:
  1625. base = (char *) SCM_UVECTOR_BASE (v);
  1626. sz = sizeof (double);
  1627. break;
  1628. case scm_tc7_cvect:
  1629. base = (char *) SCM_UVECTOR_BASE (v);
  1630. sz = 2 * sizeof (double);
  1631. break;
  1632. }
  1633. cend = vlen;
  1634. if (!SCM_UNBNDP (start))
  1635. {
  1636. offset =
  1637. SCM_NUM2LONG (3, start);
  1638. if (offset < 0 || offset >= cend)
  1639. scm_out_of_range (FUNC_NAME, start);
  1640. if (!SCM_UNBNDP (end))
  1641. {
  1642. long tend =
  1643. SCM_NUM2LONG (4, end);
  1644. if (tend <= offset || tend > cend)
  1645. scm_out_of_range (FUNC_NAME, end);
  1646. cend = tend;
  1647. }
  1648. }
  1649. if (SCM_NIMP (port_or_fd))
  1650. {
  1651. char *source = base + (cstart + offset) * sz;
  1652. ans = cend - offset;
  1653. scm_lfwrite (source, ans * sz, port_or_fd);
  1654. }
  1655. else /* file descriptor. */
  1656. {
  1657. SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
  1658. base + (cstart + offset) * sz,
  1659. (sz * (cend - offset))));
  1660. if (ans == -1)
  1661. SCM_SYSERROR;
  1662. }
  1663. if (SCM_TYP7 (v) == scm_tc7_bvect)
  1664. ans *= SCM_LONG_BIT;
  1665. return SCM_MAKINUM (ans);
  1666. }
  1667. #undef FUNC_NAME
  1668. static char cnt_tab[16] =
  1669. {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
  1670. SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
  1671. (SCM b, SCM bitvector),
  1672. "Return the number of occurrences of the boolean @var{b} in\n"
  1673. "@var{bitvector}.")
  1674. #define FUNC_NAME s_scm_bit_count
  1675. {
  1676. SCM_VALIDATE_BOOL (1, b);
  1677. SCM_ASSERT (SCM_BITVECTOR_P (bitvector), bitvector, 2, FUNC_NAME);
  1678. if (SCM_BITVECTOR_LENGTH (bitvector) == 0) {
  1679. return SCM_INUM0;
  1680. } else {
  1681. unsigned long int count = 0;
  1682. unsigned long int i = (SCM_BITVECTOR_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
  1683. unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
  1684. if (SCM_FALSEP (b)) {
  1685. w = ~w;
  1686. };
  1687. w <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
  1688. while (1) {
  1689. while (w) {
  1690. count += cnt_tab[w & 0x0f];
  1691. w >>= 4;
  1692. }
  1693. if (i == 0) {
  1694. return SCM_MAKINUM (count);
  1695. } else {
  1696. --i;
  1697. w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
  1698. if (SCM_FALSEP (b)) {
  1699. w = ~w;
  1700. }
  1701. }
  1702. }
  1703. }
  1704. }
  1705. #undef FUNC_NAME
  1706. SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
  1707. (SCM item, SCM v, SCM k),
  1708. "Return the minimum index of an occurrence of @var{bool} in\n"
  1709. "@var{bv} which is at least @var{k}. If no @var{bool} occurs\n"
  1710. "within the specified range @code{#f} is returned.")
  1711. #define FUNC_NAME s_scm_bit_position
  1712. {
  1713. long i, lenw, xbits, pos;
  1714. register unsigned long w;
  1715. SCM_VALIDATE_BOOL (1, item);
  1716. SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG2, FUNC_NAME);
  1717. SCM_VALIDATE_INUM_COPY (3,k,pos);
  1718. SCM_ASSERT_RANGE (3, k, (pos <= SCM_BITVECTOR_LENGTH (v)) && (pos >= 0));
  1719. if (pos == SCM_BITVECTOR_LENGTH (v))
  1720. return SCM_BOOL_F;
  1721. lenw = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
  1722. i = pos / SCM_LONG_BIT;
  1723. w = SCM_UNPACK (SCM_VELTS (v)[i]);
  1724. if (SCM_FALSEP (item))
  1725. w = ~w;
  1726. xbits = (pos % SCM_LONG_BIT);
  1727. pos -= xbits;
  1728. w = ((w >> xbits) << xbits);
  1729. xbits = SCM_LONG_BIT - 1 - (SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT;
  1730. while (!0)
  1731. {
  1732. if (w && (i == lenw))
  1733. w = ((w << xbits) >> xbits);
  1734. if (w)
  1735. while (w)
  1736. switch (w & 0x0f)
  1737. {
  1738. default:
  1739. return SCM_MAKINUM (pos);
  1740. case 2:
  1741. case 6:
  1742. case 10:
  1743. case 14:
  1744. return SCM_MAKINUM (pos + 1);
  1745. case 4:
  1746. case 12:
  1747. return SCM_MAKINUM (pos + 2);
  1748. case 8:
  1749. return SCM_MAKINUM (pos + 3);
  1750. case 0:
  1751. pos += 4;
  1752. w >>= 4;
  1753. }
  1754. if (++i > lenw)
  1755. break;
  1756. pos += SCM_LONG_BIT;
  1757. w = SCM_UNPACK (SCM_VELTS (v)[i]);
  1758. if (SCM_FALSEP (item))
  1759. w = ~w;
  1760. }
  1761. return SCM_BOOL_F;
  1762. }
  1763. #undef FUNC_NAME
  1764. SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
  1765. (SCM v, SCM kv, SCM obj),
  1766. "If uve is a bit-vector @var{bv} and uve must be of the same\n"
  1767. "length. If @var{bool} is @code{#t}, uve is OR'ed into\n"
  1768. "@var{bv}; If @var{bool} is @code{#f}, the inversion of uve is\n"
  1769. "AND'ed into @var{bv}.\n\n"
  1770. "If uve is a unsigned integer vector all the elements of uve\n"
  1771. "must be between 0 and the @code{length} of @var{bv}. The bits\n"
  1772. "of @var{bv} corresponding to the indexes in uve are set to\n"
  1773. "@var{bool}. The return value is unspecified.")
  1774. #define FUNC_NAME s_scm_bit_set_star_x
  1775. {
  1776. register long i, k, vlen;
  1777. SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
  1778. SCM_ASRTGO (SCM_NIMP (kv), badarg2);
  1779. switch SCM_TYP7 (kv)
  1780. {
  1781. default:
  1782. badarg2:SCM_WRONG_TYPE_ARG (2, kv);
  1783. case scm_tc7_uvect:
  1784. vlen = SCM_BITVECTOR_LENGTH (v);
  1785. if (SCM_FALSEP (obj))
  1786. for (i = SCM_UVECTOR_LENGTH (kv); i;)
  1787. {
  1788. k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
  1789. if (k >= vlen)
  1790. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
  1791. SCM_BITVEC_CLR(v,k);
  1792. }
  1793. else if (SCM_EQ_P (obj, SCM_BOOL_T))
  1794. for (i = SCM_UVECTOR_LENGTH (kv); i;)
  1795. {
  1796. k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
  1797. if (k >= vlen)
  1798. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
  1799. SCM_BITVEC_SET(v,k);
  1800. }
  1801. else
  1802. badarg3:SCM_WRONG_TYPE_ARG (3, obj);
  1803. break;
  1804. case scm_tc7_bvect:
  1805. SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
  1806. if (SCM_FALSEP (obj))
  1807. for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
  1808. SCM_BITVECTOR_BASE (v) [k] &= ~SCM_BITVECTOR_BASE (kv) [k];
  1809. else if (SCM_EQ_P (obj, SCM_BOOL_T))
  1810. for (k = (SCM_BITVECTOR_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
  1811. SCM_BITVECTOR_BASE (v) [k] |= SCM_BITVECTOR_BASE (kv) [k];
  1812. else
  1813. goto badarg3;
  1814. break;
  1815. }
  1816. return SCM_UNSPECIFIED;
  1817. }
  1818. #undef FUNC_NAME
  1819. SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
  1820. (SCM v, SCM kv, SCM obj),
  1821. "Return\n"
  1822. "@lisp\n"
  1823. "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
  1824. "@end lisp\n"
  1825. "@var{bv} is not modified.")
  1826. #define FUNC_NAME s_scm_bit_count_star
  1827. {
  1828. register long i, vlen, count = 0;
  1829. register unsigned long k;
  1830. int fObj = 0;
  1831. SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
  1832. SCM_ASRTGO (SCM_NIMP (kv), badarg2);
  1833. switch SCM_TYP7 (kv)
  1834. {
  1835. default:
  1836. badarg2:
  1837. SCM_WRONG_TYPE_ARG (2, kv);
  1838. case scm_tc7_uvect:
  1839. vlen = SCM_BITVECTOR_LENGTH (v);
  1840. if (SCM_FALSEP (obj))
  1841. for (i = SCM_UVECTOR_LENGTH (kv); i;)
  1842. {
  1843. k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
  1844. if (k >= vlen)
  1845. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
  1846. if (!SCM_BITVEC_REF(v,k))
  1847. count++;
  1848. }
  1849. else if (SCM_EQ_P (obj, SCM_BOOL_T))
  1850. for (i = SCM_UVECTOR_LENGTH (kv); i;)
  1851. {
  1852. k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
  1853. if (k >= vlen)
  1854. scm_out_of_range (FUNC_NAME, SCM_MAKINUM (k));
  1855. if (SCM_BITVEC_REF (v,k))
  1856. count++;
  1857. }
  1858. else
  1859. badarg3:SCM_WRONG_TYPE_ARG (3, obj);
  1860. break;
  1861. case scm_tc7_bvect:
  1862. SCM_ASSERT (SCM_BITVECTOR_LENGTH (v) == SCM_BITVECTOR_LENGTH (kv), v, SCM_ARG1, FUNC_NAME);
  1863. if (0 == SCM_BITVECTOR_LENGTH (v))
  1864. return SCM_INUM0;
  1865. SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
  1866. fObj = SCM_EQ_P (obj, SCM_BOOL_T);
  1867. i = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT;
  1868. k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
  1869. k <<= SCM_LONG_BIT - 1 - ((SCM_BITVECTOR_LENGTH (v) - 1) % SCM_LONG_BIT);
  1870. while (1)
  1871. {
  1872. for (; k; k >>= 4)
  1873. count += cnt_tab[k & 0x0f];
  1874. if (0 == i--)
  1875. return SCM_MAKINUM (count);
  1876. /* urg. repetitive (see above.) */
  1877. k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
  1878. }
  1879. }
  1880. return SCM_MAKINUM (count);
  1881. }
  1882. #undef FUNC_NAME
  1883. SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
  1884. (SCM v),
  1885. "Modify @var{bv} by replacing each element with its negation.")
  1886. #define FUNC_NAME s_scm_bit_invert_x
  1887. {
  1888. long int k;
  1889. SCM_ASSERT (SCM_BITVECTOR_P (v), v, SCM_ARG1, FUNC_NAME);
  1890. k = SCM_BITVECTOR_LENGTH (v);
  1891. for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
  1892. SCM_BITVECTOR_BASE (v) [k] = ~SCM_BITVECTOR_BASE (v) [k];
  1893. return SCM_UNSPECIFIED;
  1894. }
  1895. #undef FUNC_NAME
  1896. SCM
  1897. scm_istr2bve (char *str, long len)
  1898. {
  1899. SCM v = scm_make_uve (len, SCM_BOOL_T);
  1900. long *data = (long *) SCM_VELTS (v);
  1901. register unsigned long mask;
  1902. register long k;
  1903. register long j;
  1904. for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
  1905. {
  1906. data[k] = 0L;
  1907. j = len - k * SCM_LONG_BIT;
  1908. if (j > SCM_LONG_BIT)
  1909. j = SCM_LONG_BIT;
  1910. for (mask = 1L; j--; mask <<= 1)
  1911. switch (*str++)
  1912. {
  1913. case '0':
  1914. break;
  1915. case '1':
  1916. data[k] |= mask;
  1917. break;
  1918. default:
  1919. return SCM_BOOL_F;
  1920. }
  1921. }
  1922. return v;
  1923. }
  1924. static SCM
  1925. ra2l (SCM ra,unsigned long base,unsigned long k)
  1926. {
  1927. register SCM res = SCM_EOL;
  1928. register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
  1929. register size_t i;
  1930. if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
  1931. return SCM_EOL;
  1932. i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
  1933. if (k < SCM_ARRAY_NDIM (ra) - 1)
  1934. {
  1935. do
  1936. {
  1937. i -= inc;
  1938. res = scm_cons (ra2l (ra, i, k + 1), res);
  1939. }
  1940. while (i != base);
  1941. }
  1942. else
  1943. do
  1944. {
  1945. i -= inc;
  1946. res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
  1947. }
  1948. while (i != base);
  1949. return res;
  1950. }
  1951. SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
  1952. (SCM v),
  1953. "Return a list consisting of all the elements, in order, of\n"
  1954. "@var{array}.")
  1955. #define FUNC_NAME s_scm_array_to_list
  1956. {
  1957. SCM res = SCM_EOL;
  1958. register long k;
  1959. SCM_ASRTGO (SCM_NIMP (v), badarg1);
  1960. switch SCM_TYP7 (v)
  1961. {
  1962. default:
  1963. badarg1:SCM_WRONG_TYPE_ARG (1, v);
  1964. case scm_tc7_smob:
  1965. SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
  1966. return ra2l (v, SCM_ARRAY_BASE (v), 0);
  1967. case scm_tc7_vector:
  1968. case scm_tc7_wvect:
  1969. return scm_vector_to_list (v);
  1970. case scm_tc7_string:
  1971. return scm_string_to_list (v);
  1972. case scm_tc7_bvect:
  1973. {
  1974. long *data = (long *) SCM_VELTS (v);
  1975. register unsigned long mask;
  1976. for (k = (SCM_BITVECTOR_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
  1977. for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
  1978. res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
  1979. for (mask = 1L << ((SCM_BITVECTOR_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
  1980. res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
  1981. return res;
  1982. }
  1983. case scm_tc7_byvect:
  1984. {
  1985. signed char *data = (signed char *) SCM_VELTS (v);
  1986. unsigned long k = SCM_UVECTOR_LENGTH (v);
  1987. while (k != 0)
  1988. res = scm_cons (SCM_MAKINUM (data[--k]), res);
  1989. return res;
  1990. }
  1991. case scm_tc7_uvect:
  1992. {
  1993. long *data = (long *)SCM_VELTS(v);
  1994. for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
  1995. res = scm_cons(scm_ulong2num(data[k]), res);
  1996. return res;
  1997. }
  1998. case scm_tc7_ivect:
  1999. {
  2000. long *data = (long *)SCM_VELTS(v);
  2001. for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
  2002. res = scm_cons(scm_long2num(data[k]), res);
  2003. return res;
  2004. }
  2005. case scm_tc7_svect:
  2006. {
  2007. short *data = (short *)SCM_VELTS(v);
  2008. for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
  2009. res = scm_cons(scm_short2num (data[k]), res);
  2010. return res;
  2011. }
  2012. #ifdef HAVE_LONG_LONGS
  2013. case scm_tc7_llvect:
  2014. {
  2015. long long *data = (long long *)SCM_VELTS(v);
  2016. for (k = SCM_UVECTOR_LENGTH(v) - 1; k >= 0; k--)
  2017. res = scm_cons(scm_long_long2num(data[k]), res);
  2018. return res;
  2019. }
  2020. #endif
  2021. case scm_tc7_fvect:
  2022. {
  2023. float *data = (float *) SCM_VELTS (v);
  2024. for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
  2025. res = scm_cons (scm_make_real (data[k]), res);
  2026. return res;
  2027. }
  2028. case scm_tc7_dvect:
  2029. {
  2030. double *data = (double *) SCM_VELTS (v);
  2031. for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
  2032. res = scm_cons (scm_make_real (data[k]), res);
  2033. return res;
  2034. }
  2035. case scm_tc7_cvect:
  2036. {
  2037. double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
  2038. for (k = SCM_UVECTOR_LENGTH (v) - 1; k >= 0; k--)
  2039. res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
  2040. return res;
  2041. }
  2042. }
  2043. }
  2044. #undef FUNC_NAME
  2045. static int l2ra(SCM lst, SCM ra, unsigned long base, unsigned long k);
  2046. SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
  2047. (SCM ndim, SCM prot, SCM lst),
  2048. "@deffnx {Scheme Procedure} list->uniform-vector prot lst\n"
  2049. "Return a uniform array of the type indicated by prototype\n"
  2050. "@var{prot} with elements the same as those of @var{lst}.\n"
  2051. "Elements must be of the appropriate type, no coercions are\n"
  2052. "done.")
  2053. #define FUNC_NAME s_scm_list_to_uniform_array
  2054. {
  2055. SCM shp = SCM_EOL;
  2056. SCM row = lst;
  2057. SCM ra;
  2058. unsigned long k;
  2059. long n;
  2060. SCM_VALIDATE_INUM_COPY (1,ndim,k);
  2061. while (k--)
  2062. {
  2063. n = scm_ilength (row);
  2064. SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
  2065. shp = scm_cons (SCM_MAKINUM (n), shp);
  2066. if (SCM_NIMP (row))
  2067. row = SCM_CAR (row);
  2068. }
  2069. ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
  2070. SCM_UNDEFINED);
  2071. if (SCM_NULLP (shp))
  2072. {
  2073. SCM_ASRTGO (1 == scm_ilength (lst), badlst);
  2074. scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
  2075. return ra;
  2076. }
  2077. if (!SCM_ARRAYP (ra))
  2078. {
  2079. unsigned long int length = SCM_INUM (scm_uniform_vector_length (ra));
  2080. for (k = 0; k < length; k++, lst = SCM_CDR (lst))
  2081. scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
  2082. return ra;
  2083. }
  2084. if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
  2085. return ra;
  2086. else
  2087. badlst:SCM_MISC_ERROR ("Bad scm_array contents list: ~S",
  2088. scm_list_1 (lst));
  2089. }
  2090. #undef FUNC_NAME
  2091. static int
  2092. l2ra (SCM lst, SCM ra, unsigned long base, unsigned long k)
  2093. {
  2094. register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
  2095. register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
  2096. int ok = 1;
  2097. if (n <= 0)
  2098. return (SCM_NULLP (lst));
  2099. if (k < SCM_ARRAY_NDIM (ra) - 1)
  2100. {
  2101. while (n--)
  2102. {
  2103. if (SCM_IMP (lst) || SCM_NCONSP (lst))
  2104. return 0;
  2105. ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
  2106. base += inc;
  2107. lst = SCM_CDR (lst);
  2108. }
  2109. if (SCM_NNULLP (lst))
  2110. return 0;
  2111. }
  2112. else
  2113. {
  2114. while (n--)
  2115. {
  2116. if (SCM_IMP (lst) || SCM_NCONSP (lst))
  2117. return 0;
  2118. scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
  2119. base += inc;
  2120. lst = SCM_CDR (lst);
  2121. }
  2122. if (SCM_NNULLP (lst))
  2123. return 0;
  2124. }
  2125. return ok;
  2126. }
  2127. static void
  2128. rapr1 (SCM ra,unsigned long j,unsigned long k,SCM port,scm_print_state *pstate)
  2129. {
  2130. long inc = 1;
  2131. long n = (SCM_TYP7 (ra) == scm_tc7_smob
  2132. ? 0
  2133. : SCM_INUM (scm_uniform_vector_length (ra)));
  2134. int enclosed = 0;
  2135. tail:
  2136. switch SCM_TYP7 (ra)
  2137. {
  2138. case scm_tc7_smob:
  2139. if (enclosed++)
  2140. {
  2141. SCM_ARRAY_BASE (ra) = j;
  2142. if (n-- > 0)
  2143. scm_iprin1 (ra, port, pstate);
  2144. for (j += inc; n-- > 0; j += inc)
  2145. {
  2146. scm_putc (' ', port);
  2147. SCM_ARRAY_BASE (ra) = j;
  2148. scm_iprin1 (ra, port, pstate);
  2149. }
  2150. break;
  2151. }
  2152. if (k + 1 < SCM_ARRAY_NDIM (ra))
  2153. {
  2154. long i;
  2155. inc = SCM_ARRAY_DIMS (ra)[k].inc;
  2156. for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
  2157. {
  2158. scm_putc ('(', port);
  2159. rapr1 (ra, j, k + 1, port, pstate);
  2160. scm_puts (") ", port);
  2161. j += inc;
  2162. }
  2163. if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
  2164. { /* could be zero size. */
  2165. scm_putc ('(', port);
  2166. rapr1 (ra, j, k + 1, port, pstate);
  2167. scm_putc (')', port);
  2168. }
  2169. break;
  2170. }
  2171. if (SCM_ARRAY_NDIM (ra) > 0)
  2172. { /* Could be zero-dimensional */
  2173. inc = SCM_ARRAY_DIMS (ra)[k].inc;
  2174. n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
  2175. }
  2176. else
  2177. n = 1;
  2178. ra = SCM_ARRAY_V (ra);
  2179. goto tail;
  2180. default:
  2181. /* scm_tc7_bvect and scm_tc7_llvect only? */
  2182. if (n-- > 0)
  2183. scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
  2184. for (j += inc; n-- > 0; j += inc)
  2185. {
  2186. scm_putc (' ', port);
  2187. scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
  2188. }
  2189. break;
  2190. case scm_tc7_string:
  2191. if (n-- > 0)
  2192. scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
  2193. if (SCM_WRITINGP (pstate))
  2194. for (j += inc; n-- > 0; j += inc)
  2195. {
  2196. scm_putc (' ', port);
  2197. scm_iprin1 (SCM_MAKE_CHAR (SCM_STRING_UCHARS (ra)[j]), port, pstate);
  2198. }
  2199. else
  2200. for (j += inc; n-- > 0; j += inc)
  2201. scm_putc (SCM_STRING_CHARS (ra)[j], port);
  2202. break;
  2203. case scm_tc7_byvect:
  2204. if (n-- > 0)
  2205. scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
  2206. for (j += inc; n-- > 0; j += inc)
  2207. {
  2208. scm_putc (' ', port);
  2209. scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
  2210. }
  2211. break;
  2212. case scm_tc7_uvect:
  2213. {
  2214. char str[11];
  2215. if (n-- > 0)
  2216. {
  2217. /* intprint can't handle >= 2^31. */
  2218. sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
  2219. scm_puts (str, port);
  2220. }
  2221. for (j += inc; n-- > 0; j += inc)
  2222. {
  2223. scm_putc (' ', port);
  2224. sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
  2225. scm_puts (str, port);
  2226. }
  2227. }
  2228. case scm_tc7_ivect:
  2229. if (n-- > 0)
  2230. scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
  2231. for (j += inc; n-- > 0; j += inc)
  2232. {
  2233. scm_putc (' ', port);
  2234. scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
  2235. }
  2236. break;
  2237. case scm_tc7_svect:
  2238. if (n-- > 0)
  2239. scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
  2240. for (j += inc; n-- > 0; j += inc)
  2241. {
  2242. scm_putc (' ', port);
  2243. scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
  2244. }
  2245. break;
  2246. case scm_tc7_fvect:
  2247. if (n-- > 0)
  2248. {
  2249. SCM z = scm_make_real (1.0);
  2250. SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
  2251. scm_print_real (z, port, pstate);
  2252. for (j += inc; n-- > 0; j += inc)
  2253. {
  2254. scm_putc (' ', port);
  2255. SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
  2256. scm_print_real (z, port, pstate);
  2257. }
  2258. }
  2259. break;
  2260. case scm_tc7_dvect:
  2261. if (n-- > 0)
  2262. {
  2263. SCM z = scm_make_real (1.0 / 3.0);
  2264. SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
  2265. scm_print_real (z, port, pstate);
  2266. for (j += inc; n-- > 0; j += inc)
  2267. {
  2268. scm_putc (' ', port);
  2269. SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
  2270. scm_print_real (z, port, pstate);
  2271. }
  2272. }
  2273. break;
  2274. case scm_tc7_cvect:
  2275. if (n-- > 0)
  2276. {
  2277. SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
  2278. SCM_REAL_VALUE (z) =
  2279. SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
  2280. SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
  2281. scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
  2282. port, pstate);
  2283. for (j += inc; n-- > 0; j += inc)
  2284. {
  2285. scm_putc (' ', port);
  2286. SCM_REAL_VALUE (z)
  2287. = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
  2288. SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
  2289. scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
  2290. port, pstate);
  2291. }
  2292. }
  2293. break;
  2294. }
  2295. }
  2296. int
  2297. scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
  2298. {
  2299. SCM v = exp;
  2300. unsigned long base = 0;
  2301. scm_putc ('#', port);
  2302. tail:
  2303. switch SCM_TYP7 (v)
  2304. {
  2305. case scm_tc7_smob:
  2306. {
  2307. long ndim = SCM_ARRAY_NDIM (v);
  2308. base = SCM_ARRAY_BASE (v);
  2309. v = SCM_ARRAY_V (v);
  2310. if (SCM_ARRAYP (v))
  2311. {
  2312. scm_puts ("<enclosed-array ", port);
  2313. rapr1 (exp, base, 0, port, pstate);
  2314. scm_putc ('>', port);
  2315. return 1;
  2316. }
  2317. else
  2318. {
  2319. scm_intprint (ndim, 10, port);
  2320. goto tail;
  2321. }
  2322. }
  2323. case scm_tc7_bvect:
  2324. if (SCM_EQ_P (exp, v))
  2325. { /* a uve, not an scm_array */
  2326. register long i, j, w;
  2327. scm_putc ('*', port);
  2328. for (i = 0; i < (SCM_BITVECTOR_LENGTH (exp)) / SCM_LONG_BIT; i++)
  2329. {
  2330. scm_t_bits w = SCM_UNPACK (SCM_VELTS (exp)[i]);
  2331. for (j = SCM_LONG_BIT; j; j--)
  2332. {
  2333. scm_putc (w & 1 ? '1' : '0', port);
  2334. w >>= 1;
  2335. }
  2336. }
  2337. j = SCM_BITVECTOR_LENGTH (exp) % SCM_LONG_BIT;
  2338. if (j)
  2339. {
  2340. w = SCM_UNPACK (SCM_VELTS (exp)[SCM_BITVECTOR_LENGTH (exp) / SCM_LONG_BIT]);
  2341. for (; j; j--)
  2342. {
  2343. scm_putc (w & 1 ? '1' : '0', port);
  2344. w >>= 1;
  2345. }
  2346. }
  2347. return 1;
  2348. }
  2349. else
  2350. scm_putc ('b', port);
  2351. break;
  2352. case scm_tc7_string:
  2353. scm_putc ('a', port);
  2354. break;
  2355. case scm_tc7_byvect:
  2356. scm_putc ('y', port);
  2357. break;
  2358. case scm_tc7_uvect:
  2359. scm_putc ('u', port);
  2360. break;
  2361. case scm_tc7_ivect:
  2362. scm_putc ('e', port);
  2363. break;
  2364. case scm_tc7_svect:
  2365. scm_putc ('h', port);
  2366. break;
  2367. #ifdef HAVE_LONG_LONGS
  2368. case scm_tc7_llvect:
  2369. scm_putc ('l', port);
  2370. break;
  2371. #endif
  2372. case scm_tc7_fvect:
  2373. scm_putc ('s', port);
  2374. break;
  2375. case scm_tc7_dvect:
  2376. scm_putc ('i', port);
  2377. break;
  2378. case scm_tc7_cvect:
  2379. scm_putc ('c', port);
  2380. break;
  2381. }
  2382. scm_putc ('(', port);
  2383. rapr1 (exp, base, 0, port, pstate);
  2384. scm_putc (')', port);
  2385. return 1;
  2386. }
  2387. SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
  2388. (SCM ra),
  2389. "Return an object that would produce an array of the same type\n"
  2390. "as @var{array}, if used as the @var{prototype} for\n"
  2391. "@code{make-uniform-array}.")
  2392. #define FUNC_NAME s_scm_array_prototype
  2393. {
  2394. int enclosed = 0;
  2395. SCM_ASRTGO (SCM_NIMP (ra), badarg);
  2396. loop:
  2397. switch SCM_TYP7 (ra)
  2398. {
  2399. default:
  2400. badarg:SCM_WRONG_TYPE_ARG (1, ra);
  2401. case scm_tc7_smob:
  2402. SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
  2403. if (enclosed++)
  2404. return SCM_UNSPECIFIED;
  2405. ra = SCM_ARRAY_V (ra);
  2406. goto loop;
  2407. case scm_tc7_vector:
  2408. case scm_tc7_wvect:
  2409. return SCM_EOL;
  2410. case scm_tc7_bvect:
  2411. return SCM_BOOL_T;
  2412. case scm_tc7_string:
  2413. return SCM_MAKE_CHAR ('a');
  2414. case scm_tc7_byvect:
  2415. return SCM_MAKE_CHAR ('\0');
  2416. case scm_tc7_uvect:
  2417. return SCM_MAKINUM (1L);
  2418. case scm_tc7_ivect:
  2419. return SCM_MAKINUM (-1L);
  2420. case scm_tc7_svect:
  2421. return scm_str2symbol ("s");
  2422. #ifdef HAVE_LONG_LONGS
  2423. case scm_tc7_llvect:
  2424. return scm_str2symbol ("l");
  2425. #endif
  2426. case scm_tc7_fvect:
  2427. return scm_make_real (1.0);
  2428. case scm_tc7_dvect:
  2429. return scm_make_real (1.0 / 3.0);
  2430. case scm_tc7_cvect:
  2431. return scm_make_complex (0.0, 1.0);
  2432. }
  2433. }
  2434. #undef FUNC_NAME
  2435. static SCM
  2436. array_mark (SCM ptr)
  2437. {
  2438. return SCM_ARRAY_V (ptr);
  2439. }
  2440. static size_t
  2441. array_free (SCM ptr)
  2442. {
  2443. scm_must_free (SCM_ARRAY_MEM (ptr));
  2444. return sizeof (scm_t_array) +
  2445. SCM_ARRAY_NDIM (ptr) * sizeof (scm_t_array_dim);
  2446. }
  2447. void
  2448. scm_init_unif ()
  2449. {
  2450. scm_tc16_array = scm_make_smob_type ("array", 0);
  2451. scm_set_smob_mark (scm_tc16_array, array_mark);
  2452. scm_set_smob_free (scm_tc16_array, array_free);
  2453. scm_set_smob_print (scm_tc16_array, scm_raprin1);
  2454. scm_set_smob_equalp (scm_tc16_array, scm_array_equal_p);
  2455. scm_add_feature ("array");
  2456. #include "libguile/unif.x"
  2457. }
  2458. /*
  2459. Local Variables:
  2460. c-file-style: "gnu"
  2461. End:
  2462. */