*** empty log message ***
[bpt/guile.git] / libguile / num2integral.i.c
CommitLineData
1be6b49c
ML
1/* this file is #include'd (many times) by numbers.c */
2
3ITYPE
4NUM2INTEGRAL (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
84SCM
85INTEGRAL2NUM (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
106SCM
107INTEGRAL2BIG (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*/