2000-05-01 13:42:38 +04:00
/**********************************************************************
1998-01-16 15:13:05 +03:00
bignum . c -
$ Author $
created at : Fri Jun 10 00 : 48 : 55 JST 1994
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
Copyright ( C ) 1993 - 2007 Yukihiro Matsumoto
2000-05-01 13:42:38 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-01-16 15:13:05 +03:00
2007-06-10 07:06:15 +04:00
# include "ruby/ruby.h"
2012-07-10 17:57:11 +04:00
# include "ruby/thread.h"
2009-05-26 08:58:15 +04:00
# include "ruby/util.h"
* internal.h: declare internal functions here.
* node.h: declare NODE dependent internal functions here.
* iseq.h: declare rb_iseq_t dependent internal functions here.
* vm_core.h: declare rb_thread_t dependent internal functions here.
* bignum.c, class.c, compile.c, complex.c, cont.c, dir.c, encoding.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c, io.c,
iseq.c, load.c, marshal.c, math.c, numeric.c, object.c, parse.y,
proc.c, process.c, range.c, rational.c, re.c, ruby.c, string.c,
thread.c, time.c, transcode.c, variable.c, vm.c,
tool/compile_prelude.rb: don't declare internal functions declared
in above headers. include above headers if required.
Note that rb_thread_mark() was declared as
void rb_thread_mark(rb_thread_t *th) in cont.c but defined as
void rb_thread_mark(void *ptr) in vm.c. Now it is declared as
the later in internal.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-06-18 02:43:38 +04:00
# include "internal.h"
2002-05-14 10:22:31 +04:00
2012-07-18 22:48:14 +04:00
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
1998-01-16 15:13:05 +03:00
# include <math.h>
2007-05-02 12:12:31 +04:00
# include <float.h>
1999-01-20 07:59:39 +03:00
# include <ctype.h>
2003-12-22 11:23:55 +03:00
# ifdef HAVE_IEEEFP_H
# include <ieeefp.h>
# endif
2008-12-14 06:59:02 +03:00
# include <assert.h>
1998-01-16 15:13:05 +03:00
1999-01-20 07:59:39 +03:00
VALUE rb_cBignum ;
2000-06-04 19:32:19 +04:00
2011-05-22 19:37:00 +04:00
static VALUE big_three = Qnil ;
2000-06-04 19:32:19 +04:00
# if defined __MINGW32__
# define USHORT _USHORT
# endif
2007-09-01 16:02:36 +04:00
# define BDIGITS(x) (RBIGNUM_DIGITS(x))
2002-04-10 12:45:26 +04:00
# define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
2000-11-01 11:49:40 +03:00
# define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
2011-05-22 19:37:00 +04:00
# define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
2009-05-26 08:58:15 +04:00
# define DIGSPERLONG (SIZEOF_LONG / SIZEOF_BDIGITS)
2002-03-14 09:23:46 +03:00
# if HAVE_LONG_LONG
2009-05-26 08:58:15 +04:00
# define DIGSPERLL (SIZEOF_LONG_LONG / SIZEOF_BDIGITS)
2002-03-14 09:23:46 +03:00
# endif
2000-11-01 11:49:40 +03:00
# define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
2010-12-02 11:01:24 +03:00
# define BIGDN(x) RSHIFT((x),BITSPERDIG)
2000-10-31 11:37:47 +03:00
# define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
2003-01-14 10:45:19 +03:00
# define BDIGMAX ((BDIGIT)-1)
1998-01-16 15:13:05 +03:00
2008-02-22 13:50:21 +03:00
# define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
( BDIGITS ( x ) [ 0 ] = = 0 & & \
( RBIGNUM_LEN ( x ) = = 1 | | bigzero_p ( x ) ) ) )
2013-06-16 03:46:07 +04:00
# define BIGDIVREM_EXTRA_WORDS 2
2013-06-15 15:15:23 +04:00
# define roomof(n, m) ((int)(((n)+(m)-1) / (m)))
# define bdigit_roomof(n) roomof(n, sizeof(BDIGIT))
# define BARY_ARGS(ary) ary, numberof(ary)
2013-06-16 18:16:33 +04:00
# define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
# define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
# define BARY_MUL(z, x, y) bary_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
# define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
# define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
2013-06-06 15:57:35 +04:00
static int nlz ( BDIGIT x ) ;
2013-06-14 21:41:38 +04:00
static BDIGIT bdigs_small_lshift ( BDIGIT * zds , BDIGIT * xds , long n , int shift ) ;
2013-06-15 05:03:37 +04:00
static void bdigs_small_rshift ( BDIGIT * zds , BDIGIT * xds , long n , int shift , int sign_bit ) ;
2013-06-15 15:15:23 +04:00
static void bary_unpack ( BDIGIT * bdigits , size_t num_bdigits , const void * words , size_t numwords , size_t wordsize , size_t nails , int flags ) ;
2013-06-15 17:32:16 +04:00
static void bary_mul ( BDIGIT * zds , size_t zl , BDIGIT * xds , size_t xl , BDIGIT * yds , size_t yl ) ;
2013-06-15 18:52:02 +04:00
static void bary_sub ( BDIGIT * zds , size_t zn , BDIGIT * xds , size_t xn , BDIGIT * yds , size_t yn ) ;
2013-06-16 05:41:58 +04:00
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 void bary_add ( BDIGIT * zds , size_t zn , BDIGIT * xds , size_t xn , BDIGIT * yds , size_t yn ) ;
2013-06-16 13:53:45 +04:00
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 ) ;
2013-06-16 16:59:26 +04:00
static BDIGIT bary_2comp ( BDIGIT * ds , size_t n ) ;
2013-06-06 15:57:35 +04:00
2011-05-22 19:37:00 +04:00
# 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 ( " _%08 " PRIxBDIGIT , 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
2008-02-22 13:50:21 +03:00
static int
2013-06-16 05:41:58 +04:00
bary_zero_p ( BDIGIT * xds , size_t nx )
2008-02-22 13:50:21 +03:00
{
2013-06-16 05:41:58 +04:00
if ( nx = = 0 )
return 1 ;
do {
if ( xds [ - - nx ] ) return 0 ;
} while ( nx ) ;
2008-02-22 13:50:21 +03:00
return 1 ;
}
2007-09-01 16:02:36 +04:00
2013-06-16 05:41:58 +04:00
static int
bigzero_p ( VALUE x )
{
return bary_zero_p ( BDIGITS ( x ) , RBIGNUM_LEN ( x ) ) ;
}
2009-07-16 10:52:29 +04:00
int
rb_bigzero_p ( VALUE x )
{
return BIGZEROP ( x ) ;
}
2008-04-06 21:11:50 +04:00
int
rb_cmpint ( VALUE val , VALUE a , VALUE b )
{
if ( NIL_P ( val ) ) {
rb_cmperr ( a , b ) ;
}
2009-03-26 19:20:58 +03:00
if ( FIXNUM_P ( val ) ) {
long l = FIX2LONG ( val ) ;
if ( l > 0 ) return 1 ;
if ( l < 0 ) return - 1 ;
return 0 ;
}
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( val , T_BIGNUM ) ) {
2008-04-06 21:11:50 +04:00
if ( BIGZEROP ( val ) ) return 0 ;
if ( RBIGNUM_SIGN ( val ) ) return 1 ;
return - 1 ;
}
if ( RTEST ( rb_funcall ( val , ' > ' , 1 , INT2FIX ( 0 ) ) ) ) return 1 ;
if ( RTEST ( rb_funcall ( val , ' < ' , 1 , INT2FIX ( 0 ) ) ) ) return - 1 ;
return 0 ;
}
2007-09-01 16:02:36 +04:00
# define RBIGNUM_SET_LEN(b,l) \
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
( ( 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 ) ) )
2007-09-01 16:02:36 +04:00
static void
rb_big_realloc ( VALUE big , long len )
{
BDIGIT * ds ;
if ( RBASIC ( big ) - > flags & RBIGNUM_EMBED_FLAG ) {
2008-03-07 15:28:57 +03:00
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 ;
}
2007-09-01 16:02:36 +04:00
}
else {
2008-03-07 15:28:57 +03:00
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 ) ;
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
xfree ( ds ) ;
2008-03-07 15:28:57 +03:00
}
}
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 ) ;
}
}
2007-09-01 16:02:36 +04:00
}
}
void
rb_big_resize ( VALUE big , long len )
{
rb_big_realloc ( big , len ) ;
RBIGNUM_SET_LEN ( big , len ) ;
}
2003-04-09 10:44:34 +04:00
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
bignew_1 ( VALUE klass , long len , int sign )
1998-01-16 15:13:05 +03:00
{
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
NEWOBJ_OF ( big , struct RBignum , klass , T_BIGNUM | ( RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0 ) ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , sign ? 1 : 0 ) ;
if ( len < = RBIGNUM_EMBED_LEN_MAX ) {
2008-03-07 15:28:57 +03:00
RBASIC ( big ) - > flags | = RBIGNUM_EMBED_FLAG ;
RBIGNUM_SET_LEN ( big , len ) ;
2007-09-01 16:02:36 +04:00
}
else {
2009-05-26 06:19:33 +04:00
RBIGNUM ( big ) - > as . heap . digits = ALLOC_N ( BDIGIT , len ) ;
RBIGNUM ( big ) - > as . heap . len = len ;
2007-09-01 16:02:36 +04:00
}
2012-10-28 04:03:20 +04:00
OBJ_FREEZE ( big ) ;
1998-01-16 15:13:05 +03:00
return ( VALUE ) big ;
}
2010-12-02 11:01:24 +03:00
# define bignew(len,sign) bignew_1(rb_cBignum,(len),(sign))
1998-01-16 15:13:05 +03:00
2009-07-16 10:52:29 +04:00
VALUE
rb_big_new ( long len , int sign )
{
return bignew ( len , sign ! = 0 ) ;
}
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_clone ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2009-08-25 12:38:28 +04:00
long len = RBIGNUM_LEN ( x ) ;
VALUE z = bignew_1 ( CLASS_OF ( x ) , len , RBIGNUM_SIGN ( x ) ) ;
1998-01-16 15:13:05 +03:00
2009-08-25 12:38:28 +04:00
MEMCPY ( BDIGITS ( z ) , BDIGITS ( x ) , BDIGIT , len ) ;
1998-01-16 15:19:22 +03:00
return z ;
1998-01-16 15:13:05 +03:00
}
2013-06-16 16:59:26 +04:00
static BDIGIT
bary_2comp ( BDIGIT * ds , size_t n )
{
size_t i = n ;
BDIGIT_DBL num ;
if ( ! n ) return 1 ;
while ( i - - ) ds [ i ] = ~ ds [ i ] ;
i = 0 ; num = 1 ;
do {
num + = ds [ i ] ;
ds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
} while ( i < n ) ;
return ( BDIGIT ) num ;
}
2005-06-30 10:20:09 +04:00
/* modify a bignum by 2's complement */
2002-02-22 13:28:47 +03:00
static void
2005-06-30 10:20:09 +04:00
get2comp ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
long i = RBIGNUM_LEN ( x ) ;
2000-10-31 11:37:47 +03:00
BDIGIT * ds = BDIGITS ( x ) ;
2000-11-01 11:49:40 +03:00
BDIGIT_DBL num ;
1998-01-16 15:13:05 +03:00
2007-07-14 23:42:25 +04:00
if ( ! i ) return ;
1998-01-16 15:13:05 +03:00
while ( i - - ) ds [ i ] = ~ ds [ i ] ;
i = 0 ; num = 1 ;
do {
1999-01-20 07:59:39 +03:00
num + = ds [ i ] ;
1998-01-16 15:13:05 +03:00
ds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
2007-09-01 16:02:36 +04:00
} while ( i < RBIGNUM_LEN ( x ) ) ;
2005-06-30 10:20:09 +04:00
if ( num ! = 0 ) {
2008-03-07 15:28:57 +03:00
rb_big_resize ( x , RBIGNUM_LEN ( x ) + 1 ) ;
1998-01-16 15:13:05 +03:00
ds = BDIGITS ( x ) ;
2007-09-01 16:02:36 +04:00
ds [ RBIGNUM_LEN ( x ) - 1 ] = 1 ;
1998-01-16 15:13:05 +03:00
}
}
2002-02-22 13:28:47 +03:00
void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_2comp ( VALUE x ) /* get 2's complement */
2002-02-22 13:28:47 +03:00
{
2005-06-30 10:20:09 +04:00
get2comp ( x ) ;
2002-02-22 13:28:47 +03:00
}
2009-04-20 21:53:36 +04:00
static inline VALUE
2007-04-26 19:02:57 +04:00
bigtrunc ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
long len = RBIGNUM_LEN ( x ) ;
2007-04-26 19:02:57 +04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 15:13:05 +03:00
2007-08-17 02:22:24 +04:00
if ( len = = 0 ) return x ;
2007-07-15 16:07:46 +04:00
while ( - - len & & ! ds [ len ] ) ;
2009-05-26 06:19:33 +04:00
if ( RBIGNUM_LEN ( x ) > len + 1 ) {
rb_big_resize ( x , len + 1 ) ;
}
2007-04-26 19:02:57 +04:00
return x ;
}
2009-05-26 06:19:33 +04:00
static inline VALUE
2007-04-26 19:02:57 +04:00
bigfixize ( VALUE x )
{
2007-09-01 16:02:36 +04:00
long len = RBIGNUM_LEN ( x ) ;
2007-04-26 19:02:57 +04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 15:13:05 +03:00
2009-03-13 03:30:15 +03:00
if ( len = = 0 ) return INT2FIX ( 0 ) ;
2009-05-26 08:58:15 +04:00
if ( ( size_t ) ( len * SIZEOF_BDIGITS ) < = sizeof ( long ) ) {
2007-06-26 10:23:34 +04:00
long num = 0 ;
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
# if 2*SIZEOF_BDIGITS > SIZEOF_LONG
num = ( long ) ds [ 0 ] ;
# else
2007-04-26 19:02:57 +04:00
while ( len - - ) {
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
num = ( long ) ( BIGUP ( num ) + ds [ len ] ) ;
2007-04-26 19:02:57 +04:00
}
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
# endif
2007-04-26 19:02:57 +04:00
if ( num > = 0 ) {
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) ) {
2007-04-26 19:02:57 +04:00
if ( POSFIXABLE ( num ) ) return LONG2FIX ( num ) ;
2000-07-12 10:06:50 +04:00
}
2007-04-26 19:02:57 +04:00
else {
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
if ( NEGFIXABLE ( - num ) ) return LONG2FIX ( - num ) ;
1999-01-20 07:59:39 +03:00
}
1998-01-16 15:13:05 +03:00
}
}
1998-01-16 15:19:22 +03:00
return x ;
1998-01-16 15:13:05 +03:00
}
2007-04-26 19:02:57 +04:00
static VALUE
bignorm ( VALUE x )
{
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( x , T_BIGNUM ) ) {
2007-04-26 19:02:57 +04:00
x = bigfixize ( bigtrunc ( x ) ) ;
}
return x ;
}
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_norm ( VALUE x )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
return bignorm ( x ) ;
1998-01-16 15:13:05 +03:00
}
VALUE
2006-07-11 09:00:02 +04:00
rb_uint2big ( VALUE n )
1998-01-16 15:13:05 +03:00
{
2000-11-01 11:49:40 +03:00
BDIGIT_DBL num = n ;
2000-10-31 11:37:47 +03:00
long i = 0 ;
BDIGIT * digits ;
1998-01-16 15:19:22 +03:00
VALUE big ;
1998-01-16 15:13:05 +03:00
2000-01-05 07:41:21 +03:00
big = bignew ( DIGSPERLONG , 1 ) ;
1998-01-16 15:13:05 +03:00
digits = BDIGITS ( big ) ;
2000-01-05 07:41:21 +03:00
while ( i < DIGSPERLONG ) {
2000-10-31 11:37:47 +03:00
digits [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
1998-01-16 15:13:05 +03:00
}
2000-01-05 07:41:21 +03:00
i = DIGSPERLONG ;
2002-08-13 13:21:18 +04:00
while ( - - i & & ! digits [ i ] ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
1998-01-16 15:19:22 +03:00
return big ;
1998-01-16 15:13:05 +03:00
}
VALUE
2006-07-11 09:00:02 +04:00
rb_int2big ( SIGNED_VALUE n )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
long neg = 0 ;
2013-04-09 15:39:53 +04:00
VALUE u ;
1998-01-16 15:19:22 +03:00
VALUE big ;
1998-01-16 15:13:05 +03:00
if ( n < 0 ) {
2013-04-09 15:39:53 +04:00
u = 1 + ( VALUE ) ( - ( n + 1 ) ) ; /* u = -n avoiding overflow */
1998-01-16 15:13:05 +03:00
neg = 1 ;
}
2013-04-09 15:39:53 +04:00
else {
u = n ;
}
big = rb_uint2big ( u ) ;
1998-01-16 15:13:05 +03:00
if ( neg ) {
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
1998-01-16 15:13:05 +03:00
}
1998-01-16 15:19:22 +03:00
return big ;
1998-01-16 15:13:05 +03:00
}
VALUE
2006-07-11 09:00:02 +04:00
rb_uint2inum ( VALUE n )
1998-01-16 15:13:05 +03:00
{
2002-08-21 19:47:54 +04:00
if ( POSFIXABLE ( n ) ) return LONG2FIX ( n ) ;
1999-01-20 07:59:39 +03:00
return rb_uint2big ( n ) ;
1998-01-16 15:13:05 +03:00
}
VALUE
2006-07-11 09:00:02 +04:00
rb_int2inum ( SIGNED_VALUE n )
1998-01-16 15:13:05 +03:00
{
2002-08-21 19:47:54 +04:00
if ( FIXABLE ( n ) ) return LONG2FIX ( n ) ;
1999-01-20 07:59:39 +03:00
return rb_int2big ( n ) ;
1998-01-16 15:13:05 +03:00
}
2010-02-27 09:56:46 +03:00
# if SIZEOF_LONG % SIZEOF_BDIGITS != 0
# error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
# endif
2010-03-04 17:20:49 +03:00
/*
* buf is an array of long integers .
* buf is ordered from least significant word to most significant word .
* buf [ 0 ] is the least significant word and
* buf [ num_longs - 1 ] is the most significant word .
* This means words in buf is little endian .
* However each word in buf is native endian .
* ( buf [ i ] & 1 ) is the least significant bit and
* ( buf [ i ] & ( 1 < < ( SIZEOF_LONG * CHAR_BIT - 1 ) ) ) is the most significant bit
* for each 0 < = i < num_longs .
* So buf is little endian at whole on a little endian machine .
* But buf is mixed endian on a big endian machine .
2012-02-23 14:52:51 +04:00
*
* The buf represents negative integers as two ' s complement .
* So , the most significant bit of the most significant word ,
* ( buf [ num_longs - 1 ] > > ( SIZEOF_LONG * CHAR_BIT - 1 ) ) ,
* is the sign bit : 1 means negative and 0 means zero or positive .
*
* If given size of buf ( num_longs ) is not enough to represent val ,
2013-05-19 07:10:21 +04:00
* higher words ( including a sign bit ) are ignored .
2010-03-04 17:20:49 +03:00
*/
2010-02-26 21:51:02 +03:00
void
rb_big_pack ( VALUE val , unsigned long * buf , long num_longs )
{
val = rb_to_int ( val ) ;
if ( num_longs = = 0 )
return ;
if ( FIXNUM_P ( val ) ) {
long i ;
long tmp = FIX2LONG ( val ) ;
buf [ 0 ] = ( unsigned long ) tmp ;
tmp = tmp < 0 ? ~ 0L : 0 ;
for ( i = 1 ; i < num_longs ; i + + )
buf [ i ] = ( unsigned long ) tmp ;
return ;
}
else {
long len = RBIGNUM_LEN ( val ) ;
BDIGIT * ds = BDIGITS ( val ) , * dend = ds + len ;
long i , j ;
for ( i = 0 ; i < num_longs & & ds < dend ; i + + ) {
unsigned long l = 0 ;
2010-03-07 17:15:24 +03:00
for ( j = 0 ; j < DIGSPERLONG & & ds < dend ; j + + , ds + + ) {
l | = ( ( unsigned long ) * ds < < ( j * BITSPERDIG ) ) ;
2010-02-26 21:51:02 +03:00
}
buf [ i ] = l ;
}
for ( ; i < num_longs ; i + + )
buf [ i ] = 0 ;
if ( RBIGNUM_NEGATIVE_P ( val ) ) {
for ( i = 0 ; i < num_longs ; i + + ) {
buf [ i ] = ~ buf [ i ] ;
}
for ( i = 0 ; i < num_longs ; i + + ) {
buf [ i ] + + ;
if ( buf [ i ] ! = 0 )
return ;
}
}
}
}
2012-02-23 14:52:51 +04:00
/* See rb_big_pack comment for endianness and sign of buf. */
2010-02-26 21:51:02 +03:00
VALUE
rb_big_unpack ( unsigned long * buf , long num_longs )
{
while ( 2 < = num_longs ) {
if ( buf [ num_longs - 1 ] = = 0 & & ( long ) buf [ num_longs - 2 ] > = 0 )
num_longs - - ;
else if ( buf [ num_longs - 1 ] = = ~ 0UL & & ( long ) buf [ num_longs - 2 ] < 0 )
num_longs - - ;
else
break ;
}
if ( num_longs = = 0 )
return INT2FIX ( 0 ) ;
else if ( num_longs = = 1 )
return LONG2NUM ( ( long ) buf [ 0 ] ) ;
else {
VALUE big ;
BDIGIT * ds ;
2010-03-07 17:15:24 +03:00
long len = num_longs * DIGSPERLONG ;
2010-02-26 21:51:02 +03:00
long i ;
big = bignew ( len , 1 ) ;
ds = BDIGITS ( big ) ;
for ( i = 0 ; i < num_longs ; i + + ) {
unsigned long d = buf [ i ] ;
# if SIZEOF_LONG == SIZEOF_BDIGITS
* ds + + = d ;
# else
int j ;
2010-03-07 17:15:24 +03:00
for ( j = 0 ; j < DIGSPERLONG ; j + + ) {
2010-02-26 21:51:02 +03:00
* ds + + = BIGLO ( d ) ;
d = BIGDN ( d ) ;
}
# endif
}
if ( ( long ) buf [ num_longs - 1 ] < 0 ) {
get2comp ( big ) ;
RBIGNUM_SET_SIGN ( big , 0 ) ;
}
return bignorm ( big ) ;
}
}
2013-06-06 15:57:35 +04:00
/* number of bytes of abs(val). additionaly number of leading zeros can be returned. */
2013-06-09 16:37:38 +04:00
/*
2013-06-10 14:37:39 +04:00
* Calculate the number of bytes to be required to represent
2013-06-09 16:37:38 +04:00
* the absolute value of the integer given as _val_ .
*
* [ val ] an integer .
* [ nlz_bits_ret ] number of leading zero bits in the most significant byte is returned if not NULL .
*
* This function returns ( ( val_numbits * CHAR_BIT + CHAR_BIT - 1 ) / CHAR_BIT )
* where val_numbits is the number of bits of abs ( val ) .
* This function should not overflow .
*
* If nlz_bits_ret is not NULL ,
* ( return_value * CHAR_BIT - val_numbits ) is stored in * nlz_bits_ret .
* In this case , 0 < = * nlz_bits_ret < CHAR_BIT .
*
*/
2013-06-06 15:57:35 +04:00
size_t
2013-06-09 16:37:38 +04:00
rb_absint_size ( VALUE val , int * nlz_bits_ret )
2013-06-06 15:57:35 +04:00
{
BDIGIT * dp ;
BDIGIT * de ;
BDIGIT fixbuf [ ( sizeof ( long ) + SIZEOF_BDIGITS - 1 ) / SIZEOF_BDIGITS ] ;
2013-06-07 13:25:47 +04:00
2013-06-06 15:57:35 +04:00
int num_leading_zeros ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
long v = FIX2LONG ( val ) ;
if ( v < 0 ) {
v = - v ;
}
# if SIZEOF_BDIGITS == SIZEOF_LONG
fixbuf [ 0 ] = v ;
# else
2013-06-07 13:25:47 +04:00
{
int i ;
2013-06-07 14:24:07 +04:00
for ( i = 0 ; i < numberof ( fixbuf ) ; i + + ) {
2013-06-07 13:25:47 +04:00
fixbuf [ i ] = ( BDIGIT ) ( v & ( ( 1L < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
v > > = SIZEOF_BDIGITS * CHAR_BIT ;
}
2013-06-06 15:57:35 +04:00
}
# endif
dp = fixbuf ;
2013-06-07 14:24:07 +04:00
de = fixbuf + numberof ( fixbuf ) ;
2013-06-06 15:57:35 +04:00
}
else {
dp = BDIGITS ( val ) ;
de = dp + RBIGNUM_LEN ( val ) ;
}
while ( dp < de & & de [ - 1 ] = = 0 )
de - - ;
if ( dp = = de ) {
2013-06-09 16:37:38 +04:00
if ( nlz_bits_ret )
* nlz_bits_ret = 0 ;
2013-06-06 15:57:35 +04:00
return 0 ;
}
num_leading_zeros = nlz ( de [ - 1 ] ) ;
2013-06-09 16:37:38 +04:00
if ( nlz_bits_ret )
* nlz_bits_ret = num_leading_zeros % CHAR_BIT ;
2013-06-06 15:57:35 +04:00
return ( de - dp ) * SIZEOF_BDIGITS - num_leading_zeros / CHAR_BIT ;
}
2013-06-15 14:35:52 +04:00
static size_t
2013-06-10 00:39:05 +04:00
absint_numwords_small ( size_t numbytes , int nlz_bits_in_msbyte , size_t word_numbits , size_t * nlz_bits_ret )
{
size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte ;
size_t div = val_numbits / word_numbits ;
size_t mod = val_numbits % word_numbits ;
size_t numwords ;
size_t nlz_bits ;
numwords = mod = = 0 ? div : div + 1 ;
nlz_bits = mod = = 0 ? 0 : word_numbits - mod ;
* nlz_bits_ret = nlz_bits ;
return numwords ;
}
2013-06-15 14:35:52 +04:00
static size_t
2013-06-09 20:08:54 +04:00
absint_numwords_generic ( size_t numbytes , int nlz_bits_in_msbyte , size_t word_numbits , size_t * nlz_bits_ret )
{
2013-06-15 17:32:16 +04:00
BDIGIT numbytes_bary [ bdigit_roomof ( sizeof ( numbytes ) ) ] ;
BDIGIT char_bit [ 1 ] = { CHAR_BIT } ;
2013-06-15 15:15:23 +04:00
BDIGIT val_numbits_bary [ bdigit_roomof ( sizeof ( numbytes ) + 1 ) ] ;
2013-06-15 18:52:02 +04:00
BDIGIT nlz_bits_in_msbyte_bary [ 1 ] = { nlz_bits_in_msbyte } ;
2013-06-16 03:46:07 +04:00
BDIGIT word_numbits_bary [ bdigit_roomof ( sizeof ( word_numbits ) ) ] ;
BDIGIT div_bary [ numberof ( val_numbits_bary ) + BIGDIVREM_EXTRA_WORDS ] ;
BDIGIT mod_bary [ numberof ( word_numbits_bary ) ] ;
2013-06-16 05:41:58 +04:00
BDIGIT one [ 1 ] = { 1 } ;
2013-06-16 12:49:26 +04:00
size_t nlz_bits ;
size_t mod ;
int sign ;
size_t numwords ;
2013-06-15 15:15:23 +04:00
2013-06-06 15:57:35 +04:00
/*
2013-06-09 16:37:38 +04:00
* val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
2013-06-06 15:57:35 +04:00
* div , mod = val_numbits . divmod ( word_numbits )
* numwords = mod = = 0 ? div : div + 1
2013-06-09 16:37:38 +04:00
* nlz_bits = mod = = 0 ? 0 : word_numbits - mod
2013-06-06 15:57:35 +04:00
*/
2013-06-09 20:08:54 +04:00
2013-06-15 17:32:16 +04:00
bary_unpack ( BARY_ARGS ( numbytes_bary ) , & numbytes , 1 , sizeof ( numbytes ) , 0 ,
2013-06-15 15:15:23 +04:00
INTEGER_PACK_NATIVE_BYTE_ORDER ) ;
2013-06-16 18:16:33 +04:00
BARY_MUL ( val_numbits_bary , numbytes_bary , char_bit ) ;
2013-06-15 18:52:02 +04:00
if ( nlz_bits_in_msbyte )
2013-06-16 18:16:33 +04:00
BARY_SUB ( val_numbits_bary , val_numbits_bary , nlz_bits_in_msbyte_bary ) ;
2013-06-16 03:46:07 +04:00
bary_unpack ( BARY_ARGS ( word_numbits_bary ) , & word_numbits , 1 , sizeof ( word_numbits ) , 0 ,
INTEGER_PACK_NATIVE_BYTE_ORDER ) ;
2013-06-16 18:16:33 +04:00
BARY_DIVMOD ( div_bary , mod_bary , val_numbits_bary , word_numbits_bary ) ;
if ( BARY_ZERO_P ( mod_bary ) ) {
2013-06-16 12:49:26 +04:00
nlz_bits = 0 ;
2013-06-16 05:41:58 +04:00
}
else {
2013-06-16 18:16:33 +04:00
BARY_ADD ( div_bary , div_bary , one ) ;
2013-06-16 12:49:26 +04:00
bary_pack ( + 1 , BARY_ARGS ( mod_bary ) , & mod , 1 , sizeof ( mod ) , 0 ,
2013-06-16 13:53:45 +04:00
INTEGER_PACK_NATIVE_BYTE_ORDER ) ;
2013-06-16 12:49:26 +04:00
nlz_bits = word_numbits - mod ;
2013-06-16 05:41:58 +04:00
}
2013-06-16 12:49:26 +04:00
sign = bary_pack ( + 1 , BARY_ARGS ( div_bary ) , & numwords , 1 , sizeof ( numwords ) , 0 ,
2013-06-16 13:53:45 +04:00
INTEGER_PACK_NATIVE_BYTE_ORDER ) ;
2013-06-15 15:15:23 +04:00
2013-06-09 16:37:38 +04:00
if ( sign = = 2 )
return ( size_t ) - 1 ;
2013-06-09 20:08:54 +04:00
* nlz_bits_ret = nlz_bits ;
return numwords ;
}
/*
2013-06-10 14:37:39 +04:00
* Calculate the number of words to be required to represent
2013-06-09 20:08:54 +04:00
* the absolute value of the integer given as _val_ .
*
* [ val ] an integer .
* [ word_numbits ] number of bits in a word .
* [ nlz_bits_ret ] number of leading zero bits in the most significant word is returned if not NULL .
*
* This function returns ( ( val_numbits * CHAR_BIT + word_numbits - 1 ) / word_numbits )
* where val_numbits is the number of bits of abs ( val ) .
2013-06-10 17:10:11 +04:00
*
2013-06-10 17:51:20 +04:00
* This function can overflow .
2013-06-10 17:10:11 +04:00
* When overflow occur , ( size_t ) - 1 is returned .
2013-06-09 20:08:54 +04:00
*
* If nlz_bits_ret is not NULL and overflow is not occur ,
* ( return_value * word_numbits - val_numbits ) is stored in * nlz_bits_ret .
* In this case , 0 < = * nlz_bits_ret < word_numbits .
*
*/
size_t
rb_absint_numwords ( VALUE val , size_t word_numbits , size_t * nlz_bits_ret )
{
size_t numbytes ;
int nlz_bits_in_msbyte ;
size_t numwords ;
size_t nlz_bits ;
if ( word_numbits = = 0 )
return ( size_t ) - 1 ;
numbytes = rb_absint_size ( val , & nlz_bits_in_msbyte ) ;
2013-06-10 00:39:05 +04:00
if ( numbytes < = SIZE_MAX / CHAR_BIT ) {
numwords = absint_numwords_small ( numbytes , nlz_bits_in_msbyte , word_numbits , & nlz_bits ) ;
2013-06-13 07:20:28 +04:00
# ifdef DEBUG_INTEGER_PACK
{
size_t numwords0 , nlz_bits0 ;
numwords0 = absint_numwords_generic ( numbytes , nlz_bits_in_msbyte , word_numbits , & nlz_bits0 ) ;
assert ( numwords0 = = numwords ) ;
assert ( nlz_bits0 = = nlz_bits ) ;
}
2013-06-09 20:08:54 +04:00
# endif
}
else {
numwords = absint_numwords_generic ( numbytes , nlz_bits_in_msbyte , word_numbits , & nlz_bits ) ;
}
if ( numwords = = ( size_t ) - 1 )
return numwords ;
2013-06-09 16:37:38 +04:00
if ( nlz_bits_ret )
* nlz_bits_ret = nlz_bits ;
2013-06-09 20:08:54 +04:00
2013-06-06 15:57:35 +04:00
return numwords ;
}
2013-06-08 16:05:57 +04:00
int
rb_absint_singlebit_p ( VALUE val )
{
BDIGIT * dp ;
BDIGIT * de ;
BDIGIT fixbuf [ ( sizeof ( long ) + SIZEOF_BDIGITS - 1 ) / SIZEOF_BDIGITS ] ;
BDIGIT d ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
long v = FIX2LONG ( val ) ;
if ( v < 0 ) {
v = - v ;
}
# if SIZEOF_BDIGITS == SIZEOF_LONG
fixbuf [ 0 ] = v ;
# else
{
int i ;
for ( i = 0 ; i < numberof ( fixbuf ) ; i + + ) {
fixbuf [ i ] = ( BDIGIT ) ( v & ( ( 1L < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
v > > = SIZEOF_BDIGITS * CHAR_BIT ;
}
}
# endif
dp = fixbuf ;
de = fixbuf + numberof ( fixbuf ) ;
}
else {
dp = BDIGITS ( val ) ;
de = dp + RBIGNUM_LEN ( val ) ;
}
while ( dp < de & & de [ - 1 ] = = 0 )
de - - ;
while ( dp < de & & dp [ 0 ] = = 0 )
dp + + ;
if ( dp = = de ) /* no bit set. */
return 0 ;
if ( dp ! = de - 1 ) /* two non-zero words. two bits set, at least. */
return 0 ;
d = * dp ;
d = d & ( d - 1 ) ; /* Clear the least significant bit set */
return d = = 0 ;
}
2013-06-07 19:02:39 +04:00
# 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 )
2013-06-07 14:49:12 +04:00
static void
2013-06-12 13:21:11 +04:00
validate_integer_pack_format ( size_t numwords , size_t wordsize , size_t nails , int flags , int supported_flags )
2013-06-07 14:49:12 +04:00
{
2013-06-07 19:02:39 +04:00
int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK ;
int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK ;
2013-06-12 13:21:11 +04:00
if ( flags & ~ supported_flags ) {
rb_raise ( rb_eArgError , " unsupported flags specified " ) ;
}
2013-06-11 18:02:46 +04:00
if ( wordorder_bits = = 0 ) {
2013-06-11 18:40:16 +04:00
if ( 1 < numwords )
rb_raise ( rb_eArgError , " word order not specified " ) ;
2013-06-11 18:02:46 +04:00
}
else if ( wordorder_bits ! = INTEGER_PACK_MSWORD_FIRST & &
2013-06-07 19:02:39 +04:00
wordorder_bits ! = INTEGER_PACK_LSWORD_FIRST )
2013-06-08 02:16:15 +04:00
rb_raise ( rb_eArgError , " unexpected word order " ) ;
2013-06-11 18:02:46 +04:00
if ( byteorder_bits = = 0 ) {
rb_raise ( rb_eArgError , " byte order not specified " ) ;
}
else if ( byteorder_bits ! = INTEGER_PACK_MSBYTE_FIRST & &
2013-06-07 19:02:39 +04:00
byteorder_bits ! = INTEGER_PACK_LSBYTE_FIRST & &
byteorder_bits ! = INTEGER_PACK_NATIVE_BYTE_ORDER )
2013-06-08 02:16:15 +04:00
rb_raise ( rb_eArgError , " unexpected byte order " ) ;
2013-06-07 14:49:12 +04:00
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 ) ;
2013-06-11 17:28:33 +04:00
if ( SIZE_MAX / wordsize < numwords )
rb_raise ( rb_eArgError , " too big numwords * wordsize: % " PRI_SIZE_PREFIX " u * % " PRI_SIZE_PREFIX " u " , numwords , wordsize ) ;
2013-06-07 14:49:12 +04:00
}
2013-06-07 16:06:09 +04:00
static void
2013-06-07 19:39:07 +04:00
integer_pack_loop_setup (
2013-06-07 19:02:39 +04:00
size_t numwords , size_t wordsize , size_t nails , int flags ,
2013-06-07 16:06:09 +04:00
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 )
{
2013-06-07 19:02:39 +04:00
int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK ;
int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK ;
2013-06-07 16:06:09 +04:00
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 ;
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 - - ;
}
2013-06-07 19:02:39 +04:00
if ( wordorder_bits = = INTEGER_PACK_MSWORD_FIRST ) {
word_start = wordsize * ( numwords - 1 ) ;
2013-06-07 16:06:09 +04:00
word_step = - ( ssize_t ) wordsize ;
word_last = 0 ;
}
else {
word_start = 0 ;
word_step = wordsize ;
2013-06-07 19:02:39 +04:00
word_last = wordsize * ( numwords - 1 ) ;
2013-06-07 16:06:09 +04:00
}
2013-06-07 19:02:39 +04:00
if ( byteorder_bits = = INTEGER_PACK_NATIVE_BYTE_ORDER ) {
2013-06-07 16:06:09 +04:00
# ifdef WORDS_BIGENDIAN
2013-06-07 19:02:39 +04:00
byteorder_bits = INTEGER_PACK_MSBYTE_FIRST ;
2013-06-07 16:06:09 +04:00
# else
2013-06-07 19:02:39 +04:00
byteorder_bits = INTEGER_PACK_LSBYTE_FIRST ;
2013-06-07 16:06:09 +04:00
# endif
}
2013-06-07 19:02:39 +04:00
if ( byteorder_bits = = INTEGER_PACK_MSBYTE_FIRST ) {
2013-06-07 16:06:09 +04:00
byte_start = wordsize - 1 ;
2013-06-07 19:39:07 +04:00
byte_step = - 1 ;
2013-06-07 16:06:09 +04:00
}
else {
byte_start = 0 ;
2013-06-07 19:39:07 +04:00
byte_step = 1 ;
2013-06-07 16:06:09 +04:00
}
* 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 ;
}
2013-06-06 15:57:35 +04:00
static inline void
2013-06-07 19:39:07 +04:00
integer_pack_fill_dd ( BDIGIT * * dpp , BDIGIT * * dep , BDIGIT_DBL * ddp , int * numbits_in_dd_p )
2013-06-06 15:57:35 +04:00
{
if ( * dpp < * dep & & SIZEOF_BDIGITS * CHAR_BIT < = ( int ) sizeof ( * ddp ) * CHAR_BIT - * numbits_in_dd_p ) {
* ddp | = ( BDIGIT_DBL ) ( * ( * dpp ) + + ) < < * numbits_in_dd_p ;
* numbits_in_dd_p + = SIZEOF_BDIGITS * CHAR_BIT ;
}
else if ( * dpp = = * dep ) {
/* higher bits are infinity zeros */
* numbits_in_dd_p = ( int ) sizeof ( * ddp ) * CHAR_BIT ;
}
}
static inline BDIGIT_DBL
2013-06-07 19:39:07 +04:00
integer_pack_take_lowbits ( int n , BDIGIT_DBL * ddp , int * numbits_in_dd_p )
2013-06-06 15:57:35 +04:00
{
BDIGIT_DBL ret ;
ret = ( * ddp ) & ( ( ( BDIGIT_DBL ) 1 < < n ) - 1 ) ;
* ddp > > = n ;
* numbits_in_dd_p - = n ;
return ret ;
}
2013-06-11 16:06:40 +04:00
static int
2013-06-16 13:53:45 +04:00
bary_pack ( int sign , BDIGIT * ds , size_t num_bdigits , void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
2013-06-06 15:57:35 +04:00
{
2013-06-16 09:33:39 +04:00
BDIGIT * dp , * de ;
2013-06-07 02:31:23 +04:00
unsigned char * buf , * bufend ;
2013-06-06 15:57:35 +04:00
2013-06-16 09:33:39 +04:00
dp = ds ;
de = ds + num_bdigits ;
2013-06-06 15:57:35 +04:00
2013-06-12 13:21:11 +04:00
validate_integer_pack_format ( numwords , wordsize , nails , flags ,
INTEGER_PACK_MSWORD_FIRST |
INTEGER_PACK_LSWORD_FIRST |
INTEGER_PACK_MSBYTE_FIRST |
INTEGER_PACK_LSBYTE_FIRST |
2013-06-16 13:53:45 +04:00
INTEGER_PACK_NATIVE_BYTE_ORDER |
INTEGER_PACK_2COMP ) ;
2013-06-16 09:33:39 +04:00
2013-06-06 15:57:35 +04:00
while ( dp < de & & de [ - 1 ] = = 0 )
de - - ;
if ( dp = = de ) {
sign = 0 ;
}
2013-06-09 09:53:00 +04:00
buf = words ;
bufend = buf + numwords * wordsize ;
2013-06-06 15:57:35 +04:00
if ( buf = = bufend ) {
2013-06-11 16:06:40 +04:00
/* overflow if non-zero*/
2013-06-16 13:53:45 +04:00
if ( ! ( flags & INTEGER_PACK_2COMP ) | | 0 < = sign )
2013-06-11 16:06:40 +04:00
sign * = 2 ;
else {
if ( de - dp = = 1 & & dp [ 0 ] = = 1 )
sign = - 1 ; /* val == -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
else
sign = - 2 ; /* val < -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
}
2013-06-06 15:57:35 +04:00
}
else if ( dp = = de ) {
memset ( buf , ' \0 ' , bufend - buf ) ;
}
else if ( dp < de & & buf < bufend ) {
int word_num_partialbits ;
size_t word_num_fullbytes ;
ssize_t word_step ;
size_t byte_start ;
int byte_step ;
2013-06-07 16:06:09 +04:00
size_t word_start , word_last ;
2013-06-07 19:56:59 +04:00
unsigned char * wordp , * last_wordp ;
2013-06-06 15:57:35 +04:00
BDIGIT_DBL dd ;
int numbits_in_dd ;
2013-06-07 19:39:07 +04:00
integer_pack_loop_setup ( numwords , wordsize , nails , flags ,
2013-06-07 19:56:59 +04:00
& word_num_fullbytes , & word_num_partialbits ,
2013-06-07 16:06:09 +04:00
& word_start , & word_step , & word_last , & byte_start , & byte_step ) ;
2013-06-06 15:57:35 +04:00
2013-06-07 16:06:09 +04:00
wordp = buf + word_start ;
last_wordp = buf + word_last ;
2013-06-06 15:57:35 +04:00
dd = 0 ;
numbits_in_dd = 0 ;
# define FILL_DD \
2013-06-07 19:39:07 +04:00
integer_pack_fill_dd ( & dp , & de , & dd , & numbits_in_dd )
2013-06-06 15:57:35 +04:00
# define TAKE_LOWBITS(n) \
2013-06-07 19:39:07 +04:00
integer_pack_take_lowbits ( n , & dd , & numbits_in_dd )
2013-06-06 15:57:35 +04:00
while ( 1 ) {
2013-06-07 19:56:59 +04:00
size_t index_in_word = 0 ;
unsigned char * bytep = wordp + byte_start ;
2013-06-06 15:57:35 +04:00
while ( index_in_word < word_num_fullbytes ) {
FILL_DD ;
* bytep = TAKE_LOWBITS ( CHAR_BIT ) ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( word_num_partialbits ) {
FILL_DD ;
* bytep = TAKE_LOWBITS ( word_num_partialbits ) ;
bytep + = byte_step ;
index_in_word + + ;
}
2013-06-07 19:56:59 +04:00
while ( index_in_word < wordsize ) {
2013-06-06 15:57:35 +04:00
* bytep = 0 ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( wordp = = last_wordp )
break ;
wordp + = word_step ;
}
2013-06-11 16:06:40 +04:00
FILL_DD ;
/* overflow tests */
if ( dp ! = de | | 1 < dd ) {
/* 2**(numwords*(wordsize*CHAR_BIT-nails)+1) <= abs(val) */
sign * = 2 ;
}
else if ( dd = = 1 ) {
/* 2**(numwords*(wordsize*CHAR_BIT-nails)) <= abs(val) < 2**(numwords*(wordsize*CHAR_BIT-nails)+1) */
2013-06-16 13:53:45 +04:00
if ( ! ( flags & INTEGER_PACK_2COMP ) | | 0 < = sign )
2013-06-11 16:06:40 +04:00
sign * = 2 ;
else { /* overflow_2comp && sign == -1 */
/* test lower bits are all zero. */
dp = ds ;
while ( dp < de & & * dp = = 0 )
dp + + ;
if ( de - dp = = 1 & & /* only one non-zero word. */
( * dp & ( * dp - 1 ) ) = = 0 ) /* *dp contains only one bit set. */
sign = - 1 ; /* val == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
else
sign = - 2 ; /* val < -2**(numwords*(wordsize*CHAR_BIT-nails)) */
}
}
2013-06-06 15:57:35 +04:00
}
2013-06-16 13:53:45 +04:00
if ( ( flags & INTEGER_PACK_2COMP ) & & ( sign < 0 & & numwords ! = 0 ) ) {
2013-06-11 16:06:40 +04:00
unsigned char * buf ;
int word_num_partialbits ;
size_t word_num_fullbytes ;
ssize_t word_step ;
size_t byte_start ;
int byte_step ;
size_t word_start , word_last ;
unsigned char * wordp , * last_wordp ;
unsigned int partialbits_mask ;
int carry ;
integer_pack_loop_setup ( numwords , wordsize , nails , flags ,
& word_num_fullbytes , & word_num_partialbits ,
& word_start , & word_step , & word_last , & byte_start , & byte_step ) ;
partialbits_mask = ( 1 < < word_num_partialbits ) - 1 ;
buf = words ;
wordp = buf + word_start ;
last_wordp = buf + word_last ;
carry = 1 ;
while ( 1 ) {
size_t index_in_word = 0 ;
unsigned char * bytep = wordp + byte_start ;
while ( index_in_word < word_num_fullbytes ) {
carry + = ( unsigned char ) ~ * bytep ;
* bytep = ( unsigned char ) carry ;
carry > > = CHAR_BIT ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( word_num_partialbits ) {
carry + = ( * bytep & partialbits_mask ) ^ partialbits_mask ;
* bytep = carry & partialbits_mask ;
carry > > = word_num_partialbits ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( wordp = = last_wordp )
break ;
wordp + = word_step ;
}
}
return sign ;
2013-06-16 13:53:45 +04:00
# undef FILL_DD
# undef TAKE_LOWBITS
}
/*
* Export an integer into a buffer .
*
* This function fills the buffer specified by _words_ and _numwords_ as
* val in the format specified by _wordsize_ , _nails_ and _flags_ .
*
* [ val ] Fixnum , Bignum or another integer like object which has to_int method .
* [ words ] buffer to export abs ( val ) .
* [ numwords ] the size of given buffer as number of words .
* [ wordsize ] the size of word as number of bytes .
* [ nails ] number of padding bits in a word .
* Most significant nails bits of each word are filled by zero .
* [ flags ] bitwise or of constants which name starts " INTEGER_PACK_ " .
*
* flags :
* [ INTEGER_PACK_MSWORD_FIRST ] Store the most significant word as the first word .
* [ INTEGER_PACK_LSWORD_FIRST ] Store the least significant word as the first word .
* [ INTEGER_PACK_MSBYTE_FIRST ] Store the most significant byte in a word as the first byte in the word .
* [ INTEGER_PACK_LSBYTE_FIRST ] Store the least significant byte in a word as the first byte in the word .
* [ INTEGER_PACK_NATIVE_BYTE_ORDER ] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host ' s endian .
* [ INTEGER_PACK_2COMP ] Use 2 ' s complement representation .
* [ INTEGER_PACK_LITTLE_ENDIAN ] Same as INTEGER_PACK_LSWORD_FIRST | INTEGER_PACK_LSBYTE_FIRST
* [ INTEGER_PACK_BIG_ENDIAN ] Same as INTEGER_PACK_MSWORD_FIRST | INTEGER_PACK_MSBYTE_FIRST
*
* This function fills the buffer specified by _words_
* as abs ( val ) if INTEGER_PACK_2COMP is not specified in _flags_ .
* If INTEGER_PACK_2COMP is specified , 2 ' s complement representation of val is
* filled in the buffer .
*
* This function returns the signedness and overflow condition .
* The overflow condition depends on INTEGER_PACK_2COMP .
*
* INTEGER_PACK_2COMP is not specified :
* - 2 : negative overflow . val < = - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) )
* - 1 : negative without overflow . - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < val < 0
* 0 : zero . val = = 0
* 1 : positive without overflow . 0 < val < 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) )
* 2 : positive overflow . 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < = val
*
* INTEGER_PACK_2COMP is specified :
* - 2 : negative overflow . val < - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) )
* - 1 : negative without overflow . - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < = val < 0
* 0 : zero . val = = 0
* 1 : positive without overflow . 0 < val < 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) )
* 2 : positive overflow . 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < = val
*
* The value , - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) , is representable
* in 2 ' s complement representation but not representable in absolute value .
* So - 1 is returned for the value if INTEGER_PACK_2COMP is specified
* but returns - 2 if INTEGER_PACK_2COMP is not specified .
*
* The least significant words are filled in the buffer when overflow occur .
*/
int
rb_integer_pack ( VALUE val , void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
{
int sign ;
BDIGIT * ds ;
size_t num_bdigits ;
BDIGIT fixbuf [ ( sizeof ( long ) + SIZEOF_BDIGITS - 1 ) / SIZEOF_BDIGITS ] ;
RB_GC_GUARD ( val ) = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
long v = FIX2LONG ( val ) ;
if ( v < 0 ) {
sign = - 1 ;
v = - v ;
}
else {
sign = 1 ;
}
# if SIZEOF_BDIGITS == SIZEOF_LONG
fixbuf [ 0 ] = v ;
# else
{
int i ;
for ( i = 0 ; i < numberof ( fixbuf ) ; i + + ) {
fixbuf [ i ] = ( BDIGIT ) ( v & ( ( 1L < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
v > > = SIZEOF_BDIGITS * CHAR_BIT ;
}
}
# endif
ds = fixbuf ;
num_bdigits = numberof ( fixbuf ) ;
}
else {
sign = RBIGNUM_POSITIVE_P ( val ) ? 1 : - 1 ;
ds = BDIGITS ( val ) ;
num_bdigits = RBIGNUM_LEN ( val ) ;
}
return bary_pack ( sign , ds , num_bdigits , words , numwords , wordsize , nails , flags ) ;
2013-06-11 16:06:40 +04:00
}
2013-06-10 07:12:44 +04:00
static size_t
2013-06-12 19:18:00 +04:00
integer_unpack_num_bdigits_small ( size_t numwords , size_t wordsize , size_t nails , int * nlp_bits_ret )
2013-06-10 07:12:44 +04:00
{
2013-06-12 19:18:00 +04:00
/* nlp_bits stands for number of leading padding bits */
size_t num_bits = ( wordsize * CHAR_BIT - nails ) * numwords ;
size_t num_bdigits = ( num_bits + BITSPERDIG - 1 ) / BITSPERDIG ;
2013-06-13 01:13:56 +04:00
* nlp_bits_ret = ( int ) ( num_bdigits * BITSPERDIG - num_bits ) ;
2013-06-12 19:18:00 +04:00
return num_bdigits ;
2013-06-10 07:12:44 +04:00
}
static size_t
2013-06-12 19:18:00 +04:00
integer_unpack_num_bdigits_generic ( size_t numwords , size_t wordsize , size_t nails , int * nlp_bits_ret )
2013-06-10 07:12:44 +04:00
{
2013-06-12 17:25:00 +04:00
/* BITSPERDIG = SIZEOF_BDIGITS * CHAR_BIT */
2013-06-10 07:12:44 +04:00
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
2013-06-12 17:25:00 +04:00
/* num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG */
2013-06-10 07:12:44 +04:00
2013-06-12 17:25:00 +04:00
/* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
size_t num_bytes1 = wordsize * numwords ;
/* q1 * CHAR_BIT + r1 = numwords */
size_t q1 = numwords / CHAR_BIT ;
size_t r1 = numwords % CHAR_BIT ;
/* num_bits = CHAR_BIT * num_bytes1 - nails * (q1 * CHAR_BIT + r1) = CHAR_BIT * num_bytes2 - nails * r1 */
size_t num_bytes2 = num_bytes1 - nails * q1 ;
/* q2 * CHAR_BIT + r2 = nails */
size_t q2 = nails / CHAR_BIT ;
size_t r2 = nails % CHAR_BIT ;
/* num_bits = CHAR_BIT * num_bytes2 - (q2 * CHAR_BIT + r2) * r1 = CHAR_BIT * num_bytes3 - r1 * r2 */
size_t num_bytes3 = num_bytes2 - q2 * r1 ;
2013-06-10 07:12:44 +04:00
2013-06-12 17:25:00 +04:00
/* q3 * BITSPERDIG + r3 = num_bytes3 */
size_t q3 = num_bytes3 / BITSPERDIG ;
size_t r3 = num_bytes3 % BITSPERDIG ;
2013-06-10 07:12:44 +04:00
2013-06-12 17:25:00 +04:00
/* num_bits = CHAR_BIT * (q3 * BITSPERDIG + r3) - r1 * r2 = BITSPERDIG * num_digits1 + CHAR_BIT * r3 - r1 * r2 */
size_t num_digits1 = CHAR_BIT * q3 ;
/*
* if CHAR_BIT * r3 > = r1 * r2
* CHAR_BIT * r3 - r1 * r2 = CHAR_BIT * BITSPERDIG - ( CHAR_BIT * BITSPERDIG - ( CHAR_BIT * r3 - r1 * r2 ) )
* q4 * BITSPERDIG + r4 = CHAR_BIT * BITSPERDIG - ( CHAR_BIT * r3 - r1 * r2 )
* num_bits = BITSPERDIG * num_digits1 + CHAR_BIT * BITSPERDIG - ( q4 * BITSPERDIG + r4 ) = BITSPERDIG * num_digits2 - r4
* else
* q4 * BITSPERDIG + r4 = - ( CHAR_BIT * r3 - r1 * r2 )
* num_bits = BITSPERDIG * num_digits1 - ( q4 * BITSPERDIG + r4 ) = BITSPERDIG * num_digits2 - r4
* end
*/
if ( CHAR_BIT * r3 > = r1 * r2 ) {
size_t tmp1 = CHAR_BIT * BITSPERDIG - ( CHAR_BIT * r3 - r1 * r2 ) ;
size_t q4 = tmp1 / BITSPERDIG ;
2013-06-13 11:33:12 +04:00
int r4 = ( int ) ( tmp1 % BITSPERDIG ) ;
2013-06-12 17:25:00 +04:00
size_t num_digits2 = num_digits1 + CHAR_BIT - q4 ;
2013-06-12 19:18:00 +04:00
* nlp_bits_ret = r4 ;
2013-06-12 17:25:00 +04:00
return num_digits2 ;
}
else {
2013-06-13 13:56:52 +04:00
size_t tmp1 = r1 * r2 - CHAR_BIT * r3 ;
2013-06-12 17:25:00 +04:00
size_t q4 = tmp1 / BITSPERDIG ;
2013-06-13 11:33:12 +04:00
int r4 = ( int ) ( tmp1 % BITSPERDIG ) ;
2013-06-12 17:25:00 +04:00
size_t num_digits2 = num_digits1 - q4 ;
2013-06-12 19:18:00 +04:00
* nlp_bits_ret = r4 ;
2013-06-12 17:25:00 +04:00
return num_digits2 ;
}
2013-06-10 07:12:44 +04:00
}
2013-06-16 16:59:26 +04:00
static size_t
integer_unpack_num_bdigits ( size_t numwords , size_t wordsize , size_t nails , int * nlp_bits_ret )
{
size_t num_bdigits ;
if ( numwords < = ( SIZE_MAX - ( BITSPERDIG - 1 ) ) / CHAR_BIT / wordsize ) {
num_bdigits = integer_unpack_num_bdigits_small ( numwords , wordsize , nails , nlp_bits_ret ) ;
# ifdef DEBUG_INTEGER_PACK
{
int nlp_bits1 ;
size_t num_bdigits1 = integer_unpack_num_bdigits_generic ( numwords , wordsize , nails , & nlp_bits1 ) ;
assert ( num_bdigits = = num_bdigits1 ) ;
assert ( * nlp_bits_ret = = nlp_bits1 ) ;
}
# endif
}
else {
num_bdigits = integer_unpack_num_bdigits_generic ( numwords , wordsize , nails , nlp_bits_ret ) ;
}
return num_bdigits ;
}
2013-06-07 01:20:04 +04:00
static inline void
2013-06-07 19:39:07 +04:00
integer_unpack_push_bits ( int data , int numbits , BDIGIT_DBL * ddp , int * numbits_in_dd_p , BDIGIT * * dpp )
2013-06-07 01:20:04 +04:00
{
( * ddp ) | = ( ( BDIGIT_DBL ) data ) < < ( * numbits_in_dd_p ) ;
* numbits_in_dd_p + = numbits ;
while ( SIZEOF_BDIGITS * CHAR_BIT < = * numbits_in_dd_p ) {
2013-06-07 12:41:48 +04:00
* ( * dpp ) + + = ( BDIGIT ) ( ( * ddp ) & ( ( ( BDIGIT_DBL ) 1 < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
2013-06-07 01:20:04 +04:00
* ddp > > = SIZEOF_BDIGITS * CHAR_BIT ;
* numbits_in_dd_p - = SIZEOF_BDIGITS * CHAR_BIT ;
}
}
2013-06-16 16:59:26 +04:00
static int
bary_unpack_internal ( BDIGIT * bdigits , size_t num_bdigits , const void * words , size_t numwords , size_t wordsize , size_t nails , int flags , int nlp_bits )
2013-06-07 01:20:04 +04:00
{
2013-06-16 16:59:26 +04:00
int sign = ( flags & INTEGER_PACK_NEGATIVE ) ? - 1 : 1 ;
2013-06-07 03:05:59 +04:00
const unsigned char * buf = words ;
2013-06-07 01:20:04 +04:00
BDIGIT * dp ;
BDIGIT * de ;
int word_num_partialbits ;
size_t word_num_fullbytes ;
ssize_t word_step ;
size_t byte_start ;
int byte_step ;
2013-06-07 16:06:09 +04:00
size_t word_start , word_last ;
2013-06-07 19:56:59 +04:00
const unsigned char * wordp , * last_wordp ;
2013-06-07 01:20:04 +04:00
BDIGIT_DBL dd ;
int numbits_in_dd ;
2013-06-16 16:59:26 +04:00
if ( num_bdigits ) {
dp = bdigits ;
de = dp + num_bdigits ;
2013-06-07 01:20:04 +04:00
2013-06-16 16:59:26 +04:00
integer_pack_loop_setup ( numwords , wordsize , nails , flags ,
& word_num_fullbytes , & word_num_partialbits ,
& word_start , & word_step , & word_last , & byte_start , & byte_step ) ;
2013-06-07 01:20:04 +04:00
2013-06-16 16:59:26 +04:00
wordp = buf + word_start ;
last_wordp = buf + word_last ;
2013-06-07 01:20:04 +04:00
2013-06-16 16:59:26 +04:00
dd = 0 ;
numbits_in_dd = 0 ;
2013-06-07 01:20:04 +04:00
# define PUSH_BITS(data, numbits) \
2013-06-16 16:59:26 +04:00
integer_unpack_push_bits ( data , numbits , & dd , & numbits_in_dd , & dp )
2013-06-07 01:20:04 +04:00
2013-06-16 16:59:26 +04:00
while ( 1 ) {
size_t index_in_word = 0 ;
const unsigned char * bytep = wordp + byte_start ;
while ( index_in_word < word_num_fullbytes ) {
PUSH_BITS ( * bytep , CHAR_BIT ) ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( word_num_partialbits ) {
PUSH_BITS ( * bytep & ( ( 1 < < word_num_partialbits ) - 1 ) , word_num_partialbits ) ;
bytep + = byte_step ;
index_in_word + + ;
}
2013-06-15 15:15:23 +04:00
2013-06-16 16:59:26 +04:00
if ( wordp = = last_wordp )
break ;
2013-06-15 15:15:23 +04:00
2013-06-16 16:59:26 +04:00
wordp + = word_step ;
2013-06-15 15:15:23 +04:00
}
2013-06-16 16:59:26 +04:00
if ( dd )
* dp + + = ( BDIGIT ) dd ;
assert ( dp < = de ) ;
while ( dp < de )
* dp + + = 0 ;
# undef PUSH_BITS
2013-06-15 15:15:23 +04:00
}
2013-06-16 16:59:26 +04:00
if ( flags & INTEGER_PACK_2COMP ) {
if ( num_bdigits = = 0 ) {
if ( flags & INTEGER_PACK_NEGATIVE )
sign = - 1 ;
else
sign = 0 ;
}
else if ( ( flags & INTEGER_PACK_NEGATIVE ) | |
( num_bdigits ! = 0 & &
( bdigits [ num_bdigits - 1 ] > > ( BITSPERDIG - nlp_bits - 1 ) ) ) ) {
if ( nlp_bits )
bdigits [ num_bdigits - 1 ] | = ( ~ ( BDIGIT ) 0 ) < < ( BITSPERDIG - nlp_bits ) ;
bary_2comp ( bdigits , num_bdigits ) ;
sign = - 1 ;
}
}
2013-06-07 01:20:04 +04:00
2013-06-16 16:59:26 +04:00
return sign ;
2013-06-07 01:20:04 +04:00
}
2013-06-16 16:59:26 +04:00
static void
bary_unpack ( BDIGIT * bdigits , size_t num_bdigits , const void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
2013-06-12 19:18:00 +04:00
{
2013-06-16 16:59:26 +04:00
size_t num_bdigits0 ;
2013-06-12 19:18:00 +04:00
int nlp_bits ;
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 |
2013-06-16 16:59:26 +04:00
INTEGER_PACK_2COMP |
2013-06-12 19:18:00 +04:00
INTEGER_PACK_FORCE_BIGNUM |
INTEGER_PACK_NEGATIVE ) ;
2013-06-16 16:59:26 +04:00
num_bdigits0 = integer_unpack_num_bdigits ( numwords , wordsize , nails , & nlp_bits ) ;
2013-06-12 19:18:00 +04:00
2013-06-16 16:59:26 +04:00
assert ( num_bdigits0 < = num_bdigits ) ;
bary_unpack_internal ( bdigits , num_bdigits , words , numwords , wordsize , nails , flags , nlp_bits ) ;
2013-06-12 19:18:00 +04:00
}
/*
* Import an integer into a buffer .
*
* [ words ] buffer to import .
* [ numwords ] the size of given buffer as number of words .
* [ wordsize ] the size of word as number of bytes .
* [ nails ] number of padding bits in a word .
* Most significant nails bits of each word are ignored .
* [ flags ] bitwise or of constants which name starts " INTEGER_PACK_ " .
2013-06-16 16:59:26 +04:00
*
* flags :
* [ INTEGER_PACK_MSWORD_FIRST ] Interpret the first word as the most significant word .
* [ INTEGER_PACK_LSWORD_FIRST ] Interpret the first word as the least significant word .
* [ INTEGER_PACK_MSBYTE_FIRST ] Interpret the first byte in a word as the most significant byte in the word .
* [ INTEGER_PACK_LSBYTE_FIRST ] Interpret the first byte in a word as the least significant byte in the word .
* [ INTEGER_PACK_NATIVE_BYTE_ORDER ] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host ' s endian .
* [ INTEGER_PACK_2COMP ] Use 2 ' s complement representation .
* [ INTEGER_PACK_LITTLE_ENDIAN ] Same as INTEGER_PACK_LSWORD_FIRST | INTEGER_PACK_LSBYTE_FIRST
* [ INTEGER_PACK_BIG_ENDIAN ] Same as INTEGER_PACK_MSWORD_FIRST | INTEGER_PACK_MSBYTE_FIRST
* [ INTEGER_PACK_FORCE_BIGNUM ] the result will be a Bignum
* even if it is representable as a Fixnum .
* [ INTEGER_PACK_NEGATIVE ] Returns non - positive value .
* ( Returns non - negative value if not specified . )
2013-06-12 19:18:00 +04:00
*
* This function returns the imported integer as Fixnum or Bignum .
2013-06-16 16:59:26 +04:00
*
* The range of the result value depends on INTEGER_PACK_2COMP and INTEGER_PACK_NEGATIVE .
*
* INTEGER_PACK_2COMP is not set :
* 0 < = val < 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) if ! INTEGER_PACK_NEGATIVE
* - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < val < = 0 if INTEGER_PACK_NEGATIVE
*
* INTEGER_PACK_2COMP is set :
* - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) - 1 ) < = val < = 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) - 1 ) - 1 if ! INTEGER_PACK_NEGATIVE
* - 2 * * ( numwords * ( wordsize * CHAR_BIT - nails ) ) < = val < = - 1 if INTEGER_PACK_NEGATIVE
*
* INTEGER_PACK_2COMP without INTEGER_PACK_NEGATIVE means sign extension .
* INTEGER_PACK_2COMP with INTEGER_PACK_NEGATIVE mean assuming the higher bits are 1.
*
* Note that this function returns 0 when numwords is zero and
* INTEGER_PACK_2COMP is set but INTEGER_PACK_NEGATIVE is not set .
2013-06-12 19:18:00 +04:00
*/
2013-06-16 16:59:26 +04:00
2013-06-12 19:18:00 +04:00
VALUE
2013-06-16 16:59:26 +04:00
rb_integer_unpack ( const void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
2013-06-12 19:18:00 +04:00
{
VALUE val ;
2013-06-16 16:59:26 +04:00
size_t num_bdigits ;
int sign ;
2013-06-12 19:18:00 +04:00
int nlp_bits ;
2013-06-16 16:59:26 +04:00
BDIGIT * ds ;
2013-06-12 19:18:00 +04:00
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 |
2013-06-16 16:59:26 +04:00
INTEGER_PACK_2COMP |
2013-06-12 19:18:00 +04:00
INTEGER_PACK_FORCE_BIGNUM |
INTEGER_PACK_NEGATIVE ) ;
2013-06-16 16:59:26 +04:00
num_bdigits = integer_unpack_num_bdigits ( numwords , wordsize , nails , & nlp_bits ) ;
2013-06-12 19:18:00 +04:00
2013-06-16 16:59:26 +04:00
if ( LONG_MAX < num_bdigits )
rb_raise ( rb_eArgError , " too big to unpack as an integer " ) ;
val = bignew ( ( long ) num_bdigits , 0 ) ;
ds = BDIGITS ( val ) ;
sign = bary_unpack_internal ( ds , num_bdigits , words , numwords , wordsize , nails , flags , nlp_bits ) ;
if ( ( flags & INTEGER_PACK_2COMP ) & & num_bdigits = = 0 & & sign < 0 ) {
rb_big_resize ( val , 1 ) ;
ds [ 0 ] = 1 ;
2013-06-12 19:18:00 +04:00
}
2013-06-16 16:59:26 +04:00
RBIGNUM_SET_SIGN ( val , 0 < = sign ) ;
2013-06-12 19:18:00 +04:00
if ( flags & INTEGER_PACK_FORCE_BIGNUM )
return bigtrunc ( val ) ;
return bignorm ( val ) ;
}
2010-02-26 14:09:29 +03:00
# define QUAD_SIZE 8
# if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
2002-02-13 12:01:11 +03:00
void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_quad_pack ( char * buf , VALUE val )
2002-02-13 12:01:11 +03:00
{
LONG_LONG q ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
q = FIX2LONG ( val ) ;
}
else {
2007-09-01 16:02:36 +04:00
long len = RBIGNUM_LEN ( val ) ;
2002-02-13 12:01:11 +03:00
BDIGIT * ds ;
2004-01-22 21:06:38 +03:00
if ( len > SIZEOF_LONG_LONG / SIZEOF_BDIGITS ) {
2006-07-11 10:47:09 +04:00
len = SIZEOF_LONG_LONG / SIZEOF_BDIGITS ;
2004-01-22 21:06:38 +03:00
}
2002-02-13 12:01:11 +03:00
ds = BDIGITS ( val ) ;
q = 0 ;
while ( len - - ) {
q = BIGUP ( q ) ;
q + = ds [ len ] ;
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( val ) ) q = - q ;
2002-02-13 12:01:11 +03:00
}
2002-04-10 12:45:26 +04:00
memcpy ( buf , ( char * ) & q , SIZEOF_LONG_LONG ) ;
2002-02-13 12:01:11 +03:00
}
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_quad_unpack ( const char * buf , int sign )
2002-02-13 12:01:11 +03:00
{
unsigned LONG_LONG q ;
long neg = 0 ;
2002-08-21 19:47:54 +04:00
long i ;
2002-02-13 12:01:11 +03:00
BDIGIT * digits ;
VALUE big ;
2002-04-10 12:45:26 +04:00
memcpy ( & q , buf , SIZEOF_LONG_LONG ) ;
2002-02-13 12:01:11 +03:00
if ( sign ) {
2002-08-21 19:47:54 +04:00
if ( FIXABLE ( ( LONG_LONG ) q ) ) return LONG2FIX ( ( LONG_LONG ) q ) ;
2002-02-13 12:01:11 +03:00
if ( ( LONG_LONG ) q < 0 ) {
q = - ( LONG_LONG ) q ;
neg = 1 ;
}
}
else {
2002-08-21 19:47:54 +04:00
if ( POSFIXABLE ( q ) ) return LONG2FIX ( q ) ;
2002-02-13 12:01:11 +03:00
}
i = 0 ;
2002-11-19 11:07:51 +03:00
big = bignew ( DIGSPERLL , 1 ) ;
2002-02-13 12:01:11 +03:00
digits = BDIGITS ( big ) ;
2002-11-19 11:07:51 +03:00
while ( i < DIGSPERLL ) {
2002-02-13 12:01:11 +03:00
digits [ i + + ] = BIGLO ( q ) ;
q = BIGDN ( q ) ;
}
2002-11-19 11:07:51 +03:00
i = DIGSPERLL ;
2002-02-13 12:01:11 +03:00
while ( i - - & & ! digits [ i ] ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
2002-02-13 12:01:11 +03:00
if ( neg ) {
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2002-02-13 12:01:11 +03:00
}
return bignorm ( big ) ;
}
# else
2010-02-26 15:41:02 +03:00
static int
quad_buf_complement ( char * buf , size_t len )
{
size_t i ;
for ( i = 0 ; i < len ; i + + )
buf [ i ] = ~ buf [ i ] ;
for ( i = 0 ; i < len ; i + + ) {
buf [ i ] + + ;
if ( buf [ i ] ! = 0 )
return 0 ;
}
return 1 ;
}
2002-02-13 12:01:11 +03:00
void
2006-03-01 13:06:03 +03:00
rb_quad_pack ( char * buf , VALUE val )
2002-02-13 12:01:11 +03:00
{
long len ;
memset ( buf , 0 , QUAD_SIZE ) ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
2002-02-13 12:53:17 +03:00
val = rb_int2big ( FIX2LONG ( val ) ) ;
2002-02-13 12:01:11 +03:00
}
2007-09-01 16:02:36 +04:00
len = RBIGNUM_LEN ( val ) * SIZEOF_BDIGITS ;
2003-12-26 18:34:33 +03:00
if ( len > QUAD_SIZE ) {
2010-02-26 15:41:02 +03:00
len = QUAD_SIZE ;
2003-12-26 18:34:33 +03:00
}
2002-02-13 12:01:11 +03:00
memcpy ( buf , ( char * ) BDIGITS ( val ) , len ) ;
2010-02-26 15:41:02 +03:00
if ( RBIGNUM_NEGATIVE_P ( val ) ) {
quad_buf_complement ( buf , QUAD_SIZE ) ;
2002-02-13 12:53:17 +03:00
}
2002-02-13 12:01:11 +03:00
}
2010-12-02 11:01:24 +03:00
# define BNEG(b) (RSHIFT(((BDIGIT*)(b))[QUAD_SIZE / SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
2002-02-13 12:53:17 +03:00
2002-02-13 12:01:11 +03:00
VALUE
2006-03-01 13:06:03 +03:00
rb_quad_unpack ( const char * buf , int sign )
2002-02-13 12:01:11 +03:00
{
2002-04-10 12:45:26 +04:00
VALUE big = bignew ( QUAD_SIZE / SIZEOF_BDIGITS , 1 ) ;
2002-02-13 12:01:11 +03:00
memcpy ( ( char * ) BDIGITS ( big ) , buf , QUAD_SIZE ) ;
2002-02-13 12:53:17 +03:00
if ( sign & & BNEG ( buf ) ) {
char * tmp = ( char * ) BDIGITS ( big ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2010-02-26 15:41:02 +03:00
quad_buf_complement ( tmp , QUAD_SIZE ) ;
2002-02-13 12:01:11 +03:00
}
return bignorm ( big ) ;
}
# endif
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_cstr_to_inum ( const char * str , int base , int badcheck )
1998-01-16 15:13:05 +03:00
{
2000-01-05 07:41:21 +03:00
const char * s = str ;
char * end ;
2003-07-24 22:33:50 +04:00
char sign = 1 , nondigit = 0 ;
int c ;
2000-11-01 11:49:40 +03:00
BDIGIT_DBL num ;
1999-08-13 09:45:20 +04:00
long len , blen = 1 ;
long i ;
1998-01-16 15:13:05 +03:00
VALUE z ;
2000-10-31 11:37:47 +03:00
BDIGIT * zds ;
1998-01-16 15:13:05 +03:00
2010-01-28 19:34:11 +03:00
# undef ISDIGIT
# define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
2007-07-15 14:05:37 +04:00
# define conv_digit(c) \
( ! ISASCII ( c ) ? - 1 : \
2008-01-02 20:48:20 +03:00
ISDIGIT ( c ) ? ( ( c ) - ' 0 ' ) : \
ISLOWER ( c ) ? ( ( c ) - ' a ' + 10 ) : \
ISUPPER ( c ) ? ( ( c ) - ' A ' + 10 ) : \
2007-07-15 14:05:37 +04:00
- 1 )
2002-10-17 11:27:00 +04:00
if ( ! str ) {
if ( badcheck ) goto bad ;
return INT2FIX ( 0 ) ;
}
2006-06-27 20:15:22 +04:00
while ( ISSPACE ( * str ) ) str + + ;
1999-01-20 07:59:39 +03:00
2000-12-22 12:00:23 +03:00
if ( str [ 0 ] = = ' + ' ) {
1999-01-20 07:59:39 +03:00
str + + ;
}
2000-12-22 12:00:23 +03:00
else if ( str [ 0 ] = = ' - ' ) {
1998-01-16 15:13:05 +03:00
str + + ;
sign = 0 ;
}
2001-03-14 07:45:46 +03:00
if ( str [ 0 ] = = ' + ' | | str [ 0 ] = = ' - ' ) {
if ( badcheck ) goto bad ;
return INT2FIX ( 0 ) ;
}
2002-02-01 13:23:22 +03:00
if ( base < = 0 ) {
2000-12-22 12:00:23 +03:00
if ( str [ 0 ] = = ' 0 ' ) {
2002-08-16 10:39:27 +04:00
switch ( str [ 1 ] ) {
case ' x ' : case ' X ' :
1998-01-16 15:13:05 +03:00
base = 16 ;
2002-08-16 10:39:27 +04:00
break ;
case ' b ' : case ' B ' :
1999-08-13 09:45:20 +04:00
base = 2 ;
2002-08-16 10:39:27 +04:00
break ;
case ' o ' : case ' O ' :
base = 8 ;
break ;
case ' d ' : case ' D ' :
base = 10 ;
break ;
default :
1998-01-16 15:13:05 +03:00
base = 8 ;
}
}
2002-02-01 13:23:22 +03:00
else if ( base < - 1 ) {
base = - base ;
}
1998-01-16 15:13:05 +03:00
else {
base = 10 ;
}
}
2002-08-16 10:39:27 +04:00
switch ( base ) {
case 2 :
len = 1 ;
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' b ' | | str [ 1 ] = = ' B ' ) ) {
str + = 2 ;
}
break ;
2003-04-14 10:54:27 +04:00
case 3 :
len = 2 ;
break ;
2002-08-16 10:39:27 +04:00
case 8 :
2008-01-30 06:07:37 +03:00
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' o ' | | str [ 1 ] = = ' O ' ) ) {
1999-01-20 07:59:39 +03:00
str + = 2 ;
}
2003-04-14 10:54:27 +04:00
case 4 : case 5 : case 6 : case 7 :
len = 3 ;
2002-08-16 10:39:27 +04:00
break ;
case 10 :
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' d ' | | str [ 1 ] = = ' D ' ) ) {
1999-08-13 09:45:20 +04:00
str + = 2 ;
}
2003-04-21 13:36:31 +04:00
case 9 : case 11 : case 12 : case 13 : case 14 : case 15 :
2003-04-14 10:54:27 +04:00
len = 4 ;
2002-08-16 10:39:27 +04:00
break ;
case 16 :
2001-12-26 20:01:20 +03:00
len = 4 ;
2002-08-16 10:39:27 +04:00
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' x ' | | str [ 1 ] = = ' X ' ) ) {
str + = 2 ;
}
break ;
2003-04-14 10:54:27 +04:00
default :
if ( base < 2 | | 36 < base ) {
* regerror.c, string.c, io.c, lib/getoptlong.rb, lib/net/imap.rb,
compile.c, sprintf.c, parse.y, ext/win32ole/win32ole.c,
ext/tk/sample/demos-en/entry3.rb, ext/tk/lib/tcltk.rb,
ext/openssl/ossl_bn.c, numeric.c, vm.c,
benchmark/bm_so_meteor_contest.rb, bignum.c, ruby.c: don't "illegal"
for non law violation context.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14377 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-12-21 05:31:11 +03:00
rb_raise ( rb_eArgError , " invalid radix %d " , base ) ;
2003-04-14 10:54:27 +04:00
}
if ( base < = 32 ) {
len = 5 ;
}
else {
len = 6 ;
}
break ;
2001-12-26 20:01:20 +03:00
}
2007-12-31 09:43:32 +03:00
if ( * str = = ' 0 ' ) { /* squeeze preceding 0s */
2008-01-30 14:20:03 +03:00
int us = 0 ;
while ( ( c = * + + str ) = = ' 0 ' | | c = = ' _ ' ) {
if ( c = = ' _ ' ) {
if ( + + us > = 2 )
break ;
} else
us = 0 ;
}
if ( ! ( c = * str ) | | ISSPACE ( c ) ) - - str ;
2007-07-15 14:05:37 +04:00
}
c = * str ;
c = conv_digit ( c ) ;
if ( c < 0 | | c > = base ) {
if ( badcheck ) goto bad ;
return INT2FIX ( 0 ) ;
2003-01-18 08:53:53 +03:00
}
2001-12-26 20:01:20 +03:00
len * = strlen ( str ) * sizeof ( char ) ;
1998-01-16 15:13:05 +03:00
2009-05-26 08:58:15 +04:00
if ( ( size_t ) len < = ( sizeof ( long ) * CHAR_BIT ) ) {
2008-01-02 09:24:27 +03:00
unsigned long val = STRTOUL ( str , & end , base ) ;
2000-01-05 07:41:21 +03:00
2006-06-27 20:15:22 +04:00
if ( str < end & & * end = = ' _ ' ) goto bigparse ;
2000-01-05 07:41:21 +03:00
if ( badcheck ) {
2002-01-04 17:15:33 +03:00
if ( end = = str ) goto bad ; /* no number */
2002-01-16 05:20:25 +03:00
while ( * end & & ISSPACE ( * end ) ) end + + ;
2003-04-14 10:54:27 +04:00
if ( * end ) goto bad ; /* trailing garbage */
2000-01-05 07:41:21 +03:00
}
1998-01-16 15:13:05 +03:00
if ( POSFIXABLE ( val ) ) {
2002-08-21 19:47:54 +04:00
if ( sign ) return LONG2FIX ( val ) ;
1998-01-16 15:13:05 +03:00
else {
1999-01-20 07:59:39 +03:00
long result = - ( long ) val ;
2002-08-21 19:47:54 +04:00
return LONG2FIX ( result ) ;
1998-01-16 15:13:05 +03:00
}
}
else {
1999-01-20 07:59:39 +03:00
VALUE big = rb_uint2big ( val ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , sign ) ;
2002-08-13 13:21:18 +04:00
return bignorm ( big ) ;
1998-01-16 15:13:05 +03:00
}
}
2000-12-22 06:22:25 +03:00
bigparse :
1998-01-16 15:19:22 +03:00
len = ( len / BITSPERDIG ) + 1 ;
2000-12-22 06:22:25 +03:00
if ( badcheck & & * str = = ' _ ' ) goto bad ;
1998-01-16 15:13:05 +03:00
z = bignew ( len , sign ) ;
zds = BDIGITS ( z ) ;
for ( i = len ; i - - ; ) zds [ i ] = 0 ;
2007-07-15 14:05:37 +04:00
while ( ( c = * str + + ) ! = 0 ) {
2003-04-14 10:54:27 +04:00
if ( c = = ' _ ' ) {
2008-03-19 08:36:43 +03:00
if ( nondigit ) {
if ( badcheck ) goto bad ;
break ;
2002-02-01 13:23:22 +03:00
}
2012-11-21 09:09:19 +04:00
nondigit = ( char ) c ;
2000-12-22 06:22:25 +03:00
continue ;
2003-04-14 10:54:27 +04:00
}
2007-07-15 14:05:37 +04:00
else if ( ( c = conv_digit ( c ) ) < 0 ) {
1998-01-16 15:13:05 +03:00
break ;
}
if ( c > = base ) break ;
2003-04-14 10:54:27 +04:00
nondigit = 0 ;
1998-01-16 15:13:05 +03:00
i = 0 ;
num = c ;
for ( ; ; ) {
while ( i < blen ) {
2000-11-01 11:49:40 +03:00
num + = ( BDIGIT_DBL ) zds [ i ] * base ;
1998-01-16 15:13:05 +03:00
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
if ( num ) {
blen + + ;
continue ;
}
break ;
}
}
2000-12-25 09:29:27 +03:00
if ( badcheck ) {
str - - ;
if ( s + 1 < str & & str [ - 1 ] = = ' _ ' ) goto bad ;
2001-12-26 20:01:20 +03:00
while ( * str & & ISSPACE ( * str ) ) str + + ;
2003-04-14 10:54:27 +04:00
if ( * str ) {
bad :
2008-12-29 17:26:16 +03:00
rb_invalid_str ( s , " Integer() " ) ;
2003-04-14 10:54:27 +04:00
}
2000-12-25 09:29:27 +03:00
}
2000-01-05 07:41:21 +03:00
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2000-01-05 07:41:21 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_str_to_inum ( VALUE str , int base , int badcheck )
2000-01-05 07:41:21 +03:00
{
char * s ;
2002-08-21 19:47:54 +04:00
long len ;
2011-01-27 15:58:44 +03:00
VALUE v = 0 ;
VALUE ret ;
2000-01-05 07:41:21 +03:00
2001-05-02 08:22:21 +04:00
StringValue ( str ) ;
2012-03-23 08:19:24 +04:00
rb_must_asciicompat ( str ) ;
2003-07-20 21:17:52 +04:00
if ( badcheck ) {
s = StringValueCStr ( str ) ;
}
else {
2006-08-31 14:47:44 +04:00
s = RSTRING_PTR ( str ) ;
2003-07-20 21:17:52 +04:00
}
2002-10-17 11:27:00 +04:00
if ( s ) {
2006-08-31 14:47:44 +04:00
len = RSTRING_LEN ( str ) ;
2002-10-17 11:27:00 +04:00
if ( s [ len ] ) { /* no sentinel somehow */
2011-01-27 15:58:44 +03:00
char * p = ALLOCV ( v , len + 1 ) ;
2002-10-17 11:27:00 +04:00
MEMCPY ( p , s , char , len ) ;
p [ len ] = ' \0 ' ;
s = p ;
}
2000-01-05 07:41:21 +03:00
}
2011-01-27 15:58:44 +03:00
ret = rb_cstr_to_inum ( s , base , badcheck ) ;
if ( v )
ALLOCV_END ( v ) ;
return ret ;
2002-02-01 13:23:22 +03:00
}
2002-03-14 09:23:46 +03:00
# if HAVE_LONG_LONG
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_ull2big ( unsigned LONG_LONG n )
2002-03-14 09:23:46 +03:00
{
BDIGIT_DBL num = n ;
long i = 0 ;
BDIGIT * digits ;
VALUE big ;
big = bignew ( DIGSPERLL , 1 ) ;
digits = BDIGITS ( big ) ;
while ( i < DIGSPERLL ) {
digits [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
i = DIGSPERLL ;
while ( i - - & & ! digits [ i ] ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
2002-03-14 09:23:46 +03:00
return big ;
}
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_ll2big ( LONG_LONG n )
2002-03-14 09:23:46 +03:00
{
long neg = 0 ;
2013-04-10 07:34:38 +04:00
unsigned LONG_LONG u ;
2002-03-14 09:23:46 +03:00
VALUE big ;
if ( n < 0 ) {
2013-04-10 07:34:38 +04:00
u = 1 + ( unsigned LONG_LONG ) ( - ( n + 1 ) ) ; /* u = -n avoiding overflow */
2002-03-14 09:23:46 +03:00
neg = 1 ;
}
2013-04-10 07:34:38 +04:00
else {
u = n ;
}
big = rb_ull2big ( u ) ;
2002-03-14 09:23:46 +03:00
if ( neg ) {
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2002-03-14 09:23:46 +03:00
}
return big ;
}
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_ull2inum ( unsigned LONG_LONG n )
2002-03-14 09:23:46 +03:00
{
2002-08-21 19:47:54 +04:00
if ( POSFIXABLE ( n ) ) return LONG2FIX ( n ) ;
2002-03-14 09:23:46 +03:00
return rb_ull2big ( n ) ;
}
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_ll2inum ( LONG_LONG n )
2002-03-14 09:23:46 +03:00
{
2002-08-21 19:47:54 +04:00
if ( FIXABLE ( n ) ) return LONG2FIX ( n ) ;
2002-03-14 09:23:46 +03:00
return rb_ll2big ( n ) ;
}
# endif /* HAVE_LONG_LONG */
2007-05-09 07:49:18 +04:00
2002-02-01 13:23:22 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_cstr2inum ( const char * str , int base )
2002-02-01 13:23:22 +03:00
{
return rb_cstr_to_inum ( str , base , base = = 0 ) ;
}
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_str2inum ( VALUE str , int base )
2002-02-01 13:23:22 +03:00
{
return rb_str_to_inum ( str , base , base = = 0 ) ;
2000-01-05 07:41:21 +03:00
}
2003-04-14 10:54:27 +04:00
const char ruby_digitmap [ ] = " 0123456789abcdefghijklmnopqrstuvwxyz " ;
2007-08-02 19:00:22 +04:00
2007-08-06 22:03:11 +04:00
static VALUE bigsqr ( VALUE x ) ;
2009-08-25 12:38:28 +04:00
static void bigdivmod ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp ) ;
2007-08-06 22:03:11 +04:00
# define POW2_P(x) (((x)&((x)-1))==0)
2007-08-02 18:45:34 +04:00
static inline int
2007-08-06 22:03:11 +04:00
ones ( register unsigned long x )
2007-08-02 18:45:34 +04:00
{
2013-04-12 16:01:51 +04:00
# if GCC_VERSION_SINCE(3, 4, 0)
return __builtin_popcountl ( x ) ;
2007-08-06 22:03:11 +04:00
# else
2013-04-12 16:01:51 +04:00
# if SIZEOF_LONG == 8
# define MASK_55 0x5555555555555555UL
# define MASK_33 0x3333333333333333UL
# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
# else
# define MASK_55 0x55555555UL
# define MASK_33 0x33333333UL
# define MASK_0f 0x0f0f0f0fUL
# endif
2007-08-06 22:03:11 +04:00
x - = ( x > > 1 ) & MASK_55 ;
x = ( ( x > > 2 ) & MASK_33 ) + ( x & MASK_33 ) ;
x = ( ( x > > 4 ) + x ) & MASK_0f ;
x + = ( x > > 8 ) ;
x + = ( x > > 16 ) ;
2013-04-12 16:01:51 +04:00
# if SIZEOF_LONG == 8
2007-08-06 22:03:11 +04:00
x + = ( x > > 32 ) ;
2013-04-12 16:01:51 +04:00
# endif
2007-08-06 22:03:11 +04:00
return ( int ) ( x & 0x7f ) ;
2013-04-12 16:01:51 +04:00
# undef MASK_0f
# undef MASK_33
# undef MASK_55
# endif
2007-08-06 22:03:11 +04:00
}
static inline unsigned long
next_pow2 ( register unsigned long x )
{
x | = x > > 1 ;
x | = x > > 2 ;
x | = x > > 4 ;
x | = x > > 8 ;
x | = x > > 16 ;
2007-09-29 23:33:03 +04:00
# if SIZEOF_LONG == 8
2007-08-06 22:03:11 +04:00
x | = x > > 32 ;
# endif
return x + 1 ;
}
2007-08-02 18:45:34 +04:00
2007-08-06 22:03:11 +04:00
static inline int
floor_log2 ( register unsigned long x )
{
x | = x > > 1 ;
x | = x > > 2 ;
x | = x > > 4 ;
x | = x > > 8 ;
x | = x > > 16 ;
2007-09-29 23:33:03 +04:00
# if SIZEOF_LONG == 8
2007-08-06 22:03:11 +04:00
x | = x > > 32 ;
# endif
return ( int ) ones ( x ) - 1 ;
}
2007-08-02 18:45:34 +04:00
2007-08-06 22:03:11 +04:00
static inline int
ceil_log2 ( register unsigned long x )
{
return floor_log2 ( x ) + ! POW2_P ( x ) ;
2007-08-02 18:45:34 +04:00
}
2007-08-06 22:03:11 +04:00
# define LOG2_KARATSUBA_DIGITS 7
# define KARATSUBA_DIGITS (1L<<LOG2_KARATSUBA_DIGITS)
2007-08-02 18:45:34 +04:00
# define MAX_BIG2STR_TABLE_ENTRIES 64
2007-08-06 22:03:11 +04:00
static VALUE big2str_power_cache [ 35 ] [ MAX_BIG2STR_TABLE_ENTRIES ] ;
2007-08-02 18:45:34 +04:00
2007-08-06 22:03:11 +04:00
static void
power_cache_init ( void )
{
int i , j ;
for ( i = 0 ; i < 35 ; + + i ) {
2008-03-07 15:28:57 +03:00
for ( j = 0 ; j < MAX_BIG2STR_TABLE_ENTRIES ; + + j ) {
big2str_power_cache [ i ] [ j ] = Qnil ;
}
2007-08-06 22:03:11 +04:00
}
2007-08-02 18:45:34 +04:00
}
2007-08-06 22:03:11 +04:00
static inline VALUE
power_cache_get_power0 ( int base , int i )
1998-01-16 15:13:05 +03:00
{
2007-08-06 22:03:11 +04:00
if ( NIL_P ( big2str_power_cache [ base - 2 ] [ i ] ) ) {
2008-03-07 15:28:57 +03:00
big2str_power_cache [ base - 2 ] [ i ] =
2008-03-07 15:14:17 +03:00
i = = 0 ? rb_big_pow ( rb_int2big ( base ) , INT2FIX ( KARATSUBA_DIGITS ) )
: bigsqr ( power_cache_get_power0 ( base , i - 1 ) ) ;
* gc.c, include/ruby/ruby.h: rename rb_register_mark_object()
to rb_gc_register_mark_object().
* eval.c, vm.c: initialize vm->mark_object_ary at
Init_top_self().
* bignum.c, complex.c, encoding.c, ext/win32ole/win32ole.c,
io.c, load.c, marshal.c, rational.c, ruby.c, vm.c:
use rb_gc_register_mark_object() instead of
rb_global_variable() or rb_gc_register_address().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19365 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-15 18:59:14 +04:00
rb_gc_register_mark_object ( big2str_power_cache [ base - 2 ] [ i ] ) ;
2007-08-06 22:03:11 +04:00
}
return big2str_power_cache [ base - 2 ] [ i ] ;
}
static VALUE
power_cache_get_power ( int base , long n1 , long * m1 )
{
2009-05-26 08:58:15 +04:00
int i , m ;
long j ;
2007-08-06 22:03:11 +04:00
VALUE t ;
if ( n1 < = KARATSUBA_DIGITS )
2008-03-07 15:28:57 +03:00
rb_bug ( " n1 > KARATSUBA_DIGITS " ) ;
2007-08-06 22:03:11 +04:00
m = ceil_log2 ( n1 ) ;
if ( m1 ) * m1 = 1 < < m ;
i = m - LOG2_KARATSUBA_DIGITS ;
if ( i > = MAX_BIG2STR_TABLE_ENTRIES )
2008-03-07 15:28:57 +03:00
i = MAX_BIG2STR_TABLE_ENTRIES - 1 ;
2007-08-06 22:03:11 +04:00
t = power_cache_get_power0 ( base , i ) ;
j = KARATSUBA_DIGITS * ( 1 < < i ) ;
while ( n1 > j ) {
2008-03-07 15:28:57 +03:00
t = bigsqr ( t ) ;
j * = 2 ;
2007-08-06 22:03:11 +04:00
}
return t ;
}
/* big2str_muraken_find_n1
*
* Let a natural number x is given by :
* x = 2 ^ 0 * x_0 + 2 ^ 1 * x_1 + . . . + 2 ^ ( B * n_0 - 1 ) * x_ { B * n_0 - 1 } ,
* where B is BITSPERDIG ( i . e . BDIGITS * CHAR_BIT ) and n_0 is
2007-09-01 16:02:36 +04:00
* RBIGNUM_LEN ( x ) .
2007-08-06 22:03:11 +04:00
*
* Now , we assume n_1 = min_n \ { n | 2 ^ ( B * n_0 / 2 ) < = b_1 ^ ( n_1 ) \ } , so
* it is realized that 2 ^ ( B * n_0 ) < = { b_1 } ^ { 2 * n_1 } , where b_1 is a
* given radix number . And then , we have n_1 < = ( B * n_0 ) /
* ( 2 * log_2 ( b_1 ) ) , therefore n_1 is given by ceil ( ( B * n_0 ) /
* ( 2 * log_2 ( b_1 ) ) ) .
*/
static long
big2str_find_n1 ( VALUE x , int base )
{
static const double log_2 [ ] = {
2007-11-27 20:42:12 +03:00
1.0 , 1.58496250072116 , 2.0 ,
2.32192809488736 , 2.58496250072116 , 2.8073549220576 ,
3.0 , 3.16992500144231 , 3.32192809488736 ,
3.4594316186373 , 3.58496250072116 , 3.70043971814109 ,
3.8073549220576 , 3.90689059560852 , 4.0 ,
4.08746284125034 , 4.16992500144231 , 4.24792751344359 ,
4.32192809488736 , 4.39231742277876 , 4.4594316186373 ,
4.52356195605701 , 4.58496250072116 , 4.64385618977472 ,
4.70043971814109 , 4.75488750216347 , 4.8073549220576 ,
4.85798099512757 , 4.90689059560852 , 4.95419631038688 ,
5.0 , 5.04439411935845 , 5.08746284125034 ,
5.12928301694497 , 5.16992500144231
2007-08-06 22:03:11 +04:00
} ;
2007-08-08 06:48:39 +04:00
long bits ;
2007-08-06 22:03:11 +04:00
2007-12-18 18:10:37 +03:00
if ( base < 2 | | 36 < base )
2008-03-07 15:28:57 +03:00
rb_bug ( " invalid radix %d " , base ) ;
1998-01-16 15:13:05 +03:00
if ( FIXNUM_P ( x ) ) {
2008-03-07 15:28:57 +03:00
bits = ( SIZEOF_LONG * CHAR_BIT - 1 ) / 2 + 1 ;
1998-01-16 15:13:05 +03:00
}
2007-08-06 22:03:11 +04:00
else if ( BIGZEROP ( x ) ) {
2008-03-07 15:28:57 +03:00
return 0 ;
2002-08-19 09:56:09 +04:00
}
2008-02-29 20:35:11 +03:00
else if ( RBIGNUM_LEN ( x ) > = LONG_MAX / BITSPERDIG ) {
rb_raise ( rb_eRangeError , " bignum too big to convert into `string' " ) ;
}
2007-08-06 22:03:11 +04:00
else {
2008-03-07 15:28:57 +03:00
bits = BITSPERDIG * RBIGNUM_LEN ( x ) ;
1998-01-16 15:13:05 +03:00
}
2003-07-10 02:28:42 +04:00
2012-07-18 08:46:04 +04:00
/* @shyouhei note: vvvvvvvvvvvvv this cast is suspicious. But I believe it is OK, because if that cast loses data, this x value is too big, and should have raised RangeError. */
return ( long ) ceil ( ( ( double ) bits ) / log_2 [ base - 2 ] ) ;
2007-08-06 22:03:11 +04:00
}
static long
2013-06-01 02:32:55 +04:00
big2str_orig ( VALUE x , int base , char * ptr , long len , BDIGIT hbase , int hbase_numdigits , int trim )
2007-08-06 22:03:11 +04:00
{
2007-09-01 16:02:36 +04:00
long i = RBIGNUM_LEN ( x ) , j = len ;
2007-08-06 22:03:11 +04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 15:13:05 +03:00
2007-08-06 22:03:11 +04:00
while ( i & & j > 0 ) {
2008-03-07 15:28:57 +03:00
long k = i ;
BDIGIT_DBL num = 0 ;
while ( k - - ) { /* x / hbase */
num = BIGUP ( num ) + ds [ k ] ;
ds [ k ] = ( BDIGIT ) ( num / hbase ) ;
num % = hbase ;
}
if ( trim & & ds [ i - 1 ] = = 0 ) i - - ;
2013-05-31 18:24:31 +04:00
k = hbase_numdigits ;
2008-03-07 15:28:57 +03:00
while ( k - - ) {
ptr [ - - j ] = ruby_digitmap [ num % base ] ;
num / = base ;
if ( j < = 0 ) break ;
if ( trim & & i = = 0 & & num = = 0 ) break ;
}
2007-08-02 18:45:34 +04:00
}
2007-08-06 22:03:11 +04:00
if ( trim ) {
2008-03-07 15:28:57 +03:00
while ( j < len & & ptr [ j ] = = ' 0 ' ) j + + ;
MEMMOVE ( ptr , ptr + j , char , len - j ) ;
len - = j ;
1998-01-16 15:13:05 +03:00
}
2007-08-06 22:03:11 +04:00
return len ;
}
static long
big2str_karatsuba ( VALUE x , int base , char * ptr ,
2013-06-01 02:32:55 +04:00
long n1 , long len , BDIGIT hbase , int hbase_numdigits , int trim )
2007-08-06 22:03:11 +04:00
{
long lh , ll , m1 ;
VALUE b , q , r ;
if ( BIGZEROP ( x ) ) {
2008-03-07 15:28:57 +03:00
if ( trim ) return 0 ;
else {
memset ( ptr , ' 0 ' , len ) ;
return len ;
}
2006-10-30 06:39:44 +03:00
}
1998-01-16 15:13:05 +03:00
2007-08-06 22:03:11 +04:00
if ( n1 < = KARATSUBA_DIGITS ) {
2013-05-31 18:24:31 +04:00
return big2str_orig ( x , base , ptr , len , hbase , hbase_numdigits , trim ) ;
2007-08-06 22:03:11 +04:00
}
b = power_cache_get_power ( base , n1 , & m1 ) ;
bigdivmod ( x , b , & q , & r ) ;
2013-04-03 11:35:35 +04:00
rb_obj_hide ( q ) ;
rb_obj_hide ( r ) ;
2008-09-11 06:40:52 +04:00
lh = big2str_karatsuba ( q , base , ptr , ( len - m1 ) / 2 ,
2013-05-31 18:24:31 +04:00
len - m1 , hbase , hbase_numdigits , trim ) ;
2008-09-18 15:21:34 +04:00
rb_big_resize ( q , 0 ) ;
2007-08-06 22:03:11 +04:00
ll = big2str_karatsuba ( r , base , ptr + lh , m1 / 2 ,
2013-05-31 18:24:31 +04:00
m1 , hbase , hbase_numdigits , ! lh & & trim ) ;
2008-09-18 15:21:34 +04:00
rb_big_resize ( r , 0 ) ;
2007-08-06 22:03:11 +04:00
return lh + ll ;
1998-01-16 15:13:05 +03:00
}
2013-05-31 18:57:03 +04:00
static void
2013-06-01 02:32:55 +04:00
calc_hbase ( int base , BDIGIT * hbase_p , int * hbase_numdigits_p )
2013-05-31 18:57:03 +04:00
{
2013-06-01 02:32:55 +04:00
BDIGIT hbase ;
2013-05-31 18:57:03 +04:00
int hbase_numdigits ;
2013-05-31 19:24:47 +04:00
hbase = base ;
hbase_numdigits = 1 ;
while ( hbase < = ( ~ ( BDIGIT ) 0 ) / base ) {
hbase * = base ;
hbase_numdigits + + ;
}
2013-05-31 18:57:03 +04:00
* hbase_p = hbase ;
* hbase_numdigits_p = hbase_numdigits ;
}
2013-06-09 04:36:58 +04:00
static VALUE
big2str_base_powerof2 ( VALUE x , size_t len , int base , int trim )
{
int word_numbits = ffs ( base ) - 1 ;
size_t numwords ;
VALUE result ;
char * ptr ;
2013-06-09 11:53:20 +04:00
numwords = trim ? rb_absint_numwords ( x , word_numbits , NULL ) : len ;
2013-06-09 04:36:58 +04:00
if ( RBIGNUM_NEGATIVE_P ( x ) | | ! trim ) {
if ( LONG_MAX - 1 < numwords )
rb_raise ( rb_eArgError , " too big number " ) ;
result = rb_usascii_str_new ( 0 , 1 + numwords ) ;
ptr = RSTRING_PTR ( result ) ;
* ptr + + = RBIGNUM_POSITIVE_P ( x ) ? ' + ' : ' - ' ;
}
else {
if ( LONG_MAX < numwords )
rb_raise ( rb_eArgError , " too big number " ) ;
result = rb_usascii_str_new ( 0 , numwords ) ;
ptr = RSTRING_PTR ( result ) ;
}
2013-06-10 14:37:39 +04:00
rb_integer_pack ( x , ptr , numwords , 1 , CHAR_BIT - word_numbits ,
2013-06-09 04:36:58 +04:00
INTEGER_PACK_BIG_ENDIAN ) ;
while ( 0 < numwords ) {
* ptr = ruby_digitmap [ * ( unsigned char * ) ptr ] ;
ptr + + ;
numwords - - ;
}
return result ;
}
2007-08-06 22:03:11 +04:00
VALUE
rb_big2str0 ( VALUE x , int base , int trim )
2007-08-02 18:45:34 +04:00
{
2007-08-06 22:03:11 +04:00
int off ;
VALUE ss , xx ;
2013-06-01 02:32:55 +04:00
long n1 , n2 , len ;
BDIGIT hbase ;
2013-05-31 18:24:31 +04:00
int hbase_numdigits ;
2007-08-06 22:03:11 +04:00
char * ptr ;
2007-08-02 18:45:34 +04:00
2007-08-06 22:03:11 +04:00
if ( FIXNUM_P ( x ) ) {
2008-03-07 15:28:57 +03:00
return rb_fix2str ( x , base ) ;
2007-08-02 18:45:34 +04:00
}
2007-08-06 22:03:11 +04:00
if ( BIGZEROP ( x ) ) {
2008-03-07 15:28:57 +03:00
return rb_usascii_str_new2 ( " 0 " ) ;
2007-08-06 22:03:11 +04:00
}
2007-12-18 18:10:37 +03:00
if ( base < 2 | | 36 < base )
2008-03-07 15:28:57 +03:00
rb_raise ( rb_eArgError , " invalid radix %d " , base ) ;
2007-08-06 22:03:11 +04:00
2007-11-27 20:42:12 +03:00
n2 = big2str_find_n1 ( x , base ) ;
2013-06-09 04:36:58 +04:00
if ( base & ( base - 1 ) = = 0 ) {
/* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
return big2str_base_powerof2 ( x , ( size_t ) n2 , base , trim ) ;
}
2007-11-27 20:42:12 +03:00
n1 = ( n2 + 1 ) / 2 ;
2008-01-28 18:12:43 +03:00
ss = rb_usascii_str_new ( 0 , n2 + 1 ) ; /* plus one for sign */
2007-08-06 22:03:11 +04:00
ptr = RSTRING_PTR ( ss ) ;
2007-09-01 16:02:36 +04:00
ptr [ 0 ] = RBIGNUM_SIGN ( x ) ? ' + ' : ' - ' ;
2007-08-06 22:03:11 +04:00
2013-05-31 18:57:03 +04:00
calc_hbase ( base , & hbase , & hbase_numdigits ) ;
2007-09-01 16:02:36 +04:00
off = ! ( trim & & RBIGNUM_SIGN ( x ) ) ; /* erase plus sign if trim */
2007-08-06 22:03:11 +04:00
xx = rb_big_clone ( x ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( xx , 1 ) ;
2007-08-06 22:03:11 +04:00
if ( n1 < = KARATSUBA_DIGITS ) {
2013-05-31 18:24:31 +04:00
len = off + big2str_orig ( xx , base , ptr + off , n2 , hbase , hbase_numdigits , trim ) ;
2007-08-06 22:03:11 +04:00
}
else {
2008-03-07 15:28:57 +03:00
len = off + big2str_karatsuba ( xx , base , ptr + off , n1 ,
2013-05-31 18:24:31 +04:00
n2 , hbase , hbase_numdigits , trim ) ;
2007-08-06 22:03:11 +04:00
}
2008-09-18 15:21:34 +04:00
rb_big_resize ( xx , 0 ) ;
2007-08-06 22:03:11 +04:00
ptr [ len ] = ' \0 ' ;
rb_str_resize ( ss , len ) ;
return ss ;
2007-08-02 18:45:34 +04:00
}
2006-10-30 06:39:44 +03:00
VALUE
rb_big2str ( VALUE x , int base )
{
2007-08-06 22:03:11 +04:00
return rb_big2str0 ( x , base , 1 ) ;
2006-10-30 06:39:44 +03:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . to_s ( base = 10 ) - > string
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* Returns a string containing the representation of < i > big < / i > radix
* < i > base < / i > ( 2 through 36 ) .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* 12345654321. to_s # = > " 12345654321 "
* 12345654321. to_s ( 2 ) # = > " 1011011111110110111011110000110001 "
* 12345654321. to_s ( 8 ) # = > " 133766736061 "
* 12345654321. to_s ( 16 ) # = > " 2dfdbbc31 "
* 78546939656932. to_s ( 36 ) # = > " rubyrules "
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_to_s ( int argc , VALUE * argv , VALUE x )
1998-01-16 15:13:05 +03:00
{
2001-11-19 08:03:03 +03:00
int base ;
if ( argc = = 0 ) base = 10 ;
2008-03-05 08:22:17 +03:00
else {
VALUE b ;
rb_scan_args ( argc , argv , " 01 " , & b ) ;
base = NUM2INT ( b ) ;
}
2001-11-19 08:03:03 +03:00
return rb_big2str ( x , base ) ;
1998-01-16 15:13:05 +03:00
}
2006-07-11 10:47:09 +04:00
static VALUE
2005-10-21 10:28:41 +04:00
big2ulong ( VALUE x , const char * type , int check )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
long len = RBIGNUM_LEN ( x ) ;
2000-11-01 11:49:40 +03:00
BDIGIT_DBL num ;
2000-10-31 11:37:47 +03:00
BDIGIT * ds ;
1998-01-16 15:13:05 +03:00
2007-12-24 21:12:24 +03:00
if ( len > DIGSPERLONG ) {
2004-01-22 21:06:38 +03:00
if ( check )
rb_raise ( rb_eRangeError , " bignum too big to convert into `%s' " , type ) ;
2007-12-24 21:12:24 +03:00
len = DIGSPERLONG ;
2004-01-22 21:06:38 +03:00
}
1998-01-16 15:13:05 +03:00
ds = BDIGITS ( x ) ;
num = 0 ;
while ( len - - ) {
num = BIGUP ( num ) ;
num + = ds [ len ] ;
}
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
return ( VALUE ) num ;
1998-01-16 15:13:05 +03:00
}
2006-07-11 10:47:09 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big2ulong_pack ( VALUE x )
2004-01-22 21:06:38 +03:00
{
2009-07-18 12:05:32 +04:00
VALUE num = big2ulong ( x , " unsigned long " , FALSE ) ;
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
2009-03-10 08:43:14 +03:00
return ( VALUE ) ( - ( SIGNED_VALUE ) num ) ;
2004-01-22 21:06:38 +03:00
}
return num ;
}
2006-07-11 10:47:09 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big2ulong ( VALUE x )
2000-01-05 07:41:21 +03:00
{
2009-07-18 12:05:32 +04:00
VALUE num = big2ulong ( x , " unsigned long " , TRUE ) ;
2000-01-05 07:41:21 +03:00
2013-04-09 15:39:53 +04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
return num ;
}
else {
if ( num < = LONG_MAX )
return - ( long ) num ;
if ( num = = 1 + ( unsigned long ) ( - ( LONG_MIN + 1 ) ) )
return LONG_MIN ;
2003-10-09 21:45:53 +04:00
}
2013-04-10 02:47:51 +04:00
rb_raise ( rb_eRangeError , " bignum out of range of unsigned long " ) ;
2000-01-05 07:41:21 +03:00
}
2006-07-11 10:47:09 +04:00
SIGNED_VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big2long ( VALUE x )
1999-01-20 07:59:39 +03:00
{
2009-07-18 12:05:32 +04:00
VALUE num = big2ulong ( x , " long " , TRUE ) ;
1999-01-20 07:59:39 +03:00
2013-04-09 15:39:53 +04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
2013-04-10 02:47:51 +04:00
if ( num < = LONG_MAX )
return num ;
2013-04-09 15:39:53 +04:00
}
else {
if ( num < = LONG_MAX )
return - ( long ) num ;
if ( num = = 1 + ( unsigned long ) ( - ( LONG_MIN + 1 ) ) )
return LONG_MIN ;
1999-01-20 07:59:39 +03:00
}
2013-04-10 02:47:51 +04:00
rb_raise ( rb_eRangeError , " bignum too big to convert into `long' " ) ;
1999-01-20 07:59:39 +03:00
}
2002-03-14 09:23:46 +03:00
# if HAVE_LONG_LONG
* bignum.c, intern.h (rb_ull2big, rb_ll2big, rb_ull2inum, rb_ll2inum,
big2ull, rb_big2ull, rb_big2ll): use LONG_LONG macro instead of
long long.
* numeric.c, intern.h, ruby.h (rb_num2ll, rb_num2ull): ditto.
* ruby.h: use _I64_MAX and _I64_MIN if they are defined (for VC++).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-03-15 11:51:31 +03:00
static unsigned LONG_LONG
2005-10-21 10:28:41 +04:00
big2ull ( VALUE x , const char * type )
2002-03-14 09:23:46 +03:00
{
2007-09-01 16:02:36 +04:00
long len = RBIGNUM_LEN ( x ) ;
2002-03-14 09:23:46 +03:00
BDIGIT_DBL num ;
BDIGIT * ds ;
2002-04-10 12:45:26 +04:00
if ( len > SIZEOF_LONG_LONG / SIZEOF_BDIGITS )
2002-03-14 09:23:46 +03:00
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 ;
}
* bignum.c, intern.h (rb_ull2big, rb_ll2big, rb_ull2inum, rb_ll2inum,
big2ull, rb_big2ull, rb_big2ll): use LONG_LONG macro instead of
long long.
* numeric.c, intern.h, ruby.h (rb_num2ll, rb_num2ull): ditto.
* ruby.h: use _I64_MAX and _I64_MIN if they are defined (for VC++).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-03-15 11:51:31 +03:00
unsigned LONG_LONG
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big2ull ( VALUE x )
2002-03-14 09:23:46 +03:00
{
* bignum.c, intern.h (rb_ull2big, rb_ll2big, rb_ull2inum, rb_ll2inum,
big2ull, rb_big2ull, rb_big2ll): use LONG_LONG macro instead of
long long.
* numeric.c, intern.h, ruby.h (rb_num2ll, rb_num2ull): ditto.
* ruby.h: use _I64_MAX and _I64_MIN if they are defined (for VC++).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-03-15 11:51:31 +03:00
unsigned LONG_LONG num = big2ull ( x , " unsigned long long " ) ;
2002-03-14 09:23:46 +03:00
2013-04-09 15:39:53 +04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
return num ;
}
else {
if ( num < = LLONG_MAX )
return - ( LONG_LONG ) num ;
if ( num = = 1 + ( unsigned LONG_LONG ) ( - ( LLONG_MIN + 1 ) ) )
return LLONG_MIN ;
2011-11-14 07:51:56 +04:00
}
2013-04-10 02:47:51 +04:00
rb_raise ( rb_eRangeError , " bignum out of range of unsigned long long " ) ;
2002-03-14 09:23:46 +03:00
}
* bignum.c, intern.h (rb_ull2big, rb_ll2big, rb_ull2inum, rb_ll2inum,
big2ull, rb_big2ull, rb_big2ll): use LONG_LONG macro instead of
long long.
* numeric.c, intern.h, ruby.h (rb_num2ll, rb_num2ull): ditto.
* ruby.h: use _I64_MAX and _I64_MIN if they are defined (for VC++).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-03-15 11:51:31 +03:00
LONG_LONG
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big2ll ( VALUE x )
2002-03-14 09:23:46 +03:00
{
* bignum.c, intern.h (rb_ull2big, rb_ll2big, rb_ull2inum, rb_ll2inum,
big2ull, rb_big2ull, rb_big2ll): use LONG_LONG macro instead of
long long.
* numeric.c, intern.h, ruby.h (rb_num2ll, rb_num2ull): ditto.
* ruby.h: use _I64_MAX and _I64_MIN if they are defined (for VC++).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2207 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-03-15 11:51:31 +03:00
unsigned LONG_LONG num = big2ull ( x , " long long " ) ;
2002-03-14 09:23:46 +03:00
2013-04-09 15:39:53 +04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
2013-04-10 02:47:51 +04:00
if ( num < = LLONG_MAX )
return num ;
2013-04-09 15:39:53 +04:00
}
else {
if ( num < = LLONG_MAX )
return - ( LONG_LONG ) num ;
if ( num = = 1 + ( unsigned LONG_LONG ) ( - ( LLONG_MIN + 1 ) ) )
return LLONG_MIN ;
2002-03-14 09:23:46 +03:00
}
2013-04-10 02:47:51 +04:00
rb_raise ( rb_eRangeError , " bignum too big to convert into `long long' " ) ;
2002-03-14 09:23:46 +03:00
}
# endif /* HAVE_LONG_LONG */
2000-06-22 12:29:58 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
dbl2big ( double d )
1998-01-16 15:13:05 +03:00
{
2000-10-31 11:37:47 +03:00
long i = 0 ;
2000-11-02 12:04:54 +03:00
BDIGIT c ;
2000-10-31 11:37:47 +03:00
BDIGIT * digits ;
1998-01-16 15:13:05 +03:00
VALUE z ;
double u = ( d < 0 ) ? - d : d ;
1999-08-13 09:45:20 +04:00
if ( isinf ( d ) ) {
rb_raise ( rb_eFloatDomainError , d < 0 ? " -Infinity " : " Infinity " ) ;
}
if ( isnan ( d ) ) {
rb_raise ( rb_eFloatDomainError , " NaN " ) ;
}
while ( ! POSFIXABLE ( u ) | | 0 ! = ( long ) u ) {
1998-01-16 15:13:05 +03:00
u / = ( double ) ( BIGRAD ) ;
i + + ;
}
z = bignew ( i , d > = 0 ) ;
digits = BDIGITS ( z ) ;
while ( i - - ) {
u * = BIGRAD ;
2000-11-02 12:04:54 +03:00
c = ( BDIGIT ) u ;
1998-01-16 15:13:05 +03:00
u - = c ;
2000-11-02 12:04:54 +03:00
digits [ i ] = c ;
1998-01-16 15:13:05 +03:00
}
2000-06-22 12:29:58 +04:00
return z ;
}
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_dbl2big ( double d )
2000-06-22 12:29:58 +04:00
{
return bignorm ( dbl2big ( d ) ) ;
1998-01-16 15:13:05 +03:00
}
2008-04-01 11:40:23 +04:00
static int
nlz ( BDIGIT x )
{
BDIGIT y ;
int n = BITSPERDIG ;
# if BITSPERDIG > 64
y = x > > 64 ; if ( y ) { n - = 64 ; x = y ; }
# endif
# if BITSPERDIG > 32
y = x > > 32 ; if ( y ) { n - = 32 ; x = y ; }
# endif
# if BITSPERDIG > 16
y = x > > 16 ; if ( y ) { n - = 16 ; x = y ; }
# endif
y = x > > 8 ; if ( y ) { n - = 8 ; x = y ; }
y = x > > 4 ; if ( y ) { n - = 4 ; x = y ; }
y = x > > 2 ; if ( y ) { n - = 2 ; x = y ; }
y = x > > 1 ; if ( y ) { return n - 2 ; }
return n - x ;
}
2007-05-02 12:12:31 +04:00
static double
big2dbl ( VALUE x )
1998-01-16 15:13:05 +03:00
{
double d = 0.0 ;
2009-08-25 12:38:28 +04:00
long i = ( bigtrunc ( x ) , RBIGNUM_LEN ( x ) ) , lo = 0 , bits ;
2008-04-01 11:40:23 +04:00
BDIGIT * ds = BDIGITS ( x ) , dl ;
1998-01-16 15:13:05 +03:00
2008-04-01 11:40:23 +04:00
if ( i ) {
bits = i * BITSPERDIG - nlz ( ds [ i - 1 ] ) ;
if ( bits > DBL_MANT_DIG + DBL_MAX_EXP ) {
d = HUGE_VAL ;
}
else {
if ( bits > DBL_MANT_DIG + 1 )
lo = ( bits - = DBL_MANT_DIG + 1 ) / BITSPERDIG ;
else
bits = 0 ;
while ( - - i > lo ) {
d = ds [ i ] + BIGRAD * d ;
}
dl = ds [ i ] ;
if ( bits & & ( dl & ( 1UL < < ( bits % = BITSPERDIG ) ) ) ) {
2009-05-26 08:58:15 +04:00
int carry = dl & ~ ( ~ ( BDIGIT ) 0 < < bits ) ;
2008-04-01 11:40:23 +04:00
if ( ! carry ) {
while ( i - - > 0 ) {
if ( ( carry = ds [ i ] ) ! = 0 ) break ;
}
}
if ( carry ) {
2009-05-26 08:58:15 +04:00
dl & = ( BDIGIT ) ~ 0 < < bits ;
dl + = ( BDIGIT ) 1 < < bits ;
2008-04-01 11:40:23 +04:00
if ( ! dl ) d + = 1 ;
}
}
d = dl + BIGRAD * d ;
2009-05-26 08:58:15 +04:00
if ( lo ) {
if ( lo > INT_MAX / BITSPERDIG )
d = HUGE_VAL ;
else if ( lo < INT_MIN / BITSPERDIG )
d = 0.0 ;
else
d = ldexp ( d , ( int ) ( lo * BITSPERDIG ) ) ;
}
2008-04-01 11:40:23 +04:00
}
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) d = - d ;
2007-05-02 12:12:31 +04:00
return d ;
}
double
rb_big2dbl ( VALUE x )
{
double d = big2dbl ( x ) ;
2003-07-10 02:28:42 +04:00
if ( isinf ( d ) ) {
2008-05-07 08:14:57 +04:00
rb_warning ( " Bignum out of Float range " ) ;
2009-06-16 02:58:46 +04:00
if ( d < 0.0 )
d = - HUGE_VAL ;
2009-06-15 17:39:18 +04:00
else
2009-06-16 02:58:46 +04:00
d = HUGE_VAL ;
2003-07-10 02:28:42 +04:00
}
1998-01-16 15:13:05 +03:00
return d ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
* big . to_f - > float
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Converts < i > big < / i > to a < code > Float < / code > . If < i > big < / i > doesn ' t
* fit in a < code > Float < / code > , the result is infinity .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
*/
1999-01-20 07:59:39 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_to_f ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2008-09-05 22:24:21 +04:00
return DBL2NUM ( rb_big2dbl ( x ) ) ;
1998-01-16 15:13:05 +03:00
}
2012-07-16 10:02:21 +04:00
VALUE
2012-07-16 13:41:25 +04:00
rb_integer_float_cmp ( VALUE x , VALUE y )
2012-07-16 10:02:21 +04:00
{
2012-07-16 14:02:59 +04:00
double yd = RFLOAT_VALUE ( y ) ;
2012-07-16 13:08:58 +04:00
double yi , yf ;
VALUE rel ;
2012-07-16 10:02:21 +04:00
2012-07-16 14:02:59 +04:00
if ( isnan ( yd ) )
2012-07-16 12:44:32 +04:00
return Qnil ;
2012-07-16 14:02:59 +04:00
if ( isinf ( yd ) ) {
if ( yd > 0.0 ) return INT2FIX ( - 1 ) ;
2012-07-16 10:02:21 +04:00
else return INT2FIX ( 1 ) ;
}
2012-07-16 14:02:59 +04:00
yf = modf ( yd , & yi ) ;
2012-07-16 12:44:32 +04:00
if ( FIXNUM_P ( x ) ) {
2012-07-16 13:08:58 +04:00
# if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
2012-07-16 12:44:32 +04:00
double xd = ( double ) FIX2LONG ( x ) ;
2012-07-16 14:02:59 +04:00
if ( xd < yd )
2012-07-16 12:44:32 +04:00
return INT2FIX ( - 1 ) ;
2012-07-16 14:02:59 +04:00
if ( xd > yd )
2012-07-16 12:44:32 +04:00
return INT2FIX ( 1 ) ;
return INT2FIX ( 0 ) ;
2012-07-16 13:08:58 +04:00
# else
long xl , yl ;
2012-07-16 18:30:24 +04:00
if ( yi < FIXNUM_MIN )
2012-07-16 13:08:58 +04:00
return INT2FIX ( 1 ) ;
2012-07-16 18:30:24 +04:00
if ( FIXNUM_MAX + 1 < = yi )
2012-07-16 13:08:58 +04:00
return INT2FIX ( - 1 ) ;
xl = FIX2LONG ( x ) ;
yl = ( long ) yi ;
if ( xl < yl )
return INT2FIX ( - 1 ) ;
if ( xl > yl )
return INT2FIX ( 1 ) ;
if ( yf < 0.0 )
return INT2FIX ( 1 ) ;
if ( 0.0 < yf )
return INT2FIX ( - 1 ) ;
return INT2FIX ( 0 ) ;
# endif
2012-07-16 12:44:32 +04:00
}
2012-07-16 13:08:58 +04:00
y = rb_dbl2big ( yi ) ;
rel = rb_big_cmp ( x , y ) ;
if ( yf = = 0.0 | | rel ! = INT2FIX ( 0 ) )
return rel ;
if ( yf < 0.0 )
return INT2FIX ( 1 ) ;
return INT2FIX ( - 1 ) ;
2012-07-16 10:02:21 +04:00
}
2012-07-16 14:39:42 +04:00
VALUE
rb_integer_float_eq ( VALUE x , VALUE y )
{
double yd = RFLOAT_VALUE ( y ) ;
double yi , yf ;
if ( isnan ( yd ) | | isinf ( yd ) )
return Qfalse ;
yf = modf ( yd , & yi ) ;
if ( yf ! = 0 )
return Qfalse ;
if ( FIXNUM_P ( x ) ) {
# if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
double xd = ( double ) FIX2LONG ( x ) ;
if ( xd ! = yd )
return Qfalse ;
return Qtrue ;
# else
long xl , yl ;
if ( yi < LONG_MIN | | LONG_MAX < yi )
return Qfalse ;
xl = FIX2LONG ( x ) ;
yl = ( long ) yi ;
if ( xl ! = yl )
return Qfalse ;
return Qtrue ;
# endif
}
y = rb_dbl2big ( yi ) ;
return rb_big_eq ( x , y ) ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big < = > numeric - > - 1 , 0 , + 1 or nil
2007-05-09 07:49:18 +04:00
*
2013-02-23 07:35:38 +04:00
* Comparison - - - Returns - 1 , 0 , or + 1 depending on whether + big + is
* less than , equal to , or greater than + numeric + . This is the
* basis for the tests in Comparable .
*
* + nil + is returned if the two values are incomparable .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
*/
2005-08-12 12:13:28 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_cmp ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
long xlen = RBIGNUM_LEN ( x ) ;
2009-08-09 09:55:00 +04:00
BDIGIT * xds , * yds ;
1998-01-16 15:13:05 +03:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-20 07:59:39 +03:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_BIGNUM :
break ;
2000-06-05 12:46:59 +04:00
case T_FLOAT :
2012-07-16 13:41:25 +04:00
return rb_integer_float_cmp ( x , y ) ;
2000-06-05 12:46:59 +04:00
1998-01-16 15:13:05 +03:00
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_cmp ( x , y , rb_intern ( " <=> " ) ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) > RBIGNUM_SIGN ( y ) ) return INT2FIX ( 1 ) ;
if ( RBIGNUM_SIGN ( x ) < RBIGNUM_SIGN ( y ) ) return INT2FIX ( - 1 ) ;
if ( xlen < RBIGNUM_LEN ( y ) )
return ( RBIGNUM_SIGN ( x ) ) ? INT2FIX ( - 1 ) : INT2FIX ( 1 ) ;
if ( xlen > RBIGNUM_LEN ( y ) )
return ( RBIGNUM_SIGN ( x ) ) ? INT2FIX ( 1 ) : INT2FIX ( - 1 ) ;
1998-01-16 15:13:05 +03:00
2009-08-09 09:55:00 +04:00
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
2012-12-29 16:22:04 +04:00
while ( xlen - - & & ( xds [ xlen ] = = yds [ xlen ] ) ) ;
1998-01-16 15:13:05 +03:00
if ( - 1 = = xlen ) return INT2FIX ( 0 ) ;
2009-08-09 09:55:00 +04:00
return ( xds [ xlen ] > yds [ xlen ] ) ?
2007-09-01 16:02:36 +04:00
( RBIGNUM_SIGN ( x ) ? INT2FIX ( 1 ) : INT2FIX ( - 1 ) ) :
( RBIGNUM_SIGN ( x ) ? INT2FIX ( - 1 ) : INT2FIX ( 1 ) ) ;
1998-01-16 15:13:05 +03:00
}
2012-07-16 09:15:36 +04:00
enum big_op_t {
big_op_gt ,
big_op_ge ,
big_op_lt ,
big_op_le
} ;
2010-02-04 18:36:29 +03:00
static VALUE
2012-07-16 09:15:36 +04:00
big_op ( VALUE x , VALUE y , enum big_op_t op )
2010-02-04 18:36:29 +03:00
{
VALUE rel ;
int n ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
case T_BIGNUM :
rel = rb_big_cmp ( x , y ) ;
break ;
case T_FLOAT :
2012-07-16 13:41:25 +04:00
rel = rb_integer_float_cmp ( x , y ) ;
2012-07-16 10:02:21 +04:00
break ;
2010-02-04 18:36:29 +03:00
default :
{
ID id = 0 ;
switch ( op ) {
2012-07-16 09:15:36 +04:00
case big_op_gt : id = ' > ' ; break ;
case big_op_ge : id = rb_intern ( " >= " ) ; break ;
case big_op_lt : id = ' < ' ; break ;
case big_op_le : id = rb_intern ( " <= " ) ; break ;
2010-02-04 18:36:29 +03:00
}
return rb_num_coerce_relop ( x , y , id ) ;
}
}
if ( NIL_P ( rel ) ) return Qfalse ;
n = FIX2INT ( rel ) ;
switch ( op ) {
2012-07-16 09:15:36 +04:00
case big_op_gt : return n > 0 ? Qtrue : Qfalse ;
case big_op_ge : return n > = 0 ? Qtrue : Qfalse ;
case big_op_lt : return n < 0 ? Qtrue : Qfalse ;
case big_op_le : return n < = 0 ? Qtrue : Qfalse ;
2010-02-04 18:36:29 +03:00
}
return Qundef ;
}
/*
* call - seq :
* big > real - > true or false
*
* Returns < code > true < / code > if the value of < code > big < / code > is
* greater than that of < code > real < / code > .
*/
static VALUE
big_gt ( VALUE x , VALUE y )
{
2012-07-16 09:15:36 +04:00
return big_op ( x , y , big_op_gt ) ;
2010-02-04 18:36:29 +03:00
}
/*
* call - seq :
* big > = real - > true or false
*
* Returns < code > true < / code > if the value of < code > big < / code > is
* greater than or equal to that of < code > real < / code > .
*/
static VALUE
big_ge ( VALUE x , VALUE y )
{
2012-07-16 09:15:36 +04:00
return big_op ( x , y , big_op_ge ) ;
2010-02-04 18:36:29 +03:00
}
/*
* call - seq :
* big < real - > true or false
*
* Returns < code > true < / code > if the value of < code > big < / code > is
* less than that of < code > real < / code > .
*/
static VALUE
big_lt ( VALUE x , VALUE y )
{
2012-07-16 09:15:36 +04:00
return big_op ( x , y , big_op_lt ) ;
2010-02-04 18:36:29 +03:00
}
/*
* call - seq :
* big < = real - > true or false
*
* Returns < code > true < / code > if the value of < code > big < / code > is
* less than or equal to that of < code > real < / code > .
*/
static VALUE
big_le ( VALUE x , VALUE y )
{
2012-07-16 09:15:36 +04:00
return big_op ( x , y , big_op_le ) ;
2010-02-04 18:36:29 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big = = obj - > true or false
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Returns < code > true < / code > only if < i > obj < / i > has the same value
* as < i > big < / i > . Contrast this with < code > Bignum # eql ? < / code > , which
* requires < i > obj < / i > to be a < code > Bignum < / code > .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* 68719476736 = = 68719476736.0 # = > true
*/
2005-08-12 12:13:28 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_eq ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
2000-06-05 12:46:59 +04:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2013-04-03 11:34:31 +04:00
if ( bignorm ( x ) = = y ) return Qtrue ;
2000-06-05 12:46:59 +04:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
break ;
case T_BIGNUM :
break ;
case T_FLOAT :
2012-07-16 14:39:42 +04:00
return rb_integer_float_eq ( x , y ) ;
2000-06-05 12:46:59 +04:00
default :
2002-04-18 12:46:18 +04:00
return rb_equal ( y , x ) ;
2000-06-05 12:46:59 +04:00
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) ! = RBIGNUM_SIGN ( y ) ) return Qfalse ;
if ( RBIGNUM_LEN ( x ) ! = RBIGNUM_LEN ( y ) ) return Qfalse ;
if ( MEMCMP ( BDIGITS ( x ) , BDIGITS ( y ) , BDIGIT , RBIGNUM_LEN ( y ) ) ! = 0 ) return Qfalse ;
2000-06-05 12:46:59 +04:00
return Qtrue ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . eql ? ( obj ) - > true or false
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Returns < code > true < / code > only if < i > obj < / i > is a
* < code > Bignum < / code > with the same value as < i > big < / i > . Contrast this
* with < code > Bignum # = = < / code > , which performs type conversions .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* 68719476736. eql ? ( 68719476736.0 ) # = > false
*/
2012-12-25 14:14:12 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_eql ( VALUE x , VALUE y )
2001-11-08 09:43:14 +03:00
{
2011-09-29 15:07:45 +04:00
if ( ! RB_TYPE_P ( y , T_BIGNUM ) ) return Qfalse ;
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) ! = RBIGNUM_SIGN ( y ) ) return Qfalse ;
if ( RBIGNUM_LEN ( x ) ! = RBIGNUM_LEN ( y ) ) return Qfalse ;
if ( MEMCMP ( BDIGITS ( x ) , BDIGITS ( y ) , BDIGIT , RBIGNUM_LEN ( y ) ) ! = 0 ) return Qfalse ;
2001-11-08 09:43:14 +03:00
return Qtrue ;
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* - big - > integer
2003-12-19 03:01:19 +03:00
*
2009-10-12 21:49:15 +04:00
* Unary minus ( returns an integer whose value is 0 - big )
2003-12-19 03:01:19 +03:00
*/
2011-05-29 10:09:08 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_uminus ( VALUE x )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
VALUE z = rb_big_clone ( x ) ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( z , ! RBIGNUM_SIGN ( x ) ) ;
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* ~ big - > integer
2003-12-19 06:58:57 +03:00
*
* Inverts the bits in big . As Bignums are conceptually infinite
* length , the result acts as if it had an infinite number of one
* bits to the left . In hex representations , this is displayed
* as two periods to the left of the digits .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* sprintf ( " %X " , ~ 0x1122334455 ) # = > " ..FEEDDCCBBAA "
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_neg ( VALUE x )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
VALUE z = rb_big_clone ( x ) ;
2005-07-01 12:56:09 +04:00
BDIGIT * ds ;
long i ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) get2comp ( z ) ;
2005-07-01 12:56:09 +04:00
ds = BDIGITS ( z ) ;
2007-09-01 16:02:36 +04:00
i = RBIGNUM_LEN ( x ) ;
2007-07-15 16:07:46 +04:00
if ( ! i ) return INT2FIX ( ~ ( SIGNED_VALUE ) 0 ) ;
2005-06-08 06:16:35 +04:00
while ( i - - ) {
ds [ i ] = ~ ds [ i ] ;
}
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( z , ! RBIGNUM_SIGN ( z ) ) ;
if ( RBIGNUM_SIGN ( x ) ) get2comp ( z ) ;
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2008-12-14 06:59:02 +03:00
static void
bigsub_core ( BDIGIT * xds , long xn , BDIGIT * yds , long yn , BDIGIT * zds , long zn )
{
BDIGIT_DBL_SIGNED num ;
long i ;
for ( i = 0 , num = 0 ; i < yn ; i + + ) {
num + = ( BDIGIT_DBL_SIGNED ) xds [ i ] - yds [ i ] ;
zds [ i ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
while ( num & & i < xn ) {
num + = xds [ i ] ;
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
2013-06-15 18:52:02 +04:00
if ( xds = = zds & & xn = = zn )
return ;
2008-12-14 06:59:02 +03:00
while ( i < xn ) {
zds [ i ] = xds [ i ] ;
i + + ;
}
assert ( i < = zn ) ;
while ( i < zn ) {
zds [ i + + ] = 0 ;
}
}
2013-06-15 18:52:02 +04:00
static void
bary_sub ( BDIGIT * zds , size_t zn , BDIGIT * xds , size_t xn , BDIGIT * yds , size_t yn )
{
assert ( yn < = xn ) ;
assert ( xn < = zn ) ;
bigsub_core ( xds , xn , yds , yn , zds , zn ) ;
}
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
bigsub ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
1998-01-16 15:19:22 +03:00
VALUE z = 0 ;
2007-09-01 16:02:36 +04:00
long i = RBIGNUM_LEN ( x ) ;
2009-08-09 09:55:00 +04:00
BDIGIT * xds , * yds ;
2007-05-09 07:49:18 +04:00
2011-05-22 19:37:00 +04:00
/* if x is smaller than y, swap */
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_LEN ( x ) < RBIGNUM_LEN ( y ) ) {
1998-01-16 15:13:05 +03:00
z = x ; x = y ; y = z ; /* swap x y */
}
2007-09-01 16:02:36 +04:00
else if ( RBIGNUM_LEN ( x ) = = RBIGNUM_LEN ( y ) ) {
2009-08-09 09:55:00 +04:00
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
1998-01-16 15:13:05 +03:00
while ( i > 0 ) {
i - - ;
2009-08-09 09:55:00 +04:00
if ( xds [ i ] > yds [ i ] ) {
1998-01-16 15:13:05 +03:00
break ;
}
2009-08-09 09:55:00 +04:00
if ( xds [ i ] < yds [ i ] ) {
1998-01-16 15:13:05 +03:00
z = x ; x = y ; y = z ; /* swap x y */
break ;
}
}
}
2007-09-01 16:02:36 +04:00
z = bignew ( RBIGNUM_LEN ( x ) , z = = 0 ) ;
2008-12-14 06:59:02 +03:00
bigsub_core ( BDIGITS ( x ) , RBIGNUM_LEN ( x ) ,
BDIGITS ( y ) , RBIGNUM_LEN ( y ) ,
BDIGITS ( z ) , RBIGNUM_LEN ( z ) ) ;
1998-01-16 15:13:05 +03:00
2008-12-14 06:59:02 +03:00
return z ;
}
2009-04-20 21:53:36 +04:00
static VALUE bigadd_int ( VALUE x , long y ) ;
static VALUE
bigsub_int ( VALUE x , long y0 )
{
VALUE z ;
BDIGIT * xds , * zds ;
long xn ;
BDIGIT_DBL_SIGNED num ;
long i , y ;
y = y0 ;
xds = BDIGITS ( x ) ;
xn = RBIGNUM_LEN ( x ) ;
z = bignew ( xn , RBIGNUM_SIGN ( x ) ) ;
zds = BDIGITS ( z ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
num = ( BDIGIT_DBL_SIGNED ) xds [ 0 ] - y ;
if ( xn = = 1 & & num < 0 ) {
RBIGNUM_SET_SIGN ( z , ! RBIGNUM_SIGN ( x ) ) ;
2009-05-26 08:58:15 +04:00
zds [ 0 ] = ( BDIGIT ) - num ;
2011-07-15 14:16:41 +04:00
RB_GC_GUARD ( x ) ;
2009-04-20 21:53:36 +04:00
return bignorm ( z ) ;
}
zds [ 0 ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
i = 1 ;
# else
num = 0 ;
2009-05-26 08:58:15 +04:00
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
2009-04-20 21:53:36 +04:00
num + = ( BDIGIT_DBL_SIGNED ) xds [ i ] - BIGLO ( y ) ;
zds [ i ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
y = BIGDN ( y ) ;
}
# endif
while ( num & & i < xn ) {
num + = xds [ i ] ;
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
while ( i < xn ) {
zds [ i ] = xds [ i ] ;
i + + ;
}
if ( num < 0 ) {
z = bigsub ( x , rb_int2big ( y0 ) ) ;
}
2011-07-15 14:16:41 +04:00
RB_GC_GUARD ( x ) ;
2009-04-20 21:53:36 +04:00
return bignorm ( z ) ;
}
static VALUE
bigadd_int ( VALUE x , long y )
{
VALUE z ;
BDIGIT * xds , * zds ;
long xn , zn ;
BDIGIT_DBL num ;
long i ;
xds = BDIGITS ( x ) ;
xn = RBIGNUM_LEN ( x ) ;
if ( xn < 2 ) {
zn = 3 ;
}
else {
zn = xn + 1 ;
}
z = bignew ( zn , RBIGNUM_SIGN ( x ) ) ;
zds = BDIGITS ( z ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
num = ( BDIGIT_DBL ) xds [ 0 ] + y ;
zds [ 0 ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
i = 1 ;
# else
num = 0 ;
2009-05-26 08:58:15 +04:00
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
2009-04-20 21:53:36 +04:00
num + = ( BDIGIT_DBL ) xds [ i ] + BIGLO ( y ) ;
zds [ i ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
y = BIGDN ( y ) ;
}
# endif
while ( num & & i < xn ) {
num + = xds [ i ] ;
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
if ( num ) zds [ i + + ] = ( BDIGIT ) num ;
else while ( i < xn ) {
zds [ i ] = xds [ i ] ;
i + + ;
}
assert ( i < = zn ) ;
while ( i < zn ) {
zds [ i + + ] = 0 ;
}
2011-07-15 14:16:41 +04:00
RB_GC_GUARD ( x ) ;
2009-04-20 21:53:36 +04:00
return bignorm ( z ) ;
}
2008-12-14 06:59:02 +03:00
static void
bigadd_core ( BDIGIT * xds , long xn , BDIGIT * yds , long yn , BDIGIT * zds , long zn )
{
BDIGIT_DBL num = 0 ;
long i ;
if ( xn > yn ) {
BDIGIT * tds ;
tds = xds ; xds = yds ; yds = tds ;
i = xn ; xn = yn ; yn = i ;
}
i = 0 ;
while ( i < xn ) {
num + = ( BDIGIT_DBL ) xds [ i ] + yds [ i ] ;
zds [ i + + ] = BIGLO ( num ) ;
1998-01-16 15:13:05 +03:00
num = BIGDN ( num ) ;
2007-05-09 07:49:18 +04:00
}
2008-12-14 06:59:02 +03:00
while ( num & & i < yn ) {
num + = yds [ i ] ;
1998-01-16 15:13:05 +03:00
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
2008-12-14 06:59:02 +03:00
while ( i < yn ) {
zds [ i ] = yds [ i ] ;
1998-01-16 15:13:05 +03:00
i + + ;
}
2008-12-14 06:59:02 +03:00
if ( num ) zds [ i + + ] = ( BDIGIT ) num ;
assert ( i < = zn ) ;
while ( i < zn ) {
zds [ i + + ] = 0 ;
}
1998-01-16 15:13:05 +03:00
}
2013-06-16 05:41:58 +04:00
static void
bary_add ( BDIGIT * zds , size_t zn , BDIGIT * xds , size_t xn , BDIGIT * yds , size_t yn )
{
bigadd_core ( xds , xn , yds , yn , zds , zn ) ;
}
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
bigadd ( VALUE x , VALUE y , int sign )
1998-01-16 15:13:05 +03:00
{
1998-01-16 15:19:22 +03:00
VALUE z ;
2008-12-14 06:59:02 +03:00
long len ;
1998-01-16 15:19:22 +03:00
2007-09-01 16:02:36 +04:00
sign = ( sign = = RBIGNUM_SIGN ( y ) ) ;
if ( RBIGNUM_SIGN ( x ) ! = sign ) {
1999-01-20 07:59:39 +03:00
if ( sign ) return bigsub ( y , x ) ;
1998-01-16 15:13:05 +03:00
return bigsub ( x , y ) ;
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
len = RBIGNUM_LEN ( x ) + 1 ;
1998-01-16 15:13:05 +03:00
}
else {
2007-09-01 16:02:36 +04:00
len = RBIGNUM_LEN ( y ) + 1 ;
1998-01-16 15:13:05 +03:00
}
1999-01-20 07:59:39 +03:00
z = bignew ( len , sign ) ;
1998-01-16 15:13:05 +03:00
2008-12-14 06:59:02 +03:00
bigadd_core ( BDIGITS ( x ) , RBIGNUM_LEN ( x ) ,
BDIGITS ( y ) , RBIGNUM_LEN ( y ) ,
BDIGITS ( z ) , RBIGNUM_LEN ( z ) ) ;
1998-01-16 15:13:05 +03:00
2000-07-12 10:06:50 +04:00
return z ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big + other - > Numeric
2003-12-19 03:01:19 +03:00
*
* Adds big and other , returning the result .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_plus ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
2009-04-20 21:53:36 +04:00
long n ;
1998-01-16 15:13:05 +03:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2009-04-20 21:53:36 +04:00
n = FIX2LONG ( y ) ;
if ( ( n > 0 ) ! = RBIGNUM_SIGN ( x ) ) {
if ( n < 0 ) {
n = - n ;
}
return bigsub_int ( x , n ) ;
}
if ( n < 0 ) {
n = - n ;
}
return bigadd_int ( x , n ) ;
1998-01-16 15:13:05 +03:00
case T_BIGNUM :
2000-07-12 10:06:50 +04:00
return bignorm ( bigadd ( x , y , 1 ) ) ;
1998-01-16 15:13:05 +03:00
case T_FLOAT :
2008-09-05 22:24:21 +04:00
return DBL2NUM ( rb_big2dbl ( x ) + RFLOAT_VALUE ( y ) ) ;
1998-01-16 15:13:05 +03:00
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , ' + ' ) ;
1998-01-16 15:13:05 +03:00
}
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big - other - > Numeric
2003-12-19 03:01:19 +03:00
*
* Subtracts other from big , returning the result .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_minus ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
2009-04-20 21:53:36 +04:00
long n ;
1998-01-16 15:13:05 +03:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2009-04-20 21:53:36 +04:00
n = FIX2LONG ( y ) ;
if ( ( n > 0 ) ! = RBIGNUM_SIGN ( x ) ) {
if ( n < 0 ) {
n = - n ;
}
return bigadd_int ( x , n ) ;
}
if ( n < 0 ) {
n = - n ;
}
return bigsub_int ( x , n ) ;
1998-01-16 15:13:05 +03:00
case T_BIGNUM :
2000-07-12 10:06:50 +04:00
return bignorm ( bigadd ( x , y , 0 ) ) ;
1998-01-16 15:13:05 +03:00
case T_FLOAT :
2008-09-05 22:24:21 +04:00
return DBL2NUM ( rb_big2dbl ( x ) - RFLOAT_VALUE ( y ) ) ;
1998-01-16 15:13:05 +03:00
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , ' - ' ) ;
1998-01-16 15:13:05 +03:00
}
}
2008-12-14 06:59:02 +03:00
static long
big_real_len ( VALUE x )
2007-12-19 13:13:03 +03:00
{
2008-12-14 06:59:02 +03:00
long i = RBIGNUM_LEN ( x ) ;
2009-08-09 09:55:00 +04:00
BDIGIT * xds = BDIGITS ( x ) ;
while ( - - i & & ! xds [ i ] ) ;
2008-12-14 06:59:02 +03:00
return i + 1 ;
2007-12-19 13:13:03 +03:00
}
2013-06-15 17:32:16 +04:00
static void
bary_mul_single ( BDIGIT * zds , size_t zl , BDIGIT x , BDIGIT y )
{
BDIGIT_DBL n ;
assert ( 2 < = zl ) ;
n = ( BDIGIT_DBL ) x * y ;
zds [ 0 ] = BIGLO ( n ) ;
zds [ 1 ] = ( BDIGIT ) BIGDN ( n ) ;
}
2009-08-30 04:46:32 +04:00
static VALUE
bigmul1_single ( VALUE x , VALUE y )
{
VALUE z = bignew ( 2 , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
BDIGIT * xds , * yds , * zds ;
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
zds = BDIGITS ( z ) ;
2013-06-15 17:32:16 +04:00
bary_mul_single ( zds , 2 , xds [ 0 ] , yds [ 0 ] ) ;
2009-08-30 04:46:32 +04:00
return z ;
}
2013-06-15 17:32:16 +04:00
static void
bary_mul_normal ( BDIGIT * zds , size_t zl , BDIGIT * xds , size_t xl , BDIGIT * yds , size_t yl )
1998-01-16 15:13:05 +03:00
{
2013-06-15 17:32:16 +04:00
size_t i ;
size_t j = zl ;
2000-11-01 11:49:40 +03:00
BDIGIT_DBL n = 0 ;
1998-01-16 15:13:05 +03:00
2013-06-15 17:32:16 +04:00
assert ( xl + yl < = zl ) ;
1998-01-16 15:13:05 +03:00
while ( j - - ) zds [ j ] = 0 ;
2009-08-25 12:38:28 +04:00
for ( i = 0 ; i < xl ; i + + ) {
2007-12-19 14:40:52 +03:00
BDIGIT_DBL dd ;
2009-08-09 09:55:00 +04:00
dd = xds [ i ] ;
1998-01-16 15:13:05 +03:00
if ( dd = = 0 ) continue ;
n = 0 ;
2009-08-25 12:38:28 +04:00
for ( j = 0 ; j < yl ; j + + ) {
2009-08-09 09:55:00 +04:00
BDIGIT_DBL ee = n + ( BDIGIT_DBL ) dd * yds [ j ] ;
1998-01-16 15:13:05 +03:00
n = zds [ i + j ] + ee ;
if ( ee ) zds [ i + j ] = BIGLO ( n ) ;
n = BIGDN ( n ) ;
}
if ( n ) {
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
zds [ i + j ] = ( BDIGIT ) n ;
1998-01-16 15:13:05 +03:00
}
}
2013-06-15 17:32:16 +04:00
}
static VALUE
bigmul1_normal ( VALUE x , VALUE y )
{
size_t xl = RBIGNUM_LEN ( x ) , yl = RBIGNUM_LEN ( y ) , zl = xl + yl ;
VALUE z = bignew ( zl , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
BDIGIT * xds , * yds , * zds ;
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
zds = BDIGITS ( z ) ;
bary_mul_normal ( zds , zl , xds , xl , yds , yl ) ;
2008-12-14 06:59:02 +03:00
rb_thread_check_ints ( ) ;
2005-08-10 05:39:24 +04:00
return z ;
}
1998-01-16 15:13:05 +03:00
2013-06-15 17:32:16 +04:00
static void
bary_mul ( BDIGIT * zds , size_t zl , BDIGIT * xds , size_t xl , BDIGIT * yds , size_t yl )
{
size_t l ;
if ( xl = = 1 & & yl = = 1 ) {
l = 2 ;
2013-06-16 05:41:58 +04:00
bary_mul_single ( zds , zl , xds [ 0 ] , yds [ 0 ] ) ;
2013-06-15 17:32:16 +04:00
}
else {
l = xl + yl ;
bary_mul_normal ( zds , zl , xds , xl , yds , yl ) ;
}
MEMZERO ( zds + l , BDIGIT , zl - l ) ;
}
2008-12-14 06:59:02 +03:00
static VALUE bigmul0 ( VALUE x , VALUE y ) ;
/* balancing multiplication by slicing larger argument */
2007-12-19 13:13:03 +03:00
static VALUE
2008-12-14 06:59:02 +03:00
bigmul1_balance ( VALUE x , VALUE y )
2007-12-19 13:13:03 +03:00
{
2008-12-14 06:59:02 +03:00
VALUE z , t1 , t2 ;
long i , xn , yn , r , n ;
2009-08-09 09:55:00 +04:00
BDIGIT * yds , * zds , * t1ds ;
2007-12-19 13:13:03 +03:00
2008-12-14 06:59:02 +03:00
xn = RBIGNUM_LEN ( x ) ;
yn = RBIGNUM_LEN ( y ) ;
2011-05-22 19:37:00 +04:00
assert ( 2 * xn < = yn | | 3 * xn < = 2 * ( yn + 2 ) ) ;
2007-12-19 13:13:03 +03:00
2008-12-14 06:59:02 +03:00
z = bignew ( xn + yn , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
t1 = bignew ( xn , 1 ) ;
2007-12-19 13:13:03 +03:00
2009-08-09 09:55:00 +04:00
yds = BDIGITS ( y ) ;
zds = BDIGITS ( z ) ;
t1ds = BDIGITS ( t1 ) ;
for ( i = 0 ; i < xn + yn ; i + + ) zds [ i ] = 0 ;
2007-12-19 13:13:03 +03:00
2008-12-14 06:59:02 +03:00
n = 0 ;
while ( yn > 0 ) {
r = xn > yn ? yn : xn ;
2009-08-09 09:55:00 +04:00
MEMCPY ( t1ds , yds + n , BDIGIT , r ) ;
2008-12-14 06:59:02 +03:00
RBIGNUM_SET_LEN ( t1 , r ) ;
t2 = bigmul0 ( x , t1 ) ;
2009-08-09 09:55:00 +04:00
bigadd_core ( zds + n , RBIGNUM_LEN ( z ) - n ,
2008-12-14 06:59:02 +03:00
BDIGITS ( t2 ) , big_real_len ( t2 ) ,
2009-08-09 09:55:00 +04:00
zds + n , RBIGNUM_LEN ( z ) - n ) ;
2008-12-14 06:59:02 +03:00
yn - = r ;
n + = r ;
2007-12-19 13:13:03 +03:00
}
2008-12-14 06:59:02 +03:00
return z ;
}
/* split a bignum into high and low bignums */
static void
2009-08-25 12:38:28 +04:00
big_split ( VALUE v , long n , volatile VALUE * ph , volatile VALUE * pl )
2008-12-14 06:59:02 +03:00
{
2009-08-25 12:38:28 +04:00
long hn = 0 , ln = RBIGNUM_LEN ( v ) ;
2008-12-14 06:59:02 +03:00
VALUE h , l ;
2009-08-09 09:55:00 +04:00
BDIGIT * vds = BDIGITS ( v ) ;
2008-12-14 06:59:02 +03:00
2009-08-25 12:38:28 +04:00
if ( ln > n ) {
hn = ln - n ;
ln = n ;
}
2008-12-14 06:59:02 +03:00
2011-05-22 19:37:00 +04:00
if ( ! hn ) {
h = rb_uint2big ( 0 ) ;
}
else {
while ( - - hn & & ! vds [ hn + ln ] ) ;
h = bignew ( hn + = 2 , 1 ) ;
MEMCPY ( BDIGITS ( h ) , vds + ln , BDIGIT , hn - 1 ) ;
BDIGITS ( h ) [ hn - 1 ] = 0 ; /* margin for carry */
}
2008-12-14 06:59:02 +03:00
2009-08-09 09:55:00 +04:00
while ( - - ln & & ! vds [ ln ] ) ;
2008-12-14 16:39:33 +03:00
l = bignew ( ln + = 2 , 1 ) ;
2009-10-17 12:31:07 +04:00
MEMCPY ( BDIGITS ( l ) , vds , BDIGIT , ln - 1 ) ;
BDIGITS ( l ) [ ln - 1 ] = 0 ; /* margin for carry */
2008-12-14 06:59:02 +03:00
* pl = l ;
* ph = h ;
}
/* multiplication by karatsuba method */
static VALUE
bigmul1_karatsuba ( VALUE x , VALUE y )
{
long i , n , xn , yn , t1n , t2n ;
2010-04-20 19:31:46 +04:00
VALUE xh , xl , yh , yl , z , t1 , t2 , t3 ;
2008-12-14 06:59:02 +03:00
BDIGIT * zds ;
xn = RBIGNUM_LEN ( x ) ;
yn = RBIGNUM_LEN ( y ) ;
n = yn / 2 ;
big_split ( x , n , & xh , & xl ) ;
if ( x = = y ) {
yh = xh ; yl = xl ;
}
else big_split ( y , n , & yh , & yl ) ;
/* x = xh * b + xl
* y = yh * b + yl
*
* Karatsuba method :
* x * y = z2 * b ^ 2 + z1 * b + z0
* where
* z2 = xh * yh
* z0 = xl * yl
2008-12-14 15:15:07 +03:00
* z1 = ( xh + xl ) * ( yh + yl ) - z2 - z0
2008-12-14 06:59:02 +03:00
*
* ref : http : //en.wikipedia.org/wiki/Karatsuba_algorithm
*/
/* allocate a result bignum */
z = bignew ( xn + yn , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
zds = BDIGITS ( z ) ;
/* t1 <- xh * yh */
t1 = bigmul0 ( xh , yh ) ;
t1n = big_real_len ( t1 ) ;
/* copy t1 into high bytes of the result (z2) */
MEMCPY ( zds + 2 * n , BDIGITS ( t1 ) , BDIGIT , t1n ) ;
2008-12-14 15:15:07 +03:00
for ( i = 2 * n + t1n ; i < xn + yn ; i + + ) zds [ i ] = 0 ;
2007-12-19 13:13:03 +03:00
2008-12-14 06:59:02 +03:00
if ( ! BIGZEROP ( xl ) & & ! BIGZEROP ( yl ) ) {
/* t2 <- xl * yl */
2009-11-26 08:25:08 +03:00
t2 = bigmul0 ( xl , yl ) ;
t2n = big_real_len ( t2 ) ;
2007-12-19 13:13:03 +03:00
2008-12-14 06:59:02 +03:00
/* copy t2 into low bytes of the result (z0) */
MEMCPY ( zds , BDIGITS ( t2 ) , BDIGIT , t2n ) ;
2008-12-14 15:15:07 +03:00
for ( i = t2n ; i < 2 * n ; i + + ) zds [ i ] = 0 ;
2007-12-19 13:13:03 +03:00
}
else {
2010-04-20 19:31:46 +04:00
t2 = Qundef ;
2010-04-25 19:08:44 +04:00
t2n = 0 ;
2010-04-20 19:31:46 +04:00
2008-12-14 06:59:02 +03:00
/* copy 0 into low bytes of the result (z0) */
2008-12-14 15:15:07 +03:00
for ( i = 0 ; i < 2 * n ; i + + ) zds [ i ] = 0 ;
2007-12-19 13:13:03 +03:00
}
2008-12-14 16:39:33 +03:00
/* xh <- xh + xl */
if ( RBIGNUM_LEN ( xl ) > RBIGNUM_LEN ( xh ) ) {
2010-04-20 19:31:46 +04:00
t3 = xl ; xl = xh ; xh = t3 ;
2008-12-14 16:39:33 +03:00
}
2010-04-20 19:31:46 +04:00
/* xh has a margin for carry */
2008-12-14 16:39:33 +03:00
bigadd_core ( BDIGITS ( xh ) , RBIGNUM_LEN ( xh ) ,
2009-02-22 17:23:33 +03:00
BDIGITS ( xl ) , RBIGNUM_LEN ( xl ) ,
2008-12-14 16:39:33 +03:00
BDIGITS ( xh ) , RBIGNUM_LEN ( xh ) ) ;
2008-12-14 06:59:02 +03:00
2008-12-14 16:39:33 +03:00
/* yh <- yh + yl */
if ( x ! = y ) {
if ( RBIGNUM_LEN ( yl ) > RBIGNUM_LEN ( yh ) ) {
2010-04-20 19:31:46 +04:00
t3 = yl ; yl = yh ; yh = t3 ;
2008-12-14 16:39:33 +03:00
}
2010-04-20 19:31:46 +04:00
/* yh has a margin for carry */
2008-12-14 16:39:33 +03:00
bigadd_core ( BDIGITS ( yh ) , RBIGNUM_LEN ( yh ) ,
2009-02-22 17:23:33 +03:00
BDIGITS ( yl ) , RBIGNUM_LEN ( yl ) ,
2008-12-14 16:39:33 +03:00
BDIGITS ( yh ) , RBIGNUM_LEN ( yh ) ) ;
}
else yh = xh ;
2008-12-14 06:59:02 +03:00
2010-04-20 19:31:46 +04:00
/* t3 <- xh * yh */
t3 = bigmul0 ( xh , yh ) ;
i = xn + yn - n ;
2011-01-07 03:17:06 +03:00
/* subtract t1 from t3 */
bigsub_core ( BDIGITS ( t3 ) , big_real_len ( t3 ) , BDIGITS ( t1 ) , t1n , BDIGITS ( t3 ) , big_real_len ( t3 ) ) ;
2010-04-20 19:31:46 +04:00
2011-01-07 03:17:06 +03:00
/* subtract t2 from t3; t3 is now the middle term of the product */
if ( t2 ! = Qundef ) bigsub_core ( BDIGITS ( t3 ) , big_real_len ( t3 ) , BDIGITS ( t2 ) , t2n , BDIGITS ( t3 ) , big_real_len ( t3 ) ) ;
2008-12-14 06:59:02 +03:00
2011-01-07 03:17:06 +03:00
/* add t3 to middle bytes of the result (z1) */
bigadd_core ( zds + n , i , BDIGITS ( t3 ) , big_real_len ( t3 ) , zds + n , i ) ;
2008-12-14 06:59:02 +03:00
return z ;
}
2011-05-22 19:37:00 +04:00
static void
biglsh_bang ( BDIGIT * xds , long xn , unsigned long shift )
{
long const s1 = shift / BITSPERDIG ;
int const s2 = ( int ) ( shift % BITSPERDIG ) ;
int const s3 = BITSPERDIG - s2 ;
BDIGIT * zds ;
BDIGIT num ;
long i ;
if ( s1 > = xn ) {
MEMZERO ( xds , BDIGIT , xn ) ;
return ;
}
zds = xds + xn - 1 ;
xn - = s1 + 1 ;
num = xds [ xn ] < < s2 ;
do {
* zds - - = num | xds [ - - xn ] > > s3 ;
num = xds [ xn ] < < s2 ;
}
while ( xn > 0 ) ;
* zds = num ;
for ( i = s1 ; i > 0 ; - - i )
* zds - - = 0 ;
}
static void
bigrsh_bang ( BDIGIT * xds , long xn , unsigned long shift )
{
long s1 = shift / BITSPERDIG ;
int s2 = ( int ) ( shift % BITSPERDIG ) ;
int s3 = BITSPERDIG - s2 ;
int i ;
BDIGIT num ;
BDIGIT * zds ;
if ( s1 > = xn ) {
MEMZERO ( xds , BDIGIT , xn ) ;
return ;
}
i = 0 ;
zds = xds + s1 ;
num = * zds + + > > s2 ;
do {
xds [ i + + ] = ( BDIGIT ) ( * zds < < s3 ) | num ;
num = * zds + + > > s2 ;
}
while ( i < xn - s1 - 1 ) ;
xds [ i ] = num ;
MEMZERO ( xds + xn - s1 , BDIGIT , s1 ) ;
}
static void
big_split3 ( VALUE v , long n , volatile VALUE * p0 , volatile VALUE * p1 , volatile VALUE * p2 )
{
VALUE v0 , v12 , v1 , v2 ;
big_split ( v , n , & v12 , & v0 ) ;
big_split ( v12 , n , & v2 , & v1 ) ;
* p0 = bigtrunc ( v0 ) ;
* p1 = bigtrunc ( v1 ) ;
* p2 = bigtrunc ( v2 ) ;
}
static VALUE big_lshift ( VALUE , unsigned long ) ;
static VALUE big_rshift ( VALUE , unsigned long ) ;
static VALUE bigdivrem ( VALUE , VALUE , volatile VALUE * , volatile VALUE * ) ;
static VALUE
bigmul1_toom3 ( VALUE x , VALUE y )
{
2011-05-29 19:49:07 +04:00
long n , xn , yn , zn ;
2011-05-22 19:37:00 +04:00
VALUE x0 , x1 , x2 , y0 , y1 , y2 ;
VALUE u0 , u1 , u2 , u3 , u4 , v1 , v2 , v3 ;
VALUE z0 , z1 , z2 , z3 , z4 , z , t ;
BDIGIT * zds ;
xn = RBIGNUM_LEN ( x ) ;
yn = RBIGNUM_LEN ( y ) ;
assert ( xn < = yn ) ; /* assume y >= x */
n = ( yn + 2 ) / 3 ;
big_split3 ( x , n , & x0 , & x1 , & x2 ) ;
if ( x = = y ) {
y0 = x0 ; y1 = x1 ; y2 = x2 ;
}
else big_split3 ( y , n , & y0 , & y1 , & y2 ) ;
/*
* ref . http : //en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
*
* x ( b ) = x0 * b ^ 0 + x1 * b ^ 1 + x2 * b ^ 2
* y ( b ) = y0 * b ^ 0 + y1 * b ^ 1 + y2 * b ^ 2
*
* z ( b ) = x ( b ) * y ( b )
* z ( b ) = z0 * b ^ 0 + z1 * b ^ 1 + z2 * b ^ 2 + z3 * b ^ 3 + z4 * b ^ 4
* where :
* z0 = x0 * y0
* z1 = x0 * y1 + x1 * y0
* z2 = x0 * y2 + x1 * y1 + x2 * y0
* z3 = x1 * y2 + x2 * y1
* z4 = x2 * y2
*
* Toom3 method ( a . k . a . Toom - Cook method ) :
* ( Step1 ) calculating 5 points z ( b0 ) , z ( b1 ) , z ( b2 ) , z ( b3 ) , z ( b4 ) ,
* where :
* b0 = 0 , b1 = 1 , b2 = - 1 , b3 = - 2 , b4 = inf ,
* z ( 0 ) = x ( 0 ) * y ( 0 ) = x0 * y0
* z ( 1 ) = x ( 1 ) * y ( 1 ) = ( x0 + x1 + x2 ) * ( y0 + y1 + y2 )
* z ( - 1 ) = x ( - 1 ) * y ( - 1 ) = ( x0 - x1 + x2 ) * ( y0 - y1 + y2 )
* z ( - 2 ) = x ( - 2 ) * y ( - 2 ) = ( x0 - 2 * ( x1 - 2 * x2 ) ) * ( y0 - 2 * ( y1 - 2 * y2 ) )
* z ( inf ) = x ( inf ) * y ( inf ) = x2 * y2
*
* ( Step2 ) interpolating z0 , z1 , z2 , z3 , z4 , and z5 .
*
* ( Step3 ) Substituting base value into b of the polynomial z ( b ) ,
*/
/*
* [ Step1 ] calculating 5 points z ( b0 ) , z ( b1 ) , z ( b2 ) , z ( b3 ) , z ( b4 )
*/
/* u1 <- x0 + x2 */
u1 = bigtrunc ( bigadd ( x0 , x2 , 1 ) ) ;
/* x(-1) : u2 <- u1 - x1 = x0 - x1 + x2 */
u2 = bigtrunc ( bigsub ( u1 , x1 ) ) ;
/* x(1) : u1 <- u1 + x1 = x0 + x1 + x2 */
u1 = bigtrunc ( bigadd ( u1 , x1 , 1 ) ) ;
/* x(-2) : u3 <- 2 * (u2 + x2) - x0 = x0 - 2 * (x1 - 2 * x2) */
u3 = bigadd ( u2 , x2 , 1 ) ;
if ( BDIGITS ( u3 ) [ RBIGNUM_LEN ( u3 ) - 1 ] & BIGRAD_HALF ) {
rb_big_resize ( u3 , RBIGNUM_LEN ( u3 ) + 1 ) ;
BDIGITS ( u3 ) [ RBIGNUM_LEN ( u3 ) - 1 ] = 0 ;
}
biglsh_bang ( BDIGITS ( u3 ) , RBIGNUM_LEN ( u3 ) , 1 ) ;
u3 = bigtrunc ( bigadd ( bigtrunc ( u3 ) , x0 , 0 ) ) ;
if ( x = = y ) {
v1 = u1 ; v2 = u2 ; v3 = u3 ;
}
else {
/* v1 <- y0 + y2 */
v1 = bigtrunc ( bigadd ( y0 , y2 , 1 ) ) ;
/* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
v2 = bigtrunc ( bigsub ( v1 , y1 ) ) ;
/* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
v1 = bigtrunc ( bigadd ( v1 , y1 , 1 ) ) ;
/* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
v3 = bigadd ( v2 , y2 , 1 ) ;
if ( BDIGITS ( v3 ) [ RBIGNUM_LEN ( v3 ) - 1 ] & BIGRAD_HALF ) {
rb_big_resize ( v3 , RBIGNUM_LEN ( v3 ) + 1 ) ;
BDIGITS ( v3 ) [ RBIGNUM_LEN ( v3 ) - 1 ] = 0 ;
}
biglsh_bang ( BDIGITS ( v3 ) , RBIGNUM_LEN ( v3 ) , 1 ) ;
v3 = bigtrunc ( bigadd ( bigtrunc ( v3 ) , y0 , 0 ) ) ;
}
/* z(0) : u0 <- x0 * y0 */
u0 = bigtrunc ( bigmul0 ( x0 , y0 ) ) ;
/* z(1) : u1 <- u1 * v1 */
u1 = bigtrunc ( bigmul0 ( u1 , v1 ) ) ;
/* z(-1) : u2 <- u2 * v2 */
u2 = bigtrunc ( bigmul0 ( u2 , v2 ) ) ;
/* z(-2) : u3 <- u3 * v3 */
u3 = bigtrunc ( bigmul0 ( u3 , v3 ) ) ;
/* z(inf) : u4 <- x2 * y2 */
u4 = bigtrunc ( bigmul0 ( x2 , y2 ) ) ;
/* for GC */
v1 = v2 = v3 = Qnil ;
/*
* [ Step2 ] interpolating z0 , z1 , z2 , z3 , z4 , and z5 .
*/
/* z0 <- z(0) == u0 */
z0 = u0 ;
/* z4 <- z(inf) == u4 */
z4 = u4 ;
/* z3 <- (z(-2) - z(1)) / 3 == (u3 - u1) / 3 */
z3 = bigadd ( u3 , u1 , 0 ) ;
bigdivrem ( z3 , big_three , & z3 , NULL ) ; /* TODO: optimize */
bigtrunc ( z3 ) ;
/* z1 <- (z(1) - z(-1)) / 2 == (u1 - u2) / 2 */
z1 = bigtrunc ( bigadd ( u1 , u2 , 0 ) ) ;
bigrsh_bang ( BDIGITS ( z1 ) , RBIGNUM_LEN ( z1 ) , 1 ) ;
/* z2 <- z(-1) - z(0) == u2 - u0 */
z2 = bigtrunc ( bigadd ( u2 , u0 , 0 ) ) ;
/* z3 <- (z2 - z3) / 2 + 2 * z(inf) == (z2 - z3) / 2 + 2 * u4 */
2012-11-09 02:38:03 +04:00
z3 = bigtrunc ( bigadd ( z2 , z3 , 0 ) ) ;
2011-05-22 19:37:00 +04:00
bigrsh_bang ( BDIGITS ( z3 ) , RBIGNUM_LEN ( z3 ) , 1 ) ;
t = big_lshift ( u4 , 1 ) ; /* TODO: combining with next addition */
z3 = bigtrunc ( bigadd ( z3 , t , 1 ) ) ;
/* z2 <- z2 + z1 - z(inf) == z2 + z1 - u4 */
z2 = bigtrunc ( bigadd ( z2 , z1 , 1 ) ) ;
z2 = bigtrunc ( bigadd ( z2 , u4 , 0 ) ) ;
/* z1 <- z1 - z3 */
z1 = bigtrunc ( bigadd ( z1 , z3 , 0 ) ) ;
/*
* [ Step3 ] Substituting base value into b of the polynomial z ( b ) ,
*/
zn = 6 * n + 1 ;
z = bignew ( zn , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
zds = BDIGITS ( z ) ;
MEMCPY ( zds , BDIGITS ( z0 ) , BDIGIT , RBIGNUM_LEN ( z0 ) ) ;
MEMZERO ( zds + RBIGNUM_LEN ( z0 ) , BDIGIT , zn - RBIGNUM_LEN ( z0 ) ) ;
bigadd_core ( zds + n , zn - n , BDIGITS ( z1 ) , big_real_len ( z1 ) , zds + n , zn - n ) ;
bigadd_core ( zds + 2 * n , zn - 2 * n , BDIGITS ( z2 ) , big_real_len ( z2 ) , zds + 2 * n , zn - 2 * n ) ;
bigadd_core ( zds + 3 * n , zn - 3 * n , BDIGITS ( z3 ) , big_real_len ( z3 ) , zds + 3 * n , zn - 3 * n ) ;
bigadd_core ( zds + 4 * n , zn - 4 * n , BDIGITS ( z4 ) , big_real_len ( z4 ) , zds + 4 * n , zn - 4 * n ) ;
z = bignorm ( z ) ;
return bignorm ( z ) ;
}
2008-12-14 06:59:02 +03:00
/* efficient squaring (2 times faster than normal multiplication)
* ref : Handbook of Applied Cryptography , Algorithm 14.16
* http : //www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
*/
static VALUE
bigsqr_fast ( VALUE x )
{
long len = RBIGNUM_LEN ( x ) , i , j ;
VALUE z = bignew ( 2 * len + 1 , 1 ) ;
BDIGIT * xds = BDIGITS ( x ) , * zds = BDIGITS ( z ) ;
BDIGIT_DBL c , v , w ;
for ( i = 2 * len + 1 ; i - - ; ) zds [ i ] = 0 ;
for ( i = 0 ; i < len ; i + + ) {
v = ( BDIGIT_DBL ) xds [ i ] ;
if ( ! v ) continue ;
c = ( BDIGIT_DBL ) zds [ i + i ] + v * v ;
zds [ i + i ] = BIGLO ( c ) ;
c = BIGDN ( c ) ;
v * = 2 ;
for ( j = i + 1 ; j < len ; j + + ) {
w = ( BDIGIT_DBL ) xds [ j ] ;
c + = ( BDIGIT_DBL ) zds [ i + j ] + BIGLO ( v ) * w ;
zds [ i + j ] = BIGLO ( c ) ;
c = BIGDN ( c ) ;
if ( BIGDN ( v ) ) c + = w ;
}
if ( c ) {
c + = ( BDIGIT_DBL ) zds [ i + len ] ;
zds [ i + len ] = BIGLO ( c ) ;
c = BIGDN ( c ) ;
}
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
if ( c ) zds [ i + len + 1 ] + = ( BDIGIT ) c ;
2008-12-14 06:59:02 +03:00
}
2007-12-19 13:13:03 +03:00
return z ;
}
2008-12-14 06:59:02 +03:00
# define KARATSUBA_MUL_DIGITS 70
2011-05-22 19:37:00 +04:00
# define TOOM3_MUL_DIGITS 150
2008-12-14 06:59:02 +03:00
/* determine whether a bignum is sparse or not by random sampling */
static inline VALUE
big_sparse_p ( VALUE x )
{
long c = 0 , n = RBIGNUM_LEN ( x ) ;
2010-09-10 09:44:54 +04:00
if ( BDIGITS ( x ) [ rb_genrand_ulong_limited ( n / 2 ) + n / 4 ] ) c + + ;
if ( c < = 1 & & BDIGITS ( x ) [ rb_genrand_ulong_limited ( n / 2 ) + n / 4 ] ) c + + ;
if ( c < = 1 & & BDIGITS ( x ) [ rb_genrand_ulong_limited ( n / 2 ) + n / 4 ] ) c + + ;
2008-12-14 06:59:02 +03:00
return ( c < = 1 ) ? Qtrue : Qfalse ;
}
static VALUE
bigmul0 ( VALUE x , VALUE y )
{
long xn , yn ;
xn = RBIGNUM_LEN ( x ) ;
yn = RBIGNUM_LEN ( y ) ;
/* make sure that y is longer than x */
if ( xn > yn ) {
VALUE t ;
long tn ;
t = x ; x = y ; y = t ;
tn = xn ; xn = yn ; yn = tn ;
}
assert ( xn < = yn ) ;
/* normal multiplication when x is small */
if ( xn < KARATSUBA_MUL_DIGITS ) {
normal :
if ( x = = y ) return bigsqr_fast ( x ) ;
2009-08-30 04:46:32 +04:00
if ( xn = = 1 & & yn = = 1 ) return bigmul1_single ( x , y ) ;
2009-11-26 08:25:08 +03:00
return bigmul1_normal ( x , y ) ;
2008-12-14 06:59:02 +03:00
}
/* normal multiplication when x or y is a sparse bignum */
if ( big_sparse_p ( x ) ) goto normal ;
if ( big_sparse_p ( y ) ) return bigmul1_normal ( y , x ) ;
/* balance multiplication by slicing y when x is much smaller than y */
if ( 2 * xn < = yn ) return bigmul1_balance ( x , y ) ;
2012-11-09 02:38:03 +04:00
if ( xn < TOOM3_MUL_DIGITS ) {
/* multiplication by karatsuba method */
return bigmul1_karatsuba ( x , y ) ;
}
else if ( 3 * xn < = 2 * ( yn + 2 ) )
return bigmul1_balance ( x , y ) ;
return bigmul1_toom3 ( x , y ) ;
2008-12-14 06:59:02 +03:00
}
2005-08-10 05:39:24 +04:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big * other - > Numeric
2005-08-10 05:39:24 +04:00
*
* Multiplies big and other , returning the result .
*/
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_mul ( VALUE x , VALUE y )
2005-08-10 05:39:24 +04:00
{
2008-12-14 06:59:02 +03:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
y = rb_int2big ( FIX2LONG ( y ) ) ;
break ;
case T_BIGNUM :
break ;
case T_FLOAT :
return DBL2NUM ( rb_big2dbl ( x ) * RFLOAT_VALUE ( y ) ) ;
default :
return rb_num_coerce_bin ( x , y , ' * ' ) ;
}
return bignorm ( bigmul0 ( x , y ) ) ;
1998-01-16 15:13:05 +03:00
}
2007-12-19 13:13:03 +03:00
struct big_div_struct {
2012-11-27 16:46:32 +04:00
long nx , ny , j , nyzero ;
2008-01-29 15:58:24 +03:00
BDIGIT * yds , * zds ;
2012-11-26 10:49:48 +04:00
volatile VALUE stop ;
2007-12-19 13:13:03 +03:00
} ;
2012-07-10 17:57:11 +04:00
static void *
2007-12-19 13:13:03 +03:00
bigdivrem1 ( void * ptr )
1998-01-16 15:13:05 +03:00
{
2007-12-19 13:13:03 +03:00
struct big_div_struct * bds = ( struct big_div_struct * ) ptr ;
2012-11-27 16:46:32 +04:00
long ny = bds - > ny ;
long i , j ;
2008-01-29 15:58:24 +03:00
BDIGIT * yds = bds - > yds , * zds = bds - > zds ;
BDIGIT_DBL t2 ;
BDIGIT_DBL_SIGNED num ;
BDIGIT q ;
2012-11-27 16:46:32 +04:00
j = bds - > j ;
2008-01-29 15:58:24 +03:00
do {
2012-11-27 16:46:32 +04:00
if ( bds - > stop ) {
bds - > j = j ;
return 0 ;
}
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
if ( zds [ j ] = = yds [ ny - 1 ] ) q = ( BDIGIT ) BIGRAD - 1 ;
2008-01-29 15:58:24 +03:00
else q = ( BDIGIT ) ( ( BIGUP ( zds [ j ] ) + zds [ j - 1 ] ) / yds [ ny - 1 ] ) ;
if ( q ) {
2012-11-27 16:46:32 +04:00
i = bds - > nyzero ; num = 0 ; t2 = 0 ;
2008-01-29 15:58:24 +03:00
do { /* multiply and subtract */
BDIGIT_DBL ee ;
t2 + = ( BDIGIT_DBL ) yds [ i ] * q ;
ee = num - BIGLO ( t2 ) ;
num = ( BDIGIT_DBL ) zds [ j - ny + i ] + ee ;
if ( ee ) zds [ j - ny + i ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
t2 = BIGDN ( t2 ) ;
} while ( + + i < ny ) ;
num + = zds [ j - ny + i ] - t2 ; /* borrow from high digit; don't update */
while ( num ) { /* "add back" required */
i = 0 ; num = 0 ; q - - ;
do {
BDIGIT_DBL ee = num + yds [ i ] ;
num = ( BDIGIT_DBL ) zds [ j - ny + i ] + ee ;
if ( ee ) zds [ j - ny + i ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
} while ( + + i < ny ) ;
num - - ;
}
}
zds [ j ] = q ;
} while ( - - j > = ny ) ;
2012-07-10 17:57:11 +04:00
return 0 ;
2008-01-29 15:58:24 +03:00
}
2008-12-14 06:59:02 +03:00
static void
rb_big_stop ( void * ptr )
{
2012-11-26 10:49:48 +04:00
struct big_div_struct * bds = ptr ;
bds - > stop = Qtrue ;
2008-12-14 06:59:02 +03:00
}
2013-06-16 03:46:07 +04:00
static inline int
bigdivrem_num_extra_words ( long nx , long ny )
{
int ret = nx = = ny ? 2 : 1 ;
assert ( ret < = BIGDIVREM_EXTRA_WORDS ) ;
return ret ;
}
static BDIGIT
bigdivrem_single ( BDIGIT * qds , BDIGIT * xds , long nx , BDIGIT y )
{
long i ;
BDIGIT_DBL t2 ;
t2 = 0 ;
i = nx ;
while ( i - - ) {
t2 = BIGUP ( t2 ) + xds [ i ] ;
qds [ i ] = ( BDIGIT ) ( t2 / y ) ;
t2 % = y ;
}
return ( BDIGIT ) t2 ;
}
static void
bigdivrem_normal ( BDIGIT * zds , long nz , BDIGIT * xds , long nx , BDIGIT * yds , long ny , int needs_mod )
{
struct big_div_struct bds ;
BDIGIT q ;
int shift ;
q = yds [ ny - 1 ] ;
shift = nlz ( q ) ;
if ( shift ) {
bdigs_small_lshift ( yds , yds , ny , shift ) ;
zds [ nx ] = bdigs_small_lshift ( zds , xds , nx , shift ) ;
}
else {
MEMCPY ( zds , xds , BDIGIT , nx ) ;
zds [ nx ] = 0 ;
}
if ( nx + 1 < nz ) zds [ nx + 1 ] = 0 ;
bds . nx = nx ;
bds . ny = ny ;
bds . zds = zds ;
bds . yds = yds ;
bds . stop = Qfalse ;
bds . j = nz - 1 ;
for ( bds . nyzero = 0 ; ! yds [ bds . nyzero ] ; bds . nyzero + + ) ;
if ( nx > 10000 | | ny > 10000 ) {
retry :
bds . stop = Qfalse ;
rb_thread_call_without_gvl ( bigdivrem1 , & bds , rb_big_stop , & bds ) ;
if ( bds . stop = = Qtrue ) {
/* execute trap handler, but exception was not raised. */
goto retry ;
}
}
else {
bigdivrem1 ( & bds ) ;
}
if ( needs_mod & & shift ) {
bdigs_small_rshift ( zds , zds , ny , shift , 0 ) ;
}
}
static void
2013-06-16 05:41:58 +04:00
bary_divmod ( BDIGIT * qds , size_t nq , BDIGIT * rds , size_t nr , BDIGIT * xds , size_t nx , BDIGIT * yds , size_t ny )
2013-06-16 03:46:07 +04:00
{
assert ( nx < = nq ) ;
assert ( ny < = nr ) ;
while ( 0 < ny & & ! yds [ ny - 1 ] ) ny - - ;
if ( ny = = 0 )
rb_num_zerodiv ( ) ;
while ( 0 < nx & & ! xds [ nx - 1 ] ) nx - - ;
if ( nx = = 0 ) {
MEMZERO ( qds , BDIGIT , nq ) ;
MEMZERO ( rds , BDIGIT , nr ) ;
return ;
}
if ( ny = = 1 ) {
MEMCPY ( qds , xds , BDIGIT , nx ) ;
MEMZERO ( qds + nx , BDIGIT , nq - nx ) ;
rds [ 0 ] = bigdivrem_single ( qds , xds , nx , yds [ 0 ] ) ;
MEMZERO ( rds + 1 , BDIGIT , nr - 1 ) ;
}
else {
int extra_words ;
long j ;
long nz ;
BDIGIT * zds ;
VALUE tmpz = 0 ;
BDIGIT * tds ;
extra_words = bigdivrem_num_extra_words ( nx , ny ) ;
nz = nx + extra_words ;
if ( nx + extra_words < = nq )
zds = qds ;
else
zds = ALLOCV_N ( BDIGIT , tmpz , nx + extra_words ) ;
MEMCPY ( zds , xds , BDIGIT , nx ) ;
MEMZERO ( zds + nx , BDIGIT , nz - nx ) ;
if ( ( yds [ ny - 1 ] > > ( BITSPERDIG - 1 ) ) & 1 ) {
2013-06-16 03:56:32 +04:00
/* bigdivrem_normal will not modify y.
2013-06-16 03:46:07 +04:00
* So use yds directly . */
tds = yds ;
}
else {
2013-06-16 03:56:32 +04:00
/* bigdivrem_normal will modify y.
2013-06-16 03:46:07 +04:00
* So use rds as a temporary buffer . */
MEMCPY ( rds , yds , BDIGIT , ny ) ;
tds = rds ;
}
bigdivrem_normal ( zds , nz , xds , nx , tds , ny , 1 ) ;
/* copy remainder */
MEMCPY ( rds , zds , BDIGIT , ny ) ;
MEMZERO ( rds + ny , BDIGIT , nr - ny ) ;
/* move quotient */
j = nz - ny ;
MEMMOVE ( qds , zds + ny , BDIGIT , j ) ;
MEMZERO ( qds + j , BDIGIT , nq - j ) ;
if ( tmpz )
ALLOCV_END ( tmpz ) ;
}
}
2008-01-29 15:58:24 +03:00
static VALUE
2012-11-27 16:46:32 +04:00
bigdivrem ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp )
2008-01-29 15:58:24 +03:00
{
2013-06-13 16:26:33 +04:00
long nx = RBIGNUM_LEN ( x ) , ny = RBIGNUM_LEN ( y ) , nz ;
2013-06-16 03:46:07 +04:00
long j ;
2013-06-13 16:26:33 +04:00
VALUE z , zz ;
VALUE tmpy = 0 , tmpz = 0 ;
2013-06-16 03:46:07 +04:00
BDIGIT * xds , * yds , * zds , * tds ;
BDIGIT dd ;
1998-01-16 15:13:05 +03:00
yds = BDIGITS ( y ) ;
2013-06-13 19:15:07 +04:00
while ( 0 < ny & & ! yds [ ny - 1 ] ) ny - - ;
if ( ny = = 0 )
rb_num_zerodiv ( ) ;
xds = BDIGITS ( x ) ;
2013-06-13 16:26:33 +04:00
while ( 0 < nx & & ! xds [ nx - 1 ] ) nx - - ;
2013-06-13 19:15:07 +04:00
2009-08-25 12:38:28 +04:00
if ( nx < ny | | ( nx = = ny & & xds [ nx - 1 ] < yds [ ny - 1 ] ) ) {
2000-07-12 11:33:34 +04:00
if ( divp ) * divp = rb_int2big ( 0 ) ;
2000-07-12 10:06:50 +04:00
if ( modp ) * modp = x ;
2007-12-19 14:40:52 +03:00
return Qnil ;
1998-01-16 15:13:05 +03:00
}
if ( ny = = 1 ) {
dd = yds [ 0 ] ;
2013-06-14 15:13:16 +04:00
z = bignew ( nx , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
2013-06-16 03:56:32 +04:00
dd = bigdivrem_single ( zds , xds , nx , dd ) ;
2001-01-09 10:26:21 +03:00
if ( modp ) {
2013-06-16 03:56:32 +04:00
* modp = rb_uint2big ( ( VALUE ) dd ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( * modp , RBIGNUM_SIGN ( x ) ) ;
2001-01-09 10:26:21 +03:00
}
2000-07-12 10:06:50 +04:00
if ( divp ) * divp = z ;
2007-12-19 14:40:52 +03:00
return Qnil ;
1998-01-16 15:13:05 +03:00
}
2011-05-22 19:37:00 +04:00
2013-06-16 03:46:07 +04:00
if ( ( ( yds [ ny - 1 ] > > ( BITSPERDIG - 1 ) ) & 1 ) = = 0 ) {
/* Make yds modifiable. */
2013-06-13 17:02:34 +04:00
tds = ALLOCV_N ( BDIGIT , tmpy , ny ) ;
2013-06-16 03:46:07 +04:00
MEMCPY ( tds , yds , BDIGIT , ny ) ;
yds = tds ;
1998-01-16 15:13:05 +03:00
}
2000-11-08 08:29:37 +03:00
2013-06-16 03:46:07 +04:00
nz = nx + bigdivrem_num_extra_words ( nx , ny ) ;
zds = ALLOCV_N ( BDIGIT , tmpz , nz ) ;
bigdivrem_normal ( zds , nz , xds , nx , yds , ny , modp ! = NULL ) ;
2008-01-29 15:58:24 +03:00
2000-07-12 10:06:50 +04:00
if ( divp ) { /* move quotient down in z */
2013-06-13 16:26:33 +04:00
j = nz - ny ;
2013-06-14 16:05:38 +04:00
while ( 0 < j & & ! zds [ j - 1 + ny ] )
j - - ;
2013-06-13 16:26:33 +04:00
* divp = zz = bignew ( j , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
2013-06-16 03:46:07 +04:00
MEMCPY ( BDIGITS ( zz ) , zds + ny , BDIGIT , j ) ;
1998-01-16 15:13:05 +03:00
}
2002-10-07 11:44:18 +04:00
if ( modp ) { /* normalize remainder */
2013-06-16 03:46:07 +04:00
while ( ny > 0 & & ! zds [ ny - 1 ] ) - - ny ;
2013-06-13 16:26:33 +04:00
* modp = zz = bignew ( ny , RBIGNUM_SIGN ( x ) ) ;
MEMCPY ( BDIGITS ( zz ) , zds , BDIGIT , ny ) ;
}
if ( tmpy )
ALLOCV_END ( tmpy ) ;
if ( tmpz )
ALLOCV_END ( tmpz ) ;
return Qnil ;
2007-12-19 13:13:03 +03:00
}
2000-07-06 11:21:26 +04:00
static void
2009-08-25 12:38:28 +04:00
bigdivmod ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp )
2000-07-06 11:21:26 +04:00
{
VALUE mod ;
bigdivrem ( x , y , divp , & mod ) ;
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) ! = RBIGNUM_SIGN ( y ) & & ! BIGZEROP ( mod ) ) {
2000-07-06 11:21:26 +04:00
if ( divp ) * divp = bigadd ( * divp , rb_int2big ( 1 ) , 0 ) ;
if ( modp ) * modp = bigadd ( mod , y , 1 ) ;
}
2008-08-29 20:56:44 +04:00
else if ( modp ) {
* modp = mod ;
1998-01-16 15:13:05 +03:00
}
}
2003-12-19 03:01:19 +03:00
2008-04-07 17:52:26 +04:00
static VALUE
rb_big_divide ( VALUE x , VALUE y , ID op )
1998-01-16 15:13:05 +03:00
{
VALUE z ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-20 07:59:39 +03:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_BIGNUM :
break ;
case T_FLOAT :
2008-05-01 18:20:15 +04:00
{
if ( op = = ' / ' ) {
2011-11-22 06:27:53 +04:00
return DBL2NUM ( rb_big2dbl ( x ) / RFLOAT_VALUE ( y ) ) ;
2008-05-01 18:20:15 +04:00
}
else {
2011-11-22 06:27:53 +04:00
double dy = RFLOAT_VALUE ( y ) ;
if ( dy = = 0.0 ) rb_num_zerodiv ( ) ;
return rb_dbl2big ( rb_big2dbl ( x ) / dy ) ;
2008-05-01 18:20:15 +04:00
}
}
1998-01-16 15:13:05 +03:00
default :
2008-04-07 17:52:26 +04:00
return rb_num_coerce_bin ( x , y , op ) ;
1998-01-16 15:13:05 +03:00
}
2000-07-06 11:21:26 +04:00
bigdivmod ( x , y , & z , 0 ) ;
1998-01-16 15:13:05 +03:00
2000-07-12 10:06:50 +04:00
return bignorm ( z ) ;
1998-01-16 15:13:05 +03:00
}
2008-04-07 17:52:26 +04:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big / other - > Numeric
2008-04-07 17:52:26 +04:00
*
2009-09-04 12:06:12 +04:00
* Performs division : the class of the resulting object depends on
* the class of < code > numeric < / code > and on the magnitude of the
* result .
2008-04-07 17:52:26 +04:00
*/
VALUE
rb_big_div ( VALUE x , VALUE y )
{
2009-09-04 09:40:52 +04:00
return rb_big_divide ( x , y , ' / ' ) ;
2008-04-07 17:52:26 +04:00
}
2009-09-04 12:06:12 +04:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . div ( other ) - > integer
2009-09-04 12:06:12 +04:00
*
* Performs integer division : returns integer value .
*/
2008-04-07 17:52:26 +04:00
VALUE
rb_big_idiv ( VALUE x , VALUE y )
{
2009-09-04 09:40:52 +04:00
return rb_big_divide ( x , y , rb_intern ( " div " ) ) ;
2008-04-07 17:52:26 +04:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big % other - > Numeric
* big . modulo ( other ) - > Numeric
2003-12-19 03:01:19 +03:00
*
* Returns big modulo other . See Numeric . divmod for more
* information .
*/
2005-08-03 11:09:48 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_modulo ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
VALUE z ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-20 07:59:39 +03:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_BIGNUM :
break ;
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , ' % ' ) ;
1998-01-16 15:13:05 +03:00
}
2000-07-03 09:46:36 +04:00
bigdivmod ( x , y , 0 , & z ) ;
1998-01-16 15:13:05 +03:00
2000-07-12 10:06:50 +04:00
return bignorm ( z ) ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . remainder ( numeric ) - > number
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* Returns the remainder after dividing < i > big < / i > by < i > numeric < / i > .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* - 1234567890987654321. remainder ( 13731 ) # = > - 6966
* - 1234567890987654321. remainder ( 13731.24 ) # = > - 9906.22531493148
*/
2000-07-06 11:21:26 +04:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_remainder ( VALUE x , VALUE y )
2000-07-06 11:21:26 +04:00
{
VALUE z ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
y = rb_int2big ( FIX2LONG ( y ) ) ;
break ;
case T_BIGNUM :
break ;
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , rb_intern ( " remainder " ) ) ;
2000-07-06 11:21:26 +04:00
}
bigdivrem ( x , y , 0 , & z ) ;
return bignorm ( z ) ;
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . divmod ( numeric ) - > array
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* See < code > Numeric # divmod < / code > .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
*/
2000-05-12 13:07:57 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_divmod ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
VALUE div , mod ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-20 07:59:39 +03:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_BIGNUM :
break ;
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , rb_intern ( " divmod " ) ) ;
1998-01-16 15:13:05 +03:00
}
2000-07-03 09:46:36 +04:00
bigdivmod ( x , y , & div , & mod ) ;
1998-01-16 15:13:05 +03:00
2000-07-12 10:06:50 +04:00
return rb_assoc_new ( bignorm ( div ) , bignorm ( mod ) ) ;
1998-01-16 15:13:05 +03:00
}
2009-05-26 08:58:15 +04:00
static VALUE
big_shift ( VALUE x , long n )
2007-07-19 09:38:48 +04:00
{
if ( n < 0 )
2009-05-26 08:58:15 +04:00
return big_lshift ( x , ( unsigned long ) - n ) ;
2007-07-19 09:38:48 +04:00
else if ( n > 0 )
2009-05-26 08:58:15 +04:00
return big_rshift ( x , ( unsigned long ) n ) ;
2007-07-19 09:38:48 +04:00
return x ;
}
2007-05-02 12:12:31 +04:00
2010-05-29 22:51:39 +04:00
static VALUE
2009-06-17 16:55:16 +04:00
big_fdiv ( VALUE x , VALUE y )
{
# define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
VALUE z ;
long l , ex , ey ;
int i ;
bigtrunc ( x ) ;
2013-06-05 16:17:30 +04:00
l = RBIGNUM_LEN ( x ) ;
ex = l * BITSPERDIG - nlz ( BDIGITS ( x ) [ l - 1 ] ) ;
2009-06-17 16:55:16 +04:00
ex - = 2 * DBL_BIGDIG * BITSPERDIG ;
if ( ex ) x = big_shift ( x , ex ) ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
y = rb_int2big ( FIX2LONG ( y ) ) ;
2012-04-15 04:06:13 +04:00
case T_BIGNUM :
2009-06-19 03:14:08 +04:00
bigtrunc ( y ) ;
2013-06-05 16:17:30 +04:00
l = RBIGNUM_LEN ( y ) ;
ey = l * BITSPERDIG - nlz ( BDIGITS ( y ) [ l - 1 ] ) ;
2009-06-19 03:14:08 +04:00
ey - = DBL_BIGDIG * BITSPERDIG ;
if ( ey ) y = big_shift ( y , ey ) ;
2012-04-15 04:06:13 +04:00
break ;
2009-06-17 16:55:16 +04:00
case T_FLOAT :
y = dbl2big ( ldexp ( frexp ( RFLOAT_VALUE ( y ) , & i ) , DBL_MANT_DIG ) ) ;
ey = i - DBL_MANT_DIG ;
2012-04-15 04:06:13 +04:00
break ;
default :
rb_bug ( " big_fdiv " ) ;
2009-06-17 16:55:16 +04:00
}
2012-04-15 04:06:13 +04:00
bigdivrem ( x , y , & z , 0 ) ;
l = ex - ey ;
# if SIZEOF_LONG > SIZEOF_INT
{
/* Visual C++ can't be here */
if ( l > INT_MAX ) return DBL2NUM ( INFINITY ) ;
if ( l < INT_MIN ) return DBL2NUM ( 0.0 ) ;
}
# endif
return DBL2NUM ( ldexp ( big2dbl ( z ) , ( int ) l ) ) ;
2009-06-17 16:55:16 +04:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2008-05-07 08:14:57 +04:00
* big . fdiv ( numeric ) - > float
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* Returns the floating point result of dividing < i > big < / i > by
* < i > numeric < / i > .
2007-05-09 07:49:18 +04:00
*
2008-05-07 08:14:57 +04:00
* - 1234567890987654321.f div ( 13731 ) # = > - 89910996357705.5
* - 1234567890987654321.f div ( 13731.24 ) # = > - 89909424858035.7
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
*/
2009-06-17 16:55:16 +04:00
VALUE
2008-03-16 03:23:43 +03:00
rb_big_fdiv ( VALUE x , VALUE y )
2003-01-23 09:22:50 +03:00
{
2009-06-17 16:55:16 +04:00
double dx , dy ;
2003-01-23 09:22:50 +03:00
2009-06-17 16:55:16 +04:00
dx = big2dbl ( x ) ;
2003-01-23 09:22:50 +03:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
dy = ( double ) FIX2LONG ( y ) ;
2009-06-17 16:55:16 +04:00
if ( isinf ( dx ) )
return big_fdiv ( x , y ) ;
2003-01-23 09:22:50 +03:00
break ;
case T_BIGNUM :
dy = rb_big2dbl ( y ) ;
2009-06-17 16:55:16 +04:00
if ( isinf ( dx ) | | isinf ( dy ) )
return big_fdiv ( x , y ) ;
2003-01-23 09:22:50 +03:00
break ;
case T_FLOAT :
* include/ruby/ruby.h: introduce 2 macros:
RFLOAT_VALUE(v), DOUBLE2NUM(dbl).
Rename RFloat#value -> RFloat#double_value.
Do not touch RFloat#double_value directly.
* bignum.c, insns.def, marshal.c, math.c, numeric.c, object.c,
pack.c, parse.y, process.c, random.c, sprintf.c, string.c,
time.c: apply above changes.
* ext/dl/mkcallback.rb, ext/json/ext/generator/generator.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13913 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-13 19:00:53 +03:00
dy = RFLOAT_VALUE ( y ) ;
2009-06-17 16:55:16 +04:00
if ( isnan ( dy ) )
return y ;
if ( isinf ( dx ) )
return big_fdiv ( x , y ) ;
2003-01-23 09:22:50 +03:00
break ;
default :
2008-03-16 03:23:43 +03:00
return rb_num_coerce_bin ( x , y , rb_intern ( " fdiv " ) ) ;
2003-01-23 09:22:50 +03:00
}
2008-09-05 22:24:21 +04:00
return DBL2NUM ( dx / dy ) ;
2003-01-23 09:22:50 +03:00
}
2007-05-02 00:39:48 +04:00
static VALUE
bigsqr ( VALUE x )
{
2008-12-14 16:39:33 +03:00
return bigtrunc ( bigmul0 ( x , x ) ) ;
2007-05-02 00:39:48 +04:00
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big * * exponent - > numeric
2003-12-19 03:01:19 +03:00
*
* Raises _big_ to the _exponent_ power ( which may be an integer , float ,
* or anything that will coerce to a number ) . The result may be
* a Fixnum , Bignum , or Float
*
* 123456789 * * 2 # = > 15241578750190521
* 123456789 * * 1.2 # = > 5126464716.09932
* 123456789 * * - 2 # = > 6.5610001194102e-17
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_pow ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
double d ;
2007-05-02 00:39:48 +04:00
SIGNED_VALUE yy ;
1998-01-16 15:13:05 +03:00
if ( y = = INT2FIX ( 0 ) ) return INT2FIX ( 1 ) ;
switch ( TYPE ( y ) ) {
case T_FLOAT :
* include/ruby/ruby.h: introduce 2 macros:
RFLOAT_VALUE(v), DOUBLE2NUM(dbl).
Rename RFloat#value -> RFloat#double_value.
Do not touch RFloat#double_value directly.
* bignum.c, insns.def, marshal.c, math.c, numeric.c, object.c,
pack.c, parse.y, process.c, random.c, sprintf.c, string.c,
time.c: apply above changes.
* ext/dl/mkcallback.rb, ext/json/ext/generator/generator.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13913 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-13 19:00:53 +03:00
d = RFLOAT_VALUE ( y ) ;
2009-08-17 03:03:45 +04:00
if ( ( ! RBIGNUM_SIGN ( x ) & & ! BIGZEROP ( x ) ) & & d ! = round ( d ) )
return rb_funcall ( rb_complex_raw1 ( x ) , rb_intern ( " ** " ) , 1 , y ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_BIGNUM :
1999-01-20 07:59:39 +03:00
rb_warn ( " in a**b, b may be too big " ) ;
d = rb_big2dbl ( y ) ;
1998-01-16 15:13:05 +03:00
break ;
case T_FIXNUM :
2004-03-15 05:27:29 +03:00
yy = FIX2LONG ( y ) ;
2008-03-16 03:23:43 +03:00
if ( yy < 0 )
2008-09-19 17:55:52 +04:00
return rb_funcall ( rb_rational_raw1 ( x ) , rb_intern ( " ** " ) , 1 , y ) ;
2008-03-16 03:23:43 +03:00
else {
2007-05-02 00:39:48 +04:00
VALUE z = 0 ;
2007-07-15 19:26:12 +04:00
SIGNED_VALUE mask ;
2013-06-05 03:15:30 +04:00
const long xlen = RBIGNUM_LEN ( x ) ;
const long xbits = BITSPERDIG * xlen - nlz ( RBIGNUM_DIGITS ( x ) [ xlen - 1 ] ) ;
2012-03-18 12:17:50 +04:00
const long BIGLEN_LIMIT = BITSPERDIG * 1024 * 1024 ;
1999-01-20 07:59:39 +03:00
2012-03-18 12:17:50 +04:00
if ( ( xbits > BIGLEN_LIMIT ) | | ( xbits * yy > BIGLEN_LIMIT ) ) {
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
rb_warn ( " in a**b, b may be too big " ) ;
d = ( double ) yy ;
break ;
}
2007-05-02 00:39:48 +04:00
for ( mask = FIXNUM_MAX + 1 ; mask ; mask > > = 1 ) {
2008-12-14 16:39:33 +03:00
if ( z ) z = bigsqr ( z ) ;
2007-05-02 00:39:48 +04:00
if ( yy & mask ) {
2008-12-14 06:59:02 +03:00
z = z ? bigtrunc ( bigmul0 ( z , x ) ) : x ;
2007-05-02 00:39:48 +04:00
}
1999-01-20 07:59:39 +03:00
}
2002-06-11 11:02:23 +04:00
return bignorm ( z ) ;
1999-01-20 07:59:39 +03:00
}
2008-03-16 03:23:43 +03:00
/* NOTREACHED */
1998-01-16 15:13:05 +03:00
break ;
default :
2008-02-12 05:46:21 +03:00
return rb_num_coerce_bin ( x , y , rb_intern ( " ** " ) ) ;
1998-01-16 15:13:05 +03:00
}
2008-09-05 22:24:21 +04:00
return DBL2NUM ( pow ( rb_big2dbl ( x ) , d ) ) ;
1998-01-16 15:13:05 +03:00
}
2009-05-27 20:16:57 +04:00
static VALUE
bigand_int ( VALUE x , long y )
{
VALUE z ;
BDIGIT * xds , * zds ;
long xn , zn ;
long i ;
char sign ;
if ( y = = 0 ) return INT2FIX ( 0 ) ;
sign = ( y > 0 ) ;
xds = BDIGITS ( x ) ;
zn = xn = RBIGNUM_LEN ( x ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
if ( sign ) {
y & = xds [ 0 ] ;
return LONG2NUM ( y ) ;
}
# endif
z = bignew ( zn , RBIGNUM_SIGN ( x ) | | sign ) ;
zds = BDIGITS ( z ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
i = 1 ;
zds [ 0 ] = xds [ 0 ] & y ;
# else
{
BDIGIT_DBL num = y ;
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
zds [ i ] = xds [ i ] & BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
}
# endif
while ( i < xn ) {
zds [ i ] = sign ? 0 : xds [ i ] ;
i + + ;
}
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
return bignorm ( z ) ;
}
2003-12-19 03:01:19 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big & numeric - > integer
2003-12-19 03:01:19 +03:00
*
* Performs bitwise + and + between _big_ and _numeric_ .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_and ( VALUE xx , VALUE yy )
1998-01-16 15:13:05 +03:00
{
2004-08-28 18:14:11 +04:00
volatile VALUE x , y , z ;
2000-10-31 11:37:47 +03:00
BDIGIT * ds1 , * ds2 , * zds ;
1999-08-13 09:45:20 +04:00
long i , l1 , l2 ;
1998-01-16 15:13:05 +03:00
char sign ;
2012-12-22 19:06:22 +04:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' & ' ) ;
}
2004-08-28 18:14:11 +04:00
x = xx ;
2012-12-22 19:06:22 +04:00
y = yy ;
2009-05-27 20:16:57 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 15:13:05 +03:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 20:16:57 +04:00
return bigand_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-20 07:59:39 +03:00
y = rb_big_clone ( y ) ;
2005-06-30 10:20:09 +04:00
get2comp ( y ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 15:13:05 +03:00
}
else {
2007-09-01 16:02:36 +04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
z = bignew ( l2 , RBIGNUM_SIGN ( x ) | | RBIGNUM_SIGN ( y ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
for ( i = 0 ; i < l1 ; i + + ) {
zds [ i ] = ds1 [ i ] & ds2 [ i ] ;
}
for ( ; i < l2 ; i + + ) {
zds [ i ] = sign ? 0 : ds2 [ i ] ;
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2009-05-27 20:16:57 +04:00
static VALUE
bigor_int ( VALUE x , long y )
{
VALUE z ;
BDIGIT * xds , * zds ;
long xn , zn ;
long i ;
char sign ;
sign = ( y > = 0 ) ;
xds = BDIGITS ( x ) ;
zn = xn = RBIGNUM_LEN ( x ) ;
z = bignew ( zn , RBIGNUM_SIGN ( x ) & & sign ) ;
zds = BDIGITS ( z ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
i = 1 ;
zds [ 0 ] = xds [ 0 ] | y ;
# else
{
BDIGIT_DBL num = y ;
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
zds [ i ] = xds [ i ] | BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
}
# endif
while ( i < xn ) {
zds [ i ] = sign ? xds [ i ] : ( BDIGIT ) ( BIGRAD - 1 ) ;
i + + ;
}
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
return bignorm ( z ) ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big | numeric - > integer
2003-12-19 06:58:57 +03:00
*
* Performs bitwise + or + between _big_ and _numeric_ .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_or ( VALUE xx , VALUE yy )
1998-01-16 15:13:05 +03:00
{
2004-08-28 18:14:11 +04:00
volatile VALUE x , y , z ;
2000-10-31 11:37:47 +03:00
BDIGIT * ds1 , * ds2 , * zds ;
long i , l1 , l2 ;
1998-01-16 15:13:05 +03:00
char sign ;
2012-12-22 19:06:22 +04:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' | ' ) ;
}
2004-08-28 18:14:11 +04:00
x = xx ;
2012-12-22 19:06:22 +04:00
y = yy ;
2009-05-27 20:16:57 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 15:13:05 +03:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 20:16:57 +04:00
return bigor_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-20 07:59:39 +03:00
y = rb_big_clone ( y ) ;
2005-06-30 10:20:09 +04:00
get2comp ( y ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 15:13:05 +03:00
}
else {
2007-09-01 16:02:36 +04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
z = bignew ( l2 , RBIGNUM_SIGN ( x ) & & RBIGNUM_SIGN ( y ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
for ( i = 0 ; i < l1 ; i + + ) {
zds [ i ] = ds1 [ i ] | ds2 [ i ] ;
}
for ( ; i < l2 ; i + + ) {
* array.c, bignum.c, dln.c, error.c, gc.c, io.c, marshal.c,
numeric.c, pack.c, strftime.c, string.c, thread.c, transcode.c,
transcode_data.h, util.c, variable.c, vm_dump.c,
include/ruby/encoding.h, missing/crypt.c, missing/vsnprintf.c:
suppress VC type warnings. [ruby-core:22726]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22914 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-12 12:16:15 +03:00
zds [ i ] = sign ? ds2 [ i ] : ( BDIGIT ) ( BIGRAD - 1 ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2009-05-27 20:16:57 +04:00
static VALUE
bigxor_int ( VALUE x , long y )
{
VALUE z ;
BDIGIT * xds , * zds ;
long xn , zn ;
long i ;
char sign ;
sign = ( y > = 0 ) ? 1 : 0 ;
xds = BDIGITS ( x ) ;
zn = xn = RBIGNUM_LEN ( x ) ;
z = bignew ( zn , ! ( RBIGNUM_SIGN ( x ) ^ sign ) ) ;
zds = BDIGITS ( z ) ;
# if SIZEOF_BDIGITS == SIZEOF_LONG
i = 1 ;
zds [ 0 ] = xds [ 0 ] ^ y ;
# else
{
BDIGIT_DBL num = y ;
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
zds [ i ] = xds [ i ] ^ BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
}
# endif
while ( i < xn ) {
zds [ i ] = sign ? xds [ i ] : ~ xds [ i ] ;
i + + ;
}
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
return bignorm ( z ) ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big ^ numeric - > integer
2003-12-19 06:58:57 +03:00
*
* Performs bitwise + exclusive or + between _big_ and _numeric_ .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_xor ( VALUE xx , VALUE yy )
1998-01-16 15:13:05 +03:00
{
2004-09-03 13:00:52 +04:00
volatile VALUE x , y ;
1998-01-16 15:13:05 +03:00
VALUE z ;
2000-10-31 11:37:47 +03:00
BDIGIT * ds1 , * ds2 , * zds ;
long i , l1 , l2 ;
1998-01-16 15:13:05 +03:00
char sign ;
2012-12-22 19:06:22 +04:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' ^ ' ) ;
}
2004-09-03 13:00:52 +04:00
x = xx ;
2012-12-22 19:06:22 +04:00
y = yy ;
2009-05-27 20:16:57 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 15:13:05 +03:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 20:16:57 +04:00
return bigxor_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-20 07:59:39 +03:00
y = rb_big_clone ( y ) ;
2005-06-30 10:20:09 +04:00
get2comp ( y ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 15:13:05 +03:00
}
else {
2007-09-01 16:02:36 +04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 15:13:05 +03:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 16:02:36 +04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 15:13:05 +03:00
}
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( x , RBIGNUM_SIGN ( x ) ? 1 : 0 ) ;
RBIGNUM_SET_SIGN ( y , RBIGNUM_SIGN ( y ) ? 1 : 0 ) ;
z = bignew ( l2 , ! ( RBIGNUM_SIGN ( x ) ^ RBIGNUM_SIGN ( y ) ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
for ( i = 0 ; i < l1 ; i + + ) {
zds [ i ] = ds1 [ i ] ^ ds2 [ i ] ;
}
for ( ; i < l2 ; i + + ) {
zds [ i ] = sign ? ds2 [ i ] : ~ ds2 [ i ] ;
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 15:13:05 +03:00
return bignorm ( z ) ;
}
2007-07-19 09:38:48 +04:00
static VALUE
check_shiftdown ( VALUE y , VALUE x )
{
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_LEN ( x ) ) return INT2FIX ( 0 ) ;
if ( RBIGNUM_LEN ( y ) > SIZEOF_LONG / SIZEOF_BDIGITS ) {
return RBIGNUM_SIGN ( x ) ? INT2FIX ( 0 ) : INT2FIX ( - 1 ) ;
2007-07-19 09:38:48 +04:00
}
return Qnil ;
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big < < numeric - > integer
2003-12-19 06:58:57 +03:00
*
* Shifts big left _numeric_ positions ( right if _numeric_ is negative ) .
*/
1998-01-16 15:13:05 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_lshift ( VALUE x , VALUE y )
2007-07-19 09:38:48 +04:00
{
2007-08-16 08:09:02 +04:00
long shift ;
int neg = 0 ;
2007-07-19 09:38:48 +04:00
for ( ; ; ) {
if ( FIXNUM_P ( y ) ) {
2007-08-16 08:09:02 +04:00
shift = FIX2LONG ( y ) ;
2007-07-19 09:38:48 +04:00
if ( shift < 0 ) {
neg = 1 ;
shift = - shift ;
}
break ;
}
2011-09-29 15:07:45 +04:00
else if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
2007-07-19 09:38:48 +04:00
VALUE t = check_shiftdown ( y , x ) ;
if ( ! NIL_P ( t ) ) return t ;
neg = 1 ;
}
2009-07-18 12:05:32 +04:00
shift = big2ulong ( y , " long " , TRUE ) ;
2007-07-19 09:38:48 +04:00
break ;
}
y = rb_to_int ( y ) ;
}
2009-06-19 03:14:08 +04:00
x = neg ? big_rshift ( x , shift ) : big_lshift ( x , shift ) ;
return bignorm ( x ) ;
2007-07-19 09:38:48 +04:00
}
2013-06-14 21:41:38 +04:00
static BDIGIT
bdigs_small_lshift ( BDIGIT * zds , BDIGIT * xds , long n , int shift )
{
long i ;
BDIGIT_DBL num = 0 ;
for ( i = 0 ; i < n ; i + + ) {
num = num | ( BDIGIT_DBL ) * xds + + < < shift ;
* zds + + = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
return BIGLO ( num ) ;
}
2007-07-19 09:38:48 +04:00
static VALUE
2007-08-16 08:09:02 +04:00
big_lshift ( VALUE x , unsigned long shift )
1998-01-16 15:13:05 +03:00
{
2000-10-31 11:37:47 +03:00
BDIGIT * xds , * zds ;
2007-08-16 08:09:02 +04:00
long s1 = shift / BITSPERDIG ;
2009-05-26 08:58:15 +04:00
int s2 = ( int ) ( shift % BITSPERDIG ) ;
1998-01-16 15:13:05 +03:00
VALUE z ;
1999-08-13 09:45:20 +04:00
long len , i ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
len = RBIGNUM_LEN ( x ) ;
z = bignew ( len + s1 + 1 , RBIGNUM_SIGN ( x ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
for ( i = 0 ; i < s1 ; i + + ) {
* zds + + = 0 ;
}
2000-06-28 12:31:35 +04:00
xds = BDIGITS ( x ) ;
2013-06-14 21:41:38 +04:00
zds [ len ] = bdigs_small_lshift ( zds , xds , len , s2 ) ;
2009-06-19 03:14:08 +04:00
return z ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big > > numeric - > integer
2003-12-19 06:58:57 +03:00
*
* Shifts big right _numeric_ positions ( left if _numeric_ is negative ) .
*/
2007-07-19 09:38:48 +04:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_rshift ( VALUE x , VALUE y )
2007-07-19 09:38:48 +04:00
{
2007-08-16 08:09:02 +04:00
long shift ;
2007-07-19 09:38:48 +04:00
int neg = 0 ;
for ( ; ; ) {
if ( FIXNUM_P ( y ) ) {
2007-08-16 08:09:02 +04:00
shift = FIX2LONG ( y ) ;
2007-07-19 09:38:48 +04:00
if ( shift < 0 ) {
neg = 1 ;
shift = - shift ;
}
break ;
}
2011-09-29 15:07:45 +04:00
else if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( y ) ) {
2007-07-19 09:38:48 +04:00
VALUE t = check_shiftdown ( y , x ) ;
if ( ! NIL_P ( t ) ) return t ;
}
else {
neg = 1 ;
}
2009-07-18 12:05:32 +04:00
shift = big2ulong ( y , " long " , TRUE ) ;
2007-07-19 09:38:48 +04:00
break ;
}
y = rb_to_int ( y ) ;
}
2009-06-19 03:14:08 +04:00
x = neg ? big_lshift ( x , shift ) : big_rshift ( x , shift ) ;
return bignorm ( x ) ;
2007-07-19 09:38:48 +04:00
}
2013-06-15 05:03:37 +04:00
static void
bdigs_small_rshift ( BDIGIT * zds , BDIGIT * xds , long n , int shift , int sign_bit )
{
BDIGIT_DBL num = 0 ;
BDIGIT x ;
if ( sign_bit ) {
num = ( ~ ( BDIGIT_DBL ) 0 ) < < BITSPERDIG ;
}
while ( n - - ) {
num = ( num | xds [ n ] ) > > shift ;
x = xds [ n ] ;
zds [ n ] = BIGLO ( num ) ;
num = BIGUP ( x ) ;
}
}
2007-07-19 09:38:48 +04:00
static VALUE
2007-08-16 08:09:02 +04:00
big_rshift ( VALUE x , unsigned long shift )
1998-01-16 15:13:05 +03:00
{
2000-10-31 11:37:47 +03:00
BDIGIT * xds , * zds ;
2002-08-21 19:47:54 +04:00
long s1 = shift / BITSPERDIG ;
2009-05-26 08:58:15 +04:00
int s2 = ( int ) ( shift % BITSPERDIG ) ;
1998-01-16 15:13:05 +03:00
VALUE z ;
2002-08-21 19:47:54 +04:00
long i , j ;
2005-12-16 21:59:31 +03:00
volatile VALUE save_x ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
if ( s1 > RBIGNUM_LEN ( x ) ) {
if ( RBIGNUM_SIGN ( x ) )
1998-01-16 15:13:05 +03:00
return INT2FIX ( 0 ) ;
else
return INT2FIX ( - 1 ) ;
}
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
x = rb_big_clone ( x ) ;
2005-06-30 10:20:09 +04:00
get2comp ( x ) ;
2002-02-15 07:43:58 +03:00
}
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
save_x = x ;
1998-01-16 15:13:05 +03:00
xds = BDIGITS ( x ) ;
2007-09-01 16:02:36 +04:00
i = RBIGNUM_LEN ( x ) ; j = i - s1 ;
2006-10-07 19:49:00 +04:00
if ( j = = 0 ) {
2007-09-01 16:02:36 +04:00
if ( RBIGNUM_SIGN ( x ) ) return INT2FIX ( 0 ) ;
2006-10-07 19:49:00 +04:00
else return INT2FIX ( - 1 ) ;
}
2007-09-01 16:02:36 +04:00
z = bignew ( j , RBIGNUM_SIGN ( x ) ) ;
1998-01-16 15:13:05 +03:00
zds = BDIGITS ( z ) ;
2013-06-15 05:03:37 +04:00
bdigs_small_rshift ( zds , xds + s1 , j , s2 , ! RBIGNUM_SIGN ( x ) ) ;
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
2005-06-30 10:20:09 +04:00
get2comp ( z ) ;
2002-02-15 07:43:58 +03:00
}
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
RB_GC_GUARD ( save_x ) ;
2009-06-19 03:14:08 +04:00
return z ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
* big [ n ] - > 0 , 1
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Bit Reference - - - Returns the < em > n < / em > th bit in the ( assumed ) binary
* representation of < i > big < / i > , where < i > big < / i > [ 0 ] is the least
* significant bit .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* a = 9 * * 15
* 50. downto ( 0 ) do | n |
* print a [ n ]
* end
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* < em > produces : < / em >
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* 000101110110100000111000011110010100111100010111001
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_aref ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
2000-10-31 11:37:47 +03:00
BDIGIT * xds ;
2007-07-30 06:16:42 +04:00
BDIGIT_DBL num ;
VALUE shift ;
long i , s1 , s2 ;
1998-01-16 15:13:05 +03:00
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( y ) )
2001-11-01 08:11:24 +03:00
return INT2FIX ( 0 ) ;
2009-05-26 06:19:33 +04:00
bigtrunc ( y ) ;
if ( RBIGNUM_LEN ( y ) > DIGSPERLONG ) {
2007-07-30 06:16:42 +04:00
out_of_range :
2007-09-01 16:02:36 +04:00
return RBIGNUM_SIGN ( x ) ? INT2FIX ( 0 ) : INT2FIX ( 1 ) ;
2007-07-30 06:16:42 +04:00
}
2009-07-18 12:05:32 +04:00
shift = big2ulong ( y , " long " , FALSE ) ;
2007-07-30 06:16:42 +04:00
}
else {
i = NUM2LONG ( y ) ;
if ( i < 0 ) return INT2FIX ( 0 ) ;
shift = ( VALUE ) i ;
2001-11-01 08:11:24 +03:00
}
1998-01-16 15:19:22 +03:00
s1 = shift / BITSPERDIG ;
s2 = shift % BITSPERDIG ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
if ( s1 > = RBIGNUM_LEN ( x ) ) goto out_of_range ;
if ( ! RBIGNUM_SIGN ( x ) ) {
2007-07-30 06:16:42 +04:00
xds = BDIGITS ( x ) ;
i = 0 ; num = 1 ;
while ( num + = ~ xds [ i ] , + + i < = s1 ) {
num = BIGDN ( num ) ;
}
1998-01-16 15:13:05 +03:00
}
else {
2007-07-30 06:16:42 +04:00
num = BDIGITS ( x ) [ s1 ] ;
1998-01-16 15:13:05 +03:00
}
2007-07-30 06:16:42 +04:00
if ( num & ( ( BDIGIT_DBL ) 1 < < s2 ) )
1998-01-16 15:13:05 +03:00
return INT2FIX ( 1 ) ;
return INT2FIX ( 0 ) ;
}
2003-12-29 06:56:22 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* big . hash - > fixnum
2003-12-29 06:56:22 +03:00
*
* Compute a hash based on the value of _big_ .
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_hash ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2009-09-08 17:10:04 +04:00
st_index_t hash ;
1998-01-16 15:13:05 +03:00
2007-09-01 16:02:36 +04:00
hash = rb_memhash ( BDIGITS ( x ) , sizeof ( BDIGIT ) * RBIGNUM_LEN ( x ) ) ^ RBIGNUM_SIGN ( x ) ;
2006-09-22 02:52:38 +04:00
return INT2FIX ( hash ) ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 03:01:19 +03:00
/*
* MISSING : documentation
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_coerce ( VALUE x , VALUE y )
1998-01-16 15:13:05 +03:00
{
if ( FIXNUM_P ( y ) ) {
2012-04-15 04:06:13 +04:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
2005-08-10 05:39:24 +04:00
}
2012-04-15 04:06:13 +04:00
else if ( ! RB_TYPE_P ( y , T_BIGNUM ) ) {
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
rb_raise ( rb_eTypeError , " can't coerce %s to Bignum " ,
2003-01-31 07:00:17 +03:00
rb_obj_classname ( y ) ) ;
1998-01-16 15:13:05 +03:00
}
2012-04-15 04:06:13 +04:00
return rb_assoc_new ( y , x ) ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
* big . abs - > aBignum
2013-04-12 06:59:07 +04:00
* big . magnitude - > aBignum
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Returns the absolute value of < i > big < / i > .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* - 1234567890987654321. abs # = > 1234567890987654321
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_abs ( VALUE x )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
1999-01-20 07:59:39 +03:00
x = rb_big_clone ( x ) ;
2007-09-01 16:02:36 +04:00
RBIGNUM_SET_SIGN ( x , 1 ) ;
1998-01-16 15:13:05 +03:00
}
1999-01-20 07:59:39 +03:00
return x ;
1998-01-16 15:13:05 +03:00
}
2003-12-19 06:58:57 +03:00
/*
* call - seq :
* big . size - > integer
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* Returns the number of bytes in the machine representation of
* < i > big < / i > .
2007-05-09 07:49:18 +04:00
*
2003-12-19 06:58:57 +03:00
* ( 256 * * 10 - 1 ) . size # = > 12
* ( 256 * * 20 - 1 ) . size # = > 20
* ( 256 * * 40 - 1 ) . size # = > 40
*/
1998-01-16 15:13:05 +03:00
static VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_big_size ( VALUE big )
1998-01-16 15:13:05 +03:00
{
2007-09-01 16:02:36 +04:00
return LONG2FIX ( RBIGNUM_LEN ( big ) * SIZEOF_BDIGITS ) ;
1998-01-16 15:13:05 +03:00
}
2007-11-16 17:41:11 +03:00
/*
* call - seq :
* big . odd ? - > true or false
*
* Returns < code > true < / code > if < i > big < / i > is an odd number .
*/
static VALUE
rb_big_odd_p ( VALUE num )
{
if ( BDIGITS ( num ) [ 0 ] & 1 ) {
2007-11-27 20:42:12 +03:00
return Qtrue ;
2007-11-16 17:41:11 +03:00
}
return Qfalse ;
}
/*
* call - seq :
* big . even ? - > true or false
*
* Returns < code > true < / code > if < i > big < / i > is an even number .
*/
static VALUE
rb_big_even_p ( VALUE num )
{
if ( BDIGITS ( num ) [ 0 ] & 1 ) {
2007-11-27 20:42:12 +03:00
return Qfalse ;
2007-11-16 17:41:11 +03:00
}
return Qtrue ;
}
2003-12-19 03:01:19 +03:00
/*
* Bignum objects hold integers outside the range of
* Fixnum . Bignum objects are created
* automatically when integer calculations would otherwise overflow a
* Fixnum . When a calculation involving
* Bignum objects returns a result that will fit in a
* Fixnum , the result is automatically converted .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* For the purposes of the bitwise operations and < code > [ ] < / code > , a
* Bignum is treated as if it were an infinite - length
* bitstring with 2 ' s complement representation .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
* While Fixnum values are immediate , Bignum
* objects are not - - - assignment and parameter passing work with
* references to objects , not the objects themselves .
2007-05-09 07:49:18 +04:00
*
2003-12-19 03:01:19 +03:00
*/
1998-01-16 15:13:05 +03:00
void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
Init_Bignum ( void )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
rb_cBignum = rb_define_class ( " Bignum " , rb_cInteger ) ;
2001-11-19 08:03:03 +03:00
rb_define_method ( rb_cBignum , " to_s " , rb_big_to_s , - 1 ) ;
2012-08-15 15:50:01 +04:00
rb_define_alias ( rb_cBignum , " inspect " , " to_s " ) ;
1999-01-20 07:59:39 +03:00
rb_define_method ( rb_cBignum , " coerce " , rb_big_coerce , 1 ) ;
rb_define_method ( rb_cBignum , " -@ " , rb_big_uminus , 0 ) ;
rb_define_method ( rb_cBignum , " + " , rb_big_plus , 1 ) ;
rb_define_method ( rb_cBignum , " - " , rb_big_minus , 1 ) ;
rb_define_method ( rb_cBignum , " * " , rb_big_mul , 1 ) ;
rb_define_method ( rb_cBignum , " / " , rb_big_div , 1 ) ;
2000-07-06 11:21:26 +04:00
rb_define_method ( rb_cBignum , " % " , rb_big_modulo , 1 ) ;
2008-04-07 17:52:26 +04:00
rb_define_method ( rb_cBignum , " div " , rb_big_idiv , 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_method ( rb_cBignum , " divmod " , rb_big_divmod , 1 ) ;
2000-07-06 11:21:26 +04:00
rb_define_method ( rb_cBignum , " modulo " , rb_big_modulo , 1 ) ;
rb_define_method ( rb_cBignum , " remainder " , rb_big_remainder , 1 ) ;
2008-03-16 03:23:43 +03:00
rb_define_method ( rb_cBignum , " fdiv " , rb_big_fdiv , 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_method ( rb_cBignum , " ** " , rb_big_pow , 1 ) ;
rb_define_method ( rb_cBignum , " & " , rb_big_and , 1 ) ;
rb_define_method ( rb_cBignum , " | " , rb_big_or , 1 ) ;
rb_define_method ( rb_cBignum , " ^ " , rb_big_xor , 1 ) ;
rb_define_method ( rb_cBignum , " ~ " , rb_big_neg , 0 ) ;
rb_define_method ( rb_cBignum , " << " , rb_big_lshift , 1 ) ;
rb_define_method ( rb_cBignum , " >> " , rb_big_rshift , 1 ) ;
rb_define_method ( rb_cBignum , " [] " , rb_big_aref , 1 ) ;
rb_define_method ( rb_cBignum , " <=> " , rb_big_cmp , 1 ) ;
rb_define_method ( rb_cBignum , " == " , rb_big_eq , 1 ) ;
2010-02-04 18:36:29 +03:00
rb_define_method ( rb_cBignum , " > " , big_gt , 1 ) ;
rb_define_method ( rb_cBignum , " >= " , big_ge , 1 ) ;
rb_define_method ( rb_cBignum , " < " , big_lt , 1 ) ;
rb_define_method ( rb_cBignum , " <= " , big_le , 1 ) ;
2009-08-12 09:55:06 +04:00
rb_define_method ( rb_cBignum , " === " , rb_big_eq , 1 ) ;
2001-11-08 09:43:14 +03:00
rb_define_method ( rb_cBignum , " eql? " , rb_big_eql , 1 ) ;
1999-01-20 07:59:39 +03:00
rb_define_method ( rb_cBignum , " hash " , rb_big_hash , 0 ) ;
rb_define_method ( rb_cBignum , " to_f " , rb_big_to_f , 0 ) ;
rb_define_method ( rb_cBignum , " abs " , rb_big_abs , 0 ) ;
2008-08-29 18:50:43 +04:00
rb_define_method ( rb_cBignum , " magnitude " , rb_big_abs , 0 ) ;
1999-01-20 07:59:39 +03:00
rb_define_method ( rb_cBignum , " size " , rb_big_size , 0 ) ;
2007-11-16 17:41:11 +03:00
rb_define_method ( rb_cBignum , " odd? " , rb_big_odd_p , 0 ) ;
rb_define_method ( rb_cBignum , " even? " , rb_big_even_p , 0 ) ;
2008-03-07 15:14:17 +03:00
power_cache_init ( ) ;
2011-05-22 19:37:00 +04:00
big_three = rb_uint2big ( 3 ) ;
rb_gc_register_mark_object ( big_three ) ;
1998-01-16 15:13:05 +03:00
}