diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-03-14 06:23:46 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-03-14 06:23:46 +0000 |
commit | 997b69cb6ac9eb97ea644276f1af886a49c1de03 (patch) | |
tree | 1dffc60dc5f5afbec79dc8d0f314c3355f92dab2 /bignum.c | |
parent | 4f0870f74b530cdb2de4306d55e966a924a9149c (diff) | |
download | ruby-997b69cb6ac9eb97ea644276f1af886a49c1de03.tar.gz |
* re.c (rb_reg_match): should clear $~ if operand is nil.
* re.c (rb_reg_match2): ditto.
* configure: merge Jonathan Baker's large file support patch
[ruby-talk:35316], with read_all patch in [ruby-talk:35470].
* eval.c (rb_f_abort): optional message argument that be printed
on termination. [new]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2200 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r-- | bignum.c | 112 |
1 files changed, 112 insertions, 0 deletions
@@ -38,6 +38,9 @@ typedef long BDIGIT_DBL_SIGNED; #define BITSPERDIG (sizeof(BDIGIT)*CHAR_BIT) #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG) #define DIGSPERLONG ((unsigned int)(sizeof(long)/sizeof(BDIGIT))) +#if HAVE_LONG_LONG +# define DIGSPERLL ((unsigned int)(sizeof(long long)/sizeof(BDIGIT))) +#endif #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG) #define BIGDN(x) RSHIFT(x,BITSPERDIG) #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1))) @@ -507,6 +510,67 @@ rb_str_to_inum(str, base, badcheck) return rb_cstr_to_inum(s, base, badcheck); } +#if HAVE_LONG_LONG + +VALUE +rb_ull2big(n) + unsigned long long n; +{ + BDIGIT_DBL num = n; + long i = 0; + BDIGIT *digits; + VALUE big; + + i = 0; + big = bignew(DIGSPERLL, 1); + digits = BDIGITS(big); + while (i < DIGSPERLL) { + digits[i++] = BIGLO(num); + num = BIGDN(num); + } + + i = DIGSPERLL; + while (i-- && !digits[i]) ; + RBIGNUM(big)->len = i+1; + return big; +} + +VALUE +rb_ll2big(n) + long long n; +{ + long neg = 0; + VALUE big; + + if (n < 0) { + n = -n; + neg = 1; + } + big = rb_ull2big(n); + if (neg) { + RBIGNUM(big)->sign = 0; + } + return big; +} + +VALUE +rb_ull2inum(n) + unsigned long long n; +{ + if (POSFIXABLE(n)) return INT2FIX(n); + return rb_ull2big(n); +} + +VALUE +rb_ll2inum(n) + long long n; +{ + if (FIXABLE(n)) return INT2FIX(n); + return rb_ll2big(n); +} + +#endif /* HAVE_LONG_LONG */ + VALUE rb_cstr2inum(str, base) const char *str; @@ -650,6 +714,54 @@ rb_big2long(x) return num; } +#if HAVE_LONG_LONG + +static unsigned long long +big2ull(x, type) + VALUE x; + char *type; +{ + long len = RBIGNUM(x)->len; + BDIGIT_DBL num; + BDIGIT *ds; + + if (len > sizeof(long long)/sizeof(BDIGIT)) + rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); + ds = BDIGITS(x); + num = 0; + while (len--) { + num = BIGUP(num); + num += ds[len]; + } + return num; +} + +unsigned long long +rb_big2ull(x) + VALUE x; +{ + unsigned long long num = big2ull(x, "unsigned long long"); + + if (!RBIGNUM(x)->sign) return -num; + return num; +} + +long long +rb_big2ll(x) + VALUE x; +{ + unsigned long long num = big2ull(x, "long long"); + + if ((long long)num < 0 && (RBIGNUM(x)->sign + || (long long)num != LLONG_MIN)) { + rb_raise(rb_eRangeError, "bignum too big to convert into `long long'"); + } + if (!RBIGNUM(x)->sign) return -(long long)num; + return num; +} + +#endif /* HAVE_LONG_LONG */ + static VALUE dbl2big(d) double d; |