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 */
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
);
94 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
95 scm_remember_upto_here_1 (num
);
97 scm_out_of_range (s_caller
, num
);
100 numbits
= mpz_sizeinbase (SCM_I_BIG_MPZ (num
), 2);
101 scm_remember_upto_here_1 (num
);
102 if (numbits
> (sizeof (ITYPE
) * SCM_CHAR_BIT
))
103 scm_out_of_range (s_caller
, num
);
106 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
108 ITYPE result
= (ITYPE
) mpz_get_ui (SCM_I_BIG_MPZ (num
));
109 scm_remember_upto_here_1 (num
);
112 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_LONG
))
114 ITYPE result
= (ITYPE
) mpz_get_si (SCM_I_BIG_MPZ (num
));
115 scm_remember_upto_here_1 (num
);
120 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
126 #ifdef WORDS_BIGENDIAN
134 SCM_I_BIG_MPZ (num
));
135 /* mpz_export doesn't handle sign */
136 if (sgn
< 0) result
= - result
;
137 scm_remember_upto_here_1 (num
);
143 scm_wrong_type_arg (s_caller
, pos
, num
);
148 INTEGRAL2NUM (ITYPE n
)
150 /* If we know the size of the type, determine at compile time
151 whether we need to perform the FIXABLE test or not. This is not
152 done to get more optimal code out of the compiler (it can figure
153 this out on its own already), but to avoid a spurious warning.
154 If we don't know the size, assume that the test must be done.
157 /* have to use #if here rather than if because of gcc warnings about
159 #if SIZEOF_ITYPE < SIZEOF_SCM_T_BITS
160 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
161 #else /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
164 if (SCM_POSFIXABLE (n
))
165 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
170 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
172 return INTEGRAL2BIG (n
);
173 #endif /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
177 INTEGRAL2BIG (ITYPE n
)
179 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_LONG
))
181 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
182 mpz_init_set_ui (SCM_I_BIG_MPZ (z
), n
);
185 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
187 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
188 mpz_init_set_si (SCM_I_BIG_MPZ (z
), n
);
194 SCM result
= scm_i_mkbig ();
196 /* mpz_import doesn't handle sign -- have to use #if here rather
197 than if b/c gcc warnings for ushort, etc. */
206 mpz_import (SCM_I_BIG_MPZ (result
),
208 1, /* word order irrelevant when just one word */
209 SIZEOF_ITYPE
, /* word size */
210 0, /* native endianness within word */
214 /* mpz_import doesn't handle sign */
218 mpz_neg (SCM_I_BIG_MPZ (result
), SCM_I_BIG_MPZ (result
));
231 #undef UNSIGNED_ITYPE
232 #undef UNSIGNED_ITYPE_MAX