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