2000-05-01 05:42:38 -04:00
/**********************************************************************
1998-01-16 07:13:05 -05: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-24 23:29:39 -04:00
Copyright ( C ) 1993 - 2007 Yukihiro Matsumoto
2000-05-01 05:42:38 -04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-01-16 07:13:05 -05:00
2007-06-09 23:06:15 -04:00
# include "ruby/ruby.h"
2012-07-10 09:57:11 -04:00
# include "ruby/thread.h"
2009-05-26 00: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-17 18:43:38 -04:00
# include "internal.h"
2002-05-14 02:22:31 -04:00
2012-07-18 14:48:14 -04:00
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
1998-01-16 07:13:05 -05:00
# include <math.h>
2007-05-02 04:12:31 -04:00
# include <float.h>
1999-01-19 23:59:39 -05:00
# include <ctype.h>
2003-12-22 03:23:55 -05:00
# ifdef HAVE_IEEEFP_H
# include <ieeefp.h>
# endif
2008-12-13 22:59:02 -05:00
# include <assert.h>
1998-01-16 07:13:05 -05:00
1999-01-19 23:59:39 -05:00
VALUE rb_cBignum ;
2000-06-04 11:32:19 -04:00
2011-05-22 11:37:00 -04:00
static VALUE big_three = Qnil ;
2000-06-04 11:32:19 -04:00
# if defined __MINGW32__
# define USHORT _USHORT
# endif
2007-09-01 08:02:36 -04:00
# define BDIGITS(x) (RBIGNUM_DIGITS(x))
2002-04-10 04:45:26 -04:00
# define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
2000-11-01 03:49:40 -05:00
# define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
2011-05-22 11:37:00 -04:00
# define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
2009-05-26 00:58:15 -04:00
# define DIGSPERLONG (SIZEOF_LONG / SIZEOF_BDIGITS)
2002-03-14 01:23:46 -05:00
# if HAVE_LONG_LONG
2009-05-26 00:58:15 -04:00
# define DIGSPERLL (SIZEOF_LONG_LONG / SIZEOF_BDIGITS)
2002-03-14 01:23:46 -05:00
# endif
2000-11-01 03:49:40 -05:00
# define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
2010-12-02 03:01:24 -05:00
# define BIGDN(x) RSHIFT((x),BITSPERDIG)
2000-10-31 03:37:47 -05:00
# define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
2003-01-14 02:45:19 -05:00
# define BDIGMAX ((BDIGIT)-1)
1998-01-16 07:13:05 -05:00
2008-02-22 05:50:21 -05:00
# define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
( BDIGITS ( x ) [ 0 ] = = 0 & & \
( RBIGNUM_LEN ( x ) = = 1 | | bigzero_p ( x ) ) ) )
2013-06-06 07:57:35 -04:00
static int nlz ( BDIGIT x ) ;
2011-05-22 11: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 05:50:21 -05:00
static int
bigzero_p ( VALUE x )
{
long i ;
2009-08-07 22:47:02 -04:00
BDIGIT * ds = BDIGITS ( x ) ;
2008-05-12 00:44:13 -04:00
for ( i = RBIGNUM_LEN ( x ) - 1 ; 0 < = i ; i - - ) {
2009-08-07 22:47:02 -04:00
if ( ds [ i ] ) return 0 ;
2008-02-22 05:50:21 -05:00
}
return 1 ;
}
2007-09-01 08:02:36 -04:00
2009-07-16 02:52:29 -04:00
int
rb_bigzero_p ( VALUE x )
{
return BIGZEROP ( x ) ;
}
2008-04-06 13:11:50 -04:00
int
rb_cmpint ( VALUE val , VALUE a , VALUE b )
{
if ( NIL_P ( val ) ) {
rb_cmperr ( a , b ) ;
}
2009-03-26 12:20:58 -04:00
if ( FIXNUM_P ( val ) ) {
long l = FIX2LONG ( val ) ;
if ( l > 0 ) return 1 ;
if ( l < 0 ) return - 1 ;
return 0 ;
}
2011-09-29 07:07:45 -04:00
if ( RB_TYPE_P ( val , T_BIGNUM ) ) {
2008-04-06 13: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 08: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 05:16:15 -04: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 08: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 07:28:57 -05: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 08:02:36 -04:00
}
else {
2008-03-07 07:28:57 -05: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 06:01:40 -04:00
xfree ( ds ) ;
2008-03-07 07:28:57 -05: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 08: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 02:44:34 -04:00
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
bignew_1 ( VALUE klass , long len , int sign )
1998-01-16 07:13:05 -05: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 14:07:47 -04:00
NEWOBJ_OF ( big , struct RBignum , klass , T_BIGNUM | ( RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0 ) ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , sign ? 1 : 0 ) ;
if ( len < = RBIGNUM_EMBED_LEN_MAX ) {
2008-03-07 07:28:57 -05:00
RBASIC ( big ) - > flags | = RBIGNUM_EMBED_FLAG ;
RBIGNUM_SET_LEN ( big , len ) ;
2007-09-01 08:02:36 -04:00
}
else {
2009-05-25 22:19:33 -04:00
RBIGNUM ( big ) - > as . heap . digits = ALLOC_N ( BDIGIT , len ) ;
RBIGNUM ( big ) - > as . heap . len = len ;
2007-09-01 08:02:36 -04:00
}
2012-10-27 20:03:20 -04:00
OBJ_FREEZE ( big ) ;
1998-01-16 07:13:05 -05:00
return ( VALUE ) big ;
}
2010-12-02 03:01:24 -05:00
# define bignew(len,sign) bignew_1(rb_cBignum,(len),(sign))
1998-01-16 07:13:05 -05:00
2009-07-16 02:52:29 -04:00
VALUE
rb_big_new ( long len , int sign )
{
return bignew ( len , sign ! = 0 ) ;
}
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_clone ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2009-08-25 04:38:28 -04:00
long len = RBIGNUM_LEN ( x ) ;
VALUE z = bignew_1 ( CLASS_OF ( x ) , len , RBIGNUM_SIGN ( x ) ) ;
1998-01-16 07:13:05 -05:00
2009-08-25 04:38:28 -04:00
MEMCPY ( BDIGITS ( z ) , BDIGITS ( x ) , BDIGIT , len ) ;
1998-01-16 07:19:22 -05:00
return z ;
1998-01-16 07:13:05 -05:00
}
2005-06-30 02:20:09 -04:00
/* modify a bignum by 2's complement */
2002-02-22 05:28:47 -05:00
static void
2005-06-30 02:20:09 -04:00
get2comp ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
long i = RBIGNUM_LEN ( x ) ;
2000-10-31 03:37:47 -05:00
BDIGIT * ds = BDIGITS ( x ) ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num ;
1998-01-16 07:13:05 -05:00
2007-07-14 15:42:25 -04:00
if ( ! i ) return ;
1998-01-16 07:13:05 -05:00
while ( i - - ) ds [ i ] = ~ ds [ i ] ;
i = 0 ; num = 1 ;
do {
1999-01-19 23:59:39 -05:00
num + = ds [ i ] ;
1998-01-16 07:13:05 -05:00
ds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
2007-09-01 08:02:36 -04:00
} while ( i < RBIGNUM_LEN ( x ) ) ;
2005-06-30 02:20:09 -04:00
if ( num ! = 0 ) {
2008-03-07 07:28:57 -05:00
rb_big_resize ( x , RBIGNUM_LEN ( x ) + 1 ) ;
1998-01-16 07:13:05 -05:00
ds = BDIGITS ( x ) ;
2007-09-01 08:02:36 -04:00
ds [ RBIGNUM_LEN ( x ) - 1 ] = 1 ;
1998-01-16 07:13:05 -05:00
}
}
2002-02-22 05:28:47 -05: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 06:44:21 -04:00
rb_big_2comp ( VALUE x ) /* get 2's complement */
2002-02-22 05:28:47 -05:00
{
2005-06-30 02:20:09 -04:00
get2comp ( x ) ;
2002-02-22 05:28:47 -05:00
}
2009-04-20 13:53:36 -04:00
static inline VALUE
2007-04-26 11:02:57 -04:00
bigtrunc ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
long len = RBIGNUM_LEN ( x ) ;
2007-04-26 11:02:57 -04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 07:13:05 -05:00
2007-08-16 18:22:24 -04:00
if ( len = = 0 ) return x ;
2007-07-15 08:07:46 -04:00
while ( - - len & & ! ds [ len ] ) ;
2009-05-25 22:19:33 -04:00
if ( RBIGNUM_LEN ( x ) > len + 1 ) {
rb_big_resize ( x , len + 1 ) ;
}
2007-04-26 11:02:57 -04:00
return x ;
}
2009-05-25 22:19:33 -04:00
static inline VALUE
2007-04-26 11:02:57 -04:00
bigfixize ( VALUE x )
{
2007-09-01 08:02:36 -04:00
long len = RBIGNUM_LEN ( x ) ;
2007-04-26 11:02:57 -04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 07:13:05 -05:00
2009-03-12 20:30:15 -04:00
if ( len = = 0 ) return INT2FIX ( 0 ) ;
2009-05-26 00:58:15 -04:00
if ( ( size_t ) ( len * SIZEOF_BDIGITS ) < = sizeof ( long ) ) {
2007-06-26 02: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 05:16:15 -04:00
# if 2*SIZEOF_BDIGITS > SIZEOF_LONG
num = ( long ) ds [ 0 ] ;
# else
2007-04-26 11: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 05:16:15 -04:00
num = ( long ) ( BIGUP ( num ) + ds [ len ] ) ;
2007-04-26 11: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 05:16:15 -04:00
# endif
2007-04-26 11:02:57 -04:00
if ( num > = 0 ) {
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_SIGN ( x ) ) {
2007-04-26 11:02:57 -04:00
if ( POSFIXABLE ( num ) ) return LONG2FIX ( num ) ;
2000-07-12 02:06:50 -04:00
}
2007-04-26 11: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 05:16:15 -04:00
if ( NEGFIXABLE ( - num ) ) return LONG2FIX ( - num ) ;
1999-01-19 23:59:39 -05:00
}
1998-01-16 07:13:05 -05:00
}
}
1998-01-16 07:19:22 -05:00
return x ;
1998-01-16 07:13:05 -05:00
}
2007-04-26 11:02:57 -04:00
static VALUE
bignorm ( VALUE x )
{
2011-09-29 07:07:45 -04:00
if ( RB_TYPE_P ( x , T_BIGNUM ) ) {
2007-04-26 11:02:57 -04:00
x = bigfixize ( bigtrunc ( x ) ) ;
}
return x ;
}
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_norm ( VALUE x )
1998-01-16 07:13:05 -05:00
{
1999-01-19 23:59:39 -05:00
return bignorm ( x ) ;
1998-01-16 07:13:05 -05:00
}
VALUE
2006-07-11 01:00:02 -04:00
rb_uint2big ( VALUE n )
1998-01-16 07:13:05 -05:00
{
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num = n ;
2000-10-31 03:37:47 -05:00
long i = 0 ;
BDIGIT * digits ;
1998-01-16 07:19:22 -05:00
VALUE big ;
1998-01-16 07:13:05 -05:00
2000-01-04 23:41:21 -05:00
big = bignew ( DIGSPERLONG , 1 ) ;
1998-01-16 07:13:05 -05:00
digits = BDIGITS ( big ) ;
2000-01-04 23:41:21 -05:00
while ( i < DIGSPERLONG ) {
2000-10-31 03:37:47 -05:00
digits [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
1998-01-16 07:13:05 -05:00
}
2000-01-04 23:41:21 -05:00
i = DIGSPERLONG ;
2002-08-13 05:21:18 -04:00
while ( - - i & & ! digits [ i ] ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
1998-01-16 07:19:22 -05:00
return big ;
1998-01-16 07:13:05 -05:00
}
VALUE
2006-07-11 01:00:02 -04:00
rb_int2big ( SIGNED_VALUE n )
1998-01-16 07:13:05 -05:00
{
1999-01-19 23:59:39 -05:00
long neg = 0 ;
2013-04-09 07:39:53 -04:00
VALUE u ;
1998-01-16 07:19:22 -05:00
VALUE big ;
1998-01-16 07:13:05 -05:00
if ( n < 0 ) {
2013-04-09 07:39:53 -04:00
u = 1 + ( VALUE ) ( - ( n + 1 ) ) ; /* u = -n avoiding overflow */
1998-01-16 07:13:05 -05:00
neg = 1 ;
}
2013-04-09 07:39:53 -04:00
else {
u = n ;
}
big = rb_uint2big ( u ) ;
1998-01-16 07:13:05 -05:00
if ( neg ) {
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
1998-01-16 07:13:05 -05:00
}
1998-01-16 07:19:22 -05:00
return big ;
1998-01-16 07:13:05 -05:00
}
VALUE
2006-07-11 01:00:02 -04:00
rb_uint2inum ( VALUE n )
1998-01-16 07:13:05 -05:00
{
2002-08-21 11:47:54 -04:00
if ( POSFIXABLE ( n ) ) return LONG2FIX ( n ) ;
1999-01-19 23:59:39 -05:00
return rb_uint2big ( n ) ;
1998-01-16 07:13:05 -05:00
}
VALUE
2006-07-11 01:00:02 -04:00
rb_int2inum ( SIGNED_VALUE n )
1998-01-16 07:13:05 -05:00
{
2002-08-21 11:47:54 -04:00
if ( FIXABLE ( n ) ) return LONG2FIX ( n ) ;
1999-01-19 23:59:39 -05:00
return rb_int2big ( n ) ;
1998-01-16 07:13:05 -05:00
}
2010-02-27 01:56:46 -05:00
# if SIZEOF_LONG % SIZEOF_BDIGITS != 0
# error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
# endif
2010-03-04 09:20:49 -05: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 05:52:51 -05: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-18 23:10:21 -04:00
* higher words ( including a sign bit ) are ignored .
2010-03-04 09:20:49 -05:00
*/
2010-02-26 13:51:02 -05: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 09:15:24 -05:00
for ( j = 0 ; j < DIGSPERLONG & & ds < dend ; j + + , ds + + ) {
l | = ( ( unsigned long ) * ds < < ( j * BITSPERDIG ) ) ;
2010-02-26 13:51:02 -05: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 05:52:51 -05:00
/* See rb_big_pack comment for endianness and sign of buf. */
2010-02-26 13:51:02 -05: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 09:15:24 -05:00
long len = num_longs * DIGSPERLONG ;
2010-02-26 13:51:02 -05: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 09:15:24 -05:00
for ( j = 0 ; j < DIGSPERLONG ; j + + ) {
2010-02-26 13:51:02 -05: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 07:57:35 -04:00
/* number of bytes of abs(val). additionaly number of leading zeros can be returned. */
2013-06-09 08:37:38 -04:00
/*
2013-06-10 06:37:39 -04:00
* Calculate the number of bytes to be required to represent
2013-06-09 08: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 07:57:35 -04:00
size_t
2013-06-09 08:37:38 -04:00
rb_absint_size ( VALUE val , int * nlz_bits_ret )
2013-06-06 07:57:35 -04:00
{
BDIGIT * dp ;
BDIGIT * de ;
BDIGIT fixbuf [ ( sizeof ( long ) + SIZEOF_BDIGITS - 1 ) / SIZEOF_BDIGITS ] ;
2013-06-07 05:25:47 -04:00
2013-06-06 07: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 05:25:47 -04:00
{
int i ;
2013-06-07 06:24:07 -04:00
for ( i = 0 ; i < numberof ( fixbuf ) ; i + + ) {
2013-06-07 05:25:47 -04:00
fixbuf [ i ] = ( BDIGIT ) ( v & ( ( 1L < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
v > > = SIZEOF_BDIGITS * CHAR_BIT ;
}
2013-06-06 07:57:35 -04:00
}
# endif
dp = fixbuf ;
2013-06-07 06:24:07 -04:00
de = fixbuf + numberof ( fixbuf ) ;
2013-06-06 07: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 08:37:38 -04:00
if ( nlz_bits_ret )
* nlz_bits_ret = 0 ;
2013-06-06 07:57:35 -04:00
return 0 ;
}
num_leading_zeros = nlz ( de [ - 1 ] ) ;
2013-06-09 08:37:38 -04:00
if ( nlz_bits_ret )
* nlz_bits_ret = num_leading_zeros % CHAR_BIT ;
2013-06-06 07:57:35 -04:00
return ( de - dp ) * SIZEOF_BDIGITS - num_leading_zeros / CHAR_BIT ;
}
size_t
2013-06-09 12:08:54 -04:00
absint_numwords_bytes ( size_t numbytes , int nlz_bits_in_msbyte , size_t word_numbits , size_t * nlz_bits_ret )
2013-06-06 07:57:35 -04:00
{
2013-06-09 12:08:54 -04:00
/*
* word_numbytes = word_numbits / CHAR_BIT
* div , mod = val_numbits . divmod ( word_numbits )
*
* q , r = numbytes . divmod ( word_numbytes )
* s = q if r * CHAR_BIT > = nlz_bits_in_msbyte
* = q - 1 if otherwise
* t = r * CHAR_BIT - nlz_bits_in_msbyte if r * CHAR_BIT > = nlz_bits_in_msbyte
* = word_numbits + r * CHAR_BIT - nlz_bits_in_msbyte if otherwise
*
* div = ( numbytes * CHAR_BIT - nlz_bits_in_msbyte ) / word_numbits
* = ( ( q * word_numbytes + r ) * CHAR_BIT - nlz_bits_in_msbyte ) / word_numbits
* = ( q * word_numbytes * CHAR_BIT + r * CHAR_BIT - nlz_bits_in_msbyte ) / word_numbits
* = q + ( r * CHAR_BIT - nlz_bits_in_msbyte ) / word_numbits if r * CHAR_BIT > = nlz_bits_in_msbyte
* q - 1 + ( word_numbits + r * CHAR_BIT - nlz_bits_in_msbyte ) / word_numbits if r * CHAR_BIT < nlz_bits_in_msbyte
* = s + t / word_numbits
* mod = ( r * CHAR_BIT - nlz_bits_in_msbyte ) % word_numbits if r * CHAR_BIT > = nlz_bits_in_msbyte
* ( word_numbits + r * CHAR_BIT - nlz_bits_in_msbyte ) % word_numbits if r * CHAR_BIT < nlz_bits_in_msbyte
* = t % word_numbits
*
* numwords = mod = = 0 ? div : div + 1
* nlz_bits = mod = = 0 ? 0 : word_numbits - mod
*/
size_t word_numbytes = word_numbits / CHAR_BIT ;
size_t q = numbytes / word_numbytes ;
size_t r = numbytes % word_numbytes ;
size_t s , t ;
size_t div , mod ;
2013-06-06 07:57:35 -04:00
size_t numwords ;
2013-06-09 08:37:38 -04:00
size_t nlz_bits ;
2013-06-09 12:08:54 -04:00
if ( r * CHAR_BIT > = ( size_t ) nlz_bits_in_msbyte ) {
s = q ;
t = r * CHAR_BIT - nlz_bits_in_msbyte ;
}
else {
s = q - 1 ;
2013-06-09 16:39:05 -04:00
t = word_numbits - nlz_bits_in_msbyte + r * CHAR_BIT ;
2013-06-09 12:08:54 -04:00
}
div = s + t / word_numbits ;
mod = t % word_numbits ;
numwords = mod = = 0 ? div : div + 1 ;
nlz_bits = mod = = 0 ? 0 : word_numbits - mod ;
* nlz_bits_ret = nlz_bits ;
return numwords ;
}
2013-06-09 16:39:05 -04:00
size_t
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-09 12:08:54 -04:00
size_t
absint_numwords_generic ( size_t numbytes , int nlz_bits_in_msbyte , size_t word_numbits , size_t * nlz_bits_ret )
{
2013-06-09 08:37:38 -04:00
VALUE val_numbits , word_numbits_v ;
2013-06-06 07:57:35 -04:00
VALUE div_mod , div , mod ;
2013-06-09 08:37:38 -04:00
int sign ;
2013-06-09 12:08:54 -04:00
size_t numwords ;
size_t nlz_bits ;
2013-06-06 07:57:35 -04:00
/*
2013-06-09 08:37:38 -04:00
* val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
2013-06-06 07:57:35 -04:00
* div , mod = val_numbits . divmod ( word_numbits )
* numwords = mod = = 0 ? div : div + 1
2013-06-09 08:37:38 -04:00
* nlz_bits = mod = = 0 ? 0 : word_numbits - mod
2013-06-06 07:57:35 -04:00
*/
2013-06-09 12:08:54 -04:00
2013-06-06 07:57:35 -04:00
val_numbits = SIZET2NUM ( numbytes ) ;
val_numbits = rb_funcall ( val_numbits , ' * ' , 1 , LONG2FIX ( CHAR_BIT ) ) ;
2013-06-09 08:37:38 -04:00
if ( nlz_bits_in_msbyte )
val_numbits = rb_funcall ( val_numbits , ' - ' , 1 , LONG2FIX ( nlz_bits_in_msbyte ) ) ;
word_numbits_v = SIZET2NUM ( word_numbits ) ;
div_mod = rb_funcall ( val_numbits , rb_intern ( " divmod " ) , 1 , word_numbits_v ) ;
2013-06-06 07:57:35 -04:00
div = RARRAY_AREF ( div_mod , 0 ) ;
mod = RARRAY_AREF ( div_mod , 1 ) ;
if ( mod = = LONG2FIX ( 0 ) ) {
2013-06-09 08:37:38 -04:00
nlz_bits = 0 ;
2013-06-06 07:57:35 -04:00
}
else {
2013-06-09 08:37:38 -04:00
div = rb_funcall ( div , ' + ' , 1 , LONG2FIX ( 1 ) ) ;
nlz_bits = word_numbits - NUM2SIZET ( mod ) ;
2013-06-06 07:57:35 -04:00
}
2013-06-10 06:37:39 -04:00
sign = rb_integer_pack ( div , & numwords , 1 , sizeof ( numwords ) , 0 ,
2013-06-09 08:37:38 -04:00
INTEGER_PACK_MSWORD_FIRST | INTEGER_PACK_NATIVE_BYTE_ORDER ) ;
if ( sign = = 2 )
return ( size_t ) - 1 ;
2013-06-09 12:08:54 -04:00
* nlz_bits_ret = nlz_bits ;
return numwords ;
}
/*
2013-06-10 06:37:39 -04:00
* Calculate the number of words to be required to represent
2013-06-09 12: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 09:10:11 -04:00
*
* This function can overflow if _val_ is very big and word_numbits is less than CHAR_BIT .
* When overflow occur , ( size_t ) - 1 is returned .
2013-06-09 12: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-09 16:39:05 -04:00
if ( numbytes < = SIZE_MAX / CHAR_BIT ) {
numwords = absint_numwords_small ( numbytes , nlz_bits_in_msbyte , word_numbits , & nlz_bits ) ;
#if 0
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 ) ;
# endif
}
else if ( word_numbits % CHAR_BIT = = 0 ) {
2013-06-09 12:08:54 -04:00
numwords = absint_numwords_bytes ( numbytes , nlz_bits_in_msbyte , word_numbits , & nlz_bits ) ;
#if 0
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 ) ;
# 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 08:37:38 -04:00
if ( nlz_bits_ret )
* nlz_bits_ret = nlz_bits ;
2013-06-09 12:08:54 -04:00
2013-06-06 07:57:35 -04:00
return numwords ;
}
2013-06-08 08: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 11: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 06:49:12 -04:00
static void
2013-06-07 11:39:07 -04:00
validate_integer_pack_format ( size_t wordsize , size_t nails , int flags )
2013-06-07 06:49:12 -04:00
{
2013-06-07 11:02:39 -04:00
int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK ;
int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK ;
if ( wordorder_bits ! = INTEGER_PACK_MSWORD_FIRST & &
wordorder_bits ! = INTEGER_PACK_LSWORD_FIRST )
2013-06-07 18:16:15 -04:00
rb_raise ( rb_eArgError , " unexpected word order " ) ;
2013-06-07 11:02:39 -04:00
if ( byteorder_bits ! = INTEGER_PACK_MSBYTE_FIRST & &
byteorder_bits ! = INTEGER_PACK_LSBYTE_FIRST & &
byteorder_bits ! = INTEGER_PACK_NATIVE_BYTE_ORDER )
2013-06-07 18:16:15 -04:00
rb_raise ( rb_eArgError , " unexpected byte order " ) ;
2013-06-07 06: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-07 08:06:09 -04:00
static void
2013-06-07 11:39:07 -04:00
integer_pack_loop_setup (
2013-06-07 11:02:39 -04:00
size_t numwords , size_t wordsize , size_t nails , int flags ,
2013-06-07 08: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 11:02:39 -04:00
int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK ;
int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK ;
2013-06-07 08: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 11:02:39 -04:00
if ( wordorder_bits = = INTEGER_PACK_MSWORD_FIRST ) {
word_start = wordsize * ( numwords - 1 ) ;
2013-06-07 08:06:09 -04:00
word_step = - ( ssize_t ) wordsize ;
word_last = 0 ;
}
else {
word_start = 0 ;
word_step = wordsize ;
2013-06-07 11:02:39 -04:00
word_last = wordsize * ( numwords - 1 ) ;
2013-06-07 08:06:09 -04:00
}
2013-06-07 11:02:39 -04:00
if ( byteorder_bits = = INTEGER_PACK_NATIVE_BYTE_ORDER ) {
2013-06-07 08:06:09 -04:00
# ifdef WORDS_BIGENDIAN
2013-06-07 11:02:39 -04:00
byteorder_bits = INTEGER_PACK_MSBYTE_FIRST ;
2013-06-07 08:06:09 -04:00
# else
2013-06-07 11:02:39 -04:00
byteorder_bits = INTEGER_PACK_LSBYTE_FIRST ;
2013-06-07 08:06:09 -04:00
# endif
}
2013-06-07 11:02:39 -04:00
if ( byteorder_bits = = INTEGER_PACK_MSBYTE_FIRST ) {
2013-06-07 08:06:09 -04:00
byte_start = wordsize - 1 ;
2013-06-07 11:39:07 -04:00
byte_step = - 1 ;
2013-06-07 08:06:09 -04:00
}
else {
byte_start = 0 ;
2013-06-07 11:39:07 -04:00
byte_step = 1 ;
2013-06-07 08: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 07:57:35 -04:00
static inline void
2013-06-07 11:39:07 -04:00
integer_pack_fill_dd ( BDIGIT * * dpp , BDIGIT * * dep , BDIGIT_DBL * ddp , int * numbits_in_dd_p )
2013-06-06 07: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 11:39:07 -04:00
integer_pack_take_lowbits ( int n , BDIGIT_DBL * ddp , int * numbits_in_dd_p )
2013-06-06 07:57:35 -04:00
{
BDIGIT_DBL ret ;
ret = ( * ddp ) & ( ( ( BDIGIT_DBL ) 1 < < n ) - 1 ) ;
* ddp > > = n ;
* numbits_in_dd_p - = n ;
return ret ;
}
/*
* Export an integer into a buffer .
*
2013-06-10 06:55:08 -04:00
* This function fills the buffer specified by _words_ and _numwords_ as
* abs ( val ) in the format specified by _wordsize_ , _nails_ and _flags_ .
*
2013-06-10 06:37:39 -04:00
* [ val ] Fixnum , Bignum or another integer like object which has to_int method .
2013-06-09 01:53:00 -04:00
* [ words ] buffer to export abs ( val ) .
* [ numwords ] the size of given buffer as number of words .
2013-06-06 07:57:35 -04:00
* [ wordsize ] the size of word as number of bytes .
2013-06-10 06:37:39 -04:00
* [ 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_ " .
* It specifies word order and byte order .
2013-06-06 07:57:35 -04:00
*
2013-06-10 06:37:39 -04:00
* This function returns the signedness and overflow condition as follows :
2013-06-10 06:55:08 -04:00
* - 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 least significant words of abs ( val ) are filled in the buffer when overflow occur .
2013-06-06 07:57:35 -04:00
*/
2013-06-07 06:49:12 -04:00
2013-06-10 06:37:39 -04:00
int
rb_integer_pack ( VALUE val , void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
2013-06-06 07:57:35 -04:00
{
int sign ;
BDIGIT * dp ;
BDIGIT * de ;
BDIGIT fixbuf [ ( sizeof ( long ) + SIZEOF_BDIGITS - 1 ) / SIZEOF_BDIGITS ] ;
2013-06-06 18:31:23 -04:00
unsigned char * buf , * bufend ;
2013-06-06 07:57:35 -04:00
val = rb_to_int ( val ) ;
2013-06-07 11:39:07 -04:00
validate_integer_pack_format ( wordsize , nails , flags ) ;
2013-06-09 01:53:00 -04:00
if ( SIZE_MAX / wordsize < numwords )
2013-06-09 09:03:45 -04:00
rb_raise ( rb_eArgError , " too big numwords * wordsize: % " PRI_SIZE_PREFIX " u * % " PRI_SIZE_PREFIX " u " , numwords , wordsize ) ;
2013-06-06 07:57:35 -04:00
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
2013-06-07 05:25:47 -04:00
{
int i ;
2013-06-07 06:24:07 -04:00
for ( i = 0 ; i < numberof ( fixbuf ) ; i + + ) {
2013-06-07 05:25:47 -04:00
fixbuf [ i ] = ( BDIGIT ) ( v & ( ( 1L < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
v > > = SIZEOF_BDIGITS * CHAR_BIT ;
}
2013-06-06 07:57:35 -04:00
}
# endif
dp = fixbuf ;
2013-06-07 06:24:07 -04:00
de = fixbuf + numberof ( fixbuf ) ;
2013-06-06 07:57:35 -04:00
}
else {
sign = RBIGNUM_POSITIVE_P ( val ) ? 1 : - 1 ;
dp = BDIGITS ( val ) ;
de = dp + RBIGNUM_LEN ( val ) ;
}
while ( dp < de & & de [ - 1 ] = = 0 )
de - - ;
if ( dp = = de ) {
sign = 0 ;
}
2013-06-09 01:53:00 -04:00
buf = words ;
bufend = buf + numwords * wordsize ;
2013-06-06 07:57:35 -04:00
if ( buf = = bufend ) {
sign * = 2 ; /* overflow if non-zero*/
}
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 08:06:09 -04:00
size_t word_start , word_last ;
2013-06-07 11:56:59 -04:00
unsigned char * wordp , * last_wordp ;
2013-06-06 07:57:35 -04:00
BDIGIT_DBL dd ;
int numbits_in_dd ;
2013-06-07 11:39:07 -04:00
integer_pack_loop_setup ( numwords , wordsize , nails , flags ,
2013-06-07 11:56:59 -04:00
& word_num_fullbytes , & word_num_partialbits ,
2013-06-07 08:06:09 -04:00
& word_start , & word_step , & word_last , & byte_start , & byte_step ) ;
2013-06-06 07:57:35 -04:00
2013-06-07 08:06:09 -04:00
wordp = buf + word_start ;
last_wordp = buf + word_last ;
2013-06-06 07:57:35 -04:00
dd = 0 ;
numbits_in_dd = 0 ;
# define FILL_DD \
2013-06-07 11:39:07 -04:00
integer_pack_fill_dd ( & dp , & de , & dd , & numbits_in_dd )
2013-06-06 07:57:35 -04:00
# define TAKE_LOWBITS(n) \
2013-06-07 11:39:07 -04:00
integer_pack_take_lowbits ( n , & dd , & numbits_in_dd )
2013-06-06 07:57:35 -04:00
while ( 1 ) {
2013-06-07 11:56:59 -04:00
size_t index_in_word = 0 ;
unsigned char * bytep = wordp + byte_start ;
2013-06-06 07: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 11:56:59 -04:00
while ( index_in_word < wordsize ) {
2013-06-06 07:57:35 -04:00
* bytep = 0 ;
bytep + = byte_step ;
index_in_word + + ;
}
if ( wordp = = last_wordp )
break ;
wordp + = word_step ;
}
if ( dp ! = de | | dd )
sign * = 2 ; /* overflow */
}
2013-06-10 06:37:39 -04:00
return sign ;
2013-06-06 07:57:35 -04:00
# undef FILL_DD
# undef TAKE_LOWBITS
}
2013-06-09 23:12:44 -04:00
static size_t
integer_unpack_num_bdigits_small ( size_t numwords , size_t wordsize , size_t nails )
{
size_t num_bits ;
num_bits = ( wordsize * CHAR_BIT - nails ) * numwords ;
return ( num_bits + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT ) ;
}
static size_t
integer_unpack_num_bdigits_bytes ( size_t numwords , size_t wordsize )
{
/*
* num_bits = wordsize * CHAR_BIT * numwords
*
* num_bdigits = ( num_bits + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
* = ( wordsize * CHAR_BIT * numwords + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
* = ( ( wordsize * numwords + SIZEOF_BDIGITS ) * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
*
* q , r = ( wordsize * numwords ) . divmod ( SIZEOF_BDIGITS )
* q * SIZEOF_BDIGITS + r = wordsize * numwords
*
* num_bdigits = ( ( q * SIZEOF_BDIGITS + r + SIZEOF_BDIGITS ) * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
* = ( q * SIZEOF_BDIGITS * CHAR_BIT + r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
* = q + ( r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT )
*/
size_t t , q , r ;
t = wordsize * numwords ;
q = t / SIZEOF_BDIGITS ;
r = t % SIZEOF_BDIGITS ;
return q + ( r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1 ) / ( SIZEOF_BDIGITS * CHAR_BIT ) ;
}
static size_t
integer_unpack_num_bdigits_generic ( size_t numwords , size_t wordsize , size_t nails )
{
VALUE num_bits_v , num_bdigits_v ;
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
num_bits_v = SIZET2NUM ( wordsize ) ;
num_bits_v = rb_funcall ( num_bits_v , ' * ' , 1 , LONG2FIX ( CHAR_BIT ) ) ;
num_bits_v = rb_funcall ( num_bits_v , ' - ' , 1 , SIZET2NUM ( nails ) ) ;
num_bits_v = rb_funcall ( num_bits_v , ' * ' , 1 , SIZET2NUM ( numwords ) ) ;
if ( num_bits_v = = LONG2FIX ( 0 ) )
return 0 ;
/* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT) */
num_bdigits_v = rb_funcall ( num_bits_v , ' + ' , 1 , LONG2FIX ( SIZEOF_BDIGITS * CHAR_BIT - 1 ) ) ;
num_bdigits_v = rb_funcall ( num_bdigits_v , ' / ' , 1 , LONG2FIX ( SIZEOF_BDIGITS * CHAR_BIT ) ) ;
return NUM2SIZET ( num_bdigits_v ) ;
}
2013-06-06 17:20:04 -04:00
static inline void
2013-06-07 11:39:07 -04:00
integer_unpack_push_bits ( int data , int numbits , BDIGIT_DBL * ddp , int * numbits_in_dd_p , BDIGIT * * dpp )
2013-06-06 17: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 04:41:48 -04:00
* ( * dpp ) + + = ( BDIGIT ) ( ( * ddp ) & ( ( ( BDIGIT_DBL ) 1 < < ( SIZEOF_BDIGITS * CHAR_BIT ) ) - 1 ) ) ;
2013-06-06 17:20:04 -04:00
* ddp > > = SIZEOF_BDIGITS * CHAR_BIT ;
* numbits_in_dd_p - = SIZEOF_BDIGITS * CHAR_BIT ;
}
}
/*
* Import an integer into a buffer .
*
* [ sign ] signedness of the value .
* - 1 for non - positive . 0 or 1 for non - negative .
2013-06-06 19:05:59 -04:00
* [ words ] buffer to import .
2013-06-07 11:02:39 -04:00
* [ numwords ] the size of given buffer as number of words .
2013-06-06 17:20:04 -04:00
* [ wordsize ] the size of word as number of bytes .
2013-06-10 06:37:39 -04:00
* [ 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_ " .
* It specifies word order and byte order .
* Also , INTEGER_PACK_FORCE_BIGNUM specifies that the result will be a Bignum
* even if it is representable as a Fixnum .
2013-06-06 17:20:04 -04:00
*
* This function returns the imported integer as Fixnum or Bignum .
*/
VALUE
2013-06-07 11:02:39 -04:00
rb_integer_unpack ( int sign , const void * words , size_t numwords , size_t wordsize , size_t nails , int flags )
2013-06-06 17:20:04 -04:00
{
VALUE result ;
2013-06-06 19:05:59 -04:00
const unsigned char * buf = words ;
2013-06-09 23:12:44 -04:00
size_t num_bdigits ;
2013-06-06 17: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 08:06:09 -04:00
size_t word_start , word_last ;
2013-06-07 11:56:59 -04:00
const unsigned char * wordp , * last_wordp ;
2013-06-06 17:20:04 -04:00
BDIGIT_DBL dd ;
int numbits_in_dd ;
2013-06-07 11:39:07 -04:00
validate_integer_pack_format ( wordsize , nails , flags ) ;
2013-06-07 11:02:39 -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 06:49:12 -04:00
if ( sign ! = 1 & & sign ! = 0 & & sign ! = - 1 )
rb_raise ( rb_eArgError , " unexpected sign: %d " , sign ) ;
2013-06-06 17:20:04 -04:00
2013-06-08 03:40:03 -04:00
if ( numwords < = ( SIZE_MAX - ( SIZEOF_BDIGITS * CHAR_BIT - 1 ) ) / CHAR_BIT / wordsize ) {
2013-06-09 23:12:44 -04:00
num_bdigits = integer_unpack_num_bdigits_small ( numwords , wordsize , nails ) ;
#if 0
{
static int first = 1 ;
if ( first )
first = 0 ;
else {
size_t num_bdigits1 = integer_unpack_num_bdigits_generic ( numwords , wordsize , nails ) ;
assert ( num_bdigits = = num_bdigits1 ) ;
}
}
# endif
}
else if ( nails = = 0 ) {
num_bdigits = integer_unpack_num_bdigits_bytes ( numwords , wordsize ) ;
#if 0
{
static int first = 1 ;
if ( first )
first = 0 ;
else {
size_t num_bdigits1 = integer_unpack_num_bdigits_generic ( numwords , wordsize , nails ) ;
assert ( num_bdigits = = num_bdigits1 ) ;
}
}
# endif
2013-06-08 03:40:03 -04:00
}
else {
2013-06-09 23:12:44 -04:00
num_bdigits = integer_unpack_num_bdigits_generic ( numwords , wordsize , nails ) ;
}
if ( num_bdigits = = 0 ) {
if ( flags & INTEGER_PACK_FORCE_BIGNUM )
return rb_int2big ( 0 ) ;
return LONG2FIX ( 0 ) ;
2013-06-08 03:40:03 -04:00
}
2013-06-09 23:12:44 -04:00
if ( LONG_MAX < num_bdigits )
rb_raise ( rb_eArgError , " too big to unpack as an integer " ) ;
result = bignew ( ( long ) num_bdigits , 0 < = sign ) ;
2013-06-06 17:20:04 -04:00
dp = BDIGITS ( result ) ;
de = dp + RBIGNUM_LEN ( result ) ;
2013-06-07 11:39:07 -04:00
integer_pack_loop_setup ( numwords , wordsize , nails , flags ,
2013-06-07 11:56:59 -04:00
& word_num_fullbytes , & word_num_partialbits ,
2013-06-07 08:06:09 -04:00
& word_start , & word_step , & word_last , & byte_start , & byte_step ) ;
2013-06-06 17:20:04 -04:00
2013-06-07 08:06:09 -04:00
wordp = buf + word_start ;
last_wordp = buf + word_last ;
2013-06-06 17:20:04 -04:00
dd = 0 ;
numbits_in_dd = 0 ;
# define PUSH_BITS(data, numbits) \
2013-06-07 11:39:07 -04:00
integer_unpack_push_bits ( data , numbits , & dd , & numbits_in_dd , & dp )
2013-06-06 17:20:04 -04:00
while ( 1 ) {
2013-06-07 11:56:59 -04:00
size_t index_in_word = 0 ;
const unsigned char * bytep = wordp + byte_start ;
2013-06-06 17:20:04 -04:00
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 + + ;
}
if ( wordp = = last_wordp )
break ;
wordp + = word_step ;
}
if ( dd )
2013-06-06 20:29:43 -04:00
* dp + + = ( BDIGIT ) dd ;
2013-06-06 17:20:04 -04:00
while ( dp < de )
* dp + + = 0 ;
2013-06-08 02:00:04 -04:00
if ( flags & INTEGER_PACK_FORCE_BIGNUM )
return bigtrunc ( result ) ;
2013-06-06 17:20:04 -04:00
return bignorm ( result ) ;
# undef PUSH_BITS
}
2010-02-26 06:09:29 -05:00
# define QUAD_SIZE 8
# if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
2002-02-13 04:01:11 -05: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 06:44:21 -04:00
rb_quad_pack ( char * buf , VALUE val )
2002-02-13 04:01:11 -05:00
{
LONG_LONG q ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
q = FIX2LONG ( val ) ;
}
else {
2007-09-01 08:02:36 -04:00
long len = RBIGNUM_LEN ( val ) ;
2002-02-13 04:01:11 -05:00
BDIGIT * ds ;
2004-01-22 13:06:38 -05:00
if ( len > SIZEOF_LONG_LONG / SIZEOF_BDIGITS ) {
2006-07-11 02:47:09 -04:00
len = SIZEOF_LONG_LONG / SIZEOF_BDIGITS ;
2004-01-22 13:06:38 -05:00
}
2002-02-13 04:01:11 -05:00
ds = BDIGITS ( val ) ;
q = 0 ;
while ( len - - ) {
q = BIGUP ( q ) ;
q + = ds [ len ] ;
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( val ) ) q = - q ;
2002-02-13 04:01:11 -05:00
}
2002-04-10 04:45:26 -04:00
memcpy ( buf , ( char * ) & q , SIZEOF_LONG_LONG ) ;
2002-02-13 04:01:11 -05: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 06:44:21 -04:00
rb_quad_unpack ( const char * buf , int sign )
2002-02-13 04:01:11 -05:00
{
unsigned LONG_LONG q ;
long neg = 0 ;
2002-08-21 11:47:54 -04:00
long i ;
2002-02-13 04:01:11 -05:00
BDIGIT * digits ;
VALUE big ;
2002-04-10 04:45:26 -04:00
memcpy ( & q , buf , SIZEOF_LONG_LONG ) ;
2002-02-13 04:01:11 -05:00
if ( sign ) {
2002-08-21 11:47:54 -04:00
if ( FIXABLE ( ( LONG_LONG ) q ) ) return LONG2FIX ( ( LONG_LONG ) q ) ;
2002-02-13 04:01:11 -05:00
if ( ( LONG_LONG ) q < 0 ) {
q = - ( LONG_LONG ) q ;
neg = 1 ;
}
}
else {
2002-08-21 11:47:54 -04:00
if ( POSFIXABLE ( q ) ) return LONG2FIX ( q ) ;
2002-02-13 04:01:11 -05:00
}
i = 0 ;
2002-11-19 03:07:51 -05:00
big = bignew ( DIGSPERLL , 1 ) ;
2002-02-13 04:01:11 -05:00
digits = BDIGITS ( big ) ;
2002-11-19 03:07:51 -05:00
while ( i < DIGSPERLL ) {
2002-02-13 04:01:11 -05:00
digits [ i + + ] = BIGLO ( q ) ;
q = BIGDN ( q ) ;
}
2002-11-19 03:07:51 -05:00
i = DIGSPERLL ;
2002-02-13 04:01:11 -05:00
while ( i - - & & ! digits [ i ] ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
2002-02-13 04:01:11 -05:00
if ( neg ) {
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2002-02-13 04:01:11 -05:00
}
return bignorm ( big ) ;
}
# else
2010-02-26 07:41:02 -05: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 04:01:11 -05:00
void
2006-03-01 05:06:03 -05:00
rb_quad_pack ( char * buf , VALUE val )
2002-02-13 04:01:11 -05:00
{
long len ;
memset ( buf , 0 , QUAD_SIZE ) ;
val = rb_to_int ( val ) ;
if ( FIXNUM_P ( val ) ) {
2002-02-13 04:53:17 -05:00
val = rb_int2big ( FIX2LONG ( val ) ) ;
2002-02-13 04:01:11 -05:00
}
2007-09-01 08:02:36 -04:00
len = RBIGNUM_LEN ( val ) * SIZEOF_BDIGITS ;
2003-12-26 10:34:33 -05:00
if ( len > QUAD_SIZE ) {
2010-02-26 07:41:02 -05:00
len = QUAD_SIZE ;
2003-12-26 10:34:33 -05:00
}
2002-02-13 04:01:11 -05:00
memcpy ( buf , ( char * ) BDIGITS ( val ) , len ) ;
2010-02-26 07:41:02 -05:00
if ( RBIGNUM_NEGATIVE_P ( val ) ) {
quad_buf_complement ( buf , QUAD_SIZE ) ;
2002-02-13 04:53:17 -05:00
}
2002-02-13 04:01:11 -05:00
}
2010-12-02 03:01:24 -05:00
# define BNEG(b) (RSHIFT(((BDIGIT*)(b))[QUAD_SIZE / SIZEOF_BDIGITS-1],BITSPERDIG-1) != 0)
2002-02-13 04:53:17 -05:00
2002-02-13 04:01:11 -05:00
VALUE
2006-03-01 05:06:03 -05:00
rb_quad_unpack ( const char * buf , int sign )
2002-02-13 04:01:11 -05:00
{
2002-04-10 04:45:26 -04:00
VALUE big = bignew ( QUAD_SIZE / SIZEOF_BDIGITS , 1 ) ;
2002-02-13 04:01:11 -05:00
memcpy ( ( char * ) BDIGITS ( big ) , buf , QUAD_SIZE ) ;
2002-02-13 04:53:17 -05:00
if ( sign & & BNEG ( buf ) ) {
char * tmp = ( char * ) BDIGITS ( big ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2010-02-26 07:41:02 -05:00
quad_buf_complement ( tmp , QUAD_SIZE ) ;
2002-02-13 04:01:11 -05:00
}
return bignorm ( big ) ;
}
# endif
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_cstr_to_inum ( const char * str , int base , int badcheck )
1998-01-16 07:13:05 -05:00
{
2000-01-04 23:41:21 -05:00
const char * s = str ;
char * end ;
2003-07-24 14:33:50 -04:00
char sign = 1 , nondigit = 0 ;
int c ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num ;
1999-08-13 01:45:20 -04:00
long len , blen = 1 ;
long i ;
1998-01-16 07:13:05 -05:00
VALUE z ;
2000-10-31 03:37:47 -05:00
BDIGIT * zds ;
1998-01-16 07:13:05 -05:00
2010-01-28 11:34:11 -05:00
# undef ISDIGIT
# define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
2007-07-15 06:05:37 -04:00
# define conv_digit(c) \
( ! ISASCII ( c ) ? - 1 : \
2008-01-02 12:48:20 -05:00
ISDIGIT ( c ) ? ( ( c ) - ' 0 ' ) : \
ISLOWER ( c ) ? ( ( c ) - ' a ' + 10 ) : \
ISUPPER ( c ) ? ( ( c ) - ' A ' + 10 ) : \
2007-07-15 06:05:37 -04:00
- 1 )
2002-10-17 03:27:00 -04:00
if ( ! str ) {
if ( badcheck ) goto bad ;
return INT2FIX ( 0 ) ;
}
2006-06-27 12:15:22 -04:00
while ( ISSPACE ( * str ) ) str + + ;
1999-01-19 23:59:39 -05:00
2000-12-22 04:00:23 -05:00
if ( str [ 0 ] = = ' + ' ) {
1999-01-19 23:59:39 -05:00
str + + ;
}
2000-12-22 04:00:23 -05:00
else if ( str [ 0 ] = = ' - ' ) {
1998-01-16 07:13:05 -05:00
str + + ;
sign = 0 ;
}
2001-03-13 23:45:46 -05:00
if ( str [ 0 ] = = ' + ' | | str [ 0 ] = = ' - ' ) {
if ( badcheck ) goto bad ;
return INT2FIX ( 0 ) ;
}
2002-02-01 05:23:22 -05:00
if ( base < = 0 ) {
2000-12-22 04:00:23 -05:00
if ( str [ 0 ] = = ' 0 ' ) {
2002-08-16 02:39:27 -04:00
switch ( str [ 1 ] ) {
case ' x ' : case ' X ' :
1998-01-16 07:13:05 -05:00
base = 16 ;
2002-08-16 02:39:27 -04:00
break ;
case ' b ' : case ' B ' :
1999-08-13 01:45:20 -04:00
base = 2 ;
2002-08-16 02:39:27 -04:00
break ;
case ' o ' : case ' O ' :
base = 8 ;
break ;
case ' d ' : case ' D ' :
base = 10 ;
break ;
default :
1998-01-16 07:13:05 -05:00
base = 8 ;
}
}
2002-02-01 05:23:22 -05:00
else if ( base < - 1 ) {
base = - base ;
}
1998-01-16 07:13:05 -05:00
else {
base = 10 ;
}
}
2002-08-16 02: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 02:54:27 -04:00
case 3 :
len = 2 ;
break ;
2002-08-16 02:39:27 -04:00
case 8 :
2008-01-29 22:07:37 -05:00
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' o ' | | str [ 1 ] = = ' O ' ) ) {
1999-01-19 23:59:39 -05:00
str + = 2 ;
}
2003-04-14 02:54:27 -04:00
case 4 : case 5 : case 6 : case 7 :
len = 3 ;
2002-08-16 02:39:27 -04:00
break ;
case 10 :
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' d ' | | str [ 1 ] = = ' D ' ) ) {
1999-08-13 01:45:20 -04:00
str + = 2 ;
}
2003-04-21 05:36:31 -04:00
case 9 : case 11 : case 12 : case 13 : case 14 : case 15 :
2003-04-14 02:54:27 -04:00
len = 4 ;
2002-08-16 02:39:27 -04:00
break ;
case 16 :
2001-12-26 12:01:20 -05:00
len = 4 ;
2002-08-16 02:39:27 -04:00
if ( str [ 0 ] = = ' 0 ' & & ( str [ 1 ] = = ' x ' | | str [ 1 ] = = ' X ' ) ) {
str + = 2 ;
}
break ;
2003-04-14 02: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-20 21:31:11 -05:00
rb_raise ( rb_eArgError , " invalid radix %d " , base ) ;
2003-04-14 02:54:27 -04:00
}
if ( base < = 32 ) {
len = 5 ;
}
else {
len = 6 ;
}
break ;
2001-12-26 12:01:20 -05:00
}
2007-12-31 01:43:32 -05:00
if ( * str = = ' 0 ' ) { /* squeeze preceding 0s */
2008-01-30 06:20:03 -05: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 06: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 00:53:53 -05:00
}
2001-12-26 12:01:20 -05:00
len * = strlen ( str ) * sizeof ( char ) ;
1998-01-16 07:13:05 -05:00
2009-05-26 00:58:15 -04:00
if ( ( size_t ) len < = ( sizeof ( long ) * CHAR_BIT ) ) {
2008-01-02 01:24:27 -05:00
unsigned long val = STRTOUL ( str , & end , base ) ;
2000-01-04 23:41:21 -05:00
2006-06-27 12:15:22 -04:00
if ( str < end & & * end = = ' _ ' ) goto bigparse ;
2000-01-04 23:41:21 -05:00
if ( badcheck ) {
2002-01-04 09:15:33 -05:00
if ( end = = str ) goto bad ; /* no number */
2002-01-15 21:20:25 -05:00
while ( * end & & ISSPACE ( * end ) ) end + + ;
2003-04-14 02:54:27 -04:00
if ( * end ) goto bad ; /* trailing garbage */
2000-01-04 23:41:21 -05:00
}
1998-01-16 07:13:05 -05:00
if ( POSFIXABLE ( val ) ) {
2002-08-21 11:47:54 -04:00
if ( sign ) return LONG2FIX ( val ) ;
1998-01-16 07:13:05 -05:00
else {
1999-01-19 23:59:39 -05:00
long result = - ( long ) val ;
2002-08-21 11:47:54 -04:00
return LONG2FIX ( result ) ;
1998-01-16 07:13:05 -05:00
}
}
else {
1999-01-19 23:59:39 -05:00
VALUE big = rb_uint2big ( val ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , sign ) ;
2002-08-13 05:21:18 -04:00
return bignorm ( big ) ;
1998-01-16 07:13:05 -05:00
}
}
2000-12-21 22:22:25 -05:00
bigparse :
1998-01-16 07:19:22 -05:00
len = ( len / BITSPERDIG ) + 1 ;
2000-12-21 22:22:25 -05:00
if ( badcheck & & * str = = ' _ ' ) goto bad ;
1998-01-16 07:13:05 -05:00
z = bignew ( len , sign ) ;
zds = BDIGITS ( z ) ;
for ( i = len ; i - - ; ) zds [ i ] = 0 ;
2007-07-15 06:05:37 -04:00
while ( ( c = * str + + ) ! = 0 ) {
2003-04-14 02:54:27 -04:00
if ( c = = ' _ ' ) {
2008-03-19 01:36:43 -04:00
if ( nondigit ) {
if ( badcheck ) goto bad ;
break ;
2002-02-01 05:23:22 -05:00
}
2012-11-21 00:09:19 -05:00
nondigit = ( char ) c ;
2000-12-21 22:22:25 -05:00
continue ;
2003-04-14 02:54:27 -04:00
}
2007-07-15 06:05:37 -04:00
else if ( ( c = conv_digit ( c ) ) < 0 ) {
1998-01-16 07:13:05 -05:00
break ;
}
if ( c > = base ) break ;
2003-04-14 02:54:27 -04:00
nondigit = 0 ;
1998-01-16 07:13:05 -05:00
i = 0 ;
num = c ;
for ( ; ; ) {
while ( i < blen ) {
2000-11-01 03:49:40 -05:00
num + = ( BDIGIT_DBL ) zds [ i ] * base ;
1998-01-16 07:13:05 -05:00
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
if ( num ) {
blen + + ;
continue ;
}
break ;
}
}
2000-12-25 01:29:27 -05:00
if ( badcheck ) {
str - - ;
if ( s + 1 < str & & str [ - 1 ] = = ' _ ' ) goto bad ;
2001-12-26 12:01:20 -05:00
while ( * str & & ISSPACE ( * str ) ) str + + ;
2003-04-14 02:54:27 -04:00
if ( * str ) {
bad :
2008-12-29 09:26:16 -05:00
rb_invalid_str ( s , " Integer() " ) ;
2003-04-14 02:54:27 -04:00
}
2000-12-25 01:29:27 -05:00
}
2000-01-04 23:41:21 -05:00
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2000-01-04 23:41:21 -05: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 06:44:21 -04:00
rb_str_to_inum ( VALUE str , int base , int badcheck )
2000-01-04 23:41:21 -05:00
{
char * s ;
2002-08-21 11:47:54 -04:00
long len ;
2011-01-27 07:58:44 -05:00
VALUE v = 0 ;
VALUE ret ;
2000-01-04 23:41:21 -05:00
2001-05-02 00:22:21 -04:00
StringValue ( str ) ;
2012-03-23 00:19:24 -04:00
rb_must_asciicompat ( str ) ;
2003-07-20 13:17:52 -04:00
if ( badcheck ) {
s = StringValueCStr ( str ) ;
}
else {
2006-08-31 06:47:44 -04:00
s = RSTRING_PTR ( str ) ;
2003-07-20 13:17:52 -04:00
}
2002-10-17 03:27:00 -04:00
if ( s ) {
2006-08-31 06:47:44 -04:00
len = RSTRING_LEN ( str ) ;
2002-10-17 03:27:00 -04:00
if ( s [ len ] ) { /* no sentinel somehow */
2011-01-27 07:58:44 -05:00
char * p = ALLOCV ( v , len + 1 ) ;
2002-10-17 03:27:00 -04:00
MEMCPY ( p , s , char , len ) ;
p [ len ] = ' \0 ' ;
s = p ;
}
2000-01-04 23:41:21 -05:00
}
2011-01-27 07:58:44 -05:00
ret = rb_cstr_to_inum ( s , base , badcheck ) ;
if ( v )
ALLOCV_END ( v ) ;
return ret ;
2002-02-01 05:23:22 -05:00
}
2002-03-14 01:23:46 -05: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-09 17: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 06:44:21 -04:00
rb_ull2big ( unsigned LONG_LONG n )
2002-03-14 01:23:46 -05: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 08:02:36 -04:00
RBIGNUM_SET_LEN ( big , i + 1 ) ;
2002-03-14 01:23:46 -05: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-09 17: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 06:44:21 -04:00
rb_ll2big ( LONG_LONG n )
2002-03-14 01:23:46 -05:00
{
long neg = 0 ;
2013-04-09 23:34:38 -04:00
unsigned LONG_LONG u ;
2002-03-14 01:23:46 -05:00
VALUE big ;
if ( n < 0 ) {
2013-04-09 23:34:38 -04:00
u = 1 + ( unsigned LONG_LONG ) ( - ( n + 1 ) ) ; /* u = -n avoiding overflow */
2002-03-14 01:23:46 -05:00
neg = 1 ;
}
2013-04-09 23:34:38 -04:00
else {
u = n ;
}
big = rb_ull2big ( u ) ;
2002-03-14 01:23:46 -05:00
if ( neg ) {
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( big , 0 ) ;
2002-03-14 01:23:46 -05: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 06:44:21 -04:00
rb_ull2inum ( unsigned LONG_LONG n )
2002-03-14 01:23:46 -05:00
{
2002-08-21 11:47:54 -04:00
if ( POSFIXABLE ( n ) ) return LONG2FIX ( n ) ;
2002-03-14 01:23:46 -05: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 06:44:21 -04:00
rb_ll2inum ( LONG_LONG n )
2002-03-14 01:23:46 -05:00
{
2002-08-21 11:47:54 -04:00
if ( FIXABLE ( n ) ) return LONG2FIX ( n ) ;
2002-03-14 01:23:46 -05:00
return rb_ll2big ( n ) ;
}
# endif /* HAVE_LONG_LONG */
2007-05-08 23:49:18 -04:00
2002-02-01 05:23:22 -05: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 06:44:21 -04:00
rb_cstr2inum ( const char * str , int base )
2002-02-01 05:23:22 -05: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 06:44:21 -04:00
rb_str2inum ( VALUE str , int base )
2002-02-01 05:23:22 -05:00
{
return rb_str_to_inum ( str , base , base = = 0 ) ;
2000-01-04 23:41:21 -05:00
}
2003-04-14 02:54:27 -04:00
const char ruby_digitmap [ ] = " 0123456789abcdefghijklmnopqrstuvwxyz " ;
2007-08-02 11:00:22 -04:00
2007-08-06 14:03:11 -04:00
static VALUE bigsqr ( VALUE x ) ;
2009-08-25 04:38:28 -04:00
static void bigdivmod ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp ) ;
2007-08-06 14:03:11 -04:00
# define POW2_P(x) (((x)&((x)-1))==0)
2007-08-02 10:45:34 -04:00
static inline int
2007-08-06 14:03:11 -04:00
ones ( register unsigned long x )
2007-08-02 10:45:34 -04:00
{
2013-04-12 08:01:51 -04:00
# if GCC_VERSION_SINCE(3, 4, 0)
return __builtin_popcountl ( x ) ;
2007-08-06 14:03:11 -04:00
# else
2013-04-12 08: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 14: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 08:01:51 -04:00
# if SIZEOF_LONG == 8
2007-08-06 14:03:11 -04:00
x + = ( x > > 32 ) ;
2013-04-12 08:01:51 -04:00
# endif
2007-08-06 14:03:11 -04:00
return ( int ) ( x & 0x7f ) ;
2013-04-12 08:01:51 -04:00
# undef MASK_0f
# undef MASK_33
# undef MASK_55
# endif
2007-08-06 14: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 15:33:03 -04:00
# if SIZEOF_LONG == 8
2007-08-06 14:03:11 -04:00
x | = x > > 32 ;
# endif
return x + 1 ;
}
2007-08-02 10:45:34 -04:00
2007-08-06 14: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 15:33:03 -04:00
# if SIZEOF_LONG == 8
2007-08-06 14:03:11 -04:00
x | = x > > 32 ;
# endif
return ( int ) ones ( x ) - 1 ;
}
2007-08-02 10:45:34 -04:00
2007-08-06 14:03:11 -04:00
static inline int
ceil_log2 ( register unsigned long x )
{
return floor_log2 ( x ) + ! POW2_P ( x ) ;
2007-08-02 10:45:34 -04:00
}
2007-08-06 14:03:11 -04:00
# define LOG2_KARATSUBA_DIGITS 7
# define KARATSUBA_DIGITS (1L<<LOG2_KARATSUBA_DIGITS)
2007-08-02 10:45:34 -04:00
# define MAX_BIG2STR_TABLE_ENTRIES 64
2007-08-06 14:03:11 -04:00
static VALUE big2str_power_cache [ 35 ] [ MAX_BIG2STR_TABLE_ENTRIES ] ;
2007-08-02 10:45:34 -04:00
2007-08-06 14:03:11 -04:00
static void
power_cache_init ( void )
{
int i , j ;
for ( i = 0 ; i < 35 ; + + i ) {
2008-03-07 07:28:57 -05:00
for ( j = 0 ; j < MAX_BIG2STR_TABLE_ENTRIES ; + + j ) {
big2str_power_cache [ i ] [ j ] = Qnil ;
}
2007-08-06 14:03:11 -04:00
}
2007-08-02 10:45:34 -04:00
}
2007-08-06 14:03:11 -04:00
static inline VALUE
power_cache_get_power0 ( int base , int i )
1998-01-16 07:13:05 -05:00
{
2007-08-06 14:03:11 -04:00
if ( NIL_P ( big2str_power_cache [ base - 2 ] [ i ] ) ) {
2008-03-07 07:28:57 -05:00
big2str_power_cache [ base - 2 ] [ i ] =
2008-03-07 07:14:17 -05: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 10:59:14 -04:00
rb_gc_register_mark_object ( big2str_power_cache [ base - 2 ] [ i ] ) ;
2007-08-06 14: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 00:58:15 -04:00
int i , m ;
long j ;
2007-08-06 14:03:11 -04:00
VALUE t ;
if ( n1 < = KARATSUBA_DIGITS )
2008-03-07 07:28:57 -05:00
rb_bug ( " n1 > KARATSUBA_DIGITS " ) ;
2007-08-06 14: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 07:28:57 -05:00
i = MAX_BIG2STR_TABLE_ENTRIES - 1 ;
2007-08-06 14:03:11 -04:00
t = power_cache_get_power0 ( base , i ) ;
j = KARATSUBA_DIGITS * ( 1 < < i ) ;
while ( n1 > j ) {
2008-03-07 07:28:57 -05:00
t = bigsqr ( t ) ;
j * = 2 ;
2007-08-06 14: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 08:02:36 -04:00
* RBIGNUM_LEN ( x ) .
2007-08-06 14: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 12:42:12 -05: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 14:03:11 -04:00
} ;
2007-08-07 22:48:39 -04:00
long bits ;
2007-08-06 14:03:11 -04:00
2007-12-18 10:10:37 -05:00
if ( base < 2 | | 36 < base )
2008-03-07 07:28:57 -05:00
rb_bug ( " invalid radix %d " , base ) ;
1998-01-16 07:13:05 -05:00
if ( FIXNUM_P ( x ) ) {
2008-03-07 07:28:57 -05:00
bits = ( SIZEOF_LONG * CHAR_BIT - 1 ) / 2 + 1 ;
1998-01-16 07:13:05 -05:00
}
2007-08-06 14:03:11 -04:00
else if ( BIGZEROP ( x ) ) {
2008-03-07 07:28:57 -05:00
return 0 ;
2002-08-19 01:56:09 -04:00
}
2008-02-29 12:35:11 -05:00
else if ( RBIGNUM_LEN ( x ) > = LONG_MAX / BITSPERDIG ) {
rb_raise ( rb_eRangeError , " bignum too big to convert into `string' " ) ;
}
2007-08-06 14:03:11 -04:00
else {
2008-03-07 07:28:57 -05:00
bits = BITSPERDIG * RBIGNUM_LEN ( x ) ;
1998-01-16 07:13:05 -05:00
}
2003-07-09 18:28:42 -04:00
2012-07-18 00: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 14:03:11 -04:00
}
static long
2013-05-31 18:32:55 -04:00
big2str_orig ( VALUE x , int base , char * ptr , long len , BDIGIT hbase , int hbase_numdigits , int trim )
2007-08-06 14:03:11 -04:00
{
2007-09-01 08:02:36 -04:00
long i = RBIGNUM_LEN ( x ) , j = len ;
2007-08-06 14:03:11 -04:00
BDIGIT * ds = BDIGITS ( x ) ;
1998-01-16 07:13:05 -05:00
2007-08-06 14:03:11 -04:00
while ( i & & j > 0 ) {
2008-03-07 07:28:57 -05: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 10:24:31 -04:00
k = hbase_numdigits ;
2008-03-07 07:28:57 -05: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 10:45:34 -04:00
}
2007-08-06 14:03:11 -04:00
if ( trim ) {
2008-03-07 07:28:57 -05:00
while ( j < len & & ptr [ j ] = = ' 0 ' ) j + + ;
MEMMOVE ( ptr , ptr + j , char , len - j ) ;
len - = j ;
1998-01-16 07:13:05 -05:00
}
2007-08-06 14:03:11 -04:00
return len ;
}
static long
big2str_karatsuba ( VALUE x , int base , char * ptr ,
2013-05-31 18:32:55 -04:00
long n1 , long len , BDIGIT hbase , int hbase_numdigits , int trim )
2007-08-06 14:03:11 -04:00
{
long lh , ll , m1 ;
VALUE b , q , r ;
if ( BIGZEROP ( x ) ) {
2008-03-07 07:28:57 -05:00
if ( trim ) return 0 ;
else {
memset ( ptr , ' 0 ' , len ) ;
return len ;
}
2006-10-29 22:39:44 -05:00
}
1998-01-16 07:13:05 -05:00
2007-08-06 14:03:11 -04:00
if ( n1 < = KARATSUBA_DIGITS ) {
2013-05-31 10:24:31 -04:00
return big2str_orig ( x , base , ptr , len , hbase , hbase_numdigits , trim ) ;
2007-08-06 14:03:11 -04:00
}
b = power_cache_get_power ( base , n1 , & m1 ) ;
bigdivmod ( x , b , & q , & r ) ;
2013-04-03 03:35:35 -04:00
rb_obj_hide ( q ) ;
rb_obj_hide ( r ) ;
2008-09-10 22:40:52 -04:00
lh = big2str_karatsuba ( q , base , ptr , ( len - m1 ) / 2 ,
2013-05-31 10:24:31 -04:00
len - m1 , hbase , hbase_numdigits , trim ) ;
2008-09-18 07:21:34 -04:00
rb_big_resize ( q , 0 ) ;
2007-08-06 14:03:11 -04:00
ll = big2str_karatsuba ( r , base , ptr + lh , m1 / 2 ,
2013-05-31 10:24:31 -04:00
m1 , hbase , hbase_numdigits , ! lh & & trim ) ;
2008-09-18 07:21:34 -04:00
rb_big_resize ( r , 0 ) ;
2007-08-06 14:03:11 -04:00
return lh + ll ;
1998-01-16 07:13:05 -05:00
}
2013-05-31 10:57:03 -04:00
static void
2013-05-31 18:32:55 -04:00
calc_hbase ( int base , BDIGIT * hbase_p , int * hbase_numdigits_p )
2013-05-31 10:57:03 -04:00
{
2013-05-31 18:32:55 -04:00
BDIGIT hbase ;
2013-05-31 10:57:03 -04:00
int hbase_numdigits ;
2013-05-31 11:24:47 -04:00
hbase = base ;
hbase_numdigits = 1 ;
while ( hbase < = ( ~ ( BDIGIT ) 0 ) / base ) {
hbase * = base ;
hbase_numdigits + + ;
}
2013-05-31 10:57:03 -04:00
* hbase_p = hbase ;
* hbase_numdigits_p = hbase_numdigits ;
}
2013-06-08 20: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 03:53:20 -04:00
numwords = trim ? rb_absint_numwords ( x , word_numbits , NULL ) : len ;
2013-06-08 20: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 06:37:39 -04:00
rb_integer_pack ( x , ptr , numwords , 1 , CHAR_BIT - word_numbits ,
2013-06-08 20:36:58 -04:00
INTEGER_PACK_BIG_ENDIAN ) ;
while ( 0 < numwords ) {
* ptr = ruby_digitmap [ * ( unsigned char * ) ptr ] ;
ptr + + ;
numwords - - ;
}
return result ;
}
2007-08-06 14:03:11 -04:00
VALUE
rb_big2str0 ( VALUE x , int base , int trim )
2007-08-02 10:45:34 -04:00
{
2007-08-06 14:03:11 -04:00
int off ;
VALUE ss , xx ;
2013-05-31 18:32:55 -04:00
long n1 , n2 , len ;
BDIGIT hbase ;
2013-05-31 10:24:31 -04:00
int hbase_numdigits ;
2007-08-06 14:03:11 -04:00
char * ptr ;
2007-08-02 10:45:34 -04:00
2007-08-06 14:03:11 -04:00
if ( FIXNUM_P ( x ) ) {
2008-03-07 07:28:57 -05:00
return rb_fix2str ( x , base ) ;
2007-08-02 10:45:34 -04:00
}
2007-08-06 14:03:11 -04:00
if ( BIGZEROP ( x ) ) {
2008-03-07 07:28:57 -05:00
return rb_usascii_str_new2 ( " 0 " ) ;
2007-08-06 14:03:11 -04:00
}
2007-12-18 10:10:37 -05:00
if ( base < 2 | | 36 < base )
2008-03-07 07:28:57 -05:00
rb_raise ( rb_eArgError , " invalid radix %d " , base ) ;
2007-08-06 14:03:11 -04:00
2007-11-27 12:42:12 -05:00
n2 = big2str_find_n1 ( x , base ) ;
2013-06-08 20: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 12:42:12 -05:00
n1 = ( n2 + 1 ) / 2 ;
2008-01-28 10:12:43 -05:00
ss = rb_usascii_str_new ( 0 , n2 + 1 ) ; /* plus one for sign */
2007-08-06 14:03:11 -04:00
ptr = RSTRING_PTR ( ss ) ;
2007-09-01 08:02:36 -04:00
ptr [ 0 ] = RBIGNUM_SIGN ( x ) ? ' + ' : ' - ' ;
2007-08-06 14:03:11 -04:00
2013-05-31 10:57:03 -04:00
calc_hbase ( base , & hbase , & hbase_numdigits ) ;
2007-09-01 08:02:36 -04:00
off = ! ( trim & & RBIGNUM_SIGN ( x ) ) ; /* erase plus sign if trim */
2007-08-06 14:03:11 -04:00
xx = rb_big_clone ( x ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( xx , 1 ) ;
2007-08-06 14:03:11 -04:00
if ( n1 < = KARATSUBA_DIGITS ) {
2013-05-31 10:24:31 -04:00
len = off + big2str_orig ( xx , base , ptr + off , n2 , hbase , hbase_numdigits , trim ) ;
2007-08-06 14:03:11 -04:00
}
else {
2008-03-07 07:28:57 -05:00
len = off + big2str_karatsuba ( xx , base , ptr + off , n1 ,
2013-05-31 10:24:31 -04:00
n2 , hbase , hbase_numdigits , trim ) ;
2007-08-06 14:03:11 -04:00
}
2008-09-18 07:21:34 -04:00
rb_big_resize ( xx , 0 ) ;
2007-08-06 14:03:11 -04:00
ptr [ len ] = ' \0 ' ;
rb_str_resize ( ss , len ) ;
return ss ;
2007-08-02 10:45:34 -04:00
}
2006-10-29 22:39:44 -05:00
VALUE
rb_big2str ( VALUE x , int base )
{
2007-08-06 14:03:11 -04:00
return rb_big2str0 ( x , base , 1 ) ;
2006-10-29 22:39:44 -05:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . to_s ( base = 10 ) - > string
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
* Returns a string containing the representation of < i > big < / i > radix
* < i > base < / i > ( 2 through 36 ) .
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05: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 07:13:05 -05: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 06:44:21 -04:00
rb_big_to_s ( int argc , VALUE * argv , VALUE x )
1998-01-16 07:13:05 -05:00
{
2001-11-19 00:03:03 -05:00
int base ;
if ( argc = = 0 ) base = 10 ;
2008-03-05 00:22:17 -05:00
else {
VALUE b ;
rb_scan_args ( argc , argv , " 01 " , & b ) ;
base = NUM2INT ( b ) ;
}
2001-11-19 00:03:03 -05:00
return rb_big2str ( x , base ) ;
1998-01-16 07:13:05 -05:00
}
2006-07-11 02:47:09 -04:00
static VALUE
2005-10-21 02:28:41 -04:00
big2ulong ( VALUE x , const char * type , int check )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
long len = RBIGNUM_LEN ( x ) ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num ;
2000-10-31 03:37:47 -05:00
BDIGIT * ds ;
1998-01-16 07:13:05 -05:00
2007-12-24 13:12:24 -05:00
if ( len > DIGSPERLONG ) {
2004-01-22 13:06:38 -05:00
if ( check )
rb_raise ( rb_eRangeError , " bignum too big to convert into `%s' " , type ) ;
2007-12-24 13:12:24 -05:00
len = DIGSPERLONG ;
2004-01-22 13:06:38 -05:00
}
1998-01-16 07:13:05 -05: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 05:16:15 -04:00
return ( VALUE ) num ;
1998-01-16 07:13:05 -05:00
}
2006-07-11 02: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 06:44:21 -04:00
rb_big2ulong_pack ( VALUE x )
2004-01-22 13:06:38 -05:00
{
2009-07-18 04:05:32 -04:00
VALUE num = big2ulong ( x , " unsigned long " , FALSE ) ;
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
2009-03-10 01:43:14 -04:00
return ( VALUE ) ( - ( SIGNED_VALUE ) num ) ;
2004-01-22 13:06:38 -05:00
}
return num ;
}
2006-07-11 02: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 06:44:21 -04:00
rb_big2ulong ( VALUE x )
2000-01-04 23:41:21 -05:00
{
2009-07-18 04:05:32 -04:00
VALUE num = big2ulong ( x , " unsigned long " , TRUE ) ;
2000-01-04 23:41:21 -05:00
2013-04-09 07: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 13:45:53 -04:00
}
2013-04-09 18:47:51 -04:00
rb_raise ( rb_eRangeError , " bignum out of range of unsigned long " ) ;
2000-01-04 23:41:21 -05:00
}
2006-07-11 02: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 06:44:21 -04:00
rb_big2long ( VALUE x )
1999-01-19 23:59:39 -05:00
{
2009-07-18 04:05:32 -04:00
VALUE num = big2ulong ( x , " long " , TRUE ) ;
1999-01-19 23:59:39 -05:00
2013-04-09 07:39:53 -04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
2013-04-09 18:47:51 -04:00
if ( num < = LONG_MAX )
return num ;
2013-04-09 07: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-19 23:59:39 -05:00
}
2013-04-09 18:47:51 -04:00
rb_raise ( rb_eRangeError , " bignum too big to convert into `long' " ) ;
1999-01-19 23:59:39 -05:00
}
2002-03-14 01:23:46 -05: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 03:51:31 -05:00
static unsigned LONG_LONG
2005-10-21 02:28:41 -04:00
big2ull ( VALUE x , const char * type )
2002-03-14 01:23:46 -05:00
{
2007-09-01 08:02:36 -04:00
long len = RBIGNUM_LEN ( x ) ;
2002-03-14 01:23:46 -05:00
BDIGIT_DBL num ;
BDIGIT * ds ;
2002-04-10 04:45:26 -04:00
if ( len > SIZEOF_LONG_LONG / SIZEOF_BDIGITS )
2002-03-14 01:23:46 -05: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 03:51:31 -05: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 06:44:21 -04:00
rb_big2ull ( VALUE x )
2002-03-14 01:23:46 -05: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 03:51:31 -05:00
unsigned LONG_LONG num = big2ull ( x , " unsigned long long " ) ;
2002-03-14 01:23:46 -05:00
2013-04-09 07: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-13 22:51:56 -05:00
}
2013-04-09 18:47:51 -04:00
rb_raise ( rb_eRangeError , " bignum out of range of unsigned long long " ) ;
2002-03-14 01:23:46 -05: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 03:51:31 -05: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 06:44:21 -04:00
rb_big2ll ( VALUE x )
2002-03-14 01:23:46 -05: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 03:51:31 -05:00
unsigned LONG_LONG num = big2ull ( x , " long long " ) ;
2002-03-14 01:23:46 -05:00
2013-04-09 07:39:53 -04:00
if ( RBIGNUM_POSITIVE_P ( x ) ) {
2013-04-09 18:47:51 -04:00
if ( num < = LLONG_MAX )
return num ;
2013-04-09 07: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 01:23:46 -05:00
}
2013-04-09 18:47:51 -04:00
rb_raise ( rb_eRangeError , " bignum too big to convert into `long long' " ) ;
2002-03-14 01:23:46 -05:00
}
# endif /* HAVE_LONG_LONG */
2000-06-22 04: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 06:44:21 -04:00
dbl2big ( double d )
1998-01-16 07:13:05 -05:00
{
2000-10-31 03:37:47 -05:00
long i = 0 ;
2000-11-02 04:04:54 -05:00
BDIGIT c ;
2000-10-31 03:37:47 -05:00
BDIGIT * digits ;
1998-01-16 07:13:05 -05:00
VALUE z ;
double u = ( d < 0 ) ? - d : d ;
1999-08-13 01: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 07:13:05 -05:00
u / = ( double ) ( BIGRAD ) ;
i + + ;
}
z = bignew ( i , d > = 0 ) ;
digits = BDIGITS ( z ) ;
while ( i - - ) {
u * = BIGRAD ;
2000-11-02 04:04:54 -05:00
c = ( BDIGIT ) u ;
1998-01-16 07:13:05 -05:00
u - = c ;
2000-11-02 04:04:54 -05:00
digits [ i ] = c ;
1998-01-16 07:13:05 -05:00
}
2000-06-22 04: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 06:44:21 -04:00
rb_dbl2big ( double d )
2000-06-22 04:29:58 -04:00
{
return bignorm ( dbl2big ( d ) ) ;
1998-01-16 07:13:05 -05:00
}
2008-04-01 03: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 04:12:31 -04:00
static double
big2dbl ( VALUE x )
1998-01-16 07:13:05 -05:00
{
double d = 0.0 ;
2009-08-25 04:38:28 -04:00
long i = ( bigtrunc ( x ) , RBIGNUM_LEN ( x ) ) , lo = 0 , bits ;
2008-04-01 03:40:23 -04:00
BDIGIT * ds = BDIGITS ( x ) , dl ;
1998-01-16 07:13:05 -05:00
2008-04-01 03: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 00:58:15 -04:00
int carry = dl & ~ ( ~ ( BDIGIT ) 0 < < bits ) ;
2008-04-01 03:40:23 -04:00
if ( ! carry ) {
while ( i - - > 0 ) {
if ( ( carry = ds [ i ] ) ! = 0 ) break ;
}
}
if ( carry ) {
2009-05-26 00:58:15 -04:00
dl & = ( BDIGIT ) ~ 0 < < bits ;
dl + = ( BDIGIT ) 1 < < bits ;
2008-04-01 03:40:23 -04:00
if ( ! dl ) d + = 1 ;
}
}
d = dl + BIGRAD * d ;
2009-05-26 00: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 03:40:23 -04:00
}
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) d = - d ;
2007-05-02 04:12:31 -04:00
return d ;
}
double
rb_big2dbl ( VALUE x )
{
double d = big2dbl ( x ) ;
2003-07-09 18:28:42 -04:00
if ( isinf ( d ) ) {
2008-05-07 00:14:57 -04:00
rb_warning ( " Bignum out of Float range " ) ;
2009-06-15 18:58:46 -04:00
if ( d < 0.0 )
d = - HUGE_VAL ;
2009-06-15 09:39:18 -04:00
else
2009-06-15 18:58:46 -04:00
d = HUGE_VAL ;
2003-07-09 18:28:42 -04:00
}
1998-01-16 07:13:05 -05:00
return d ;
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
* big . to_f - > float
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
*/
1999-01-19 23:59:39 -05: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 06:44:21 -04:00
rb_big_to_f ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2008-09-05 14:24:21 -04:00
return DBL2NUM ( rb_big2dbl ( x ) ) ;
1998-01-16 07:13:05 -05:00
}
2012-07-16 02:02:21 -04:00
VALUE
2012-07-16 05:41:25 -04:00
rb_integer_float_cmp ( VALUE x , VALUE y )
2012-07-16 02:02:21 -04:00
{
2012-07-16 06:02:59 -04:00
double yd = RFLOAT_VALUE ( y ) ;
2012-07-16 05:08:58 -04:00
double yi , yf ;
VALUE rel ;
2012-07-16 02:02:21 -04:00
2012-07-16 06:02:59 -04:00
if ( isnan ( yd ) )
2012-07-16 04:44:32 -04:00
return Qnil ;
2012-07-16 06:02:59 -04:00
if ( isinf ( yd ) ) {
if ( yd > 0.0 ) return INT2FIX ( - 1 ) ;
2012-07-16 02:02:21 -04:00
else return INT2FIX ( 1 ) ;
}
2012-07-16 06:02:59 -04:00
yf = modf ( yd , & yi ) ;
2012-07-16 04:44:32 -04:00
if ( FIXNUM_P ( x ) ) {
2012-07-16 05:08:58 -04:00
# if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
2012-07-16 04:44:32 -04:00
double xd = ( double ) FIX2LONG ( x ) ;
2012-07-16 06:02:59 -04:00
if ( xd < yd )
2012-07-16 04:44:32 -04:00
return INT2FIX ( - 1 ) ;
2012-07-16 06:02:59 -04:00
if ( xd > yd )
2012-07-16 04:44:32 -04:00
return INT2FIX ( 1 ) ;
return INT2FIX ( 0 ) ;
2012-07-16 05:08:58 -04:00
# else
long xl , yl ;
2012-07-16 10:30:24 -04:00
if ( yi < FIXNUM_MIN )
2012-07-16 05:08:58 -04:00
return INT2FIX ( 1 ) ;
2012-07-16 10:30:24 -04:00
if ( FIXNUM_MAX + 1 < = yi )
2012-07-16 05: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 04:44:32 -04:00
}
2012-07-16 05: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 02:02:21 -04:00
}
2012-07-16 06: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-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big < = > numeric - > - 1 , 0 , + 1 or nil
2007-05-08 23:49:18 -04:00
*
2013-02-22 22:35:38 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
*/
2005-08-12 04: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 06:44:21 -04:00
rb_big_cmp ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
long xlen = RBIGNUM_LEN ( x ) ;
2009-08-09 01:55:00 -04:00
BDIGIT * xds , * yds ;
1998-01-16 07:13:05 -05:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-19 23:59:39 -05:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
break ;
case T_BIGNUM :
break ;
2000-06-05 04:46:59 -04:00
case T_FLOAT :
2012-07-16 05:41:25 -04:00
return rb_integer_float_cmp ( x , y ) ;
2000-06-05 04:46:59 -04:00
1998-01-16 07:13:05 -05:00
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_cmp ( x , y , rb_intern ( " <=> " ) ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08: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 07:13:05 -05:00
2009-08-09 01:55:00 -04:00
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
2012-12-29 07:22:04 -05:00
while ( xlen - - & & ( xds [ xlen ] = = yds [ xlen ] ) ) ;
1998-01-16 07:13:05 -05:00
if ( - 1 = = xlen ) return INT2FIX ( 0 ) ;
2009-08-09 01:55:00 -04:00
return ( xds [ xlen ] > yds [ xlen ] ) ?
2007-09-01 08:02:36 -04:00
( RBIGNUM_SIGN ( x ) ? INT2FIX ( 1 ) : INT2FIX ( - 1 ) ) :
( RBIGNUM_SIGN ( x ) ? INT2FIX ( - 1 ) : INT2FIX ( 1 ) ) ;
1998-01-16 07:13:05 -05:00
}
2012-07-16 01:15:36 -04:00
enum big_op_t {
big_op_gt ,
big_op_ge ,
big_op_lt ,
big_op_le
} ;
2010-02-04 10:36:29 -05:00
static VALUE
2012-07-16 01:15:36 -04:00
big_op ( VALUE x , VALUE y , enum big_op_t op )
2010-02-04 10:36:29 -05: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 05:41:25 -04:00
rel = rb_integer_float_cmp ( x , y ) ;
2012-07-16 02:02:21 -04:00
break ;
2010-02-04 10:36:29 -05:00
default :
{
ID id = 0 ;
switch ( op ) {
2012-07-16 01: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 10:36:29 -05:00
}
return rb_num_coerce_relop ( x , y , id ) ;
}
}
if ( NIL_P ( rel ) ) return Qfalse ;
n = FIX2INT ( rel ) ;
switch ( op ) {
2012-07-16 01: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 10:36:29 -05: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 01:15:36 -04:00
return big_op ( x , y , big_op_gt ) ;
2010-02-04 10:36:29 -05: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 01:15:36 -04:00
return big_op ( x , y , big_op_ge ) ;
2010-02-04 10:36:29 -05: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 01:15:36 -04:00
return big_op ( x , y , big_op_lt ) ;
2010-02-04 10:36:29 -05: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 01:15:36 -04:00
return big_op ( x , y , big_op_le ) ;
2010-02-04 10:36:29 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big = = obj - > true or false
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* 68719476736 = = 68719476736.0 # = > true
*/
2005-08-12 04: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 06:44:21 -04:00
rb_big_eq ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2000-06-05 04:46:59 -04:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2013-04-03 03:34:31 -04:00
if ( bignorm ( x ) = = y ) return Qtrue ;
2000-06-05 04:46:59 -04:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
break ;
case T_BIGNUM :
break ;
case T_FLOAT :
2012-07-16 06:39:42 -04:00
return rb_integer_float_eq ( x , y ) ;
2000-06-05 04:46:59 -04:00
default :
2002-04-18 04:46:18 -04:00
return rb_equal ( y , x ) ;
2000-06-05 04:46:59 -04:00
}
2007-09-01 08: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 04:46:59 -04:00
return Qtrue ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . eql ? ( obj ) - > true or false
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* 68719476736. eql ? ( 68719476736.0 ) # = > false
*/
2012-12-25 05:14:12 -05: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 06:44:21 -04:00
rb_big_eql ( VALUE x , VALUE y )
2001-11-08 01:43:14 -05:00
{
2011-09-29 07:07:45 -04:00
if ( ! RB_TYPE_P ( y , T_BIGNUM ) ) return Qfalse ;
2007-09-01 08: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 01:43:14 -05:00
return Qtrue ;
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* - big - > integer
2003-12-18 19:01:19 -05:00
*
2009-10-12 13:49:15 -04:00
* Unary minus ( returns an integer whose value is 0 - big )
2003-12-18 19:01:19 -05:00
*/
2011-05-29 02: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 06:44:21 -04:00
rb_big_uminus ( VALUE x )
1998-01-16 07:13:05 -05:00
{
1999-01-19 23:59:39 -05:00
VALUE z = rb_big_clone ( x ) ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( z , ! RBIGNUM_SIGN ( x ) ) ;
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* ~ big - > integer
2003-12-18 22:58:57 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* sprintf ( " %X " , ~ 0x1122334455 ) # = > " ..FEEDDCCBBAA "
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_neg ( VALUE x )
1998-01-16 07:13:05 -05:00
{
1999-01-19 23:59:39 -05:00
VALUE z = rb_big_clone ( x ) ;
2005-07-01 04:56:09 -04:00
BDIGIT * ds ;
long i ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) get2comp ( z ) ;
2005-07-01 04:56:09 -04:00
ds = BDIGITS ( z ) ;
2007-09-01 08:02:36 -04:00
i = RBIGNUM_LEN ( x ) ;
2007-07-15 08:07:46 -04:00
if ( ! i ) return INT2FIX ( ~ ( SIGNED_VALUE ) 0 ) ;
2005-06-07 22:16:35 -04:00
while ( i - - ) {
ds [ i ] = ~ ds [ i ] ;
}
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( z , ! RBIGNUM_SIGN ( z ) ) ;
if ( RBIGNUM_SIGN ( x ) ) get2comp ( z ) ;
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2008-12-13 22:59:02 -05: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 ) ;
}
while ( i < xn ) {
zds [ i ] = xds [ i ] ;
i + + ;
}
assert ( i < = zn ) ;
while ( i < zn ) {
zds [ i + + ] = 0 ;
}
}
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
bigsub ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
1998-01-16 07:19:22 -05:00
VALUE z = 0 ;
2007-09-01 08:02:36 -04:00
long i = RBIGNUM_LEN ( x ) ;
2009-08-09 01:55:00 -04:00
BDIGIT * xds , * yds ;
2007-05-08 23:49:18 -04:00
2011-05-22 11:37:00 -04:00
/* if x is smaller than y, swap */
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_LEN ( x ) < RBIGNUM_LEN ( y ) ) {
1998-01-16 07:13:05 -05:00
z = x ; x = y ; y = z ; /* swap x y */
}
2007-09-01 08:02:36 -04:00
else if ( RBIGNUM_LEN ( x ) = = RBIGNUM_LEN ( y ) ) {
2009-08-09 01:55:00 -04:00
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
1998-01-16 07:13:05 -05:00
while ( i > 0 ) {
i - - ;
2009-08-09 01:55:00 -04:00
if ( xds [ i ] > yds [ i ] ) {
1998-01-16 07:13:05 -05:00
break ;
}
2009-08-09 01:55:00 -04:00
if ( xds [ i ] < yds [ i ] ) {
1998-01-16 07:13:05 -05:00
z = x ; x = y ; y = z ; /* swap x y */
break ;
}
}
}
2007-09-01 08:02:36 -04:00
z = bignew ( RBIGNUM_LEN ( x ) , z = = 0 ) ;
2008-12-13 22:59:02 -05:00
bigsub_core ( BDIGITS ( x ) , RBIGNUM_LEN ( x ) ,
BDIGITS ( y ) , RBIGNUM_LEN ( y ) ,
BDIGITS ( z ) , RBIGNUM_LEN ( z ) ) ;
1998-01-16 07:13:05 -05:00
2008-12-13 22:59:02 -05:00
return z ;
}
2009-04-20 13: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 00:58:15 -04:00
zds [ 0 ] = ( BDIGIT ) - num ;
2011-07-15 06:16:41 -04:00
RB_GC_GUARD ( x ) ;
2009-04-20 13:53:36 -04:00
return bignorm ( z ) ;
}
zds [ 0 ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
i = 1 ;
# else
num = 0 ;
2009-05-26 00:58:15 -04:00
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
2009-04-20 13: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 06:16:41 -04:00
RB_GC_GUARD ( x ) ;
2009-04-20 13: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 00:58:15 -04:00
for ( i = 0 ; i < ( int ) ( sizeof ( y ) / sizeof ( BDIGIT ) ) ; i + + ) {
2009-04-20 13: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 06:16:41 -04:00
RB_GC_GUARD ( x ) ;
2009-04-20 13:53:36 -04:00
return bignorm ( z ) ;
}
2008-12-13 22:59:02 -05: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 07:13:05 -05:00
num = BIGDN ( num ) ;
2007-05-08 23:49:18 -04:00
}
2008-12-13 22:59:02 -05:00
while ( num & & i < yn ) {
num + = yds [ i ] ;
1998-01-16 07:13:05 -05:00
zds [ i + + ] = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
2008-12-13 22:59:02 -05:00
while ( i < yn ) {
zds [ i ] = yds [ i ] ;
1998-01-16 07:13:05 -05:00
i + + ;
}
2008-12-13 22:59:02 -05:00
if ( num ) zds [ i + + ] = ( BDIGIT ) num ;
assert ( i < = zn ) ;
while ( i < zn ) {
zds [ i + + ] = 0 ;
}
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
bigadd ( VALUE x , VALUE y , int sign )
1998-01-16 07:13:05 -05:00
{
1998-01-16 07:19:22 -05:00
VALUE z ;
2008-12-13 22:59:02 -05:00
long len ;
1998-01-16 07:19:22 -05:00
2007-09-01 08:02:36 -04:00
sign = ( sign = = RBIGNUM_SIGN ( y ) ) ;
if ( RBIGNUM_SIGN ( x ) ! = sign ) {
1999-01-19 23:59:39 -05:00
if ( sign ) return bigsub ( y , x ) ;
1998-01-16 07:13:05 -05:00
return bigsub ( x , y ) ;
}
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
len = RBIGNUM_LEN ( x ) + 1 ;
1998-01-16 07:13:05 -05:00
}
else {
2007-09-01 08:02:36 -04:00
len = RBIGNUM_LEN ( y ) + 1 ;
1998-01-16 07:13:05 -05:00
}
1999-01-19 23:59:39 -05:00
z = bignew ( len , sign ) ;
1998-01-16 07:13:05 -05:00
2008-12-13 22:59:02 -05:00
bigadd_core ( BDIGITS ( x ) , RBIGNUM_LEN ( x ) ,
BDIGITS ( y ) , RBIGNUM_LEN ( y ) ,
BDIGITS ( z ) , RBIGNUM_LEN ( z ) ) ;
1998-01-16 07:13:05 -05:00
2000-07-12 02:06:50 -04:00
return z ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big + other - > Numeric
2003-12-18 19:01:19 -05:00
*
* Adds big and other , returning the result .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_plus ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2009-04-20 13:53:36 -04:00
long n ;
1998-01-16 07:13:05 -05:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2009-04-20 13: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 07:13:05 -05:00
case T_BIGNUM :
2000-07-12 02:06:50 -04:00
return bignorm ( bigadd ( x , y , 1 ) ) ;
1998-01-16 07:13:05 -05:00
case T_FLOAT :
2008-09-05 14:24:21 -04:00
return DBL2NUM ( rb_big2dbl ( x ) + RFLOAT_VALUE ( y ) ) ;
1998-01-16 07:13:05 -05:00
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , ' + ' ) ;
1998-01-16 07:13:05 -05:00
}
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big - other - > Numeric
2003-12-18 19:01:19 -05:00
*
* Subtracts other from big , returning the result .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_minus ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2009-04-20 13:53:36 -04:00
long n ;
1998-01-16 07:13:05 -05:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
2009-04-20 13: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 07:13:05 -05:00
case T_BIGNUM :
2000-07-12 02:06:50 -04:00
return bignorm ( bigadd ( x , y , 0 ) ) ;
1998-01-16 07:13:05 -05:00
case T_FLOAT :
2008-09-05 14:24:21 -04:00
return DBL2NUM ( rb_big2dbl ( x ) - RFLOAT_VALUE ( y ) ) ;
1998-01-16 07:13:05 -05:00
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , ' - ' ) ;
1998-01-16 07:13:05 -05:00
}
}
2008-12-13 22:59:02 -05:00
static long
big_real_len ( VALUE x )
2007-12-19 05:13:03 -05:00
{
2008-12-13 22:59:02 -05:00
long i = RBIGNUM_LEN ( x ) ;
2009-08-09 01:55:00 -04:00
BDIGIT * xds = BDIGITS ( x ) ;
while ( - - i & & ! xds [ i ] ) ;
2008-12-13 22:59:02 -05:00
return i + 1 ;
2007-12-19 05:13:03 -05:00
}
2009-08-29 20:46:32 -04:00
static VALUE
bigmul1_single ( VALUE x , VALUE y )
{
BDIGIT_DBL n ;
VALUE z = bignew ( 2 , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
BDIGIT * xds , * yds , * zds ;
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
zds = BDIGITS ( z ) ;
n = ( BDIGIT_DBL ) xds [ 0 ] * yds [ 0 ] ;
zds [ 0 ] = BIGLO ( n ) ;
2009-09-13 00:15:06 -04:00
zds [ 1 ] = ( BDIGIT ) BIGDN ( n ) ;
2009-08-29 20:46:32 -04:00
return z ;
}
2005-08-09 21:39:24 -04:00
static VALUE
2008-12-13 22:59:02 -05:00
bigmul1_normal ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2009-08-25 04:38:28 -04:00
long xl = RBIGNUM_LEN ( x ) , yl = RBIGNUM_LEN ( y ) , i , j = xl + yl + 1 ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL n = 0 ;
2009-08-25 04:38:28 -04:00
VALUE z = bignew ( j , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
2009-08-09 01:55:00 -04:00
BDIGIT * xds , * yds , * zds ;
1998-01-16 07:13:05 -05:00
2009-08-09 01:55:00 -04:00
xds = BDIGITS ( x ) ;
yds = BDIGITS ( y ) ;
1998-01-16 07:13:05 -05:00
zds = BDIGITS ( z ) ;
while ( j - - ) zds [ j ] = 0 ;
2009-08-25 04:38:28 -04:00
for ( i = 0 ; i < xl ; i + + ) {
2007-12-19 06:40:52 -05:00
BDIGIT_DBL dd ;
2009-08-09 01:55:00 -04:00
dd = xds [ i ] ;
1998-01-16 07:13:05 -05:00
if ( dd = = 0 ) continue ;
n = 0 ;
2009-08-25 04:38:28 -04:00
for ( j = 0 ; j < yl ; j + + ) {
2009-08-09 01:55:00 -04:00
BDIGIT_DBL ee = n + ( BDIGIT_DBL ) dd * yds [ j ] ;
1998-01-16 07:13:05 -05: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 05:16:15 -04:00
zds [ i + j ] = ( BDIGIT ) n ;
1998-01-16 07:13:05 -05:00
}
}
2008-12-13 22:59:02 -05:00
rb_thread_check_ints ( ) ;
2005-08-09 21:39:24 -04:00
return z ;
}
1998-01-16 07:13:05 -05:00
2008-12-13 22:59:02 -05:00
static VALUE bigmul0 ( VALUE x , VALUE y ) ;
/* balancing multiplication by slicing larger argument */
2007-12-19 05:13:03 -05:00
static VALUE
2008-12-13 22:59:02 -05:00
bigmul1_balance ( VALUE x , VALUE y )
2007-12-19 05:13:03 -05:00
{
2008-12-13 22:59:02 -05:00
VALUE z , t1 , t2 ;
long i , xn , yn , r , n ;
2009-08-09 01:55:00 -04:00
BDIGIT * yds , * zds , * t1ds ;
2007-12-19 05:13:03 -05:00
2008-12-13 22:59:02 -05:00
xn = RBIGNUM_LEN ( x ) ;
yn = RBIGNUM_LEN ( y ) ;
2011-05-22 11:37:00 -04:00
assert ( 2 * xn < = yn | | 3 * xn < = 2 * ( yn + 2 ) ) ;
2007-12-19 05:13:03 -05:00
2008-12-13 22:59:02 -05:00
z = bignew ( xn + yn , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
t1 = bignew ( xn , 1 ) ;
2007-12-19 05:13:03 -05:00
2009-08-09 01: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 05:13:03 -05:00
2008-12-13 22:59:02 -05:00
n = 0 ;
while ( yn > 0 ) {
r = xn > yn ? yn : xn ;
2009-08-09 01:55:00 -04:00
MEMCPY ( t1ds , yds + n , BDIGIT , r ) ;
2008-12-13 22:59:02 -05:00
RBIGNUM_SET_LEN ( t1 , r ) ;
t2 = bigmul0 ( x , t1 ) ;
2009-08-09 01:55:00 -04:00
bigadd_core ( zds + n , RBIGNUM_LEN ( z ) - n ,
2008-12-13 22:59:02 -05:00
BDIGITS ( t2 ) , big_real_len ( t2 ) ,
2009-08-09 01:55:00 -04:00
zds + n , RBIGNUM_LEN ( z ) - n ) ;
2008-12-13 22:59:02 -05:00
yn - = r ;
n + = r ;
2007-12-19 05:13:03 -05:00
}
2008-12-13 22:59:02 -05:00
return z ;
}
/* split a bignum into high and low bignums */
static void
2009-08-25 04:38:28 -04:00
big_split ( VALUE v , long n , volatile VALUE * ph , volatile VALUE * pl )
2008-12-13 22:59:02 -05:00
{
2009-08-25 04:38:28 -04:00
long hn = 0 , ln = RBIGNUM_LEN ( v ) ;
2008-12-13 22:59:02 -05:00
VALUE h , l ;
2009-08-09 01:55:00 -04:00
BDIGIT * vds = BDIGITS ( v ) ;
2008-12-13 22:59:02 -05:00
2009-08-25 04:38:28 -04:00
if ( ln > n ) {
hn = ln - n ;
ln = n ;
}
2008-12-13 22:59:02 -05:00
2011-05-22 11: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-13 22:59:02 -05:00
2009-08-09 01:55:00 -04:00
while ( - - ln & & ! vds [ ln ] ) ;
2008-12-14 08:39:33 -05:00
l = bignew ( ln + = 2 , 1 ) ;
2009-10-17 04:31:07 -04:00
MEMCPY ( BDIGITS ( l ) , vds , BDIGIT , ln - 1 ) ;
BDIGITS ( l ) [ ln - 1 ] = 0 ; /* margin for carry */
2008-12-13 22:59:02 -05: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 11:31:46 -04:00
VALUE xh , xl , yh , yl , z , t1 , t2 , t3 ;
2008-12-13 22:59:02 -05: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 07:15:07 -05:00
* z1 = ( xh + xl ) * ( yh + yl ) - z2 - z0
2008-12-13 22:59:02 -05: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 07:15:07 -05:00
for ( i = 2 * n + t1n ; i < xn + yn ; i + + ) zds [ i ] = 0 ;
2007-12-19 05:13:03 -05:00
2008-12-13 22:59:02 -05:00
if ( ! BIGZEROP ( xl ) & & ! BIGZEROP ( yl ) ) {
/* t2 <- xl * yl */
2009-11-26 00:25:08 -05:00
t2 = bigmul0 ( xl , yl ) ;
t2n = big_real_len ( t2 ) ;
2007-12-19 05:13:03 -05:00
2008-12-13 22:59:02 -05:00
/* copy t2 into low bytes of the result (z0) */
MEMCPY ( zds , BDIGITS ( t2 ) , BDIGIT , t2n ) ;
2008-12-14 07:15:07 -05:00
for ( i = t2n ; i < 2 * n ; i + + ) zds [ i ] = 0 ;
2007-12-19 05:13:03 -05:00
}
else {
2010-04-20 11:31:46 -04:00
t2 = Qundef ;
2010-04-25 11:08:44 -04:00
t2n = 0 ;
2010-04-20 11:31:46 -04:00
2008-12-13 22:59:02 -05:00
/* copy 0 into low bytes of the result (z0) */
2008-12-14 07:15:07 -05:00
for ( i = 0 ; i < 2 * n ; i + + ) zds [ i ] = 0 ;
2007-12-19 05:13:03 -05:00
}
2008-12-14 08:39:33 -05:00
/* xh <- xh + xl */
if ( RBIGNUM_LEN ( xl ) > RBIGNUM_LEN ( xh ) ) {
2010-04-20 11:31:46 -04:00
t3 = xl ; xl = xh ; xh = t3 ;
2008-12-14 08:39:33 -05:00
}
2010-04-20 11:31:46 -04:00
/* xh has a margin for carry */
2008-12-14 08:39:33 -05:00
bigadd_core ( BDIGITS ( xh ) , RBIGNUM_LEN ( xh ) ,
2009-02-22 09:23:33 -05:00
BDIGITS ( xl ) , RBIGNUM_LEN ( xl ) ,
2008-12-14 08:39:33 -05:00
BDIGITS ( xh ) , RBIGNUM_LEN ( xh ) ) ;
2008-12-13 22:59:02 -05:00
2008-12-14 08:39:33 -05:00
/* yh <- yh + yl */
if ( x ! = y ) {
if ( RBIGNUM_LEN ( yl ) > RBIGNUM_LEN ( yh ) ) {
2010-04-20 11:31:46 -04:00
t3 = yl ; yl = yh ; yh = t3 ;
2008-12-14 08:39:33 -05:00
}
2010-04-20 11:31:46 -04:00
/* yh has a margin for carry */
2008-12-14 08:39:33 -05:00
bigadd_core ( BDIGITS ( yh ) , RBIGNUM_LEN ( yh ) ,
2009-02-22 09:23:33 -05:00
BDIGITS ( yl ) , RBIGNUM_LEN ( yl ) ,
2008-12-14 08:39:33 -05:00
BDIGITS ( yh ) , RBIGNUM_LEN ( yh ) ) ;
}
else yh = xh ;
2008-12-13 22:59:02 -05:00
2010-04-20 11:31:46 -04:00
/* t3 <- xh * yh */
t3 = bigmul0 ( xh , yh ) ;
i = xn + yn - n ;
2011-01-06 19:17:06 -05: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 11:31:46 -04:00
2011-01-06 19:17:06 -05: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-13 22:59:02 -05:00
2011-01-06 19:17:06 -05: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-13 22:59:02 -05:00
return z ;
}
2011-05-22 11: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 11:49:07 -04:00
long n , xn , yn , zn ;
2011-05-22 11: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-08 17:38:03 -05:00
z3 = bigtrunc ( bigadd ( z2 , z3 , 0 ) ) ;
2011-05-22 11: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-13 22:59:02 -05: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 05:16:15 -04:00
if ( c ) zds [ i + len + 1 ] + = ( BDIGIT ) c ;
2008-12-13 22:59:02 -05:00
}
2007-12-19 05:13:03 -05:00
return z ;
}
2008-12-13 22:59:02 -05:00
# define KARATSUBA_MUL_DIGITS 70
2011-05-22 11:37:00 -04:00
# define TOOM3_MUL_DIGITS 150
2008-12-13 22:59:02 -05: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 01: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-13 22:59:02 -05: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-29 20:46:32 -04:00
if ( xn = = 1 & & yn = = 1 ) return bigmul1_single ( x , y ) ;
2009-11-26 00:25:08 -05:00
return bigmul1_normal ( x , y ) ;
2008-12-13 22:59:02 -05: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-08 17:38:03 -05: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-13 22:59:02 -05:00
}
2005-08-09 21:39:24 -04:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big * other - > Numeric
2005-08-09 21: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 06:44:21 -04:00
rb_big_mul ( VALUE x , VALUE y )
2005-08-09 21:39:24 -04:00
{
2008-12-13 22:59:02 -05: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 07:13:05 -05:00
}
2007-12-19 05:13:03 -05:00
struct big_div_struct {
2012-11-27 07:46:32 -05:00
long nx , ny , j , nyzero ;
2008-01-29 07:58:24 -05:00
BDIGIT * yds , * zds ;
2012-11-26 01:49:48 -05:00
volatile VALUE stop ;
2007-12-19 05:13:03 -05:00
} ;
2012-07-10 09:57:11 -04:00
static void *
2007-12-19 05:13:03 -05:00
bigdivrem1 ( void * ptr )
1998-01-16 07:13:05 -05:00
{
2007-12-19 05:13:03 -05:00
struct big_div_struct * bds = ( struct big_div_struct * ) ptr ;
2012-11-27 07:46:32 -05:00
long ny = bds - > ny ;
long i , j ;
2008-01-29 07:58:24 -05:00
BDIGIT * yds = bds - > yds , * zds = bds - > zds ;
BDIGIT_DBL t2 ;
BDIGIT_DBL_SIGNED num ;
BDIGIT q ;
2012-11-27 07:46:32 -05:00
j = bds - > j ;
2008-01-29 07:58:24 -05:00
do {
2012-11-27 07:46:32 -05: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 05:16:15 -04:00
if ( zds [ j ] = = yds [ ny - 1 ] ) q = ( BDIGIT ) BIGRAD - 1 ;
2008-01-29 07:58:24 -05:00
else q = ( BDIGIT ) ( ( BIGUP ( zds [ j ] ) + zds [ j - 1 ] ) / yds [ ny - 1 ] ) ;
if ( q ) {
2012-11-27 07:46:32 -05:00
i = bds - > nyzero ; num = 0 ; t2 = 0 ;
2008-01-29 07:58:24 -05: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 09:57:11 -04:00
return 0 ;
2008-01-29 07:58:24 -05:00
}
2008-12-13 22:59:02 -05:00
static void
rb_big_stop ( void * ptr )
{
2012-11-26 01:49:48 -05:00
struct big_div_struct * bds = ptr ;
bds - > stop = Qtrue ;
2008-12-13 22:59:02 -05:00
}
2008-01-29 07:58:24 -05:00
static VALUE
2012-11-27 07:46:32 -05:00
bigdivrem ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp )
2008-01-29 07:58:24 -05:00
{
struct big_div_struct bds ;
2012-11-27 07:46:32 -05:00
long nx = RBIGNUM_LEN ( x ) , ny = RBIGNUM_LEN ( y ) ;
1999-08-13 01:45:20 -04:00
long i , j ;
2009-08-25 04:38:28 -04:00
VALUE z , yy , zz ;
2000-10-31 03:37:47 -05:00
BDIGIT * xds , * yds , * zds , * tds ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL t2 ;
2000-10-31 03:37:47 -05:00
BDIGIT dd , q ;
1998-01-16 07:13:05 -05:00
2003-04-09 02:44:34 -04:00
if ( BIGZEROP ( y ) ) rb_num_zerodiv ( ) ;
2009-08-25 04:38:28 -04:00
xds = BDIGITS ( x ) ;
1998-01-16 07:13:05 -05:00
yds = BDIGITS ( y ) ;
2009-08-25 04:38:28 -04:00
if ( nx < ny | | ( nx = = ny & & xds [ nx - 1 ] < yds [ ny - 1 ] ) ) {
2000-07-12 03:33:34 -04:00
if ( divp ) * divp = rb_int2big ( 0 ) ;
2000-07-12 02:06:50 -04:00
if ( modp ) * modp = x ;
2007-12-19 06:40:52 -05:00
return Qnil ;
1998-01-16 07:13:05 -05:00
}
if ( ny = = 1 ) {
dd = yds [ 0 ] ;
1999-01-19 23:59:39 -05:00
z = rb_big_clone ( x ) ;
1998-01-16 07:13:05 -05:00
zds = BDIGITS ( z ) ;
t2 = 0 ; i = nx ;
while ( i - - ) {
t2 = BIGUP ( t2 ) + zds [ i ] ;
2000-10-31 03:37:47 -05:00
zds [ i ] = ( BDIGIT ) ( t2 / dd ) ;
1998-01-16 07:13:05 -05:00
t2 % = dd ;
}
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( z , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
2001-01-09 02:26:21 -05:00
if ( modp ) {
2006-07-11 01:00:02 -04:00
* modp = rb_uint2big ( ( VALUE ) t2 ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( * modp , RBIGNUM_SIGN ( x ) ) ;
2001-01-09 02:26:21 -05:00
}
2000-07-12 02:06:50 -04:00
if ( divp ) * divp = z ;
2007-12-19 06:40:52 -05:00
return Qnil ;
1998-01-16 07:13:05 -05:00
}
2011-05-22 11:37:00 -04:00
2007-09-01 08:02:36 -04:00
z = bignew ( nx = = ny ? nx + 2 : nx + 1 , RBIGNUM_SIGN ( x ) = = RBIGNUM_SIGN ( y ) ) ;
1998-01-16 07:13:05 -05:00
zds = BDIGITS ( z ) ;
if ( nx = = ny ) zds [ nx + 1 ] = 0 ;
while ( ! yds [ ny - 1 ] ) ny - - ;
2000-11-08 00:29:37 -05:00
dd = 0 ;
q = yds [ ny - 1 ] ;
2010-03-24 23:08:28 -04:00
while ( ( q & ( BDIGIT ) ( 1UL < < ( BITSPERDIG - 1 ) ) ) = = 0 ) {
2006-07-03 16:07:10 -04:00
q < < = 1UL ;
2000-11-08 00:29:37 -05:00
dd + + ;
}
if ( dd ) {
1999-01-19 23:59:39 -05:00
yy = rb_big_clone ( y ) ;
tds = BDIGITS ( yy ) ;
1998-01-16 07:13:05 -05:00
j = 0 ;
2000-11-08 00:29:37 -05:00
t2 = 0 ;
1998-01-16 07:13:05 -05:00
while ( j < ny ) {
2000-11-08 00:29:37 -05:00
t2 + = ( BDIGIT_DBL ) yds [ j ] < < dd ;
tds [ j + + ] = BIGLO ( t2 ) ;
t2 = BIGDN ( t2 ) ;
1998-01-16 07:13:05 -05:00
}
yds = tds ;
2009-08-25 04:38:28 -04:00
RB_GC_GUARD ( y ) = yy ;
1998-01-16 07:13:05 -05:00
j = 0 ;
2000-11-08 00:29:37 -05:00
t2 = 0 ;
1998-01-16 07:13:05 -05:00
while ( j < nx ) {
2000-11-08 00:29:37 -05:00
t2 + = ( BDIGIT_DBL ) xds [ j ] < < dd ;
zds [ j + + ] = BIGLO ( t2 ) ;
t2 = BIGDN ( t2 ) ;
1998-01-16 07:13:05 -05:00
}
2000-11-08 00:29:37 -05:00
zds [ j ] = ( BDIGIT ) t2 ;
1998-01-16 07:13:05 -05:00
}
else {
zds [ nx ] = 0 ;
j = nx ;
while ( j - - ) zds [ j ] = xds [ j ] ;
}
2000-11-08 00:29:37 -05:00
2008-01-29 07:58:24 -05:00
bds . nx = nx ;
bds . ny = ny ;
bds . zds = zds ;
bds . yds = yds ;
bds . stop = Qfalse ;
2012-11-27 07:46:32 -05:00
bds . j = nx = = ny ? nx + 1 : nx ;
for ( bds . nyzero = 0 ; ! yds [ bds . nyzero ] ; bds . nyzero + + ) ;
2009-08-25 04:38:28 -04:00
if ( nx > 10000 | | ny > 10000 ) {
2012-11-27 07:46:32 -05:00
retry :
bds . stop = Qfalse ;
2012-11-26 01:49:48 -05:00
rb_thread_call_without_gvl ( bigdivrem1 , & bds , rb_big_stop , & bds ) ;
2012-11-26 02:00:04 -05:00
if ( bds . stop = = Qtrue ) {
/* execute trap handler, but exception was not raised. */
goto retry ;
}
2008-01-29 07:58:24 -05:00
}
else {
bigdivrem1 ( & bds ) ;
}
2000-07-12 02:06:50 -04:00
if ( divp ) { /* move quotient down in z */
2009-08-25 04:38:28 -04:00
* divp = zz = rb_big_clone ( z ) ;
zds = BDIGITS ( zz ) ;
1998-01-16 07:13:05 -05:00
j = ( nx = = ny ? nx + 2 : nx + 1 ) - ny ;
for ( i = 0 ; i < j ; i + + ) zds [ i ] = zds [ i + ny ] ;
2008-09-11 02:30:56 -04:00
if ( ! zds [ i - 1 ] ) i - - ;
2009-08-25 04:38:28 -04:00
RBIGNUM_SET_LEN ( zz , i ) ;
1998-01-16 07:13:05 -05:00
}
2002-10-07 03:44:18 -04:00
if ( modp ) { /* normalize remainder */
2009-08-25 04:38:28 -04:00
* modp = zz = rb_big_clone ( z ) ;
zds = BDIGITS ( zz ) ;
2012-08-21 12:49:00 -04:00
while ( ny > 1 & & ! zds [ ny - 1 ] ) - - ny ;
1998-01-16 07:13:05 -05:00
if ( dd ) {
2001-05-02 00:22:21 -04:00
t2 = 0 ; i = ny ;
2012-12-29 07:22:04 -05:00
while ( i - - ) {
2000-11-08 00:29:37 -05:00
t2 = ( t2 | zds [ i ] ) > > dd ;
q = zds [ i ] ;
zds [ i ] = BIGLO ( t2 ) ;
t2 = BIGUP ( q ) ;
1998-01-16 07:13:05 -05:00
}
}
2008-09-11 02:30:56 -04:00
if ( ! zds [ ny - 1 ] ) ny - - ;
2009-08-25 04:38:28 -04:00
RBIGNUM_SET_LEN ( zz , ny ) ;
RBIGNUM_SET_SIGN ( zz , RBIGNUM_SIGN ( x ) ) ;
2000-07-06 03:21:26 -04:00
}
2007-12-19 05:13:03 -05:00
return z ;
}
2000-07-06 03:21:26 -04:00
static void
2009-08-25 04:38:28 -04:00
bigdivmod ( VALUE x , VALUE y , volatile VALUE * divp , volatile VALUE * modp )
2000-07-06 03:21:26 -04:00
{
VALUE mod ;
bigdivrem ( x , y , divp , & mod ) ;
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_SIGN ( x ) ! = RBIGNUM_SIGN ( y ) & & ! BIGZEROP ( mod ) ) {
2000-07-06 03:21:26 -04:00
if ( divp ) * divp = bigadd ( * divp , rb_int2big ( 1 ) , 0 ) ;
if ( modp ) * modp = bigadd ( mod , y , 1 ) ;
}
2008-08-29 12:56:44 -04:00
else if ( modp ) {
* modp = mod ;
1998-01-16 07:13:05 -05:00
}
}
2003-12-18 19:01:19 -05:00
2008-04-07 09:52:26 -04:00
static VALUE
rb_big_divide ( VALUE x , VALUE y , ID op )
1998-01-16 07:13:05 -05:00
{
VALUE z ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-19 23:59:39 -05:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
break ;
case T_BIGNUM :
break ;
case T_FLOAT :
2008-05-01 10:20:15 -04:00
{
if ( op = = ' / ' ) {
2011-11-21 21:27:53 -05:00
return DBL2NUM ( rb_big2dbl ( x ) / RFLOAT_VALUE ( y ) ) ;
2008-05-01 10:20:15 -04:00
}
else {
2011-11-21 21:27:53 -05:00
double dy = RFLOAT_VALUE ( y ) ;
if ( dy = = 0.0 ) rb_num_zerodiv ( ) ;
return rb_dbl2big ( rb_big2dbl ( x ) / dy ) ;
2008-05-01 10:20:15 -04:00
}
}
1998-01-16 07:13:05 -05:00
default :
2008-04-07 09:52:26 -04:00
return rb_num_coerce_bin ( x , y , op ) ;
1998-01-16 07:13:05 -05:00
}
2000-07-06 03:21:26 -04:00
bigdivmod ( x , y , & z , 0 ) ;
1998-01-16 07:13:05 -05:00
2000-07-12 02:06:50 -04:00
return bignorm ( z ) ;
1998-01-16 07:13:05 -05:00
}
2008-04-07 09:52:26 -04:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big / other - > Numeric
2008-04-07 09:52:26 -04:00
*
2009-09-04 04: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 09:52:26 -04:00
*/
VALUE
rb_big_div ( VALUE x , VALUE y )
{
2009-09-04 01:40:52 -04:00
return rb_big_divide ( x , y , ' / ' ) ;
2008-04-07 09:52:26 -04:00
}
2009-09-04 04:06:12 -04:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . div ( other ) - > integer
2009-09-04 04:06:12 -04:00
*
* Performs integer division : returns integer value .
*/
2008-04-07 09:52:26 -04:00
VALUE
rb_big_idiv ( VALUE x , VALUE y )
{
2009-09-04 01:40:52 -04:00
return rb_big_divide ( x , y , rb_intern ( " div " ) ) ;
2008-04-07 09:52:26 -04:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big % other - > Numeric
* big . modulo ( other ) - > Numeric
2003-12-18 19:01:19 -05:00
*
* Returns big modulo other . See Numeric . divmod for more
* information .
*/
2005-08-03 03: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 06:44:21 -04:00
rb_big_modulo ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
VALUE z ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-19 23:59:39 -05:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
break ;
case T_BIGNUM :
break ;
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , ' % ' ) ;
1998-01-16 07:13:05 -05:00
}
2000-07-03 01:46:36 -04:00
bigdivmod ( x , y , 0 , & z ) ;
1998-01-16 07:13:05 -05:00
2000-07-12 02:06:50 -04:00
return bignorm ( z ) ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . remainder ( numeric ) - > number
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
* Returns the remainder after dividing < i > big < / i > by < i > numeric < / i > .
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
* - 1234567890987654321. remainder ( 13731 ) # = > - 6966
* - 1234567890987654321. remainder ( 13731.24 ) # = > - 9906.22531493148
*/
2000-07-06 03: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 06:44:21 -04:00
rb_big_remainder ( VALUE x , VALUE y )
2000-07-06 03: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-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , rb_intern ( " remainder " ) ) ;
2000-07-06 03:21:26 -04:00
}
bigdivrem ( x , y , 0 , & z ) ;
return bignorm ( z ) ;
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . divmod ( numeric ) - > array
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
* See < code > Numeric # divmod < / code > .
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
*/
2000-05-12 05: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 06:44:21 -04:00
rb_big_divmod ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
VALUE div , mod ;
switch ( TYPE ( y ) ) {
case T_FIXNUM :
1999-01-19 23:59:39 -05:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
break ;
case T_BIGNUM :
break ;
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , rb_intern ( " divmod " ) ) ;
1998-01-16 07:13:05 -05:00
}
2000-07-03 01:46:36 -04:00
bigdivmod ( x , y , & div , & mod ) ;
1998-01-16 07:13:05 -05:00
2000-07-12 02:06:50 -04:00
return rb_assoc_new ( bignorm ( div ) , bignorm ( mod ) ) ;
1998-01-16 07:13:05 -05:00
}
2009-05-26 00:58:15 -04:00
static VALUE
big_shift ( VALUE x , long n )
2007-07-19 01:38:48 -04:00
{
if ( n < 0 )
2009-05-26 00:58:15 -04:00
return big_lshift ( x , ( unsigned long ) - n ) ;
2007-07-19 01:38:48 -04:00
else if ( n > 0 )
2009-05-26 00:58:15 -04:00
return big_rshift ( x , ( unsigned long ) n ) ;
2007-07-19 01:38:48 -04:00
return x ;
}
2007-05-02 04:12:31 -04:00
2010-05-29 14:51:39 -04:00
static VALUE
2009-06-17 08: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 08:17:30 -04:00
l = RBIGNUM_LEN ( x ) ;
ex = l * BITSPERDIG - nlz ( BDIGITS ( x ) [ l - 1 ] ) ;
2009-06-17 08: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-14 20:06:13 -04:00
case T_BIGNUM :
2009-06-18 19:14:08 -04:00
bigtrunc ( y ) ;
2013-06-05 08:17:30 -04:00
l = RBIGNUM_LEN ( y ) ;
ey = l * BITSPERDIG - nlz ( BDIGITS ( y ) [ l - 1 ] ) ;
2009-06-18 19:14:08 -04:00
ey - = DBL_BIGDIG * BITSPERDIG ;
if ( ey ) y = big_shift ( y , ey ) ;
2012-04-14 20:06:13 -04:00
break ;
2009-06-17 08: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-14 20:06:13 -04:00
break ;
default :
rb_bug ( " big_fdiv " ) ;
2009-06-17 08:55:16 -04:00
}
2012-04-14 20: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 08:55:16 -04:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2008-05-07 00:14:57 -04:00
* big . fdiv ( numeric ) - > float
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
* Returns the floating point result of dividing < i > big < / i > by
* < i > numeric < / i > .
2007-05-08 23:49:18 -04:00
*
2008-05-07 00:14:57 -04:00
* - 1234567890987654321.f div ( 13731 ) # = > - 89910996357705.5
* - 1234567890987654321.f div ( 13731.24 ) # = > - 89909424858035.7
2007-05-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
*/
2009-06-17 08:55:16 -04:00
VALUE
2008-03-15 20:23:43 -04:00
rb_big_fdiv ( VALUE x , VALUE y )
2003-01-23 01:22:50 -05:00
{
2009-06-17 08:55:16 -04:00
double dx , dy ;
2003-01-23 01:22:50 -05:00
2009-06-17 08:55:16 -04:00
dx = big2dbl ( x ) ;
2003-01-23 01:22:50 -05:00
switch ( TYPE ( y ) ) {
case T_FIXNUM :
dy = ( double ) FIX2LONG ( y ) ;
2009-06-17 08:55:16 -04:00
if ( isinf ( dx ) )
return big_fdiv ( x , y ) ;
2003-01-23 01:22:50 -05:00
break ;
case T_BIGNUM :
dy = rb_big2dbl ( y ) ;
2009-06-17 08:55:16 -04:00
if ( isinf ( dx ) | | isinf ( dy ) )
return big_fdiv ( x , y ) ;
2003-01-23 01:22:50 -05: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 11:00:53 -05:00
dy = RFLOAT_VALUE ( y ) ;
2009-06-17 08:55:16 -04:00
if ( isnan ( dy ) )
return y ;
if ( isinf ( dx ) )
return big_fdiv ( x , y ) ;
2003-01-23 01:22:50 -05:00
break ;
default :
2008-03-15 20:23:43 -04:00
return rb_num_coerce_bin ( x , y , rb_intern ( " fdiv " ) ) ;
2003-01-23 01:22:50 -05:00
}
2008-09-05 14:24:21 -04:00
return DBL2NUM ( dx / dy ) ;
2003-01-23 01:22:50 -05:00
}
2007-05-01 16:39:48 -04:00
static VALUE
bigsqr ( VALUE x )
{
2008-12-14 08:39:33 -05:00
return bigtrunc ( bigmul0 ( x , x ) ) ;
2007-05-01 16:39:48 -04:00
}
2003-12-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big * * exponent - > numeric
2003-12-18 19:01:19 -05: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 07:13:05 -05: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 06:44:21 -04:00
rb_big_pow ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
double d ;
2007-05-01 16:39:48 -04:00
SIGNED_VALUE yy ;
1998-01-16 07:13:05 -05: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 11:00:53 -05:00
d = RFLOAT_VALUE ( y ) ;
2009-08-16 19: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 07:13:05 -05:00
break ;
case T_BIGNUM :
1999-01-19 23:59:39 -05:00
rb_warn ( " in a**b, b may be too big " ) ;
d = rb_big2dbl ( y ) ;
1998-01-16 07:13:05 -05:00
break ;
case T_FIXNUM :
2004-03-14 21:27:29 -05:00
yy = FIX2LONG ( y ) ;
2008-03-15 20:23:43 -04:00
if ( yy < 0 )
2008-09-19 09:55:52 -04:00
return rb_funcall ( rb_rational_raw1 ( x ) , rb_intern ( " ** " ) , 1 , y ) ;
2008-03-15 20:23:43 -04:00
else {
2007-05-01 16:39:48 -04:00
VALUE z = 0 ;
2007-07-15 11:26:12 -04:00
SIGNED_VALUE mask ;
2013-06-04 19:15:30 -04:00
const long xlen = RBIGNUM_LEN ( x ) ;
const long xbits = BITSPERDIG * xlen - nlz ( RBIGNUM_DIGITS ( x ) [ xlen - 1 ] ) ;
2012-03-18 04:17:50 -04:00
const long BIGLEN_LIMIT = BITSPERDIG * 1024 * 1024 ;
1999-01-19 23:59:39 -05:00
2012-03-18 04: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-09 17:20:17 -04:00
rb_warn ( " in a**b, b may be too big " ) ;
d = ( double ) yy ;
break ;
}
2007-05-01 16:39:48 -04:00
for ( mask = FIXNUM_MAX + 1 ; mask ; mask > > = 1 ) {
2008-12-14 08:39:33 -05:00
if ( z ) z = bigsqr ( z ) ;
2007-05-01 16:39:48 -04:00
if ( yy & mask ) {
2008-12-13 22:59:02 -05:00
z = z ? bigtrunc ( bigmul0 ( z , x ) ) : x ;
2007-05-01 16:39:48 -04:00
}
1999-01-19 23:59:39 -05:00
}
2002-06-11 03:02:23 -04:00
return bignorm ( z ) ;
1999-01-19 23:59:39 -05:00
}
2008-03-15 20:23:43 -04:00
/* NOTREACHED */
1998-01-16 07:13:05 -05:00
break ;
default :
2008-02-11 21:46:21 -05:00
return rb_num_coerce_bin ( x , y , rb_intern ( " ** " ) ) ;
1998-01-16 07:13:05 -05:00
}
2008-09-05 14:24:21 -04:00
return DBL2NUM ( pow ( rb_big2dbl ( x ) , d ) ) ;
1998-01-16 07:13:05 -05:00
}
2009-05-27 12: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-18 19:01:19 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big & numeric - > integer
2003-12-18 19:01:19 -05:00
*
* Performs bitwise + and + between _big_ and _numeric_ .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_and ( VALUE xx , VALUE yy )
1998-01-16 07:13:05 -05:00
{
2004-08-28 10:14:11 -04:00
volatile VALUE x , y , z ;
2000-10-31 03:37:47 -05:00
BDIGIT * ds1 , * ds2 , * zds ;
1999-08-13 01:45:20 -04:00
long i , l1 , l2 ;
1998-01-16 07:13:05 -05:00
char sign ;
2012-12-22 10:06:22 -05:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' & ' ) ;
}
2004-08-28 10:14:11 -04:00
x = xx ;
2012-12-22 10:06:22 -05:00
y = yy ;
2009-05-27 12:16:57 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 07:13:05 -05:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 12:16:57 -04:00
return bigand_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-19 23:59:39 -05:00
y = rb_big_clone ( y ) ;
2005-06-30 02:20:09 -04:00
get2comp ( y ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 07:13:05 -05:00
}
else {
2007-09-01 08:02:36 -04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
z = bignew ( l2 , RBIGNUM_SIGN ( x ) | | RBIGNUM_SIGN ( y ) ) ;
1998-01-16 07:13:05 -05: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 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2009-05-27 12: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-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big | numeric - > integer
2003-12-18 22:58:57 -05:00
*
* Performs bitwise + or + between _big_ and _numeric_ .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_or ( VALUE xx , VALUE yy )
1998-01-16 07:13:05 -05:00
{
2004-08-28 10:14:11 -04:00
volatile VALUE x , y , z ;
2000-10-31 03:37:47 -05:00
BDIGIT * ds1 , * ds2 , * zds ;
long i , l1 , l2 ;
1998-01-16 07:13:05 -05:00
char sign ;
2012-12-22 10:06:22 -05:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' | ' ) ;
}
2004-08-28 10:14:11 -04:00
x = xx ;
2012-12-22 10:06:22 -05:00
y = yy ;
2009-05-27 12:16:57 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 07:13:05 -05:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 12:16:57 -04:00
return bigor_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-19 23:59:39 -05:00
y = rb_big_clone ( y ) ;
2005-06-30 02:20:09 -04:00
get2comp ( y ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 07:13:05 -05:00
}
else {
2007-09-01 08:02:36 -04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
z = bignew ( l2 , RBIGNUM_SIGN ( x ) & & RBIGNUM_SIGN ( y ) ) ;
1998-01-16 07:13:05 -05: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 05:16:15 -04:00
zds [ i ] = sign ? ds2 [ i ] : ( BDIGIT ) ( BIGRAD - 1 ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2009-05-27 12: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-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big ^ numeric - > integer
2003-12-18 22:58:57 -05:00
*
* Performs bitwise + exclusive or + between _big_ and _numeric_ .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_xor ( VALUE xx , VALUE yy )
1998-01-16 07:13:05 -05:00
{
2004-09-03 05:00:52 -04:00
volatile VALUE x , y ;
1998-01-16 07:13:05 -05:00
VALUE z ;
2000-10-31 03:37:47 -05:00
BDIGIT * ds1 , * ds2 , * zds ;
long i , l1 , l2 ;
1998-01-16 07:13:05 -05:00
char sign ;
2012-12-22 10:06:22 -05:00
if ( ! FIXNUM_P ( yy ) & & ! RB_TYPE_P ( yy , T_BIGNUM ) ) {
return rb_num_coerce_bit ( xx , yy , ' ^ ' ) ;
}
2004-09-03 05:00:52 -04:00
x = xx ;
2012-12-22 10:06:22 -05:00
y = yy ;
2009-05-27 12:16:57 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
x = rb_big_clone ( x ) ;
get2comp ( x ) ;
}
1998-01-16 07:13:05 -05:00
if ( FIXNUM_P ( y ) ) {
2009-05-27 12:16:57 -04:00
return bigxor_int ( x , FIX2LONG ( y ) ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
1999-01-19 23:59:39 -05:00
y = rb_big_clone ( y ) ;
2005-06-30 02:20:09 -04:00
get2comp ( y ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_LEN ( x ) > RBIGNUM_LEN ( y ) ) {
l1 = RBIGNUM_LEN ( y ) ;
l2 = RBIGNUM_LEN ( x ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( y ) ;
ds2 = BDIGITS ( x ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( y ) ;
1998-01-16 07:13:05 -05:00
}
else {
2007-09-01 08:02:36 -04:00
l1 = RBIGNUM_LEN ( x ) ;
l2 = RBIGNUM_LEN ( y ) ;
1998-01-16 07:13:05 -05:00
ds1 = BDIGITS ( x ) ;
ds2 = BDIGITS ( y ) ;
2007-09-01 08:02:36 -04:00
sign = RBIGNUM_SIGN ( x ) ;
1998-01-16 07:13:05 -05:00
}
2007-09-01 08: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 07:13:05 -05: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 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( z ) ) get2comp ( z ) ;
1998-01-16 07:13:05 -05:00
return bignorm ( z ) ;
}
2007-07-19 01:38:48 -04:00
static VALUE
check_shiftdown ( VALUE y , VALUE x )
{
2007-09-01 08: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 01:38:48 -04:00
}
return Qnil ;
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big < < numeric - > integer
2003-12-18 22:58:57 -05:00
*
* Shifts big left _numeric_ positions ( right if _numeric_ is negative ) .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_lshift ( VALUE x , VALUE y )
2007-07-19 01:38:48 -04:00
{
2007-08-16 00:09:02 -04:00
long shift ;
int neg = 0 ;
2007-07-19 01:38:48 -04:00
for ( ; ; ) {
if ( FIXNUM_P ( y ) ) {
2007-08-16 00:09:02 -04:00
shift = FIX2LONG ( y ) ;
2007-07-19 01:38:48 -04:00
if ( shift < 0 ) {
neg = 1 ;
shift = - shift ;
}
break ;
}
2011-09-29 07:07:45 -04:00
else if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( y ) ) {
2007-07-19 01:38:48 -04:00
VALUE t = check_shiftdown ( y , x ) ;
if ( ! NIL_P ( t ) ) return t ;
neg = 1 ;
}
2009-07-18 04:05:32 -04:00
shift = big2ulong ( y , " long " , TRUE ) ;
2007-07-19 01:38:48 -04:00
break ;
}
y = rb_to_int ( y ) ;
}
2009-06-18 19:14:08 -04:00
x = neg ? big_rshift ( x , shift ) : big_lshift ( x , shift ) ;
return bignorm ( x ) ;
2007-07-19 01:38:48 -04:00
}
static VALUE
2007-08-16 00:09:02 -04:00
big_lshift ( VALUE x , unsigned long shift )
1998-01-16 07:13:05 -05:00
{
2000-10-31 03:37:47 -05:00
BDIGIT * xds , * zds ;
2007-08-16 00:09:02 -04:00
long s1 = shift / BITSPERDIG ;
2009-05-26 00:58:15 -04:00
int s2 = ( int ) ( shift % BITSPERDIG ) ;
1998-01-16 07:13:05 -05:00
VALUE z ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num = 0 ;
1999-08-13 01:45:20 -04:00
long len , i ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
len = RBIGNUM_LEN ( x ) ;
z = bignew ( len + s1 + 1 , RBIGNUM_SIGN ( x ) ) ;
1998-01-16 07:13:05 -05:00
zds = BDIGITS ( z ) ;
for ( i = 0 ; i < s1 ; i + + ) {
* zds + + = 0 ;
}
2000-06-28 04:31:35 -04:00
xds = BDIGITS ( x ) ;
1998-01-16 07:13:05 -05:00
for ( i = 0 ; i < len ; i + + ) {
2000-12-21 22:22:25 -05:00
num = num | ( BDIGIT_DBL ) * xds + + < < s2 ;
1998-01-16 07:13:05 -05:00
* zds + + = BIGLO ( num ) ;
num = BIGDN ( num ) ;
}
* zds = BIGLO ( num ) ;
2009-06-18 19:14:08 -04:00
return z ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big > > numeric - > integer
2003-12-18 22:58:57 -05:00
*
* Shifts big right _numeric_ positions ( left if _numeric_ is negative ) .
*/
2007-07-19 01: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 06:44:21 -04:00
rb_big_rshift ( VALUE x , VALUE y )
2007-07-19 01:38:48 -04:00
{
2007-08-16 00:09:02 -04:00
long shift ;
2007-07-19 01:38:48 -04:00
int neg = 0 ;
for ( ; ; ) {
if ( FIXNUM_P ( y ) ) {
2007-08-16 00:09:02 -04:00
shift = FIX2LONG ( y ) ;
2007-07-19 01:38:48 -04:00
if ( shift < 0 ) {
neg = 1 ;
shift = - shift ;
}
break ;
}
2011-09-29 07:07:45 -04:00
else if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_SIGN ( y ) ) {
2007-07-19 01:38:48 -04:00
VALUE t = check_shiftdown ( y , x ) ;
if ( ! NIL_P ( t ) ) return t ;
}
else {
neg = 1 ;
}
2009-07-18 04:05:32 -04:00
shift = big2ulong ( y , " long " , TRUE ) ;
2007-07-19 01:38:48 -04:00
break ;
}
y = rb_to_int ( y ) ;
}
2009-06-18 19:14:08 -04:00
x = neg ? big_lshift ( x , shift ) : big_rshift ( x , shift ) ;
return bignorm ( x ) ;
2007-07-19 01:38:48 -04:00
}
static VALUE
2007-08-16 00:09:02 -04:00
big_rshift ( VALUE x , unsigned long shift )
1998-01-16 07:13:05 -05:00
{
2000-10-31 03:37:47 -05:00
BDIGIT * xds , * zds ;
2002-08-21 11:47:54 -04:00
long s1 = shift / BITSPERDIG ;
2009-05-26 00:58:15 -04:00
int s2 = ( int ) ( shift % BITSPERDIG ) ;
1998-01-16 07:13:05 -05:00
VALUE z ;
2000-11-01 03:49:40 -05:00
BDIGIT_DBL num = 0 ;
2002-08-21 11:47:54 -04:00
long i , j ;
2005-12-16 13:59:31 -05:00
volatile VALUE save_x ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
if ( s1 > RBIGNUM_LEN ( x ) ) {
if ( RBIGNUM_SIGN ( x ) )
1998-01-16 07:13:05 -05:00
return INT2FIX ( 0 ) ;
else
return INT2FIX ( - 1 ) ;
}
2007-09-01 08: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 04:57:00 -05:00
x = rb_big_clone ( x ) ;
2005-06-30 02:20:09 -04:00
get2comp ( x ) ;
2002-02-14 23:43:58 -05: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 04:57:00 -05:00
save_x = x ;
1998-01-16 07:13:05 -05:00
xds = BDIGITS ( x ) ;
2007-09-01 08:02:36 -04:00
i = RBIGNUM_LEN ( x ) ; j = i - s1 ;
2006-10-07 11:49:00 -04:00
if ( j = = 0 ) {
2007-09-01 08:02:36 -04:00
if ( RBIGNUM_SIGN ( x ) ) return INT2FIX ( 0 ) ;
2006-10-07 11:49:00 -04:00
else return INT2FIX ( - 1 ) ;
}
2007-09-01 08:02:36 -04:00
z = bignew ( j , RBIGNUM_SIGN ( x ) ) ;
if ( ! RBIGNUM_SIGN ( x ) ) {
2002-10-04 13:54:29 -04:00
num = ( ( BDIGIT_DBL ) ~ 0 ) < < BITSPERDIG ;
}
1998-01-16 07:13:05 -05:00
zds = BDIGITS ( z ) ;
while ( i - - , j - - ) {
num = ( num | xds [ i ] ) > > s2 ;
zds [ j ] = BIGLO ( num ) ;
num = BIGUP ( xds [ i ] ) ;
}
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
2005-06-30 02:20:09 -04:00
get2comp ( z ) ;
2002-02-14 23:43:58 -05: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 04:57:00 -05:00
RB_GC_GUARD ( save_x ) ;
2009-06-18 19:14:08 -04:00
return z ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
* big [ n ] - > 0 , 1
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05: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-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* a = 9 * * 15
* 50. downto ( 0 ) do | n |
* print a [ n ]
* end
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* < em > produces : < / em >
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* 000101110110100000111000011110010100111100010111001
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_aref ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
2000-10-31 03:37:47 -05:00
BDIGIT * xds ;
2007-07-29 22:16:42 -04:00
BDIGIT_DBL num ;
VALUE shift ;
long i , s1 , s2 ;
1998-01-16 07:13:05 -05:00
2011-09-29 07:07:45 -04:00
if ( RB_TYPE_P ( y , T_BIGNUM ) ) {
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( y ) )
2001-11-01 00:11:24 -05:00
return INT2FIX ( 0 ) ;
2009-05-25 22:19:33 -04:00
bigtrunc ( y ) ;
if ( RBIGNUM_LEN ( y ) > DIGSPERLONG ) {
2007-07-29 22:16:42 -04:00
out_of_range :
2007-09-01 08:02:36 -04:00
return RBIGNUM_SIGN ( x ) ? INT2FIX ( 0 ) : INT2FIX ( 1 ) ;
2007-07-29 22:16:42 -04:00
}
2009-07-18 04:05:32 -04:00
shift = big2ulong ( y , " long " , FALSE ) ;
2007-07-29 22:16:42 -04:00
}
else {
i = NUM2LONG ( y ) ;
if ( i < 0 ) return INT2FIX ( 0 ) ;
shift = ( VALUE ) i ;
2001-11-01 00:11:24 -05:00
}
1998-01-16 07:19:22 -05:00
s1 = shift / BITSPERDIG ;
s2 = shift % BITSPERDIG ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
if ( s1 > = RBIGNUM_LEN ( x ) ) goto out_of_range ;
if ( ! RBIGNUM_SIGN ( x ) ) {
2007-07-29 22:16:42 -04:00
xds = BDIGITS ( x ) ;
i = 0 ; num = 1 ;
while ( num + = ~ xds [ i ] , + + i < = s1 ) {
num = BIGDN ( num ) ;
}
1998-01-16 07:13:05 -05:00
}
else {
2007-07-29 22:16:42 -04:00
num = BDIGITS ( x ) [ s1 ] ;
1998-01-16 07:13:05 -05:00
}
2007-07-29 22:16:42 -04:00
if ( num & ( ( BDIGIT_DBL ) 1 < < s2 ) )
1998-01-16 07:13:05 -05:00
return INT2FIX ( 1 ) ;
return INT2FIX ( 0 ) ;
}
2003-12-28 22:56:22 -05:00
/*
* call - seq :
2010-05-17 17:07:33 -04:00
* big . hash - > fixnum
2003-12-28 22:56:22 -05:00
*
* Compute a hash based on the value of _big_ .
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_hash ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2009-09-08 09:10:04 -04:00
st_index_t hash ;
1998-01-16 07:13:05 -05:00
2007-09-01 08:02:36 -04:00
hash = rb_memhash ( BDIGITS ( x ) , sizeof ( BDIGIT ) * RBIGNUM_LEN ( x ) ) ^ RBIGNUM_SIGN ( x ) ;
2006-09-21 18:52:38 -04:00
return INT2FIX ( hash ) ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 19:01:19 -05:00
/*
* MISSING : documentation
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_coerce ( VALUE x , VALUE y )
1998-01-16 07:13:05 -05:00
{
if ( FIXNUM_P ( y ) ) {
2012-04-14 20:06:13 -04:00
y = rb_int2big ( FIX2LONG ( y ) ) ;
2005-08-09 21:39:24 -04:00
}
2012-04-14 20: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 01:47:45 -05:00
rb_raise ( rb_eTypeError , " can't coerce %s to Bignum " ,
2003-01-30 23:00:17 -05:00
rb_obj_classname ( y ) ) ;
1998-01-16 07:13:05 -05:00
}
2012-04-14 20:06:13 -04:00
return rb_assoc_new ( y , x ) ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
* big . abs - > aBignum
2013-04-11 22:59:07 -04:00
* big . magnitude - > aBignum
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* Returns the absolute value of < i > big < / i > .
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* - 1234567890987654321. abs # = > 1234567890987654321
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_abs ( VALUE x )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
if ( ! RBIGNUM_SIGN ( x ) ) {
1999-01-19 23:59:39 -05:00
x = rb_big_clone ( x ) ;
2007-09-01 08:02:36 -04:00
RBIGNUM_SET_SIGN ( x , 1 ) ;
1998-01-16 07:13:05 -05:00
}
1999-01-19 23:59:39 -05:00
return x ;
1998-01-16 07:13:05 -05:00
}
2003-12-18 22:58:57 -05:00
/*
* call - seq :
* big . size - > integer
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* Returns the number of bytes in the machine representation of
* < i > big < / i > .
2007-05-08 23:49:18 -04:00
*
2003-12-18 22:58:57 -05:00
* ( 256 * * 10 - 1 ) . size # = > 12
* ( 256 * * 20 - 1 ) . size # = > 20
* ( 256 * * 40 - 1 ) . size # = > 40
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
rb_big_size ( VALUE big )
1998-01-16 07:13:05 -05:00
{
2007-09-01 08:02:36 -04:00
return LONG2FIX ( RBIGNUM_LEN ( big ) * SIZEOF_BDIGITS ) ;
1998-01-16 07:13:05 -05:00
}
2007-11-16 09:41:11 -05: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 12:42:12 -05:00
return Qtrue ;
2007-11-16 09:41:11 -05: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 12:42:12 -05:00
return Qfalse ;
2007-11-16 09:41:11 -05:00
}
return Qtrue ;
}
2003-12-18 19:01:19 -05: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-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05: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-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05: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-08 23:49:18 -04:00
*
2003-12-18 19:01:19 -05:00
*/
1998-01-16 07:13:05 -05: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 06:44:21 -04:00
Init_Bignum ( void )
1998-01-16 07:13:05 -05:00
{
1999-01-19 23:59:39 -05:00
rb_cBignum = rb_define_class ( " Bignum " , rb_cInteger ) ;
2001-11-19 00:03:03 -05:00
rb_define_method ( rb_cBignum , " to_s " , rb_big_to_s , - 1 ) ;
2012-08-15 07:50:01 -04:00
rb_define_alias ( rb_cBignum , " inspect " , " to_s " ) ;
1999-01-19 23:59:39 -05: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 03:21:26 -04:00
rb_define_method ( rb_cBignum , " % " , rb_big_modulo , 1 ) ;
2008-04-07 09:52:26 -04:00
rb_define_method ( rb_cBignum , " div " , rb_big_idiv , 1 ) ;
1999-01-19 23:59:39 -05:00
rb_define_method ( rb_cBignum , " divmod " , rb_big_divmod , 1 ) ;
2000-07-06 03: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-15 20:23:43 -04:00
rb_define_method ( rb_cBignum , " fdiv " , rb_big_fdiv , 1 ) ;
1999-01-19 23:59:39 -05: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 10:36:29 -05: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 01:55:06 -04:00
rb_define_method ( rb_cBignum , " === " , rb_big_eq , 1 ) ;
2001-11-08 01:43:14 -05:00
rb_define_method ( rb_cBignum , " eql? " , rb_big_eql , 1 ) ;
1999-01-19 23:59:39 -05: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 10:50:43 -04:00
rb_define_method ( rb_cBignum , " magnitude " , rb_big_abs , 0 ) ;
1999-01-19 23:59:39 -05:00
rb_define_method ( rb_cBignum , " size " , rb_big_size , 0 ) ;
2007-11-16 09:41:11 -05: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 07:14:17 -05:00
power_cache_init ( ) ;
2011-05-22 11:37:00 -04:00
big_three = rb_uint2big ( 3 ) ;
rb_gc_register_mark_object ( big_three ) ;
1998-01-16 07:13:05 -05:00
}