[前][次][番号順一覧][スレッド一覧]

ruby-changes:29770

From: akr <ko1@a...>
Date: Sun, 7 Jul 2013 20:02:59 +0900 (JST)
Subject: [ruby-changes:29770] akr:r41822 (trunk): * bignum.c: Reorder functions to decrease forward reference.

akr	2013-07-07 20:02:47 +0900 (Sun, 07 Jul 2013)

  New Revision: 41822

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41822

  Log:
    * bignum.c: Reorder functions to decrease forward reference.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 41821)
+++ ChangeLog	(revision 41822)
@@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Jul  7 19:21:30 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c: Reorder functions to decrease forward reference.
+
 Sun Jul  7 14:41:57 2013  Tanaka Akira  <akr@f...>
 
 	* bignum.c: (bigsub_core): Use bary_sub.
Index: bignum.c
===================================================================
--- bignum.c	(revision 41821)
+++ bignum.c	(revision 41822)
@@ -26,6 +26,7 @@ https://github.com/ruby/ruby/blob/trunk/bignum.c#L26
 #include <assert.h>
 
 VALUE rb_cBignum;
+const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
 static VALUE big_three = Qnil;
 
@@ -93,51 +94,23 @@ static VALUE big_three = Qnil; https://github.com/ruby/ruby/blob/trunk/bignum.c#L94
 #define RBIGNUM_SET_NEGATIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 0)
 #define RBIGNUM_SET_POSITIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 1)
 
+#define bignew(len,sign) bignew_1(rb_cBignum,(len),(sign))
+
 #define KARATSUBA_MUL_DIGITS 70
 #define TOOM3_MUL_DIGITS 150
 
 static BDIGIT bary_small_lshift(BDIGIT *zds, BDIGIT *xds, long n, int shift);
 static void bary_small_rshift(BDIGIT *zds, BDIGIT *xds, long n, int shift, int sign_bit);
-static void bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
-static void bary_mul1(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl);
 static void bary_mul(BDIGIT *zds, size_t zl, BDIGIT *xds, size_t xl, BDIGIT *yds, size_t yl);
-static int bary_sub(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn);
-static int bary_subb(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn, int borrow);
 static void bary_divmod(BDIGIT *qds, size_t nq, BDIGIT *rds, size_t nr, BDIGIT *xds, size_t nx, BDIGIT *yds, size_t ny);
-static int bary_add(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn);
-static int bary_addc(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn, BDIGIT *yds, size_t yn, int carry);
-static int bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
-static int bary_2comp(BDIGIT *ds, size_t n);
 
-static void bary_sq_fast(BDIGIT *zds, size_t zn, BDIGIT *xds, size_t xn);
-static inline int bary_sparse_p(BDIGIT *ds, size_t n);
 static VALUE bigmul0(VALUE x, VALUE y);
 static VALUE bigmul1_toom3(VALUE x, VALUE y);
+static VALUE bignew_1(VALUE klass, long len, int sign);
+static inline VALUE bigtrunc(VALUE x);
 
-#define BIGNUM_DEBUG 0
-#if BIGNUM_DEBUG
-#define ON_DEBUG(x) do { x; } while (0)
-static void
-dump_bignum(VALUE x)
-{
-    long i;
-    printf("%c0x0", RBIGNUM_SIGN(x) ? '+' : '-');
-    for (i = RBIGNUM_LEN(x); i--; ) {
-        printf("_%0*"PRIxBDIGIT, SIZEOF_BDIGITS*2, BDIGITS(x)[i]);
-    }
-    printf(", len=%lu", RBIGNUM_LEN(x));
-    puts("");
-}
-
-static VALUE
-rb_big_dump(VALUE x)
-{
-    dump_bignum(x);
-    return x;
-}
-#else
-#define ON_DEBUG(x)
-#endif
+static VALUE bigsqr(VALUE x);
+static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp);
 
 static int
 nlz16(uint16_t x)
