array-handle.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. void
  49. scm_array_get_handle (SCM array, scm_t_array_handle *h)
  50. {
  51. scm_t_array_implementation *impl = scm_i_array_implementation_for_obj (array);
  52. if (!impl)
  53. scm_wrong_type_arg_msg (NULL, 0, array, "array");
  54. h->array = array;
  55. h->impl = impl;
  56. h->base = 0;
  57. h->ndims = 0;
  58. h->dims = NULL;
  59. h->element_type = SCM_ARRAY_ELEMENT_TYPE_SCM; /* have to default to
  60. something... */
  61. h->elements = NULL;
  62. h->writable_elements = NULL;
  63. h->impl->get_handle (array, h);
  64. }
  65. ssize_t
  66. scm_array_handle_pos (scm_t_array_handle *h, SCM indices)
  67. {
  68. scm_t_array_dim *s = scm_array_handle_dims (h);
  69. ssize_t pos = 0, i;
  70. size_t k = scm_array_handle_rank (h);
  71. while (k > 0 && scm_is_pair (indices))
  72. {
  73. i = scm_to_signed_integer (SCM_CAR (indices), s->lbnd, s->ubnd);
  74. pos += (i - s->lbnd) * s->inc;
  75. k--;
  76. s++;
  77. indices = SCM_CDR (indices);
  78. }
  79. if (k > 0 || !scm_is_null (indices))
  80. scm_misc_error (NULL, "wrong number of indices, expecting ~a",
  81. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  82. return pos;
  83. }
  84. static void
  85. check_array_index_bounds (scm_t_array_dim *dim, ssize_t idx)
  86. {
  87. if (idx < dim->lbnd || idx > dim->ubnd)
  88. scm_error (scm_out_of_range_key, NULL, "Value out of range ~S to ~S: ~S",
  89. scm_list_3 (scm_from_ssize_t (dim->lbnd),
  90. scm_from_ssize_t (dim->ubnd),
  91. scm_from_ssize_t (idx)),
  92. scm_list_1 (scm_from_ssize_t (idx)));
  93. }
  94. ssize_t
  95. scm_array_handle_pos_1 (scm_t_array_handle *h, ssize_t idx0)
  96. {
  97. scm_t_array_dim *dim = scm_array_handle_dims (h);
  98. if (scm_array_handle_rank (h) != 1)
  99. scm_misc_error (NULL, "wrong number of indices, expecting ~A",
  100. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  101. check_array_index_bounds (&dim[0], idx0);
  102. return (idx0 - dim[0].lbnd) * dim[0].inc;
  103. }
  104. ssize_t
  105. scm_array_handle_pos_2 (scm_t_array_handle *h, ssize_t idx0, ssize_t idx1)
  106. {
  107. scm_t_array_dim *dim = scm_array_handle_dims (h);
  108. if (scm_array_handle_rank (h) != 2)
  109. scm_misc_error (NULL, "wrong number of indices, expecting ~A",
  110. scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
  111. check_array_index_bounds (&dim[0], idx0);
  112. check_array_index_bounds (&dim[1], idx1);
  113. return ((idx0 - dim[0].lbnd) * dim[0].inc
  114. + (idx1 - dim[1].lbnd) * dim[1].inc);
  115. }
  116. SCM
  117. scm_array_handle_element_type (scm_t_array_handle *h)
  118. {
  119. if (h->element_type < 0 || h->element_type > SCM_ARRAY_ELEMENT_TYPE_LAST)
  120. abort (); /* guile programming error */
  121. return scm_i_array_element_types[h->element_type];
  122. }
  123. void
  124. scm_array_handle_release (scm_t_array_handle *h)
  125. {
  126. /* Nothing to do here until arrays need to be reserved for real.
  127. */
  128. }
  129. const SCM *
  130. scm_array_handle_elements (scm_t_array_handle *h)
  131. {
  132. if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
  133. scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
  134. return ((const SCM*)h->elements) + h->base;
  135. }
  136. SCM *
  137. scm_array_handle_writable_elements (scm_t_array_handle *h)
  138. {
  139. if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
  140. scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
  141. return ((SCM*)h->elements) + h->base;
  142. }
  143. void
  144. scm_init_array_handle (void)
  145. {
  146. #define DEFINE_ARRAY_TYPE(tag, TAG) \
  147. scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_##TAG] = scm_from_utf8_symbol (#tag)
  148. scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_SCM] = SCM_BOOL_T;
  149. DEFINE_ARRAY_TYPE (a, CHAR);
  150. DEFINE_ARRAY_TYPE (b, BIT);
  151. DEFINE_ARRAY_TYPE (vu8, VU8);
  152. DEFINE_ARRAY_TYPE (u8, U8);
  153. DEFINE_ARRAY_TYPE (s8, S8);
  154. DEFINE_ARRAY_TYPE (u16, U16);
  155. DEFINE_ARRAY_TYPE (s16, S16);
  156. DEFINE_ARRAY_TYPE (u32, U32);
  157. DEFINE_ARRAY_TYPE (s32, S32);
  158. DEFINE_ARRAY_TYPE (u64, U64);
  159. DEFINE_ARRAY_TYPE (s64, S64);
  160. DEFINE_ARRAY_TYPE (f32, F32);
  161. DEFINE_ARRAY_TYPE (f64, F64);
  162. DEFINE_ARRAY_TYPE (c32, C32);
  163. DEFINE_ARRAY_TYPE (c64, C64);
  164. #include "libguile/array-handle.x"
  165. }
  166. /*
  167. Local Variables:
  168. c-file-style: "gnu"
  169. End:
  170. */