Commit | Line | Data |
---|---|---|
1be6b49c ML |
1 | /* this file is #include'd (many times) by numbers.c */ |
2 | ||
3 | ITYPE | |
4 | NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller) | |
5 | { | |
6 | if (SCM_INUMP (num)) | |
7 | { /* immediate */ | |
8 | ||
b858464a | 9 | scm_t_signed_bits n = SCM_INUM (num); |
1be6b49c ML |
10 | |
11 | #ifdef UNSIGNED | |
12 | if (n < 0) | |
13 | scm_out_of_range (s_caller, num); | |
14 | #endif | |
15 | ||
b858464a | 16 | if (sizeof (ITYPE) >= sizeof (scm_t_signed_bits)) |
1be6b49c ML |
17 | /* can't fit anything too big for this type in an inum |
18 | anyway */ | |
19 | return (ITYPE) n; | |
20 | else | |
21 | { /* an inum can be out of range, so check */ | |
b858464a | 22 | if (n > (scm_t_signed_bits)MAX_VALUE |
1be6b49c | 23 | #ifndef UNSIGNED |
b858464a | 24 | || n < (scm_t_signed_bits)MIN_VALUE |
1be6b49c ML |
25 | #endif |
26 | ) | |
27 | scm_out_of_range (s_caller, num); | |
28 | else | |
29 | return (ITYPE) n; | |
30 | } | |
31 | } | |
32 | else if (SCM_BIGP (num)) | |
33 | { /* bignum */ | |
34 | ||
35 | ITYPE res = 0; | |
36 | size_t l; | |
37 | ||
38 | for (l = SCM_NUMDIGS (num); l--;) | |
39 | { | |
40 | ITYPE new = SCM_I_BIGUP (ITYPE, res) + SCM_BDIGITS (num)[l]; | |
41 | if (new < res | |
42 | #ifndef UNSIGNED | |
43 | && !(new == MIN_VALUE && l == 0) | |
44 | #endif | |
45 | ) | |
46 | scm_out_of_range (s_caller, num); | |
47 | res = new; | |
48 | } | |
49 | ||
50 | #ifndef UNSIGNED | |
51 | if (SCM_BIGSIGN (num)) | |
52 | { | |
53 | res = -res; | |
54 | if (res <= 0) | |
55 | return res; | |
56 | else | |
57 | scm_out_of_range (s_caller, num); | |
58 | } | |
59 | else | |
60 | { | |
61 | if (res >= 0) | |
62 | return res; | |
63 | else | |
64 | scm_out_of_range (s_caller, num); | |
65 | } | |
66 | #endif | |
67 | ||
68 | return res; | |
69 | } | |
70 | else if (SCM_REALP (num)) | |
71 | { /* inexact */ | |
72 | ||
73 | double u = SCM_REAL_VALUE (num); | |
74 | ITYPE res = u; | |
75 | if ((double) res == u) | |
76 | return res; | |
77 | else | |
78 | scm_out_of_range (s_caller, num); | |
79 | } | |
80 | else | |
81 | scm_wrong_type_arg (s_caller, pos, num); | |
82 | } | |
83 | ||
84 | SCM | |
85 | INTEGRAL2NUM (ITYPE n) | |
86 | { | |
b858464a | 87 | if (sizeof (ITYPE) < sizeof (scm_t_signed_bits) |
1be6b49c ML |
88 | || |
89 | #ifndef UNSIGNED | |
90 | SCM_FIXABLE (n) | |
91 | #else | |
92 | SCM_POSFIXABLE (n) | |
93 | #endif | |
94 | ) | |
dd85ce47 | 95 | return SCM_MAKINUM ((long) n); |
1be6b49c ML |
96 | |
97 | #ifdef SCM_BIGDIG | |
98 | return INTEGRAL2BIG (n); | |
99 | #else | |
100 | return scm_make_real ((double) n); | |
101 | #endif | |
102 | } | |
103 | ||
104 | #ifdef SCM_BIGDIG | |
105 | ||
106 | SCM | |
107 | INTEGRAL2BIG (ITYPE n) | |
108 | { | |
109 | SCM res; | |
110 | int neg_p; | |
111 | int n_digits; | |
112 | size_t i; | |
113 | SCM_BIGDIG *digits; | |
114 | ||
115 | #ifndef UNSIGNED | |
116 | neg_p = (n < 0); | |
117 | if (neg_p) n = -n; | |
118 | #else | |
119 | neg_p = 0; | |
120 | #endif | |
121 | ||
122 | #ifndef UNSIGNED | |
123 | if (n == MIN_VALUE) | |
124 | /* special case */ | |
125 | n_digits = | |
126 | (sizeof (ITYPE) + sizeof (SCM_BIGDIG) - 1) / sizeof (SCM_BIGDIG); | |
127 | else | |
128 | #endif | |
129 | { | |
130 | ITYPE tn; | |
131 | for (tn = n, n_digits = 0; | |
132 | tn; | |
133 | ++n_digits, tn = SCM_BIGDN (tn)) | |
134 | ; | |
135 | } | |
136 | ||
137 | i = 0; | |
138 | res = scm_i_mkbig (n_digits, neg_p); | |
139 | digits = SCM_BDIGITS (res); | |
140 | ||
141 | while (i < n_digits) | |
142 | { | |
143 | digits[i++] = SCM_BIGLO (n); | |
144 | n = SCM_BIGDN (n); | |
145 | } | |
146 | ||
147 | return res; | |
148 | } | |
149 | ||
150 | #endif | |
151 | ||
152 | /* clean up */ | |
153 | #undef INTEGRAL2NUM | |
154 | #undef INTEGRAL2BIG | |
155 | #undef NUM2INTEGRAL | |
156 | #undef UNSIGNED | |
157 | #undef ITYPE | |
158 | #undef MIN_VALUE | |
159 | #undef MAX_VALUE | |
160 | ||
161 | /* | |
162 | Local Variables: | |
163 | c-file-style: "gnu" | |
164 | End: | |
165 | */ |