@@ -479,121 +452,172 @@ bary_zero_p(BDIGIT *xds, size_t nx) https://github.com/ruby/ruby/blob/trunk/bignum.c#L452
     return 1;
 }
 
+static void
+bary_neg(BDIGIT *ds, size_t n)
+{
+    while (n--)
+        ds[n] = BIGLO(~ds[n]);
+}
+
 static int
-bigzero_p(VALUE x)
+bary_plus_one(BDIGIT *ds, size_t n)
 {
-    return bary_zero_p(BDIGITS(x), RBIGNUM_LEN(x));
+    size_t i;
+    for (i = 0; i < n; i++) {
+	ds[i] = BIGLO(ds[i]+1);
+        if (ds[i] != 0)
+            return 0;
+    }
+    return 1;
 }
 
-int
-rb_bigzero_p(VALUE x)
+static int
+bary_2comp(BDIGIT *ds, size_t n)
 {
-    return BIGZEROP(x);
+    if (!n) return 1;
+    bary_neg(ds, n);
+    return bary_plus_one(ds, n);
 }
 
-int
-rb_cmpint(VALUE val, VALUE a, VALUE b)
+static void
+bary_swap(BDIGIT *ds, size_t num_bdigits)
 {
-    if (NIL_P(val)) {
-	rb_cmperr(a, b);
-    }
-    if (FIXNUM_P(val)) {
-        long l = FIX2LONG(val);
-        if (l > 0) return 1;
-        if (l < 0) return -1;
-        return 0;
-    }
-    if (RB_TYPE_P(val, T_BIGNUM)) {
-	if (BIGZEROP(val)) return 0;
-	if (RBIGNUM_SIGN(val)) return 1;
-	return -1;
+    BDIGIT *p1 = ds;
+    BDIGIT *p2 = ds + num_bdigits - 1;
+    for (; p1 < p2; p1++, p2--) {
+        BDIGIT tmp = *p1;
+        *p1 = *p2;
+        *p2 = tmp;
     }
-    if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
-    if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
-    return 0;
 }
 
-#define RBIGNUM_SET_LEN(b,l) \
-    ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
-     (void)(RBASIC(b)->flags = \
-	    (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
-	    ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
-     (void)(RBIGNUM(b)->as.heap.len = (l)))
+#define INTEGER_PACK_WORDORDER_MASK \
+    (INTEGER_PACK_MSWORD_FIRST | \
+     INTEGER_PACK_LSWORD_FIRST)
+#define INTEGER_PACK_BYTEORDER_MASK \
+    (INTEGER_PACK_MSBYTE_FIRST | \
+     INTEGER_PACK_LSBYTE_FIRST | \
+     INTEGER_PACK_NATIVE_BYTE_ORDER)
 
 static void
-rb_big_realloc(VALUE big, long len)
+validate_integer_pack_format(size_t numwords, size_t wordsize, size_t nails, int flags, int supported_flags)
 {
-    BDIGIT *ds;
-    if (RBASIC(big)->flags & RBIGNUM_EMBED_FLAG) {
-	if (RBIGNUM_EMBED_LEN_MAX < len) {
-	    ds = ALLOC_N(BDIGIT, len);
-	    MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
-	    RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
-	    RBIGNUM(big)->as.heap.digits = ds;
-	    RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
-	}
+    int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
+    int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
+
+    if (flags & ~supported_flags) {
+        rb_raise(rb_eArgError, "unsupported flags specified");
     }
-    else {
-	if (len <= RBIGNUM_EMBED_LEN_MAX) {
-	    ds = RBIGNUM(big)->as.heap.digits;
-	    RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
-	    RBIGNUM_SET_LEN(big, len);
-	    if (ds) {
-		MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
-		xfree(ds);
-	    }
-	}
-	else {
-	    if (RBIGNUM_LEN(big) == 0) {
-		RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
-	    }
-	    else {
-		REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
-	    }
-	}
+    if (wordorder_bits == 0) {
+        if (1 < numwords)
+            rb_raise(rb_eArgError, "word order not specified");
+    }
+    else if (wordorder_bits != INTEGER_PACK_MSWORD_FIRST &&
+        wordorder_bits != INTEGER_PACK_LSWORD_FIRST)
+        rb_raise(rb_eArgError, "unexpected word order");
+    if (byteorder_bits == 0) {
+        rb_raise(rb_eArgError, "byte order not specified");
     }
+    else if (byteorder_bits != INTEGER_PACK_MSBYTE_FIRST &&
+        byteorder_bits != INTEGER_PACK_LSBYTE_FIRST &&
+        byteorder_bits != INTEGER_PACK_NATIVE_BYTE_ORDER)
+        rb_raise(rb_eArgError, "unexpected byte order");
+    if (wordsize == 0)
+        rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
+    if (SSIZE_MAX < wordsize)
+        rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
+    if (wordsize <= nails / CHAR_BIT)
+        rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails);
+    if (SIZE_MAX / wordsize < numwords)
+        rb_raise(rb_eArgError, "too big numwords * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", numwords, wordsize);
 }
 
-void
-rb_big_resize(VALUE big, long len)
+static void
+integer_pack_loop_setup(
+    size_t numwords, size_t wordsize, size_t nails, int flags,
+    size_t *word_num_fullbytes_ret,
+    int *word_num_partialbits_ret,
+    size_t *word_start_ret,
+    ssize_t *word_step_ret,
+    size_t *word_last_ret,
+    size_t *byte_start_ret,
+    int *byte_step_ret)
 {
-    rb_big_realloc(big, len);
-    RBIGNUM_SET_LEN(big, len);
-}
+    int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
+    int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
+    size_t word_num_fullbytes;
+    int word_num_partialbits;
+    size_t word_start;
+    ssize_t word_step;
+    size_t word_last;
+    size_t byte_start;
+    int byte_step;
 
-static VALUE
-bignew_1(VALUE klass, long len, int sign)
-{
-    NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0));
-    RBIGNUM_SET_SIGN(big, sign?1:0);
-    if (len <= RBIGNUM_EMBED_LEN_MAX) {
-	RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
-	RBIGNUM_SET_LEN(big, len);
+    word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
+    if (word_num_partialbits == CHAR_BIT)
+        word_num_partialbits = 0;
+    word_num_fullbytes = wordsize - (nails / CHAR_BIT);
+    if (word_num_partialbits != 0) {
+        word_num_fullbytes--;
+    }
+
+    if (wordorder_bits == INTEGER_PACK_MSWORD_FIRST) {
+        word_start = wordsize*(numwords-1);
+        word_step = -(ssize_t)wordsize;
+        word_last = 0;
     }
     else {
-	RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
-	RBIGNUM(big)->as.heap.len = len;
+        word_start = 0;
+        word_step = wordsize;
+        word_last = wordsize*(numwords-1);
     }
-    OBJ_FREEZE(big);
-    return (VALUE)big;
-}
 
-#define bignew(len,sign) bignew_1(rb_cBignum,(len),(sign))
+    if (byteorder_bits == INTEGER_PACK_NATIVE_BYTE_ORDER) {
+#ifdef WORDS_BIGENDIAN
+        byteorder_bits = INTEGER_PACK_MSBYTE_FIRST;
+#else
+        byteorder_bits = INTEGER_PACK_LSBYTE_FIRST;
+#endif
+    }
+    if (byteorder_bits == INTEGER_PACK_MSBYTE_FIRST) {
+        byte_start = wordsize-1;
+        byte_step = -1;
+    }
+    else {
+        byte_start = 0;
+        byte_step = 1;
+    }
 
-VALUE
-rb_big_new(long len, int sign)
-{
-    return bignew(len, sign != 0);
+    *word_num_partialbits_ret = word_num_partialbits;
+    *word_num_fullbytes_ret = word_num_fullbytes;
+    *word_start_ret = word_start;
+    *word_step_ret = word_step;
+    *word_last_ret = word_last;
+    *byte_start_ret = byte_start;
+    *byte_step_ret = byte_step;
 }
 
-VALUE
-rb_big_clone(VALUE x)
+static inline void
+integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
 {
-    long len = RBIGNUM_LEN(x);
-    VALUE z = bignew_1(CLASS_OF(x), len, RBIGNUM_SIGN(x));
+    if (*dpp < *dep && BITSPERDIG <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
+        *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
+        *numbits_in_dd_p += BITSPERDIG;
+    }
+    else if (*dpp == *dep) {
+        /* higher bits are infinity zeros */
+        *numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT;
+    }
+}
 
-    MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
-    return z;
+static inline BDIGIT_DBL
+integer_pack_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
+{
+    BDIGIT_DBL ret;
+    ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
+    *ddp >>= n;
+    *numbits_in_dd_p -= n;
+    return ret;
 }
 
 static int
@@ -610,3663 +634,3686 @@ bytes_2comp(unsigned char *buf, size_t l https://github.com/ruby/ruby/blob/trunk/bignum.c#L634
     return 1;
 }
 
-static void
-bary_neg(BDIGIT *ds, size_t n)
+static int
+bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
 {
-    while (n--)
-        ds[n] = BIGLO(~ds[n]);
-}
+    BDIGIT *dp, *de;
+    unsigned char *buf, *bufend;
 
-static int
-bary_plus_one(BDIGIT *ds, size_t n)
-{
-    size_t i;
-    for (i = 0; i < n; i++) {
-	ds[i] = BIGLO(ds[i]+1);
-        if (ds[i] != 0)
+    dp = ds;
+    de = ds + num_bdigits;
+
+    validate_integer_pack_format(numwords, wordsize, nails, flags,
+            INTEGER_PACK_MSWORD_FIRST|
+            INTEGER_PACK_LSWORD_FIRST|
+            INTEGER_PACK_MSBYTE_FIRST|
+            INTEGER_PACK_LSBYTE_FIRST|
+            INTEGER_PACK_NATIVE_BYTE_ORDER|
+            INTEGER_PACK_2COMP|
+            INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
+
+    while (dp < de && de[-1] == 0)
+        de--;
+    if (dp == de) {
+        sign = 0;
+    }
+
+    if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) {
+        if (sign == 0) {
+            MEMZERO(words, unsigned char, numwords * wordsize);
             return 0;
+        }
+        if (nails == 0 && numwords == 1) {
+            int need_swap = wordsize != 1 &&
+                (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER &&
+                ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P);
+            if (0 < sign || !(flags & INTEGER_PACK_2COMP)) {
+                BDIGIT d;
+                if (wordsize == 1) {
+                    *((unsigned char *)words) = (unsigned char)(d = dp[0]);
+                    return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
+                }
+#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS
+                if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) {
+                    uint16_t u = (uint16_t)(d = dp[0]);
+                    if (need_swap) u = swap16(u);
+                    *((uint16_t *)words) = u;
+                    return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
+                }
+#endif
+#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS
+                if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) {
+                    uint32_t u = (uint32_t)(d = dp[0]);
+                    if (need_swap) u = swap32(u);
+                    *((uint32_t *)words) = u;
+                    return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
+                }
+#endif
+#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS
+                if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) {
+                    uint64_t u = (uint64_t)(d = dp[0]);
+                    if (need_swap) u = swap64(u);
+                    *((uint64_t *)words) = u;
+                    return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
+                }
+#endif
+            }
+            else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */
+                BDIGIT_DBL_SIGNED d;
+                if (wordsize == 1) {
+                    *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
+                    return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
+                }
+#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS
+                if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) {
+                    uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
+                    if (need_swap) u = swap16(u);
+                    *((uint16_t *)words) = u;
+                    return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
+                        (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
+                }
+#endif
+#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS
+                if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) {
+                    uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
+                    if (need_swap) u = swap32(u);
+                    *((uint32_t *)words) = u;
+                    return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
+                        (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
+                }
+#endif
+#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS
+                if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) {
+                    uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
+                    if (need_swap) u = swap64(u);
+                    *((uint64_t *)words) = u;
+                    return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
+                        (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
+                }
+#endif
+            }
+        }
+#if !defined(WORDS_BIGENDIAN)
+        if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
+            (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST &&
+            (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) {
+            size_t src_size = (de - dp) * SIZEOF_BDIGITS;
+            size_t dst_size = numwords * wordsize;
+            int overflow = 0;
+            while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0)
+                src_size--;
+            if (src_size <= dst_size) {
+                MEMCPY(words, dp, char, src_size);
+                MEMZERO((char*)words + src_size, char, dst_size - src_size);
+            }
+            else {
+                MEMCPY(words, dp, char, dst_size);
+                overflow = 1;
+            }
+            if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
+                int zero_p = bytes_2comp(words, dst_size);
+                if (zero_p && overflow) {
+                    unsigned char *p = (unsigned char *)dp;
+                    if (dst_size == src_size-1 &&
+                        p[dst_size] == 1) {
+                        overflow = 0;
+                    }
+                }
+            }
+            if (overflow)
+                sign *= 2;
+            return sign;
+        }
+#endif
+        if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
+            wordsize % SIZEOF_BDIGITS == 0 && (uintptr_t)words % ALIGNOF(BDIGIT) == 0) {
+            size_t bdigits_per_word = wordsize / SIZEOF_BDIGITS;
+            size_t src_num_bdigits = de - dp;
+            size_t dst_num_bdigits = numwords * bdigits_per_word;
+            int overflow = 0;
+            int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
+            int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
+                (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
+            if (src_num_bdigits <= dst_num_bdigits) {
+                MEMCPY(words, dp, BDIGIT, src_num_bdigits);
+                MEMZERO((BDIGIT*)words + src_num_bdigits, BDIGIT, dst_num_bdigits - src_num_bdigits);
+            }
+            else {
+                MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
+                overflow = 1;
+            }
+            if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
+                int zero_p = bary_2comp(words, dst_num_bdigits);
+                if (zero_p && overflow &&
+                    dst_num_bdigits == src_num_bdigits-1 &&
+                    dp[dst_num_bdigits] == 1)
+                    overflow = 0;
+            }
+            if (msbytefirst_p != HOST_BIGENDIAN_P) {
+                size_t i;
+                for (i = 0; i < dst_num_bdigits; i++) {
+                    BDIGIT d = ((BDIGIT*)words)[i];
+                    ((BDIGIT*)words)[i] = swap_bdigit(d);
+                }
+            }
+            if (mswordfirst_p ?  !msbytefirst_p : msbytefirst_p) {
+                size_t i;
+                BDIGIT *p = words;
+                for (i = 0; i < numwords; i++) {
+                    bary_swap(p, bdigits_per_word);
+                    p += bdigits_per_word;
+                }
+            }
+            if (mswordfirst_p) {
+                bary_swap(words, dst_num_bdigits);
+            }
+            if (overflow)
+                sign *= 2;
+            return sign;
+        }
     }
-    return 1;
-}
 
-static int
-bary_2comp(BDIGIT *ds, size_t n)
-{
-    if (!n) return 1;
-    bary_neg(ds, n);
-    return bary_plus_one(ds, n);
-}
+    buf = words;
+    bufend = buf + numwords * wordsize;
 
-static void
-big_extend_carry(VALUE x)
-{
-    rb_big_resize(x, RBIGNUM_LEN(x)+1);
-    BDIGITS(x)[RBIGNUM_LEN(x)-1] = 1;
-}
+    if (buf == bufend) {
+        /* overflow if non-zero*/
+        if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
+     (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]