1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-23 21:10:29 +02:00

(scm_list_to_typed_array): Allow the specification of the

upper bound as well.  This is needed for empty arrays.
(l2ra): Give needed number of elements in error message.
(scm_i_print_array): Print length information for arrays that need
it.
(scm_i_read_array): Parse it.
This commit is contained in:
Marius Vollmer 2005-01-10 19:06:48 +00:00
parent 66d3378432
commit 2caaadd1c2

View file

@ -764,7 +764,7 @@ SCM_DEFINE (scm_make_typed_array, "make-typed-array", 2, 0, 1,
while (k--) while (k--)
{ {
s[k].inc = rlen; s[k].inc = rlen;
SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd); SCM_ASSERT_RANGE (1, bounds, s[k].lbnd <= s[k].ubnd + 1);
rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc; rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
} }
@ -2332,45 +2332,59 @@ SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
static void l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k); static void l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k);
SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0, SCM_DEFINE (scm_list_to_typed_array, "list->typed-array", 3, 0, 0,
(SCM type, SCM ndim, SCM lst), (SCM type, SCM shape, SCM lst),
"Return an array of the type @var{type}\n" "Return an array of the type @var{type}\n"
"with elements the same as those of @var{lst}.\n" "with elements the same as those of @var{lst}.\n"
"\n" "\n"
"The argument @var{ndim} determines the number of dimensions\n" "The argument @var{shape} determines the number of dimensions\n"
"of the array. It is either an exact integer, giving the\n" "of the array and their shape. It is either an exact integer,\n"
"number directly, or a list of exact integers, whose length\n" "giving the\n"
"specifies the number of dimensions and each element is the\n" "number of dimensions directly, or a list whose length\n"
"lower index bound of its dimension.") "specifies the number of dimensions and each element specified\n"
"the lower and optionally the upper bound of the corresponding\n"
"dimension.\n"
"When the element is list of two elements, these elements\n"
"give the lower and upper bounds. When it is an exact\n"
"integer, it gives only the lower bound.")
#define FUNC_NAME s_scm_list_to_typed_array #define FUNC_NAME s_scm_list_to_typed_array
{ {
SCM shape, row; SCM row;
SCM ra; SCM ra;
scm_t_array_handle handle; scm_t_array_handle handle;
shape = SCM_EOL;
row = lst; row = lst;
if (scm_is_integer (ndim)) if (scm_is_integer (shape))
{ {
size_t k = scm_to_size_t (ndim); size_t k = scm_to_size_t (shape);
shape = SCM_EOL;
while (k-- > 0) while (k-- > 0)
{ {
shape = scm_cons (scm_length (row), shape); shape = scm_cons (scm_length (row), shape);
if (k > 0) if (k > 0 && !scm_is_null (row))
row = scm_car (row); row = scm_car (row);
} }
} }
else else
{ {
SCM shape_spec = shape;
shape = SCM_EOL;
while (1) while (1)
{ {
shape = scm_cons (scm_list_2 (scm_car (ndim), SCM spec = scm_car (shape_spec);
scm_sum (scm_sum (scm_car (ndim), if (scm_is_pair (spec))
scm_length (row)), shape = scm_cons (spec, shape);
scm_from_int (-1))), else
shape); shape = scm_cons (scm_list_2 (spec,
ndim = scm_cdr (ndim); scm_sum (scm_sum (spec,
if (scm_is_pair (ndim)) scm_length (row)),
row = scm_car (row); scm_from_int (-1))),
shape);
shape_spec = scm_cdr (shape_spec);
if (scm_is_pair (shape_spec))
{
if (!scm_is_null (row))
row = scm_car (row);
}
else else
break; break;
} }
@ -2405,8 +2419,10 @@ l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
{ {
scm_t_array_dim *dim = scm_array_handle_dims (handle) + k; scm_t_array_dim *dim = scm_array_handle_dims (handle) + k;
ssize_t inc = dim->inc; ssize_t inc = dim->inc;
size_t n = 1 + dim->ubnd - dim->lbnd; size_t len = 1 + dim->ubnd - dim->lbnd, n;
char *errmsg = NULL;
n = len;
while (n > 0 && scm_is_pair (lst)) while (n > 0 && scm_is_pair (lst))
{ {
l2ra (SCM_CAR (lst), handle, pos, k + 1); l2ra (SCM_CAR (lst), handle, pos, k + 1);
@ -2415,11 +2431,12 @@ l2ra (SCM lst, scm_t_array_handle *handle, ssize_t pos, size_t k)
n -= 1; n -= 1;
} }
if (n != 0) if (n != 0)
scm_misc_error (NULL, "too few elements for array dimension ~a", errmsg = "too few elements for array dimension ~a, need ~a";
scm_list_1 (scm_from_ulong (k)));
if (!scm_is_null (lst)) if (!scm_is_null (lst))
scm_misc_error (NULL, "too many elements for array dimension ~a", errmsg = "too many elements for array dimension ~a, want ~a";
scm_list_1 (scm_from_ulong (k))); if (errmsg)
scm_misc_error (NULL, errmsg, scm_list_2 (scm_from_ulong (k),
scm_from_size_t (len)));
} }
} }
@ -2485,6 +2502,7 @@ scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
SCM v = SCM_ARRAY_V (array); SCM v = SCM_ARRAY_V (array);
unsigned long base = SCM_ARRAY_BASE (array); unsigned long base = SCM_ARRAY_BASE (array);
long i; long i;
int print_lbnds = 0, zero_size = 0, print_lens = 0;
scm_putc ('#', port); scm_putc ('#', port);
if (ndim != 1 || dim_specs[0].lbnd != 0) if (ndim != 1 || dim_specs[0].lbnd != 0)
@ -2499,14 +2517,29 @@ scm_i_print_array (SCM array, SCM port, scm_print_state *pstate)
scm_puts ("?", port); scm_puts ("?", port);
for (i = 0; i < ndim; i++) for (i = 0; i < ndim; i++)
if (dim_specs[i].lbnd != 0) {
if (dim_specs[i].lbnd != 0)
print_lbnds = 1;
if (dim_specs[i].ubnd - dim_specs[i].lbnd + 1 == 0)
zero_size = 1;
else if (zero_size)
print_lens = 1;
}
if (print_lbnds || print_lens)
for (i = 0; i < ndim; i++)
{ {
for (i = 0; i < ndim; i++) if (print_lbnds)
{ {
scm_putc ('@', port); scm_putc ('@', port);
scm_uintprint (dim_specs[i].lbnd, 10, port); scm_intprint (dim_specs[i].lbnd, 10, port);
}
if (print_lens)
{
scm_putc (':', port);
scm_intprint (dim_specs[i].ubnd - dim_specs[i].lbnd + 1,
10, port);
} }
break;
} }
if (ndim == 0) if (ndim == 0)
@ -2615,6 +2648,31 @@ tag_to_type (const char *tag, SCM port)
return scm_from_locale_symbol (tag); return scm_from_locale_symbol (tag);
} }
static int
read_decimal_integer (SCM port, int c, ssize_t *resp)
{
ssize_t sign = 1;
ssize_t res = 0;
int got_it = 0;
if (c == '-')
{
sign = -1;
c = scm_getc (port);
}
while ('0' <= c && c <= '9')
{
res = 10*res + c-'0';
got_it = 1;
c = scm_getc (port);
}
if (got_it)
*resp = res;
return c;
}
SCM SCM
scm_i_read_array (SCM port, int c) scm_i_read_array (SCM port, int c)
{ {
@ -2623,7 +2681,7 @@ scm_i_read_array (SCM port, int c)
char tag[80]; char tag[80];
int tag_len; int tag_len;
SCM lower_bounds = SCM_BOOL_F, elements; SCM shape = SCM_BOOL_F, elements;
/* XXX - shortcut for ordinary vectors. Shouldn't be necessary but /* XXX - shortcut for ordinary vectors. Shouldn't be necessary but
the array code can not deal with zero-length dimensions yet, and the array code can not deal with zero-length dimensions yet, and
@ -2653,55 +2711,55 @@ scm_i_read_array (SCM port, int c)
goto continue_reading_tag; goto continue_reading_tag;
} }
/* Read rank. */ /* Read rank.
rank = 0; */
got_rank = 0; rank = 1;
while ('0' <= c && c <= '9') c = read_decimal_integer (port, c, &rank);
{ if (rank < 0)
rank = 10*rank + c-'0'; scm_i_input_error (NULL, port, "array rank must be non-negative",
got_rank = 1; SCM_EOL);
c = scm_getc (port);
}
if (!got_rank)
rank = 1;
/* Read tag. */ /* Read tag.
*/
tag_len = 0; tag_len = 0;
continue_reading_tag: continue_reading_tag:
while (c != EOF && c != '(' && c != '@' && tag_len < 80) while (c != EOF && c != '(' && c != '@' && c != ':' && tag_len < 80)
{ {
tag[tag_len++] = c; tag[tag_len++] = c;
c = scm_getc (port); c = scm_getc (port);
} }
tag[tag_len] = '\0'; tag[tag_len] = '\0';
/* Read lower bounds. */ /* Read shape.
if (c == '@') */
if (c == '@' || c == ':')
{ {
lower_bounds = SCM_EOL; shape = SCM_EOL;
do do
{ {
/* Yeah, right, we should use some ready-made integer parsing ssize_t lbnd = 0, len = 0;
routine for this... SCM s;
*/
long lbnd = 0; if (c == '@')
long sign = 1; {
c = scm_getc (port);
c = read_decimal_integer (port, c, &lbnd);
}
c = scm_getc (port); s = scm_from_ssize_t (lbnd);
if (c == '-')
if (c == ':')
{ {
sign = -1;
c = scm_getc (port); c = scm_getc (port);
c = read_decimal_integer (port, c, &len);
s = scm_list_2 (s, scm_from_ssize_t (lbnd+len-1));
} }
while ('0' <= c && c <= '9')
{ shape = scm_cons (s, shape);
lbnd = 10*lbnd + c-'0'; } while (c == '@' || c == ':');
c = scm_getc (port);
} shape = scm_reverse_x (shape, SCM_EOL);
lower_bounds = scm_cons (scm_from_long (sign*lbnd), lower_bounds);
} while (c == '@');
} }
/* Read nested lists of elements. /* Read nested lists of elements.
@ -2713,24 +2771,33 @@ scm_i_read_array (SCM port, int c)
scm_ungetc (c, port); scm_ungetc (c, port);
elements = scm_read (port); elements = scm_read (port);
if (scm_is_false (lower_bounds)) if (scm_is_false (shape))
lower_bounds = scm_from_size_t (rank); shape = scm_from_size_t (rank);
else if (scm_ilength (lower_bounds) != rank) else if (scm_ilength (shape) != rank)
scm_i_input_error (NULL, port, scm_i_input_error
"the number of lower bounds must match the array rank", (NULL, port,
SCM_EOL); "the number of shape specifications must match the array rank",
SCM_EOL);
/* Handle special print syntax of rank zero arrays; see /* Handle special print syntax of rank zero arrays; see
scm_i_print_array for a rationale. scm_i_print_array for a rationale.
*/ */
if (rank == 0) if (rank == 0)
elements = scm_car (elements); {
if (!scm_is_pair (elements))
scm_i_input_error (NULL, port,
"too few elements in array literal, need 1",
SCM_EOL);
if (!scm_is_null (SCM_CDR (elements)))
scm_i_input_error (NULL, port,
"too many elements in array literal, want 1",
SCM_EOL);
elements = SCM_CAR (elements);
}
/* Construct array. /* Construct array.
*/ */
return scm_list_to_typed_array (tag_to_type (tag, port), return scm_list_to_typed_array (tag_to_type (tag, port), shape, elements);
lower_bounds,
elements);
} }
int int