vectors.c 13 KB

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