vectors.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2006, 2008, 2009, 2010,
  2. * 2011, 2012, 2014 Free Software Foundation, Inc.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public License
  6. * as published by the Free Software Foundation; either version 3 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301 USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22. #include "libguile/_scm.h"
  23. #include "libguile/eq.h"
  24. #include "libguile/root.h"
  25. #include "libguile/strings.h"
  26. #include "libguile/validate.h"
  27. #include "libguile/vectors.h"
  28. #include "libguile/arrays.h" /* Hit me with the ugly stick */
  29. #include "libguile/generalized-vectors.h"
  30. #include "libguile/strings.h"
  31. #include "libguile/srfi-13.h"
  32. #include "libguile/dynwind.h"
  33. #include "libguile/bdw-gc.h"
  34. #define VECTOR_MAX_LENGTH (SCM_T_BITS_MAX >> 8)
  35. int
  36. scm_is_vector (SCM obj)
  37. {
  38. return SCM_I_IS_VECTOR (obj);
  39. }
  40. int
  41. scm_is_simple_vector (SCM obj)
  42. {
  43. return SCM_I_IS_VECTOR (obj);
  44. }
  45. const SCM *
  46. scm_vector_elements (SCM vec, scm_t_array_handle *h,
  47. size_t *lenp, ssize_t *incp)
  48. {
  49. return scm_vector_writable_elements (vec, h, lenp, incp);
  50. }
  51. SCM *
  52. scm_vector_writable_elements (SCM vec, scm_t_array_handle *h,
  53. size_t *lenp, ssize_t *incp)
  54. {
  55. scm_generalized_vector_get_handle (vec, h);
  56. if (lenp)
  57. {
  58. scm_t_array_dim *dim = scm_array_handle_dims (h);
  59. *lenp = dim->ubnd - dim->lbnd + 1;
  60. *incp = dim->inc;
  61. }
  62. return scm_array_handle_writable_elements (h);
  63. }
  64. SCM_DEFINE (scm_vector_p, "vector?", 1, 0, 0,
  65. (SCM obj),
  66. "Return @code{#t} if @var{obj} is a vector, otherwise return\n"
  67. "@code{#f}.")
  68. #define FUNC_NAME s_scm_vector_p
  69. {
  70. return scm_from_bool (scm_is_vector (obj));
  71. }
  72. #undef FUNC_NAME
  73. SCM_DEFINE (scm_vector_length, "vector-length", 1, 0, 0,
  74. (SCM v),
  75. "Returns the number of elements in @var{vector} as an exact integer.")
  76. #define FUNC_NAME s_scm_vector_length
  77. {
  78. return scm_from_size_t (scm_c_vector_length (v));
  79. }
  80. #undef FUNC_NAME
  81. size_t
  82. scm_c_vector_length (SCM v)
  83. #define FUNC_NAME s_scm_vector_length
  84. {
  85. SCM_VALIDATE_VECTOR (1, v);
  86. return SCM_I_VECTOR_LENGTH (v);
  87. }
  88. #undef FUNC_NAME
  89. SCM_REGISTER_PROC (s_list_to_vector, "list->vector", 1, 0, 0, scm_vector);
  90. /*
  91. "Return a newly created vector initialized to the elements of"
  92. "the list @var{list}.\n\n"
  93. "@lisp\n"
  94. "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
  95. "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
  96. "@end lisp")
  97. */
  98. SCM_DEFINE (scm_vector, "vector", 0, 0, 1,
  99. (SCM l),
  100. "@deffnx {Scheme Procedure} list->vector l\n"
  101. "Return a newly allocated vector composed of the\n"
  102. "given arguments. Analogous to @code{list}.\n"
  103. "\n"
  104. "@lisp\n"
  105. "(vector 'a 'b 'c) @result{} #(a b c)\n"
  106. "@end lisp")
  107. #define FUNC_NAME s_scm_vector
  108. {
  109. SCM res;
  110. SCM *data;
  111. long i, len;
  112. SCM_VALIDATE_LIST_COPYLEN (1, l, len);
  113. res = scm_c_make_vector (len, SCM_UNSPECIFIED);
  114. data = SCM_I_VECTOR_WELTS (res);
  115. i = 0;
  116. while (scm_is_pair (l) && i < len)
  117. {
  118. data[i] = SCM_CAR (l);
  119. l = SCM_CDR (l);
  120. i += 1;
  121. }
  122. return res;
  123. }
  124. #undef FUNC_NAME
  125. SCM_DEFINE (scm_vector_ref, "vector-ref", 2, 0, 0,
  126. (SCM vector, SCM k),
  127. "@var{k} must be a valid index of @var{vector}.\n"
  128. "@samp{Vector-ref} returns the contents of element @var{k} of\n"
  129. "@var{vector}.\n\n"
  130. "@lisp\n"
  131. "(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8\n"
  132. "(vector-ref '#(1 1 2 3 5 8 13 21)\n"
  133. " (let ((i (round (* 2 (acos -1)))))\n"
  134. " (if (inexact? i)\n"
  135. " (inexact->exact i)\n"
  136. " i))) @result{} 13\n"
  137. "@end lisp")
  138. #define FUNC_NAME s_scm_vector_ref
  139. {
  140. return scm_c_vector_ref (vector, scm_to_size_t (k));
  141. }
  142. #undef FUNC_NAME
  143. SCM
  144. scm_c_vector_ref (SCM v, size_t k)
  145. #define FUNC_NAME s_scm_vector_ref
  146. {
  147. SCM_VALIDATE_VECTOR (1, v);
  148. if (k >= SCM_I_VECTOR_LENGTH (v))
  149. scm_out_of_range (NULL, scm_from_size_t (k));
  150. return SCM_SIMPLE_VECTOR_REF (v, k);
  151. }
  152. #undef FUNC_NAME
  153. SCM_DEFINE (scm_vector_set_x, "vector-set!", 3, 0, 0,
  154. (SCM vector, SCM k, SCM obj),
  155. "@var{k} must be a valid index of @var{vector}.\n"
  156. "@code{Vector-set!} stores @var{obj} in element @var{k} of @var{vector}.\n"
  157. "The value returned by @samp{vector-set!} is unspecified.\n"
  158. "@lisp\n"
  159. "(let ((vec (vector 0 '(2 2 2 2) \"Anna\")))\n"
  160. " (vector-set! vec 1 '(\"Sue\" \"Sue\"))\n"
  161. " vec) @result{} #(0 (\"Sue\" \"Sue\") \"Anna\")\n"
  162. "(vector-set! '#(0 1 2) 1 \"doe\") @result{} @emph{error} ; constant vector\n"
  163. "@end lisp")
  164. #define FUNC_NAME s_scm_vector_set_x
  165. {
  166. scm_c_vector_set_x (vector, scm_to_size_t (k), obj);
  167. return SCM_UNSPECIFIED;
  168. }
  169. #undef FUNC_NAME
  170. void
  171. scm_c_vector_set_x (SCM v, size_t k, SCM obj)
  172. #define FUNC_NAME s_scm_vector_set_x
  173. {
  174. SCM_VALIDATE_VECTOR (1, v);
  175. if (k >= SCM_I_VECTOR_LENGTH (v))
  176. scm_out_of_range (NULL, scm_from_size_t (k));
  177. SCM_SIMPLE_VECTOR_SET (v, k, obj);
  178. }
  179. #undef FUNC_NAME
  180. SCM_DEFINE (scm_make_vector, "make-vector", 1, 1, 0,
  181. (SCM k, SCM fill),
  182. "Return a newly allocated vector of @var{k} elements. If a\n"
  183. "second argument is given, then each position is initialized to\n"
  184. "@var{fill}. Otherwise the initial contents of each position is\n"
  185. "unspecified.")
  186. #define FUNC_NAME s_scm_make_vector
  187. {
  188. size_t l = scm_to_unsigned_integer (k, 0, VECTOR_MAX_LENGTH);
  189. if (SCM_UNBNDP (fill))
  190. fill = SCM_UNSPECIFIED;
  191. return scm_c_make_vector (l, fill);
  192. }
  193. #undef FUNC_NAME
  194. SCM
  195. scm_c_make_vector (size_t k, SCM fill)
  196. #define FUNC_NAME s_scm_make_vector
  197. {
  198. SCM vector;
  199. unsigned long int j;
  200. SCM_ASSERT_RANGE (1, scm_from_size_t (k), k <= VECTOR_MAX_LENGTH);
  201. vector = scm_words ((k << 8) | scm_tc7_vector, k + 1);
  202. for (j = 0; j < k; ++j)
  203. SCM_SIMPLE_VECTOR_SET (vector, j, fill);
  204. return vector;
  205. }
  206. #undef FUNC_NAME
  207. SCM_DEFINE (scm_vector_copy, "vector-copy", 1, 0, 0,
  208. (SCM vec),
  209. "Return a copy of @var{vec}.")
  210. #define FUNC_NAME s_scm_vector_copy
  211. {
  212. scm_t_array_handle handle;
  213. size_t i, len;
  214. ssize_t inc;
  215. const SCM *src;
  216. SCM result, *dst;
  217. src = scm_vector_elements (vec, &handle, &len, &inc);
  218. result = scm_c_make_vector (len, SCM_UNDEFINED);
  219. dst = SCM_I_VECTOR_WELTS (result);
  220. for (i = 0; i < len; i++, src += inc)
  221. dst[i] = *src;
  222. scm_array_handle_release (&handle);
  223. return result;
  224. }
  225. #undef FUNC_NAME
  226. SCM_DEFINE (scm_vector_to_list, "vector->list", 1, 0, 0,
  227. (SCM v),
  228. "Return a newly allocated list composed of the elements of @var{v}.\n"
  229. "\n"
  230. "@lisp\n"
  231. "(vector->list '#(dah dah didah)) @result{} (dah dah didah)\n"
  232. "(list->vector '(dididit dah)) @result{} #(dididit dah)\n"
  233. "@end lisp")
  234. #define FUNC_NAME s_scm_vector_to_list
  235. {
  236. SCM res = SCM_EOL;
  237. const SCM *data;
  238. scm_t_array_handle handle;
  239. size_t i, count, len;
  240. ssize_t inc;
  241. data = scm_vector_elements (v, &handle, &len, &inc);
  242. for (i = (len - 1) * inc, count = 0;
  243. count < len;
  244. i -= inc, count++)
  245. res = scm_cons (data[i], res);
  246. scm_array_handle_release (&handle);
  247. return res;
  248. }
  249. #undef FUNC_NAME
  250. SCM_DEFINE (scm_vector_fill_x, "vector-fill!", 2, 0, 0,
  251. (SCM v, SCM fill),
  252. "Store @var{fill} in every position of @var{vector}. The value\n"
  253. "returned by @code{vector-fill!} is unspecified.")
  254. #define FUNC_NAME s_scm_vector_fill_x
  255. {
  256. scm_t_array_handle handle;
  257. SCM *data;
  258. size_t i, len;
  259. ssize_t inc;
  260. data = scm_vector_writable_elements (v, &handle, &len, &inc);
  261. for (i = 0; i < len; i += inc)
  262. data[i] = fill;
  263. scm_array_handle_release (&handle);
  264. return SCM_UNSPECIFIED;
  265. }
  266. #undef FUNC_NAME
  267. SCM
  268. scm_i_vector_equal_p (SCM x, SCM y)
  269. {
  270. long i;
  271. for (i = SCM_I_VECTOR_LENGTH (x) - 1; i >= 0; i--)
  272. if (scm_is_false (scm_equal_p (SCM_I_VECTOR_ELTS (x)[i],
  273. SCM_I_VECTOR_ELTS (y)[i])))
  274. return SCM_BOOL_F;
  275. return SCM_BOOL_T;
  276. }
  277. SCM_DEFINE (scm_vector_move_left_x, "vector-move-left!", 5, 0, 0,
  278. (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
  279. "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
  280. "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
  281. "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
  282. "@code{vector-move-left!} copies elements in leftmost order.\n"
  283. "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
  284. "same vector, @code{vector-move-left!} is usually appropriate when\n"
  285. "@var{start1} is greater than @var{start2}.")
  286. #define FUNC_NAME s_scm_vector_move_left_x
  287. {
  288. scm_t_array_handle handle1, handle2;
  289. const SCM *elts1;
  290. SCM *elts2;
  291. size_t len1, len2;
  292. ssize_t inc1, inc2;
  293. size_t i, j, e;
  294. elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
  295. elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
  296. i = scm_to_unsigned_integer (start1, 0, len1);
  297. e = scm_to_unsigned_integer (end1, i, len1);
  298. SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
  299. j = scm_to_unsigned_integer (start2, 0, len2);
  300. SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
  301. i *= inc1;
  302. e *= inc1;
  303. j *= inc2;
  304. for (; i < e; i += inc1, j += inc2)
  305. elts2[j] = elts1[i];
  306. scm_array_handle_release (&handle2);
  307. scm_array_handle_release (&handle1);
  308. return SCM_UNSPECIFIED;
  309. }
  310. #undef FUNC_NAME
  311. SCM_DEFINE (scm_vector_move_right_x, "vector-move-right!", 5, 0, 0,
  312. (SCM vec1, SCM start1, SCM end1, SCM vec2, SCM start2),
  313. "Copy elements from @var{vec1}, positions @var{start1} to @var{end1},\n"
  314. "to @var{vec2} starting at position @var{start2}. @var{start1} and\n"
  315. "@var{start2} are inclusive indices; @var{end1} is exclusive.\n\n"
  316. "@code{vector-move-right!} copies elements in rightmost order.\n"
  317. "Therefore, in the case where @var{vec1} and @var{vec2} refer to the\n"
  318. "same vector, @code{vector-move-right!} is usually appropriate when\n"
  319. "@var{start1} is less than @var{start2}.")
  320. #define FUNC_NAME s_scm_vector_move_right_x
  321. {
  322. scm_t_array_handle handle1, handle2;
  323. const SCM *elts1;
  324. SCM *elts2;
  325. size_t len1, len2;
  326. ssize_t inc1, inc2;
  327. size_t i, j, e;
  328. elts1 = scm_vector_elements (vec1, &handle1, &len1, &inc1);
  329. elts2 = scm_vector_writable_elements (vec2, &handle2, &len2, &inc2);
  330. i = scm_to_unsigned_integer (start1, 0, len1);
  331. e = scm_to_unsigned_integer (end1, i, len1);
  332. SCM_ASSERT_RANGE (SCM_ARG3, end1, (e-i) <= len2);
  333. j = scm_to_unsigned_integer (start2, 0, len2);
  334. SCM_ASSERT_RANGE (SCM_ARG5, start2, j <= len2 - (e - i));
  335. j += (e - i);
  336. i *= inc1;
  337. e *= inc1;
  338. j *= inc2;
  339. while (i < e)
  340. {
  341. e -= inc1;
  342. j -= inc2;
  343. elts2[j] = elts1[e];
  344. }
  345. scm_array_handle_release (&handle2);
  346. scm_array_handle_release (&handle1);
  347. return SCM_UNSPECIFIED;
  348. }
  349. #undef FUNC_NAME
  350. SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_SCM, scm_make_vector)
  351. void
  352. scm_init_vectors ()
  353. {
  354. #include "libguile/vectors.x"
  355. }
  356. /*
  357. Local Variables:
  358. c-file-style: "gnu"
  359. End:
  360. */