mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			246 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef INTERNAL_BIGNUM_H /* -*- C -*- */
 | |
| #define INTERNAL_BIGNUM_H
 | |
| /**
 | |
|  * @file
 | |
|  * @brief      Internal header for Bignums.
 | |
|  * @author     \@shyouhei
 | |
|  * @copyright  This  file  is   a  part  of  the   programming  language  Ruby.
 | |
|  *             Permission  is hereby  granted,  to  either redistribute  and/or
 | |
|  *             modify this file, provided that  the conditions mentioned in the
 | |
|  *             file COPYING are met.  Consult the file for details.
 | |
|  */
 | |
| #include "ruby/config.h"        /* for HAVE_LIBGMP */
 | |
| #include <stddef.h>             /* for size_t */
 | |
| 
 | |
| #ifdef HAVE_SYS_TYPES_H
 | |
| # include <sys/types.h>         /* for ssize_t (note: on Windows ssize_t is */
 | |
| #endif                          /* `#define`d in ruby/config.h) */
 | |
| 
 | |
| #include "internal/stdbool.h"   /* for bool */
 | |
| #include "ruby/ruby.h"          /* for struct RBasic */
 | |
| 
 | |
| #ifndef BDIGIT
 | |
| # if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
 | |
| #  define BDIGIT unsigned int
 | |
| #  define SIZEOF_BDIGIT SIZEOF_INT
 | |
| #  define BDIGIT_DBL unsigned LONG_LONG
 | |
| #  define BDIGIT_DBL_SIGNED LONG_LONG
 | |
| #  define PRI_BDIGIT_PREFIX ""
 | |
| #  define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
 | |
| # elif SIZEOF_INT*2 <= SIZEOF_LONG
 | |
| #  define BDIGIT unsigned int
 | |
| #  define SIZEOF_BDIGIT SIZEOF_INT
 | |
| #  define BDIGIT_DBL unsigned long
 | |
| #  define BDIGIT_DBL_SIGNED long
 | |
| #  define PRI_BDIGIT_PREFIX ""
 | |
| #  define PRI_BDIGIT_DBL_PREFIX "l"
 | |
| # elif SIZEOF_SHORT*2 <= SIZEOF_LONG
 | |
| #  define BDIGIT unsigned short
 | |
| #  define SIZEOF_BDIGIT SIZEOF_SHORT
 | |
| #  define BDIGIT_DBL unsigned long
 | |
| #  define BDIGIT_DBL_SIGNED long
 | |
| #  define PRI_BDIGIT_PREFIX "h"
 | |
| #  define PRI_BDIGIT_DBL_PREFIX "l"
 | |
| # else
 | |
| #  define BDIGIT unsigned short
 | |
| #  define SIZEOF_BDIGIT (SIZEOF_LONG/2)
 | |
| #  define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG
 | |
| #  define BDIGIT_DBL unsigned long
 | |
| #  define BDIGIT_DBL_SIGNED long
 | |
| #  define PRI_BDIGIT_PREFIX "h"
 | |
| #  define PRI_BDIGIT_DBL_PREFIX "l"
 | |
| # endif
 | |
| #endif
 | |
| 
 | |
| #ifndef SIZEOF_ACTUAL_BDIGIT
 | |
| # define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT
 | |
| #endif
 | |
| 
 | |
| #ifdef PRI_BDIGIT_PREFIX
 | |
| # define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
 | |
| # define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
 | |
| # define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
 | |
| # define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
 | |
| # define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
 | |
| # define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
 | |
| #endif
 | |
| 
 | |
| #ifdef PRI_BDIGIT_DBL_PREFIX
 | |
| # define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
 | |
| # define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
 | |
| # define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
 | |
| # define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
 | |
| # define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
 | |
| # define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
 | |
| #endif
 | |
| 
 | |
| #define RBIGNUM(obj) (R_CAST(RBignum)(obj))
 | |
