1 /* this file is #include'd (many times) by numbers.c */
9 # define UNSIGNED_ITYPE ITYPE
11 # define UNSIGNED_ITYPE unsigned ITYPE
15 #define UNSIGNED_ITYPE_MAX (~((UNSIGNED_ITYPE)0))
18 #error SIZEOF_ITYPE must be defined.
22 # if SIZEOF_ITYPE == SIZEOF_UNSIGNED_SHORT
23 # define BIGMPZ_FITSP mpz_fits_ushort_p
24 # elif SIZEOF_ITYPE == SIZEOF_UNSIGNED_INT
25 # define BIGMPZ_FITSP mpz_fits_uint_p
26 # elif SIZEOF_ITYPE == SIZEOF_UNSIGNED_LONG
27 # define BIGMPZ_FITSP mpz_fits_ulong_p
29 # define BIGMPZ_FITSP ((int (*)(void *)) 0)
30 # endif /* sizeof checks */
32 /* UNSIGNED is not defined */
33 # if SIZEOF_ITYPE == SIZEOF_SHORT
34 # define BIGMPZ_FITSP mpz_fits_sshort_p
35 # elif SIZEOF_ITYPE == SIZEOF_INT
36 # define BIGMPZ_FITSP mpz_fits_sint_p
37 # elif SIZEOF_ITYPE == SIZEOF_LONG
38 # define BIGMPZ_FITSP mpz_fits_slong_p
40 # define BIGMPZ_FITSP ((int (*)(void *)) 0)
41 # endif /* sizeof checks */
42 #endif /* UNSIGNED check */
44 /* We rely heavily on the compiler's optimizer to remove branches that
45 have constant value guards. */
48 NUM2INTEGRAL (SCM num
, unsigned long int pos
, const char *s_caller
)
52 scm_t_signed_bits n
= SCM_INUM (num
);
54 if (UNSIGNED
&& (n
< 0))
55 scm_out_of_range (s_caller
, num
);
57 if (SIZEOF_ITYPE
>= SIZEOF_SCM_T_BITS
)
58 /* the target type is large enough to hold any possible inum */
62 #if SIZEOF_SCM_T_BITS > SIZEOF_ITYPE
63 /* an inum can be out of range, so check */
64 if (UNSIGNED
) /* n is known to be >= 0 */
66 if (((scm_t_bits
) n
) > UNSIGNED_ITYPE_MAX
)
67 scm_out_of_range (s_caller
, num
);
69 else if (((ITYPE
) n
) != n
)
70 scm_out_of_range (s_caller
, num
);
75 else if (SCM_BIGP (num
))
77 if (SIZEOF_ITYPE
< SIZEOF_SCM_T_BITS
)
78 scm_out_of_range (s_caller
, num
);
81 /* make sure the result will fit */
82 if (BIGMPZ_FITSP
!= 0)
84 int fits_p
= BIGMPZ_FITSP (SCM_I_BIG_MPZ (num
));
85 scm_remember_upto_here_1 (num
);
87 scm_out_of_range (s_caller
, num
);
91 size_t itype_bits
= sizeof (ITYPE
) * SCM_CHAR_BIT
;
92 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
98 scm_out_of_range (s_caller
, num
);
101 numbits
= mpz_sizeinbase (SCM_I_BIG_MPZ (num
), 2);
105 if (numbits
> itype_bits
)
106 scm_out_of_range (s_caller
, num
);
112 /* positive, require num < 2^(itype_bits-1) */
113 if (numbits
> itype_bits
-1)
114 scm_out_of_range (s_caller
, num
);
118 /* negative, require abs(num) < 2^(itype_bits-1), but
119 also allow num == -2^(itype_bits-1), the latter
120 detected by numbits==itype_bits plus the lowest
121 (and only) 1 bit at position itype_bits-1 */
122 if (numbits
> itype_bits
123 || (numbits
== itype_bits
124 && (mpz_scan1 (SCM_I_BIG_MPZ (num
), 0)
126 scm_out_of_range (s_caller
, num
);
131 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
133 ITYPE result
= (ITYPE
) mpz_get_ui (SCM_I_BIG_MPZ (num
));
134 scm_remember_upto_here_1 (num
);
137 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_LONG
))
139 ITYPE result
= (ITYPE
) mpz_get_si (SCM_I_BIG_MPZ (num
));
140 scm_remember_upto_here_1 (num
);
145 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
151 #ifdef WORDS_BIGENDIAN
159 SCM_I_BIG_MPZ (num
));
160 /* mpz_export doesn't handle sign */
161 if (sgn
< 0) result
= - result
;
162 scm_remember_upto_here_1 (num
);
168 scm_wrong_type_arg (s_caller
, pos
, num
);
173 INTEGRAL2NUM (ITYPE n
)
175 /* If we know the size of the type, determine at compile time
176 whether we need to perform the FIXABLE test or not. This is not
177 done to get more optimal code out of the compiler (it can figure
178 this out on its own already), but to avoid a spurious warning.
179 If we don't know the size, assume that the test must be done.
182 /* have to use #if here rather than if because of gcc warnings about
184 #if SIZEOF_ITYPE < SIZEOF_SCM_T_BITS
185 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
186 #else /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
189 if (SCM_POSFIXABLE (n
))
190 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
195 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
197 return INTEGRAL2BIG (n
);
198 #endif /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
202 INTEGRAL2BIG (ITYPE n
)
204 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_LONG
))
206 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
207 mpz_init_set_ui (SCM_I_BIG_MPZ (z
), n
);
210 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
212 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
213 mpz_init_set_si (SCM_I_BIG_MPZ (z
), n
);
219 SCM result
= scm_i_mkbig ();
221 /* mpz_import doesn't handle sign -- have to use #if here rather
222 than if b/c gcc warnings for ushort, etc. */
231 mpz_import (SCM_I_BIG_MPZ (result
),
233 1, /* word order irrelevant when just one word */
234 SIZEOF_ITYPE
, /* word size */
235 0, /* native endianness within word */
239 /* mpz_import doesn't handle sign */
243 mpz_neg (SCM_I_BIG_MPZ (result
), SCM_I_BIG_MPZ (result
));
256 #undef UNSIGNED_ITYPE
257 #undef UNSIGNED_ITYPE_MAX