array-handle.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005,
  2. * 2006, 2009, 2011, 2013 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/__scm.h"
  24. #include "libguile/array-handle.h"
  25. SCM scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_LAST + 1];
  26. #define ARRAY_IMPLS_N_STATIC_ALLOC 7
  27. static scm_t_array_implementation array_impls[ARRAY_IMPLS_N_STATIC_ALLOC];
  28. static int num_array_impls_registered = 0;
  29. void
  30. scm_i_register_array_implementation (scm_t_array_implementation *impl)
  31. {
  32. if (num_array_impls_registered >= ARRAY_IMPLS_N_STATIC_ALLOC)
  33. /* need to increase ARRAY_IMPLS_N_STATIC_ALLOC, buster */
  34. abort ();
  35. else
  36. array_impls[num_array_impls_registered++] = *impl;
  37. }
  38. scm_t_array_implementation*
  39. scm_i_array_implementation_for_obj (SCM obj)
  40. {
  41. int i;
  42. for (i = 0; i < num_array_impls_registered; i++)
  43. if (SCM_NIMP (obj)
  44. && (SCM_CELL_TYPE (obj) & array_impls[i].mask) == array_impls[i].tag)
  45. return &array_impls[i];
  46. return NULL;
  47. }
  48. /* see bitvector_get_handle, string_get_handle, bytevector_get_handle,
  49. vector_get_handle, only ever called from here */
  50. void
  51. scm_array_get_handle (SCM array, scm_t_array_handle *h)
  52. {
  53. scm_t_array_implementation *impl;
  54. if (SCM_I_ARRAYP (array))
  55. {
  56. SCM v = SCM_I_ARRAY_V (array);
  57. impl = scm_i_array_implementation_for_obj (v);
  58. h->impl = impl;
  59. h->impl->get_handle (v, h);
  60. /* this works because the v's impl NEVER uses dims/ndims/base */
  61. h->dims = SCM_I_ARRAY_DIMS (array);
  62. h->ndims = SCM_I_ARRAY_NDIM (array);
  63. h->base = SCM_I_ARRAY_BASE (array);
  64. }
  65. else
  66. {
  67. impl = scm_i_array_implementation_for_obj (array);
  68. if (!impl)
  69. scm_wrong_type_arg_msg (NULL, 0, array, "array");
  70. h->impl = impl;
  71. h->impl->get_handle (array, h);
  72. }
  73. }
  74. ssize_t
  75. scm_array_handle_pos (scm_t_array_handle *h, SCM indices)
  76. {
  77. scm_t_array_dim *s = scm_array_handle_dims (h);
  78. ssize_t pos = 0, i;
  79. size_t k = scm_array_handle_rank (h);
  80. while (k > 0 && scm_is_pair (indices))
  81. {
  82. i = scm_to_signed_integer (SCM_CAR (indices), s->lbnd, s->ubnd);
  83. pos += (i - s->lbnd) * s->inc;
  84. k--;
  85. s++;
  86. indices = SCM_CDR (indices);
  87. }
  88. if (k > 0 || !scm_is_null (indices))
  89. scm_misc_error (NULL, "wrong number of indices, expecting ~a",
  90. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  91. return pos;
  92. }
  93. static void
  94. check_array_index_bounds (scm_t_array_dim *dim, ssize_t idx)
  95. {
  96. if (idx < dim->lbnd || idx > dim->ubnd)
  97. scm_error (scm_out_of_range_key, NULL, "Value out of range ~S to ~S: ~S",
  98. scm_list_3 (scm_from_ssize_t (dim->lbnd),
  99. scm_from_ssize_t (dim->ubnd),
  100. scm_from_ssize_t (idx)),
  101. scm_list_1 (scm_from_ssize_t (idx)));
  102. }
  103. ssize_t
  104. scm_array_handle_pos_1 (scm_t_array_handle *h, ssize_t idx0)
  105. {
  106. scm_t_array_dim *dim = scm_array_handle_dims (h);
  107. if (scm_array_handle_rank (h) != 1)
  108. scm_misc_error (NULL, "wrong number of indices, expecting ~A",
  109. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  110. check_array_index_bounds (&dim[0], idx0);
  111. return (idx0 - dim[0].lbnd) * dim[0].inc;
  112. }
  113. ssize_t
  114. scm_array_handle_pos_2 (scm_t_array_handle *h, ssize_t idx0, ssize_t idx1)
  115. {
  116. scm_t_array_dim *dim = scm_array_handle_dims (h);
  117. if (scm_array_handle_rank (h) != 2)
  118. scm_misc_error (NULL, "wrong number of indices, expecting ~A",
  119. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  120. check_array_index_bounds (&dim[0], idx0);
  121. check_array_index_bounds (&dim[1], idx1);
  122. return ((idx0 - dim[0].lbnd) * dim[0].inc
  123. + (idx1 - dim[1].lbnd) * dim[1].inc);
  124. }
  125. SCM
  126. scm_array_handle_element_type (scm_t_array_handle *h)
  127. {
  128. if (h->element_type < 0 || h->element_type > SCM_ARRAY_ELEMENT_TYPE_LAST)
  129. abort (); /* guile programming error */
  130. return scm_i_array_element_types[h->element_type];
  131. }
  132. void
  133. scm_array_handle_release (scm_t_array_handle *h)
  134. {
  135. /* Nothing to do here until arrays need to be reserved for real.
  136. */
  137. }
  138. const SCM *
  139. scm_array_handle_elements (scm_t_array_handle *h)
  140. {
  141. if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
  142. scm_wrong_type_arg_msg (NULL, 0, h->root, "non-uniform array");
  143. return ((const SCM*)h->elements) + h->base;
  144. }
  145. SCM *
  146. scm_array_handle_writable_elements (scm_t_array_handle *h)
  147. {
  148. if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
  149. scm_wrong_type_arg_msg (NULL, 0, h->root, "non-uniform array");
  150. return ((SCM*)h->elements) + h->base;
  151. }
  152. void
  153. scm_init_array_handle (void)
  154. {
  155. #define DEFINE_ARRAY_TYPE(tag, TAG) \
  156. scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_##TAG] = scm_from_utf8_symbol (#tag)
  157. scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_SCM] = SCM_BOOL_T;
  158. DEFINE_ARRAY_TYPE (a, CHAR);
  159. DEFINE_ARRAY_TYPE (b, BIT);
  160. DEFINE_ARRAY_TYPE (vu8, VU8);
  161. DEFINE_ARRAY_TYPE (u8, U8);
  162. DEFINE_ARRAY_TYPE (s8, S8);
  163. DEFINE_ARRAY_TYPE (u16, U16);
  164. DEFINE_ARRAY_TYPE (s16, S16);
  165. DEFINE_ARRAY_TYPE (u32, U32);
  166. DEFINE_ARRAY_TYPE (s32, S32);
  167. DEFINE_ARRAY_TYPE (u64, U64);
  168. DEFINE_ARRAY_TYPE (s64, S64);
  169. DEFINE_ARRAY_TYPE (f32, F32);
  170. DEFINE_ARRAY_TYPE (f64, F64);
  171. DEFINE_ARRAY_TYPE (c32, C32);
  172. DEFINE_ARRAY_TYPE (c64, C64);
  173. #include "libguile/array-handle.x"
  174. }
  175. /*
  176. Local Variables:
  177. c-file-style: "gnu"
  178. End:
  179. */