Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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)));
  }
}
Example #4
0
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
}
Example #5
0
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;
}
Example #7
0
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;
    }
}
Example #8
0
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;
}
Example #9
0
static VALUE bignum_spec_RBIGNUM_LEN(VALUE self, VALUE num) {
  return LONG2NUM(RBIGNUM_LEN(num));
}
Example #10
0
VALUE rb_big_barrett_mu(VALUE m)
{
    long len = RBIGNUM_LEN(m);
    return rb_big_div(power_of_two(2 * len * BITSPERDIG), m);
}
Example #11
0
/* 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;
}