| #define BIGNUM_SIGN_BIT FL_USER1
 | |
| #define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2)
 | |
| #define BIGNUM_EMBED_LEN_NUMBITS 3
 | |
| #define BIGNUM_EMBED_LEN_MASK \
 | |
|     (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT)
 | |
| #define BIGNUM_EMBED_LEN_SHIFT \
 | |
|     (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */
 | |
| #ifndef BIGNUM_EMBED_LEN_MAX
 | |
| # if (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1
 | |
| #  define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT)
 | |
| # else
 | |
| #  define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1)
 | |
| # endif
 | |
| #endif
 | |
| 
 | |
| enum rb_int_parse_flags {
 | |
|     RB_INT_PARSE_SIGN       = 0x01,
 | |
|     RB_INT_PARSE_UNDERSCORE = 0x02,
 | |
|     RB_INT_PARSE_PREFIX     = 0x04,
 | |
|     RB_INT_PARSE_ALL        = 0x07,
 | |
|     RB_INT_PARSE_DEFAULT    = 0x07,
 | |
| };
 | |
| 
 | |
| struct RBignum {
 | |
|     struct RBasic basic;
 | |
|     union {
 | |
|         struct {
 | |
|             size_t len;
 | |
|             BDIGIT *digits;
 | |
|         } heap;
 | |
|         BDIGIT ary[BIGNUM_EMBED_LEN_MAX];
 | |
|     } as;
 | |
| };
 | |
| 
 | |
| /* bignum.c */
 | |
| extern const char ruby_digitmap[];
 | |
| double rb_big_fdiv_double(VALUE x, VALUE y);
 | |
| VALUE rb_big_uminus(VALUE x);
 | |
| VALUE rb_big_hash(VALUE);
 | |
| VALUE rb_big_odd_p(VALUE);
 | |
| VALUE rb_big_even_p(VALUE);
 | |
| size_t rb_big_size(VALUE);
 | |
| VALUE rb_integer_float_cmp(VALUE x, VALUE y);
 | |
| VALUE rb_integer_float_eq(VALUE x, VALUE y);
 | |
| VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception);
 | |
| VALUE rb_big_comp(VALUE x);
 | |
| VALUE rb_big_aref(VALUE x, VALUE y);
 | |
| VALUE rb_big_abs(VALUE x);
 | |
| VALUE rb_big_size_m(VALUE big);
 | |
| VALUE rb_big_bit_length(VALUE big);
 | |
| VALUE rb_big_remainder(VALUE x, VALUE y);
 | |
| VALUE rb_big_gt(VALUE x, VALUE y);
 | |
| VALUE rb_big_ge(VALUE x, VALUE y);
 | |
| VALUE rb_big_lt(VALUE x, VALUE y);
 | |
| VALUE rb_big_le(VALUE x, VALUE y);
 | |
| VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num);
 | |
| static inline bool BIGNUM_SIGN(VALUE b);
 | |
| static inline bool BIGNUM_POSITIVE_P(VALUE b);
 | |
| static inline bool BIGNUM_NEGATIVE_P(VALUE b);
 | |
| static inline void BIGNUM_SET_SIGN(VALUE b, bool sign);
 | |
| static inline void BIGNUM_NEGATE(VALUE b);
 | |
| static inline size_t BIGNUM_LEN(VALUE b);
 | |
| static inline BDIGIT *BIGNUM_DIGITS(VALUE b);
 | |
| static inline int BIGNUM_LENINT(VALUE b);
 | |
| static inline bool BIGNUM_EMBED_P(VALUE b);
 | |
| 
 | |
| RUBY_SYMBOL_EXPORT_BEGIN
 | |
| /* bignum.c (export) */
 | |
| VALUE rb_big_mul_normal(VALUE x, VALUE y);
 | |
| VALUE rb_big_mul_balance(VALUE x, VALUE y);
 | |
| VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
 | |
| VALUE rb_big_mul_toom3(VALUE x, VALUE y);
 | |
| VALUE rb_big_sq_fast(VALUE x);
 | |
| VALUE rb_big_divrem_normal(VALUE x, VALUE y);
 | |
| VALUE rb_big2str_poweroftwo(VALUE x, int base);
 | |
| VALUE rb_big2str_generic(VALUE x, int base);
 | |
| VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck);
 | |
| VALUE rb_str2big_normal(VALUE arg, int base, int badcheck);
 | |
| VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck);
 | |
| #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
 | |
| VALUE rb_big_mul_gmp(VALUE x, VALUE y);
 | |
| VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
 | |
| VALUE rb_big2str_gmp(VALUE x, int base);
 | |
| VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
 | |
| #endif
 | |
| VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
 | |
| RUBY_SYMBOL_EXPORT_END
 | |
| 
 | |
| MJIT_SYMBOL_EXPORT_BEGIN
 | |
| #if defined(HAVE_INT128_T)
 | |
| VALUE rb_int128t2big(int128_t n);
 | |
| #endif
 | |
| MJIT_SYMBOL_EXPORT_END
 | |
| 
 | |
| /* sign: positive:1, negative:0 */
 | |
| static inline bool
 | |
| BIGNUM_SIGN(VALUE b)
 | |
| {
 | |
|     return FL_TEST_RAW(b, BIGNUM_SIGN_BIT);
 | |
| }
 | |
| 
 | |
| static inline bool
 | |
| BIGNUM_POSITIVE_P(VALUE b)
 | |
| {
 | |
|     return BIGNUM_SIGN(b);
 | |
| }
 | |
| 
 | |
| static inline bool
 | |
| BIGNUM_NEGATIVE_P(VALUE b)
 | |
| {
 | |
|     return ! BIGNUM_POSITIVE_P(b);
 | |
| }
 | |
| 
 | |
| static inline void
 | |
| BIGNUM_SET_SIGN(VALUE b, bool sign)
 | |
| {
 | |
|     if (sign) {
 | |
|         FL_SET_RAW(b, BIGNUM_SIGN_BIT);
 | |
|     }
 | |
|     else {
 | |
|         FL_UNSET_RAW(b, BIGNUM_SIGN_BIT);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static inline void
 | |
| BIGNUM_NEGATE(VALUE b)
 | |
| {
 | |
|     FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT);
 | |
| }
 | |
| 
 | |
| static inline size_t
 | |
| BIGNUM_LEN(VALUE b)
 | |
| {
 | |
|     if (! BIGNUM_EMBED_P(b)) {
 | |
|         return RBIGNUM(b)->as.heap.len;
 | |
|     }
 | |
|     else {
 | |
|         size_t ret = RBASIC(b)->flags;
 | |
|         ret &= BIGNUM_EMBED_LEN_MASK;
 | |
|         ret >>= BIGNUM_EMBED_LEN_SHIFT;
 | |
|         return ret;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static inline int
 | |
| BIGNUM_LENINT(VALUE b)
 | |
| {
 | |
|     return rb_long2int(BIGNUM_LEN(b));
 | |
| }
 | |
| 
 | |
| /* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
 | |
| static inline BDIGIT *
 | |
| BIGNUM_DIGITS(VALUE b)
 | |
| {
 | |
|     if (BIGNUM_EMBED_P(b)) {
 | |
|         return RBIGNUM(b)->as.ary;
 | |
|     }
 | |
|     else {
 | |
|         return RBIGNUM(b)->as.heap.digits;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static inline bool
 | |
| BIGNUM_EMBED_P(VALUE b)
 | |
| {
 | |
|     return FL_TEST_RAW(b, BIGNUM_EMBED_FLAG);
 | |
| }
 | |
| 
 | |
| #endif /* INTERNAL_BIGNUM_H */
 | 
