Commit | Line | Data |
---|---|---|
9d3ebce4 MV |
1 | /* This code in included by number.s.c to generate integer conversion |
2 | functions like scm_to_int and scm_from_int. It is only for | |
3 | unsigned types, see conv-integer.i.c for the signed variant. | |
4 | */ | |
5 | ||
6 | /* You need to define the following macros before including this | |
7 | template. They are undefined at the end of this file to giove a | |
8 | clean slate for the next inclusion. | |
9 | ||
10 | TYPE - the integral type to be converted | |
11 | TYPE_MIN - the smallest representable number of TYPE, typically 0. | |
12 | TYPE_MAX - the largest representable number of TYPE | |
13 | SIZEOF_TYPE - the size of TYPE, equal to "sizeof (TYPE)" but | |
14 | in a form that can be computed by the preprocessor. | |
15 | When this number is 0, the preprocessor is not used | |
16 | to select which code to compile; the most general | |
17 | code is always used. | |
18 | ||
19 | SCM_TO_TYPE_PROTO(arg), SCM_FROM_TYPE_PROTO(arg) | |
20 | - These two macros should expand into the prototype | |
21 | for the two defined functions, without the return | |
22 | type. | |
23 | ||
24 | */ | |
25 | ||
bfd7932e MV |
26 | TYPE |
27 | SCM_TO_TYPE_PROTO (SCM val) | |
28 | { | |
29 | if (SCM_I_INUMP (val)) | |
30 | { | |
31 | scm_t_signed_bits n = SCM_I_INUM (val); | |
32 | if (n >= 0 | |
33 | && ((scm_t_uintmax)n) >= TYPE_MIN && ((scm_t_uintmax)n) <= TYPE_MAX) | |
34 | return n; | |
35 | else | |
36 | { | |
37 | out_of_range: | |
1713d319 MV |
38 | scm_i_range_error (val, |
39 | scm_from_unsigned_integer (TYPE_MIN), | |
40 | scm_from_unsigned_integer (TYPE_MAX)); | |
bfd7932e MV |
41 | return 0; |
42 | } | |
43 | } | |
44 | else if (SCM_BIGP (val)) | |
45 | { | |
46 | if (TYPE_MAX <= SCM_MOST_POSITIVE_FIXNUM) | |
47 | goto out_of_range; | |
48 | else if (TYPE_MAX <= ULONG_MAX) | |
49 | { | |
50 | if (mpz_fits_ulong_p (SCM_I_BIG_MPZ (val))) | |
51 | { | |
52 | unsigned long n = mpz_get_ui (SCM_I_BIG_MPZ (val)); | |
53 | #if SIZEOF_TYPE != 0 && SIZEOF_TYPE > SCM_SIZEOF_LONG | |
54 | return n; | |
55 | #else | |
43d5626c | 56 | |
43d5626c MG |
57 | if (n >= TYPE_MIN && n <= TYPE_MAX) |
58 | return n; | |
43d5626c MG |
59 | else |
60 | goto out_of_range; | |
61 | ||
bfd7932e MV |
62 | #endif |
63 | } | |
64 | else | |
65 | goto out_of_range; | |
66 | } | |
67 | else | |
68 | { | |
69 | scm_t_uintmax n; | |
70 | size_t count; | |
71 | ||
72 | if (mpz_sgn (SCM_I_BIG_MPZ (val)) < 0) | |
73 | goto out_of_range; | |
74 | ||
75 | if (mpz_sizeinbase (SCM_I_BIG_MPZ (val), 2) | |
76 | > CHAR_BIT*sizeof (TYPE)) | |
77 | goto out_of_range; | |
78 | ||
79 | mpz_export (&n, &count, 1, sizeof (TYPE), 0, 0, SCM_I_BIG_MPZ (val)); | |
80 | ||
81 | if (n >= TYPE_MIN && n <= TYPE_MAX) | |
82 | return n; | |
43d5626c MG |
83 | else |
84 | goto out_of_range; | |
85 | ||
bfd7932e MV |
86 | } |
87 | } | |
88 | else | |
89 | { | |
90 | scm_wrong_type_arg_msg (NULL, 0, val, "exact integer"); | |
91 | return 0; | |
92 | } | |
93 | } | |
94 | ||
95 | SCM | |
96 | SCM_FROM_TYPE_PROTO (TYPE val) | |
97 | { | |
98 | #if SIZEOF_TYPE != 0 && SIZEOF_TYPE < SIZEOF_SCM_T_BITS | |
99 | return SCM_I_MAKINUM (val); | |
100 | #else | |
101 | if (SCM_POSFIXABLE (val)) | |
102 | return SCM_I_MAKINUM (val); | |
103 | else if (val <= ULONG_MAX) | |
c71b0706 | 104 | return scm_i_ulong2big (val); |
bfd7932e MV |
105 | else |
106 | { | |
107 | SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0); | |
108 | mpz_init (SCM_I_BIG_MPZ (z)); | |
109 | mpz_import (SCM_I_BIG_MPZ (z), 1, 1, sizeof (TYPE), 0, 0, &val); | |
110 | return z; | |
111 | } | |
112 | #endif | |
113 | } | |
114 | ||
115 | #undef TYPE | |
116 | #undef TYPE_MIN | |
117 | #undef TYPE_MAX | |
118 | #undef SIZEOF_TYPE | |
119 | #undef SCM_TO_TYPE_PROTO | |
120 | #undef SCM_FROM_TYPE_PROTO | |
121 |