1 /*
2  * Bignum.h -
3  *
4  *   Copyright (c) 2008  Higepon(Taro Minowa)  <higepon@users.sourceforge.jp>
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *   1. Redistributions of source code must retain the above copyright
11  *      notice, this list of conditions and the following disclaimer.
12  *
13  *   2. Redistributions in binary form must reproduce the above copyright
14  *      notice, this list of conditions and the following disclaimer in the
15  *      documentation and/or other materials provided with the distribution.
16  *
17  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23  *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  $Id: Bignum.h 261 2008-07-25 06:16:44Z higepon $
30  */
31 
32 #ifndef SCHEME_BIGNUM_
33 #define SCHEME_BIGNUM_
34 
35 #include "scheme.h"
36 #include "Fixnum.h"
37 
38 #ifdef _WIN32
39     #ifdef _WIN64
40         #define MOSH_BIGNUM_SIZEOF_INTPTR_T 8
41     #else
42         #define MOSH_BIGNUM_SIZEOF_INTPTR_T 4
43     #endif
44 #elif defined(__GNUC__)
45     #if defined(__WORDSIZE) && (__WORDSIZE == 64) // Some FreeBSD have no __WORDSIZE.
46         #define MOSH_BIGNUM_SIZEOF_INTPTR_T 8
47     #else
48         #define MOSH_BIGNUM_SIZEOF_INTPTR_T 4
49     #endif
50 #else
51     #error "define MOSH_BIGNUM_SIZEOF_INTPTR_T"
52 #endif
53 
54 namespace scheme {
55 
56 // N.B.
57 //   Since we want to reduce memory allocation,
58 //   we pass mpz_t to makeIntger() function.
59 //   It is the callee responsbility to call mpz_clear mpz_t.
60 //   If it fits into fixnum, makeIntger immediately call mpz_clear().
61 //   If not, makeIntger make Bignum instance with mpz_t. ~Bignum will call mpz_clear().
62 class Bignum : public gc_cleanup
63 {
64     friend class Ratnum; // Ratnum and Bignum share the mpz_t and mpq_t
65 
66 // N.B. Don't expose the mpz_t to outside of this class and friend class Ratnum.
67 private:
68     mpz_t value_;
69 
70     // N.B. mpz_t is shared between caller and this class.
Bignum(mpz_t value)71     Bignum(mpz_t value)
72     {
73         value_[0] = value[0];
74     }
75 
makeInteger(mpz_t v)76     static Object makeInteger(mpz_t v)
77     {
78         if (mpz_fits_slong_p(v) != 0) {
79             const intptr_t val = mpz_get_si(v);
80             if (val >= Fixnum::MIN &&
81                 val <= Fixnum::MAX) {
82                 mpz_clear(v);
83                 return Object::makeFixnum(val);
84             }
85         }
86         return Object::makeBignum(new Bignum(v));
87     }
88 
89 public:
~Bignum()90     virtual ~Bignum()
91     {
92         mpz_clear(value_);
93     }
94 
Bignum(long value)95     Bignum(long value)
96     {
97         mpz_init(value_);
98         mpz_set_si(value_, value);
99     }
100 
101     char* toString(int radix = 10) const
102     {
103         return mpz_get_str(NULL, radix, value_);
104     }
105 
toDouble()106     double toDouble() const
107     {
108         return mpz_get_d(value_);
109     }
110 
isEven()111     bool isEven() const
112     {
113         return mpz_even_p(value_) != 0;
114     }
115 
sqrt()116     Object sqrt() const
117     {
118         mpz_t ret;
119         mpz_init(ret);
120         if (isNegative()) {
121             mpz_neg(ret, value_);
122             mpz_sqrt(ret, ret);
123             return makeInteger(ret);
124         } else {
125             mpz_sqrt(ret, value_);
126             return makeInteger(ret);
127         }
128     }
129 
abs()130     Object abs() const
131     {
132         mpz_t ret;
133         mpz_init(ret);
134         mpz_abs(ret, value_);
135         return makeInteger(ret);
136     }
137 
isNegative()138     bool isNegative() const
139     {
140         return mpz_cmp_si(value_, 0) < 0;
141     }
142 
fitsU32()143     bool fitsU32() const
144     {
145         return mpz_cmp_si(value_, 0) >= 0
146             && mpz_sizeinbase(value_, 2) <= 32;
147     }
148 
fitsS32()149     bool fitsS32() const
150     {
151         mpz_t temp;
152         mpz_init(temp);
153         mpz_abs(temp, value_);
154         bool ret = mpz_sizeinbase(temp, 2) <= 31;
155         mpz_clear(temp);
156         return ret;
157     }
158 
toU32()159     uint32_t toU32() const
160     {
161         return (uint32_t)mpz_get_ui(value_);
162     }
163 
toS32()164     int32_t toS32() const
165     {
166         MOSH_ASSERT(fitsS32());
167         return (int32_t)mpz_get_si(value_);
168     }
169 
fitsU64()170     bool fitsU64() const
171     {
172         return mpz_cmp_si(value_, 0) >= 0
173             && mpz_sizeinbase(value_, 2) <= 64;
174     }
175 
fitsS64()176     bool fitsS64() const
177     {
178         mpz_t temp;
179         mpz_init(temp);
180         mpz_abs(temp, value_);
181         bool ret = mpz_sizeinbase(temp, 2) <= 64;
182         mpz_clear(temp);
183         return ret;
184     }
185 
toU64()186     uint64_t toU64() const
187     {
188         MOSH_ASSERT(fitsU64());
189 #if (MOSH_BIGNUM_SIZEOF_INTPTR_T == 4)
190         uint64_t ret = 0;
191         mpz_t temp;
192         mpz_init(temp);
193         mpz_fdiv_q_2exp(temp, value_, 32);
194         ret = mpz_get_ui(temp);
195         ret = ret << 32; // upper 32bit
196         mpz_set_ui(temp, 0xffffffff);
197         mpz_and(temp, value_, temp);
198         ret += mpz_get_ui(temp); // lower 32bit
199         mpz_clear(temp);
200         return ret;
201 #else
202         return mpz_get_ui(value_);
203 #endif
204     }
205 
toS64()206     int64_t toS64() const
207     {
208         MOSH_ASSERT(fitsS64());
209 #if (MOSH_BIGNUM_SIZEOF_INTPTR_T == 4)
210         uint64_t ret = 0;
211         mpz_t temp;
212         mpz_init(temp);
213         mpz_fdiv_q_2exp(temp, value_, 32);
214         ret = mpz_get_si(temp);
215         ret = ret << 32; // upper 32bit
216         mpz_set_ui(temp, 0xffffffff);
217         mpz_and(temp, value_, temp);
218         ret += mpz_get_ui(temp); // lower 32bit
219         mpz_clear(temp);
220         return ret;
221 #else
222         return mpz_get_si(value_);
223 #endif
224     }
225 
setU32(uint32_t value)226     void setU32(uint32_t value)
227     {
228         mpz_set_ui(value_, value);
229     }
230 
setDouble(double value)231     void setDouble(double value)
232     {
233         mpz_set_d(value_, value);
234     }
235 
bitwiseNot()236     Object bitwiseNot() const
237     {
238         mpz_t ret;
239         mpz_init(ret);
240         mpz_com(ret, value_);
241         return makeInteger(ret);
242     }
243 
bitwiseAnd(int n)244     Object bitwiseAnd(int n) const
245     {
246         mpz_t ret;
247         mpz_init_set_si(ret, n);
248         mpz_and(ret, ret, value_);
249         return makeInteger(ret);
250     }
251 
bitwiseAnd(Bignum * b)252     Object bitwiseAnd(Bignum* b) const
253     {
254         mpz_t ret;
255         mpz_init(ret);
256         mpz_and(ret, b->value_, value_);
257         return makeInteger(ret);
258     }
259 
bitwiseIor(int n)260     Object bitwiseIor(int n) const
261     {
262         mpz_t ret;
263         mpz_init_set_si(ret, n);
264         mpz_ior(ret, ret, value_);
265         return makeInteger(ret);
266     }
267 
bitwiseIor(Bignum * b)268     Object bitwiseIor(Bignum* b) const
269     {
270         mpz_t ret;
271         mpz_init(ret);
272         mpz_ior(ret, b->value_, value_);
273         return makeInteger(ret);
274     }
275 
bitwiseXor(int n)276     Object bitwiseXor(int n) const
277     {
278         mpz_t ret;
279         mpz_init_set_si(ret, n);
280         mpz_xor(ret, ret, value_);
281         return makeInteger(ret);
282     }
283 
bitwiseXor(Bignum * b)284     Object bitwiseXor(Bignum* b) const
285     {
286         mpz_t ret;
287         mpz_init(ret);
288         mpz_xor(ret, b->value_, value_);
289         return makeInteger(ret);
290     }
291 
bitwiseBitCount()292     Object bitwiseBitCount() const
293     {
294         if (gt(this, 0)) {
295             return makeInteger(mpz_popcount(value_));
296         } else {
297             mpz_t temp;
298             mpz_init(temp);
299             mpz_com(temp, value_);
300             const unsigned long ret = mpz_popcount(temp);
301             mpz_clear(temp);
302             return makeInteger(~ret);
303         }
304     }
305 
bitwiseLength()306     Object bitwiseLength() const
307     {
308         if (mpz_cmp_si(value_, 0) < 0) {
309             return bitwiseNot().toBignum()->bitwiseLength();
310         } else {
311             size_t size = mpz_sizeinbase(value_, 2);
312             return makeInteger(size);
313         }
314     }
315 
bitwiseFirstBitSet()316     Object bitwiseFirstBitSet()
317     {
318         const unsigned long int found = mpz_scan1(value_, 0);
319         if (found == ULONG_MAX) {
320             return Object::makeFixnum(-1);
321         } else {
322             return makeInteger(found);
323         }
324     }
325 
quotient(int n1,const Bignum * n2)326     static Object quotient(int n1, const Bignum* n2)
327     {
328         mpz_t ret;
329         mpz_init_set_si(ret, n1);
330         mpz_tdiv_q(ret, ret, n2->value_);
331         return makeInteger(ret);
332     }
333 
quotient(const Bignum * n1,int n2)334     static Object quotient(const Bignum* n1, int n2)
335     {
336         mpz_t ret;
337         mpz_init_set_si(ret, n2);
338         mpz_tdiv_q(ret, n1->value_, ret);
339         return makeInteger(ret);
340     }
341 
quotient(const Bignum * n1,const Bignum * n2)342     static Object quotient(const Bignum* n1, const Bignum* n2)
343     {
344         mpz_t ret;
345         mpz_init(ret);
346         mpz_tdiv_q(ret, n1->value_, n2->value_);
347         return makeInteger(ret);
348     }
349 
remainder(int n1,const Bignum * n2)350     static Object remainder(int n1, const Bignum* n2)
351     {
352         mpz_t ret;
353         mpz_init_set_si(ret, n1);
354         mpz_tdiv_r(ret, ret, n2->value_);
355         return makeInteger(ret);
356     }
357 
remainder(const Bignum * n1,int n2)358     static Object remainder(const Bignum* n1, int n2)
359     {
360         mpz_t ret;
361         mpz_init_set_si(ret, n2);
362         mpz_tdiv_r(ret, n1->value_, ret);
363         return makeInteger(ret);
364     }
365 
remainder(const Bignum * n1,const Bignum * n2)366     static Object remainder(const Bignum* n1, const Bignum* n2)
367     {
368         mpz_t ret;
369         mpz_init(ret);
370         mpz_tdiv_r(ret, n1->value_, n2->value_);
371         return makeInteger(ret);
372     }
373 
374 
bitwiseShiftLeft(const Bignum * n1,unsigned long n2)375     static Object bitwiseShiftLeft(const Bignum* n1, unsigned long n2)
376     {
377         mpz_t ret;
378         mpz_init(ret);
379         mpz_mul_2exp(ret, n1->value_, n2);
380         return makeInteger(ret);
381     }
382 
bitwiseShiftLeft(int n1,unsigned long n2)383     static Object bitwiseShiftLeft(int n1, unsigned long n2)
384     {
385         mpz_t ret;
386         mpz_init_set_si(ret, n1);
387         mpz_mul_2exp(ret, ret, n2);
388         return makeInteger(ret);
389     }
390 
bitwiseShiftRight(const Bignum * n1,unsigned long n2)391     static Object bitwiseShiftRight(const Bignum* n1, unsigned long n2)
392     {
393         mpz_t ret;
394         mpz_init(ret);
395         mpz_fdiv_q_2exp(ret, n1->value_, n2);
396         return makeInteger(ret);
397     }
398 
bitwiseShiftRight(int n1,unsigned long n2)399     static Object bitwiseShiftRight(int n1, unsigned long n2)
400     {
401         mpz_t ret;
402         mpz_init_set_si(ret, n1);
403         mpz_fdiv_q_2exp(ret, ret, n2);
404         return makeInteger(ret);
405     }
406 
pow(unsigned int n1,unsigned int n2)407     static Object pow(unsigned int n1, unsigned int n2)
408     {
409         mpz_t ret;
410         mpz_init_set_ui(ret, n1);
411         mpz_pow_ui(ret, ret, n2);
412         return makeInteger(ret);
413     }
414 
pow(int n1,unsigned int n2)415     static Object pow(int n1, unsigned int n2)
416     {
417         mpz_t ret;
418         mpz_init_set_si(ret, n1);
419         mpz_pow_ui(ret, ret, n2);
420         return makeInteger(ret);
421     }
422 
mul(int n1,Bignum * n2)423     static Object mul(int n1, Bignum* n2)
424     {
425         mpz_t ret;
426         mpz_init_set_si(ret, n1);
427         mpz_mul(ret, ret, n2->value_);
428         return makeInteger(ret);
429     }
mul(Bignum * n1,int n2)430     static Object mul(Bignum* n1, int n2)
431     {
432         mpz_t ret;
433         mpz_init_set_si(ret, n2);
434         mpz_mul(ret, ret, n1->value_);
435         return makeInteger(ret);
436     }
mul(Bignum * n1,Bignum * n2)437     static Object mul(Bignum* n1, Bignum* n2)
438     {
439         mpz_t ret;
440         mpz_init(ret);
441         mpz_mul(ret, n1->value_, n2->value_);
442         return makeInteger(ret);
443     }
444 
add(int n1,Bignum * n2)445     static Object add(int n1, Bignum* n2)
446     {
447         mpz_t ret;
448         mpz_init_set_si(ret, n1);
449         mpz_add(ret, ret, n2->value_);
450         return makeInteger(ret);
451     }
add(Bignum * n1,int n2)452     static Object add(Bignum* n1, int n2)
453     {
454         mpz_t ret;
455         mpz_init_set_si(ret, n2);
456         mpz_add(ret, ret, n1->value_);
457         return makeInteger(ret);
458     }
add(Bignum * n1,Bignum * n2)459     static Object add(Bignum* n1, Bignum* n2)
460     {
461         mpz_t ret;
462         mpz_init(ret);
463         mpz_add(ret, n1->value_, n2->value_);
464         return makeInteger(ret);
465     }
466 
sub(int n1,Bignum * n2)467     static Object sub(int n1, Bignum* n2)
468     {
469         mpz_t ret;
470         mpz_init_set_si(ret, n1);
471         mpz_sub(ret, ret, n2->value_);
472         return makeInteger(ret);
473     }
sub(Bignum * n1,int n2)474     static Object sub(Bignum* n1, int n2)
475     {
476         mpz_t ret;
477         mpz_init_set_si(ret, n2);
478         mpz_sub(ret, n1->value_, ret);
479         return makeInteger(ret);
480     }
sub(Bignum * n1,Bignum * n2)481     static Object sub(Bignum* n1, Bignum* n2)
482     {
483         mpz_t ret;
484         mpz_init(ret);
485         mpz_sub(ret, n1->value_, n2->value_);
486         return makeInteger(ret);
487     }
488 
489 #define MAKE_BIGNUM_COMPARE(compare, symbol)\
490     static bool compare(const Bignum* n1, int n2)\
491     {\
492         return mpz_cmp_si(n1->value_, n2) symbol;\
493     }\
494     static bool compare(int n1, const Bignum* n2)\
495     {\
496         return (- mpz_cmp_si(n2->value_, n1)) symbol;\
497     }\
498     static bool compare(const Bignum* n1, const Bignum* n2)\
499     {\
500         return mpz_cmp(n1->value_, n2->value_) symbol;\
501     }
502 
503     MAKE_BIGNUM_COMPARE(gt, >0)
504     MAKE_BIGNUM_COMPARE(ge, >=0)
505     MAKE_BIGNUM_COMPARE(lt, <0)
506     MAKE_BIGNUM_COMPARE(le, <=0)
507     MAKE_BIGNUM_COMPARE(eq, ==0)
508 
add(int n1,int n2)509     static Object add(int n1, int n2)
510     {
511         const fixedint ret = (fixedint)n1 + n2;
512         if (Fixnum::canFit(ret)) {
513             return Object::makeFixnum(ret);
514         } else {
515             return Object::makeBignum(ret);
516         }
517     }
sub(int n1,int n2)518     static Object sub(int n1, int n2)
519     {
520         const fixedint ret = (fixedint)n1 - n2;
521         if (Fixnum::canFit(ret)) {
522             return Object::makeFixnum(ret);
523         } else {
524             return Object::makeBignum(ret);
525         }
526     }
527 
mul(int n1,int n2)528     static Object mul(int n1, int n2)
529     {
530         const fixedint ret = (fixedint)n1 * n2;
531 
532         /* Overflow check from Gauche */
533         if ((n2 != 0 && ret / n2 != n1) || !Fixnum::canFit(ret)) {
534             return Bignum::mul(new Bignum(n1), n2);
535         } else {
536             return Object::makeFixnum(ret);
537         }
538     }
539 
makeIntegerFromU32(uint32_t n)540     static Object makeIntegerFromU32(uint32_t n)
541     {
542         if (Fixnum::canFit(n)) {
543             return Object::makeFixnum(n);
544         } else {
545             mpz_t ret;
546             mpz_init_set_ui(ret, n);
547             return Object::makeBignum(new Bignum(ret));
548         }
549     }
550 
makeIntegerFromU64(uint64_t n)551     static Object makeIntegerFromU64(uint64_t n)
552     {
553         mpz_t ret;
554         mpz_init_set_ui(ret, n >> 32);
555         mpz_mul_2exp(ret, ret, 32);
556         mpz_add_ui(ret, ret, (n & 0xffffffff));
557         return makeInteger(ret);
558     }
559 
makeIntegerFromS64(int64_t n)560     static Object makeIntegerFromS64(int64_t n)
561     {
562         mpz_t ret;
563         mpz_init_set_si(ret, n >> 32);
564         mpz_mul_2exp(ret, ret, 32);
565         const unsigned int val = n & 0xffffffff;
566         mpz_add_ui(ret, ret, val);
567         return makeInteger(ret);
568     }
569 
570 //     static Object makeIntegerFromIntprt_t(intptr_t p)
571 //     {
572 //         MOSH_ASSERT(sizeof(uint64_t) >= sizeof(intptr_t));
573 //         const uint64_t val = static_cast<uint64_t>(p);
574 //         if (Fixnum::canFit(val)) {
575 //             return Object::makeFixnum(static_cast<int>(val));
576 //         } else {
577 //             return makeIntegerFromU64(val);
578 //         }
579 //     }
580 
581 //     static Object makeIntegerFromUintprt_t(uintptr_t p)
582 //     {
583 // #if (MOSH_BIGNUM_SIZEOF_INTPTR_T == 4)
584 //         const uint32_t val = static_cast<uint32_t>(p);
585 //         if (Fixnum::canFit(val)) {
586 //             return Object::makeFixnum(val);
587 //         } else {
588 //             return makeIntegerFromU32(val);
589 //         }
590 // #else
591 //         const uint64_t val = static_cast<uint64_t>(p);
592 //         if (Fixnum::canFit(val)) {
593 //             return Object::makeFixnum(static_cast<int>(val));
594 //         } else {
595 //             return makeIntegerFromU64(val);
596 //         }
597 // #endif
598 //     }
599 
toIntptr_t()600     intptr_t toIntptr_t()
601     {
602 #if (MOSH_BIGNUM_SIZEOF_INTPTR_T == 4)
603         return toS32();
604 #else
605         return toS64();
606 #endif
607     }
608 
toUintptr_t()609     uintptr_t toUintptr_t()
610     {
611 #if (MOSH_BIGNUM_SIZEOF_INTPTR_T == 4)
612         return toU32();
613 #else
614         return toU64();
615 #endif
616     }
617 
serialize(size_t * countp)618     uint8_t* serialize(size_t* countp)
619     {
620         const int order = 1;
621         const int endian = 1;
622         const size_t nails = 0;
623         const size_t size = 1;
624         const int numb = 8 * size - nails;
625         const int count = (mpz_sizeinbase (value_, 2) + numb - 1) / numb;
626         uint8_t* rop = allocatePointerFreeU8Array(count * size + 1); // 1 for sign
627         uint8_t* ret = (uint8_t*)mpz_export(rop, countp, order, size, endian, nails, value_);
628         if (mpz_sgn(value_) < 0) {
629             rop[*countp] = 1;
630         } else {
631             rop[*countp] = 0;
632         }
633         (*countp)++;
634         return ret;
635     }
636 
deserialize(uint8_t * data,size_t count)637     static Object deserialize(uint8_t* data, size_t count)
638     {
639         mpz_t z;
640         mpz_init(z);
641         const int order = 1;
642         const int endian = 1;
643         const size_t nails = 0;
644         const size_t size = 1;
645         mpz_import(z, count - 1, order, size, endian, nails, data);
646         if (data[count - 1]) {
647             mpz_neg(z, z);
648         }
649         return Object::makeBignum(new Bignum(z));
650     }
651 
toIntptr_t(Object n)652     static intptr_t toIntptr_t(Object n)
653     {
654         MOSH_ASSERT(n.isFixnum() || n.isBignum());
655         if (n.isFixnum()) {
656             return n.toFixnum();
657         } else if (n.isBignum()) {
658             return n.toBignum()->toIntptr_t();
659         } else {
660             // not reached
661             MOSH_ASSERT(false);
662             return 0;
663         }
664     }
665 
toUintptr_t(Object n)666     static uintptr_t toUintptr_t(Object n)
667     {
668         MOSH_ASSERT(n.isFixnum() || n.isBignum());
669         if (n.isFixnum()) {
670             return n.toFixnum();
671         } else if (n.isBignum()) {
672             return n.toBignum()->toUintptr_t();
673         } else {
674             // not reached
675             return 0;
676         }
677     }
678 
makeInteger(long n)679     static Object makeInteger(long n)
680     {
681         if (Fixnum::canFit(n)) {
682             return Object::makeFixnum(n);
683         } else {
684             return Object::makeBignum(n);
685         }
686     }
687 
makeIntegerFromSigned(T val)688     template <typename T> static Object makeIntegerFromSigned(T val)
689     {
690         if (sizeof(T) <= 4) {
691             return Bignum::makeInteger(static_cast<long>(val)); // todo
692         } else if (sizeof(T) == 8) {
693             return Bignum::makeIntegerFromS64(static_cast<int64_t>(val));
694         } else {
695             MOSH_FATAL("unexpected size");
696         }
697     }
698 
makeIntegerFromUnsigned(T val)699     template <typename T> static Object makeIntegerFromUnsigned(T val)
700     {
701         if (sizeof(T) <= 4) {
702             return Bignum::makeIntegerFromU32(static_cast<uint32_t>(val));
703         } else if (sizeof(T) == 8) {
704             return Bignum::makeIntegerFromU64(static_cast<uint64_t>(val));
705         } else {
706             MOSH_FATAL("unexpected size");
707         }
708     }
709 
makeInteger(const ucs4string & text)710     static Object makeInteger(const ucs4string& text)
711     {
712         mpz_t ret;
713         mpz_init_set_str(ret, text.ascii_c_str(), 10);
714         return makeInteger(ret);
715     }
716 };
717 
makeBignum(long n)718 inline Object Object::makeBignum(long n)
719 {
720     return Object(reinterpret_cast<intptr_t>(new HeapObject(HeapObject::Bignum,
721                                                         reinterpret_cast<intptr_t>(new Bignum(n)))));
722 }
723 
makeBignum(Bignum * b)724 inline Object Object::makeBignum(Bignum* b)
725 {
726     return Object(reinterpret_cast<intptr_t>(new HeapObject(HeapObject::Bignum,
727                                                         reinterpret_cast<intptr_t>(b))));
728 }
729 
730 } // namespace scheme
731 
732 #endif // SCHEME_BIGNUM_
733