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 /* an inum can be out of range, so check */
63 if (UNSIGNED
) /* n is known to be >= 0 */
65 if (((scm_t_bits
) n
) > UNSIGNED_ITYPE_MAX
)
66 scm_out_of_range (s_caller
, num
);
68 else if (((ITYPE
) n
) != n
)
69 scm_out_of_range (s_caller
, num
);
73 else if (SCM_BIGP (num
))
75 if (SIZEOF_ITYPE
< SIZEOF_SCM_T_BITS
)
76 scm_out_of_range (s_caller
, num
);
79 /* make sure the result will fit */
82 int fits_p
= BIGMPZ_FITSP (SCM_I_BIG_MPZ (num
));
83 scm_remember_upto_here_1 (num
);
85 scm_out_of_range (s_caller
, num
);
92 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
93 scm_remember_upto_here_1 (num
);
95 scm_out_of_range (s_caller
, num
);
98 numbits
= mpz_sizeinbase (SCM_I_BIG_MPZ (num
), 2);
99 if (UNSIGNED
) numbits
++;
100 scm_remember_upto_here_1 (num
);
101 if (numbits
> (sizeof (ITYPE
) * 8))
102 scm_out_of_range (s_caller
, num
);
105 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
107 ITYPE result
= (ITYPE
) mpz_get_ui (SCM_I_BIG_MPZ (num
));
108 scm_remember_upto_here_1 (num
);
111 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_LONG
))
113 ITYPE result
= (ITYPE
) mpz_get_si (SCM_I_BIG_MPZ (num
));
114 scm_remember_upto_here_1 (num
);
119 int sgn
= mpz_sgn (SCM_I_BIG_MPZ (num
));
125 #ifdef WORDS_BIGENDIAN
133 SCM_I_BIG_MPZ (num
));
134 /* mpz_export doesn't handle sign */
135 if (sgn
< 0) result
= - result
;
136 scm_remember_upto_here_1 (num
);
142 scm_wrong_type_arg (s_caller
, pos
, num
);
147 INTEGRAL2NUM (ITYPE n
)
149 /* If we know the size of the type, determine at compile time
150 whether we need to perform the FIXABLE test or not. This is not
151 done to get more optimal code out of the compiler (it can figure
152 this out on its own already), but to avoid a spurious warning.
153 If we don't know the size, assume that the test must be done.
156 /* have to use #if here rather than if because of gcc warnings about
158 #if SIZEOF_ITYPE < SIZEOF_SCM_T_BITS
159 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
160 #else /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
163 if (SCM_POSFIXABLE (n
))
164 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
169 return SCM_MAKINUM ((scm_t_signed_bits
) n
);
171 return INTEGRAL2BIG (n
);
172 #endif /* not SIZEOF_ITYPE < SIZEOF_SCM_T_BITS */
176 INTEGRAL2BIG (ITYPE n
)
178 if (UNSIGNED
&& (SIZEOF_ITYPE
<= SIZEOF_LONG
))
180 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
181 mpz_init_set_ui (SCM_I_BIG_MPZ (z
), n
);
184 else if ((!UNSIGNED
) && (SIZEOF_ITYPE
<= SIZEOF_UNSIGNED_LONG
))
186 SCM z
= scm_double_cell (scm_tc16_big
, 0, 0, 0);
187 mpz_init_set_si (SCM_I_BIG_MPZ (z
), n
);
193 SCM result
= scm_i_mkbig ();
195 /* mpz_import doesn't handle sign -- have to use #if here rather
196 than if b/c gcc warnings for ushort, etc. */
205 mpz_import (SCM_I_BIG_MPZ (result
),
207 #ifdef WORDS_BIGENDIAN
217 /* mpz_import doesn't handle sign */
221 mpz_neg (SCM_I_BIG_MPZ (result
), SCM_I_BIG_MPZ (result
));
234 #undef UNSIGNED_ITYPE
235 #undef UNSIGNED_ITYPE_MAX