VALUE rb_big_barrett_reduce(VALUE x, VALUE m, VALUE mu, int inplace) { if (!NEGATIVE_P(x) && MORE(m, x)) { return x; } unsigned long len = RBIGNUM_LEN(m); /* >= 1 */ if (FIXNUM_P(x)) { return FIX2LONG(x) >= 0 ? x : rb_big_plus(m, x); } VALUE q = bigmul_high_digits(x, mu, len - 1, len - 1); /* q is not normed */ q = rshift_digits_inplace(q, len + 1); /* [x/m] - 3 <= q <= [x/m] */ q = bigmul_low_digits(q, m, len + 1); /* q is normed */ VALUE a = inplace ? x : rb_big_clone(x); if (RBIGNUM_LEN(a) > (long)len + 1) { RBIGNUM_SET_LEN(a, len + 1); } a = rb_big_minus(a, q); if (NEGATIVE_P(a)) a = ADD(a, power_of_two((len + 1) * BITSPERDIG)); /* a = (x - q * m) mod (base ** (len + 1)) */ while (!MORE(m, a)) /* that is, m <= a */ a = SUB(a, m); return rb_big_norm(a); }
static VALUE bigmul_low_digits(VALUE x, VALUE y, int digits) { int xn = RBIGNUM_LEN(x); if (FIXNUM_P(y)) y = INTVALUE2BIG(y); int yn = RBIGNUM_LEN(y); if (digits > xn + yn) { digits = xn + yn; } VALUE z = rb_big_new(digits, 1); BDIGIT* xds = RBIGNUM_DIGITS(x); BDIGIT* yds = RBIGNUM_DIGITS(y); BDIGIT* zds = RBIGNUM_DIGITS(z); BDIGIT c0,c1,c2; // carry int i, j, k, beg, end; for (k = c0 = c1 = c2 = 0; k < digits; k++) { beg = k >= yn - 1 ? k - yn + 1 : 0; end = k >= xn ? xn - 1 : k; for (i = beg, j = k - beg; i <= end; ++i, --j) MULADD(xds[i], yds[j]); zds[k] = c0; c0 = c1; c1 = c2; c2 = 0; } return rb_big_norm(z); }
static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) { switch(TYPE(result)) { case T_NIL: sqlite3_result_null(ctx); break; case T_FIXNUM: sqlite3_result_int64(ctx, (sqlite3_int64)FIX2LONG(result)); break; case T_BIGNUM: #if SIZEOF_LONG < 8 if (RBIGNUM_LEN(result) * SIZEOF_BDIGITS <= 8) { sqlite3_result_int64(ctx, NUM2LL(result)); break; } #endif case T_FLOAT: sqlite3_result_double(ctx, NUM2DBL(result)); break; case T_STRING: sqlite3_result_text( ctx, (const char *)StringValuePtr(result), (int)RSTRING_LEN(result), SQLITE_TRANSIENT ); break; default: rb_raise(rb_eRuntimeError, "can't return %s", rb_class2name(CLASS_OF(result))); } }
int bignum_to_int64(VALUE value, sqlite3_int64 *result) { #ifdef HAVE_RB_INTEGER_PACK const int nails = 0; int t = rb_integer_pack(value, result, 1, sizeof(*result), nails, INTEGER_PACK_NATIVE_BYTE_ORDER| INTEGER_PACK_2COMP); switch (t) { case -2: case +2: return 0; case +1: if (!nails) { if (*result < 0) return 0; } break; case -1: if (!nails) { if (*result >= 0) return 0; } else { *result += INT64_MIN; } break; } return 1; #else # ifndef RBIGNUM_LEN # define RBIGNUM_LEN(x) RBIGNUM(x)->len # endif const long len = RBIGNUM_LEN(value); if (len == 0) { *result = 0; return 1; } if (len > 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) return 0; if (len == 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) { const BDIGIT *digits = RBIGNUM_DIGITS(value); BDIGIT blast = digits[len-1]; BDIGIT bmax = (BDIGIT)1UL << (63 % (CHAR_BIT * SIZEOF_BDIGITS)); if (blast > bmax) return 0; if (blast == bmax) { if (RBIGNUM_POSITIVE_P(value)) { return 0; } else { long i = len-1; while (i) { if (digits[--i]) return 0; } } } } *result = (sqlite3_int64)NUM2LL(value); return 1; #endif }
static VALUE bigmul_high_digits(VALUE x, VALUE y, int dontcare, int x_right_shift) { int xn = RBIGNUM_LEN(x); if (FIXNUM_P(y)) y = INTVALUE2BIG(y); int yn = RBIGNUM_LEN(y); BDIGIT* xds = RBIGNUM_DIGITS(x); BDIGIT* yds = RBIGNUM_DIGITS(y); /* in order to avoid rb_big_clone call, let's virtually "shift" x instead of actual shifting */ if (x_right_shift >= xn) { return INT2BIG(0); } else { xds += x_right_shift; xn -= x_right_shift; } int digits = xn + yn; int i, j, k; VALUE z = rb_big_new(digits, 1); BDIGIT* zds = RBIGNUM_DIGITS(z); for (i = 0; i < digits; zds[i++] = 0); int beg, end; BDIGIT c0, c1, c2; for (k = dontcare, c0 = c1 = c2 = 0; k < digits; k++) { beg = k >= yn - 1 ? k - yn + 1 : 0; end = k >= xn ? xn - 1 : k; for (i = beg, j = k - beg; i <= end; ++i, --j) MULADD(xds[i], yds[j]); zds[k] = c0; c0 = c1; c1 = c2; c2 = 0; } return z; }
static VALUE apply_actions(VALUE field, VALUE actions) { long j, actions_len = RARRAY_LEN(actions); long beg, len; VALUE num = 0, modi = 0; for (j = 0; j < actions_len; j++) { VALUE action = rb_ary_entry(actions, j); VALUE klass = rb_class_of(action); if (klass == rb_cRange) { /* copied from rb_str_aref */ len = rb_str_strlen(field); if (RTEST(rb_range_beg_len(action, &beg, &len, len, 0))) field = rb_str_substr(field, beg, len); } else if (klass == rb_cArray) { num = rb_str_to_inum(field, 10, 0); modi = rb_ary_entry(action, 1); if ( (FIXNUM_P(num) || TYPE(num) == T_BIGNUM && RBIGNUM_LEN(num) <= (SIZEOF_LONG/SIZEOF_BDIGITS) ) && FIXNUM_P(modi) && FIX2LONG(modi)) { long modl = NUM2LONG(modi); long numl = (NUM2LONG(num) / modl) * modl; char buf[30]; int wrtn = snprintf(buf, 30, RSTRING_PTR(rb_ary_entry(action, 0)), numl); if (wrtn < 30) { field = rb_str_new(buf, wrtn); continue; } } else { num = rb_funcall2(num, idDiv, 1, &modi); num = rb_funcall2(num, idMul, 1, &modi); } field = rb_str_format(1, &num, rb_ary_entry(action, 0)); } } return field; }
inline static VALUE rshift_digits_inplace(VALUE n, int k) { if (FIXNUM_P(n)) { return INT2FIX(0); } BDIGIT* ds = RBIGNUM_DIGITS(n); int len = RBIGNUM_LEN(n); if (len > k) { memmove(ds, ds + k, SIZEOF_BDIGITS * (len - k)); RBIGNUM_SET_LEN(n, len - k); return n; } else { RBIGNUM_SET_LEN(n, 0); return n; } }
static size_t memsize_of(VALUE obj) { size_t size = 0; if (SPECIAL_CONST_P(obj)) { return 0; } if (FL_TEST(obj, FL_EXIVAR)) { size += rb_generic_ivar_memsize(obj); } switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if (!(RBASIC(obj)->flags & ROBJECT_EMBED) && ROBJECT(obj)->as.heap.ivptr) { size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE); } break; case T_MODULE: case T_CLASS: size += st_memsize(RCLASS_M_TBL(obj)); if (RCLASS_IV_TBL(obj)) { size += st_memsize(RCLASS_IV_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); } if (RCLASS(obj)->ptr->iv_tbl) { size += st_memsize(RCLASS(obj)->ptr->iv_tbl); } if (RCLASS(obj)->ptr->const_tbl) { size += st_memsize(RCLASS(obj)->ptr->const_tbl); } size += sizeof(rb_classext_t); break; case T_STRING: size += rb_str_memsize(obj); break; case T_ARRAY: size += rb_ary_memsize(obj); break; case T_HASH: if (RHASH(obj)->ntbl) { size += st_memsize(RHASH(obj)->ntbl); } break; case T_REGEXP: if (RREGEXP(obj)->ptr) { size += onig_memsize(RREGEXP(obj)->ptr); } break; case T_DATA: size += rb_objspace_data_type_memsize(obj); break; case T_MATCH: if (RMATCH(obj)->rmatch) { struct rmatch *rm = RMATCH(obj)->rmatch; size += sizeof(struct re_registers); /* TODO: onig_region_memsize(&rm->regs); */ size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated; size += sizeof(struct rmatch); } break; case T_FILE: if (RFILE(obj)->fptr) { size += rb_io_memsize(RFILE(obj)->fptr); } break; case T_RATIONAL: case T_COMPLEX: break; case T_ICLASS: /* iClass shares table with the module */ break; case T_FLOAT: break; case T_BIGNUM: if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { size += RBIGNUM_LEN(obj) * sizeof(BDIGIT); } break; case T_NODE: switch (nd_type(obj)) { case NODE_SCOPE: if (RNODE(obj)->u1.tbl) { /* TODO: xfree(RANY(obj)->as.node.u1.tbl); */ } break; case NODE_ALLOCA: /* TODO: xfree(RANY(obj)->as.node.u1.node); */ ; } break; /* no need to free iv_tbl */ case T_STRUCT: if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && RSTRUCT(obj)->as.heap.ptr) { size += sizeof(VALUE) * RSTRUCT_LEN(obj); } break; case T_ZOMBIE: break; default: rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)", BUILTIN_TYPE(obj), (void*)obj); } return size; }
static VALUE bignum_spec_RBIGNUM_LEN(VALUE self, VALUE num) { return LONG2NUM(RBIGNUM_LEN(num)); }
VALUE rb_big_barrett_mu(VALUE m) { long len = RBIGNUM_LEN(m); return rb_big_div(power_of_two(2 * len * BITSPERDIG), m); }
/* call-seq: stmt.bind_param(key, value) * * Binds value to the named (or positional) placeholder. If +param+ is a * Fixnum, it is treated as an index for a positional placeholder. * Otherwise it is used as the name of the placeholder to bind to. * * See also #bind_params. */ static VALUE bind_param(VALUE self, VALUE key, VALUE value) { sqlite3StmtRubyPtr ctx; int status; int index; Data_Get_Struct(self, sqlite3StmtRuby, ctx); REQUIRE_OPEN_STMT(ctx); switch(TYPE(key)) { case T_SYMBOL: key = rb_funcall(key, rb_intern("to_s"), 0); case T_STRING: if(RSTRING_PTR(key)[0] != ':') key = rb_str_plus(rb_str_new2(":"), key); index = sqlite3_bind_parameter_index(ctx->st, StringValuePtr(key)); break; default: index = (int)NUM2INT(key); } if(index == 0) rb_raise(rb_path2class("SQLite3::Exception"), "no such bind parameter"); switch(TYPE(value)) { case T_STRING: if(CLASS_OF(value) == cSqlite3Blob #ifdef HAVE_RUBY_ENCODING_H || rb_enc_get_index(value) == rb_ascii8bit_encindex() #endif ) { status = sqlite3_bind_blob( ctx->st, index, (const char *)StringValuePtr(value), (int)RSTRING_LEN(value), SQLITE_TRANSIENT ); } else { #ifdef HAVE_RUBY_ENCODING_H if(!UTF8_P(value)) { VALUE db = rb_iv_get(self, "@connection"); VALUE encoding = rb_funcall(db, rb_intern("encoding"), 0); rb_encoding * enc = rb_to_encoding(encoding); value = rb_str_export_to_enc(value, enc); } #endif status = sqlite3_bind_text( ctx->st, index, (const char *)StringValuePtr(value), (int)RSTRING_LEN(value), SQLITE_TRANSIENT ); } break; case T_BIGNUM: #if SIZEOF_LONG < 8 if (RBIGNUM_LEN(value) * SIZEOF_BDIGITS <= 8) { status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)NUM2LL(value)); break; } #endif case T_FLOAT: status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value)); break; case T_FIXNUM: status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)FIX2LONG(value)); break; case T_NIL: status = sqlite3_bind_null(ctx->st, index); break; default: rb_raise(rb_eRuntimeError, "can't prepare %s", rb_class2name(CLASS_OF(value))); break; } CHECK(sqlite3_db_handle(ctx->st), status); return self; }