~ubuntu-branches/ubuntu/natty/ruby1.8/natty-updates

« back to all changes in this revision

Viewing changes to bignum.c

  • Committer: Package Import Robot
  • Author(s): Daigo Moriwaki
  • Date: 2010-06-27 22:16:44 UTC
  • mfrom: (22.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20100627221644-7n8891uzqc17nvyq
Tags: 1.8.7.299-1
* New upstream release
* Removed patches that the upstrem has applied:
  - debian/patches/100312_timeout-fix.dpatch
  - debian/patches/100620_fix_pathname_warning.dpatch
  - debian/patches/100620_fix_super_called_outside_of_method.dpatch

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
  bignum.c -
4
4
 
5
5
  $Author: shyouhei $
6
 
  $Date: 2009-07-30 09:31:59 +0900 (Thu, 30 Jul 2009) $
 
6
  $Date: 2010-06-08 17:42:55 +0900 (Tue, 08 Jun 2010) $
7
7
  created at: Fri Jun 10 00:48:55 JST 1994
8
8
 
9
9
  Copyright (C) 1993-2003 Yukihiro Matsumoto
222
222
    return rb_int2big(n);
223
223
}
224
224
 
225
 
#ifdef HAVE_LONG_LONG
 
225
#if SIZEOF_LONG % SIZEOF_BDIGITS != 0
 
226
# error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
 
227
#endif
 
228
 
 
229
/*
 
230
 * buf is an array of long integers.
 
231
 * buf is ordered from least significant word to most significant word.
 
232
 * buf[0] is the least significant word and
 
233
 * buf[num_longs-1] is the most significant word.
 
234
 * This means words in buf is little endian.
 
235
 * However each word in buf is native endian.
 
236
 * (buf[i]&1) is the least significant bit and
 
237
 * (buf[i]&(1<<(SIZEOF_LONG*CHAR_BIT-1))) is the most significant bit
 
238
 * for each 0 <= i < num_longs.
 
239
 * So buf is little endian at whole on a little endian machine.
 
240
 * But buf is mixed endian on a big endian machine.
 
241
 */
 
242
void
 
243
rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
 
244
{
 
245
    val = rb_to_int(val);
 
246
    if (num_longs == 0)
 
247
        return;
 
248
    if (FIXNUM_P(val)) {
 
249
        long i;
 
250
        long tmp = FIX2LONG(val);
 
251
        buf[0] = (unsigned long)tmp;
 
252
        tmp = tmp < 0 ? ~0L : 0;
 
253
        for (i = 1; i < num_longs; i++)
 
254
            buf[i] = (unsigned long)tmp;
 
255
        return;
 
256
    }
 
257
    else {
 
258
        long len = RBIGNUM_LEN(val);
 
259
        BDIGIT *ds = BDIGITS(val), *dend = ds + len;
 
260
        long i, j;
 
261
        for (i = 0; i < num_longs && ds < dend; i++) {
 
262
            unsigned long l = 0;
 
263
            for (j = 0; j < DIGSPERLONG && ds < dend; j++, ds++) {
 
264
                l |= ((unsigned long)*ds << (j * BITSPERDIG));
 
265
            }
 
266
            buf[i] = l;
 
267
        }
 
268
        for (; i < num_longs; i++)
 
269
            buf[i] = 0;
 
270
        if (RBIGNUM_NEGATIVE_P(val)) {
 
271
            for (i = 0; i < num_longs; i++) {
 
272
                buf[i] = ~buf[i];
 
273
            }
 
274
            for (i = 0; i < num_longs; i++) {
 
275
                buf[i]++;
 
276
                if (buf[i] != 0)
 
277
                    return;
 
278
            }
 
279
        }
 
280
    }
 
281
}
 
282
 
 
283
/* See rb_big_pack comment for endianness of buf. */
 
284
VALUE
 
285
rb_big_unpack(unsigned long *buf, long num_longs)
 
286
{
 
287
    while (2 <= num_longs) {
 
288
        if (buf[num_longs-1] == 0 && (long)buf[num_longs-2] >= 0)
 
289
            num_longs--;
 
290
        else if (buf[num_longs-1] == ~0UL && (long)buf[num_longs-2] < 0)
 
291
            num_longs--;
 
292
        else
 
293
            break;
 
294
    }
 
295
    if (num_longs == 0)
 
296
        return INT2FIX(0);
 
297
    else if (num_longs == 1)
 
298
        return LONG2NUM((long)buf[0]);
 
299
    else {
 
300
        VALUE big;
 
301
        BDIGIT *ds;
 
302
        long len = num_longs * DIGSPERLONG;
 
303
        long i;
 
304
        big = bignew(len, 1);
 
305
        ds = BDIGITS(big);
 
306
        for (i = 0; i < num_longs; i++) {
 
307
            unsigned long d = buf[i];
 
308
#if SIZEOF_LONG == SIZEOF_BDIGITS
 
309
            *ds++ = d;
 
310
#else
 
311
            int j;
 
312
            for (j = 0; j < DIGSPERLONG; j++) {
 
313
                *ds++ = BIGLO(d);
 
314
                d = BIGDN(d);
 
315
            }
 
316
#endif
 
317
        }
 
318
        if ((long)buf[num_longs-1] < 0) {
 
319
            get2comp(big);
 
320
            RBIGNUM_SET_SIGN(big, 0);
 
321
        }
 
322
        return bignorm(big);
 
323
    }
 
324
}
 
325
 
 
326
#define QUAD_SIZE 8
 
327
 
 
328
#if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
226
329
 
227
330
void
228
331
rb_quad_pack(buf, val)
295
398
 
296
399
#else
297
400
 
298
 
#define QUAD_SIZE 8
 
401
static int
 
402
quad_buf_complement(char *buf, size_t len)
 
403
{
 
404
    size_t i;
 
405
    for (i = 0; i < len; i++)
 
406
        buf[i] = ~buf[i];
 
407
    for (i = 0; i < len; i++) {
 
408
        buf[i]++;
 
409
        if (buf[i] != 0)
 
410
            return 0;
 
411
    }
 
412
    return 1;
 
413
}
299
414
 
300
415
void
301
416
rb_quad_pack(buf, val)
314
429
        rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
315
430
    }
316
431
    memcpy(buf, (char*)BDIGITS(val), len);
317
 
    if (!RBIGNUM(val)->sign) {
318
 
        len = QUAD_SIZE;
319
 
        while (len--) {
320
 
            *buf = ~*buf;
321
 
            buf++;
322
 
        }
 
432
    if (RBIGNUM_NEGATIVE_P(val)) {
 
433
        quad_buf_complement(buf, QUAD_SIZE);
323
434
    }
324
435
}
325
436
 
334
445
 
335
446
    memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
336
447
    if (sign && BNEG(buf)) {
337
 
        long len = QUAD_SIZE;
338
448
        char *tmp = (char*)BDIGITS(big);
339
449
 
340
450
        RBIGNUM(big)->sign = 0;
341
 
        while (len--) {
342
 
            *tmp = ~*tmp;
343
 
            tmp++;
344
 
        }
 
451
        quad_buf_complement(tmp, QUAD_SIZE);
345
452
    }
346
453
 
347
454
    return bignorm(big);