VALUE rb_num_cbrt( VALUE num) { #if HAVE_FUNC_CBRT return rb_float_new( cbrt( RFLOAT_VALUE( rb_Float( num)))); #else double n; int neg; int i; n = RFLOAT_VALUE( rb_Float( num)); if ((neg = n < 0)) n = -n; n = sqrt( sqrt( n)); i = 2; for (;;) { double w = n; int j; for (j=i;j;--j) w = sqrt( w); i *= 2; w *= n; if (n == w) break; n = w; } return rb_float_new( neg ? -n : n); #endif }
static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv) { N_TYPE m[2][2], ai, maxden = R2N(rb_Integer(dv)); double startx, x = RFLOAT_VALUE(rb_Float(rv)); int sign = 1; if (maxden <= 0) rb_raise(rb_eArgError, "maximum denominator should be > 0"); if (x < 0) { sign = -1; x = -x; } startx = x; /* initialize matrix */ m[0][0] = m[1][1] = 1; m[0][1] = m[1][0] = 0; /* loop finding terms until denom gets too big */ while (m[1][0] * ( ai = (N_TYPE)x ) + m[1][1] <= maxden) { N_TYPE t; t = m[0][0] * ai + m[0][1]; m[0][1] = m[0][0]; m[0][0] = t; t = m[1][0] * ai + m[1][1]; m[1][1] = m[1][0]; m[1][0] = t; if(x==(double)ai) break; // AF: division by zero x = 1/(x - (double) ai); if(x>(double)0x7FFFFFFF) break; // AF: representation failure } { /* now remaining x is between 0 and 1/ai */ /* approx as either 0 or 1/m where m is max that will fit in maxden */ /* first try zero */ VALUE num1, den1, err1, num2, den2, err2; num1 = N2R(sign*m[0][0]); den1 = N2R(m[1][0]); err1 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0])); /* now try other possibility */ ai = (maxden - m[1][1]) / m[1][0]; m[0][0] = m[0][0] * ai + m[0][1]; m[1][0] = m[1][0] * ai + m[1][1]; num2 = N2R(sign*m[0][0]); den2 = N2R(m[1][0]); err2 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0])); return rb_ary_new3(6, num1, den1, err1, num2, den2, err2); } }
static void ra_buffer_index_set(RA_BUFFER *buf, long i, VALUE val) { if(buf->type == RA_BUFFER_TYPE_SHORT || buf->type == RA_BUFFER_TYPE_INT) { // Convert val to an integer VALUE int_obj = rb_Integer(val); if(TYPE(int_obj) != T_FIXNUM) rb_raise(eRubyAudioError, "could not convert frame value to an integer"); long int_val = FIX2LONG(int_obj); // Set it if(buf->type == RA_BUFFER_TYPE_SHORT) ((short*)buf->data)[i] = (short)int_val; else ((int*)buf->data)[i] = (int)int_val; } else { // Convert val to a float double float_val = RFLOAT_VALUE(rb_Float(val)); // Set it if(buf->type == RA_BUFFER_TYPE_FLOAT) ((float*)buf->data)[i] = (float)float_val; else ((double*)buf->data)[i] = float_val; } }
static inline double rval_to_double(VALUE rval) { return RFLOAT_VALUE(rb_Float(bool_to_fix(rval))); }
static VALUE float_spec_rb_Float(VALUE self, VALUE float_str) { return rb_Float(float_str); }
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt) { enum {default_float_precision = 6}; rb_encoding *enc; const char *p, *end; char *buf; long blen, bsiz; VALUE result; long scanned = 0; int coderange = ENC_CODERANGE_7BIT; int width, prec, flags = FNONE; int nextarg = 1; int posarg = 0; int tainted = 0; VALUE nextvalue; VALUE tmp; VALUE str; volatile VALUE hash = Qundef; #define CHECK_FOR_WIDTH(f) \ if ((f) & FWIDTH) { \ rb_raise(rb_eArgError, "width given twice"); \ } \ if ((f) & FPREC0) { \ rb_raise(rb_eArgError, "width after precision"); \ } #define CHECK_FOR_FLAGS(f) \ if ((f) & FWIDTH) { \ rb_raise(rb_eArgError, "flag after width"); \ } \ if ((f) & FPREC0) { \ rb_raise(rb_eArgError, "flag after precision"); \ } ++argc; --argv; if (OBJ_TAINTED(fmt)) tainted = 1; StringValue(fmt); enc = rb_enc_get(fmt); fmt = rb_str_new4(fmt); p = RSTRING_PTR(fmt); end = p + RSTRING_LEN(fmt); blen = 0; bsiz = 120; result = rb_str_buf_new(bsiz); rb_enc_copy(result, fmt); buf = RSTRING_PTR(result); memset(buf, 0, bsiz); ENC_CODERANGE_SET(result, coderange); for (; p < end; p++) { const char *t; int n; VALUE sym = Qnil; for (t = p; t < end && *t != '%'; t++) ; PUSH(p, t - p); if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange); ENC_CODERANGE_SET(result, coderange); } if (t >= end) { /* end of fmt string */ goto sprint_exit; } p = t + 1; /* skip `%' */ width = prec = -1; nextvalue = Qundef; retry: switch (*p) { default: if (rb_enc_isprint(*p, enc)) rb_raise(rb_eArgError, "malformed format string - %%%c", *p); else rb_raise(rb_eArgError, "malformed format string"); break; case ' ': CHECK_FOR_FLAGS(flags); flags |= FSPACE; p++; goto retry; case '#': CHECK_FOR_FLAGS(flags); flags |= FSHARP; p++; goto retry; case '+': CHECK_FOR_FLAGS(flags); flags |= FPLUS; p++; goto retry; case '-': CHECK_FOR_FLAGS(flags); flags |= FMINUS; p++; goto retry; case '0': CHECK_FOR_FLAGS(flags); flags |= FZERO; p++; goto retry; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; GETNUM(n, width); if (*p == '$') { if (nextvalue != Qundef) { rb_raise(rb_eArgError, "value given twice - %d$", n); } nextvalue = GETPOSARG(n); p++; goto retry; } CHECK_FOR_WIDTH(flags); width = n; flags |= FWIDTH; goto retry; case '<': case '{': { const char *start = p; char term = (*p == '<') ? '>' : '}'; int len; for (; p < end && *p != term; ) { p += rb_enc_mbclen(p, end, enc); } if (p >= end) { rb_raise(rb_eArgError, "malformed name - unmatched parenthesis"); } #if SIZEOF_INT < SIZEOF_SIZE_T if ((size_t)(p - start) >= INT_MAX) { const int message_limit = 20; len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start); rb_enc_raise(enc, rb_eArgError, "too long name (%"PRIdSIZE" bytes) - %.*s...%c", (size_t)(p - start - 2), len, start, term); } #endif len = (int)(p - start + 1); /* including parenthesis */ if (sym != Qnil) { rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">", len, start, rb_sym2str(sym)); } CHECKNAMEARG(start, len, enc); get_hash(&hash, argc, argv); sym = rb_check_symbol_cstr(start + 1, len - 2 /* without parenthesis */, enc); if (sym != Qnil) nextvalue = rb_hash_lookup2(hash, sym, Qundef); if (nextvalue == Qundef) { rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start); } if (term == '}') goto format_s; p++; goto retry; } case '*': CHECK_FOR_WIDTH(flags); flags |= FWIDTH; GETASTER(width); if (width < 0) { flags |= FMINUS; width = -width; } p++; goto retry; case '.': if (flags & FPREC0) { rb_raise(rb_eArgError, "precision given twice"); } flags |= FPREC|FPREC0; prec = 0; p++; if (*p == '*') { GETASTER(prec); if (prec < 0) { /* ignore negative precision */ flags &= ~FPREC; } p++; goto retry; } GETNUM(prec, precision); goto retry; case '\n': case '\0': p--; case '%': if (flags != FNONE) { rb_raise(rb_eArgError, "invalid format character - %%"); } PUSH("%", 1); break; case 'c': { VALUE val = GETARG(); VALUE tmp; unsigned int c; int n; tmp = rb_check_string_type(val); if (!NIL_P(tmp)) { if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) { rb_raise(rb_eArgError, "%%c requires a character"); } c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc); RB_GC_GUARD(tmp); } else { c = NUM2INT(val); n = rb_enc_codelen(c, enc); } if (n <= 0) { rb_raise(rb_eArgError, "invalid character"); } if (!(flags & FWIDTH)) { CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; } else if ((flags & FMINUS)) { CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; FILL(' ', width-1); } else { FILL(' ', width-1); CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; } } break; case 's': case 'p': format_s: { VALUE arg = GETARG(); long len, slen; if (*p == 'p') arg = rb_inspect(arg); str = rb_obj_as_string(arg); if (OBJ_TAINTED(str)) tainted = 1; len = RSTRING_LEN(str); rb_str_set_len(result, blen); if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { int cr = coderange; scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr); ENC_CODERANGE_SET(result, (cr == ENC_CODERANGE_UNKNOWN ? ENC_CODERANGE_BROKEN : (coderange = cr))); } enc = rb_enc_check(result, str); if (flags&(FPREC|FWIDTH)) { slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc); if (slen < 0) { rb_raise(rb_eArgError, "invalid mbstring sequence"); } if ((flags&FPREC) && (prec < slen)) { char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str), prec, enc); slen = prec; len = p - RSTRING_PTR(str); } /* need to adjust multi-byte string pos */ if ((flags&FWIDTH) && (width > slen)) { width -= (int)slen; if (!(flags&FMINUS)) { CHECK(width); while (width--) { buf[blen++] = ' '; } } CHECK(len); memcpy(&buf[blen], RSTRING_PTR(str), len); RB_GC_GUARD(str); blen += len; if (flags&FMINUS) { CHECK(width); while (width--) { buf[blen++] = ' '; } } rb_enc_associate(result, enc); break; } } PUSH(RSTRING_PTR(str), len); RB_GC_GUARD(str); rb_enc_associate(result, enc); } break; case 'd': case 'i': case 'o': case 'x': case 'X': case 'b': case 'B': case 'u': { volatile VALUE val = GETARG(); int valsign; char nbuf[64], *s; const char *prefix = 0; int sign = 0, dots = 0; char sc = 0; long v = 0; int base, bignum = 0; int len; switch (*p) { case 'd': case 'i': case 'u': sign = 1; break; case 'o': case 'x': case 'X': case 'b': case 'B': if (flags&(FPLUS|FSPACE)) sign = 1; break; } if (flags & FSHARP) { switch (*p) { case 'o': prefix = "0"; break; case 'x': prefix = "0x"; break; case 'X': prefix = "0X"; break; case 'b': prefix = "0b"; break; case 'B': prefix = "0B"; break; } } bin_retry: switch (TYPE(val)) { case T_FLOAT: if (FIXABLE(RFLOAT_VALUE(val))) { val = LONG2FIX((long)RFLOAT_VALUE(val)); goto bin_retry; } val = rb_dbl2big(RFLOAT_VALUE(val)); if (FIXNUM_P(val)) goto bin_retry; bignum = 1; break; case T_STRING: val = rb_str_to_inum(val, 0, TRUE); goto bin_retry; case T_BIGNUM: bignum = 1; break; case T_FIXNUM: v = FIX2LONG(val); break; default: val = rb_Integer(val); goto bin_retry; } switch (*p) { case 'o': base = 8; break; case 'x': case 'X': base = 16; break; case 'b': case 'B': base = 2; break; case 'u': case 'd': case 'i': default: base = 10; break; } if (base != 10) { int numbits = ffs(base)-1; size_t abs_nlz_bits; size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits); long i; if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */ rb_raise(rb_eArgError, "size too big"); if (sign) { if (numdigits == 0) numdigits = 1; tmp = rb_str_new(NULL, numdigits); valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp), 1, CHAR_BIT-numbits, INTEGER_PACK_BIG_ENDIAN); for (i = 0; i < RSTRING_LEN(tmp); i++) RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]]; s = RSTRING_PTR(tmp); if (valsign < 0) { sc = '-'; width--; } else if (flags & FPLUS) { sc = '+'; width--; } else if (flags & FSPACE) { sc = ' '; width--; } } else { /* Following conditional "numdigits++" guarantees the * most significant digit as * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers * - '0' for zero * - not '0' for positive numbers. * * It also guarantees the most significant two * digits will not be '11'(bin), '77'(oct), 'ff'(hex) * or '00'. */ if (numdigits == 0 || ((abs_nlz_bits != (size_t)(numbits-1) || !rb_absint_singlebit_p(val)) && (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val)))) numdigits++; tmp = rb_str_new(NULL, numdigits); valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp), 1, CHAR_BIT-numbits, INTEGER_PACK_2COMP | INTEGER_PACK_BIG_ENDIAN); for (i = 0; i < RSTRING_LEN(tmp); i++) RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]]; s = RSTRING_PTR(tmp); dots = valsign < 0; } len = rb_long2int(RSTRING_END(tmp) - s); } else if (!bignum) { valsign = 1; if (v < 0) { v = -v; sc = '-'; width--; valsign = -1; } else if (flags & FPLUS) { sc = '+'; width--; } else if (flags & FSPACE) { sc = ' '; width--; } snprintf(nbuf, sizeof(nbuf), "%ld", v); s = nbuf; len = (int)strlen(s); } else { tmp = rb_big2str(val, 10); s = RSTRING_PTR(tmp); valsign = 1; if (s[0] == '-') { s++; sc = '-'; width--; valsign = -1; } else if (flags & FPLUS) { sc = '+'; width--; } else if (flags & FSPACE) { sc = ' '; width--; } len = rb_long2int(RSTRING_END(tmp) - s); } if (dots) { prec -= 2; width -= 2; } if (*p == 'X') { char *pp = s; int c; while ((c = (int)(unsigned char)*pp) != 0) { *pp = rb_enc_toupper(c, enc); pp++; } } if (prefix && !prefix[1]) { /* octal */ if (dots) { prefix = 0; } else if (len == 1 && *s == '0') { len = 0; if (flags & FPREC) prec--; } else if ((flags & FPREC) && (prec > len)) { prefix = 0; } } else if (len == 1 && *s == '0') { prefix = 0; } if (prefix) { width -= (int)strlen(prefix); } if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) { prec = width; width = 0; } else { if (prec < len) { if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0; prec = len; } width -= prec; } if (!(flags&FMINUS)) { CHECK(width); while (width-- > 0) { buf[blen++] = ' '; } } if (sc) PUSH(&sc, 1); if (prefix) { int plen = (int)strlen(prefix); PUSH(prefix, plen); } CHECK(prec - len); if (dots) PUSH("..", 2); if (!sign && valsign < 0) { char c = sign_bits(base, p); while (len < prec--) { buf[blen++] = c; } } else if ((flags & (FMINUS|FPREC)) != FMINUS) { while (len < prec--) { buf[blen++] = '0'; } } PUSH(s, len); RB_GC_GUARD(tmp); CHECK(width); while (width-- > 0) { buf[blen++] = ' '; } } break; case 'f': { VALUE val = GETARG(), num, den; int sign = (flags&FPLUS) ? 1 : 0, zero = 0; long len, done = 0; int prefix = 0; if (!RB_TYPE_P(val, T_RATIONAL)) { nextvalue = val; goto float_value; } if (!(flags&FPREC)) prec = default_float_precision; den = rb_rational_den(val); num = rb_rational_num(val); if (FIXNUM_P(num)) { if ((SIGNED_VALUE)num < 0) { long n = -FIX2LONG(num); num = LONG2FIX(n); sign = -1; } } else if (rb_num_negative_p(num)) { sign = -1; num = rb_funcallv(num, idUMinus, 0, 0); } if (den != INT2FIX(1) || prec > 1) { const ID idDiv = rb_intern("div"); VALUE p10 = rb_int_positive_pow(10, prec); VALUE den_2 = rb_funcall(den, idDiv, 1, INT2FIX(2)); num = rb_funcallv(num, '*', 1, &p10); num = rb_funcallv(num, '+', 1, &den_2); num = rb_funcallv(num, idDiv, 1, &den); } else if (prec >= 0) { zero = prec; } val = rb_obj_as_string(num); len = RSTRING_LEN(val) + zero; if (prec >= len) ++len; /* integer part 0 */ if (sign || (flags&FSPACE)) ++len; if (prec > 0) ++len; /* period */ CHECK(len > width ? len : width); if (sign || (flags&FSPACE)) { buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' '; prefix++; done++; } len = RSTRING_LEN(val) + zero; t = RSTRING_PTR(val); if (len > prec) { memcpy(&buf[blen], t, len - prec); blen += len - prec; done += len - prec; } else { buf[blen++] = '0'; done++; } if (prec > 0) { buf[blen++] = '.'; done++; } if (zero) { FILL('0', zero); done += zero; } else if (prec > len) { FILL('0', prec - len); memcpy(&buf[blen], t, len); blen += len; done += prec; } else if (prec > 0) { memcpy(&buf[blen], t + len - prec, prec); blen += prec; done += prec; } if ((flags & FWIDTH) && width > done) { int fill = ' '; long shifting = 0; if (!(flags&FMINUS)) { shifting = done; if (flags&FZERO) { shifting -= prefix; fill = '0'; } blen -= shifting; memmove(&buf[blen + width - done], &buf[blen], shifting); } FILL(fill, width - done); blen += shifting; } RB_GC_GUARD(val); break; } case 'g': case 'G': case 'e': case 'E': /* TODO: rational support */ case 'a': case 'A': float_value: { VALUE val = GETARG(); double fval; int i, need; char fbuf[32]; fval = RFLOAT_VALUE(rb_Float(val)); if (isnan(fval) || isinf(fval)) { const char *expr; if (isnan(fval)) { expr = "NaN"; } else { expr = "Inf"; } need = (int)strlen(expr); if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS)) need++; if ((flags & FWIDTH) && need < width) need = width; CHECK(need + 1); snprintf(&buf[blen], need + 1, "%*s", need, ""); if (flags & FMINUS) { if (!isnan(fval) && fval < 0.0) buf[blen++] = '-'; else if (flags & FPLUS) buf[blen++] = '+'; else if (flags & FSPACE) blen++; memcpy(&buf[blen], expr, strlen(expr)); } else { if (!isnan(fval) && fval < 0.0) buf[blen + need - strlen(expr) - 1] = '-'; else if (flags & FPLUS) buf[blen + need - strlen(expr) - 1] = '+'; else if ((flags & FSPACE) && need > width) blen++; memcpy(&buf[blen + need - strlen(expr)], expr, strlen(expr)); } blen += strlen(&buf[blen]); break; } fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); need = 0; if (*p != 'e' && *p != 'E') { i = INT_MIN; frexp(fval, &i); if (i > 0) need = BIT_DIGITS(i); } need += (flags&FPREC) ? prec : default_float_precision; if ((flags&FWIDTH) && need < width) need = width; need += 20; CHECK(need); snprintf(&buf[blen], need, fbuf, fval); blen += strlen(&buf[blen]); } break; } flags = FNONE; } sprint_exit: RB_GC_GUARD(fmt); /* XXX - We cannot validate the number of arguments if (digit)$ style used. */ if (posarg >= 0 && nextarg < argc) { const char *mesg = "too many arguments for format string"; if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg); if (RTEST(ruby_verbose)) rb_warn("%s", mesg); } rb_str_resize(result, blen); if (tainted) OBJ_TAINT(result); return result; }
/* @api private */ VALUE rb_do_kcluster(int argc, VALUE *argv, VALUE self) { VALUE size, data, mask, weights, options; rb_scan_args(argc, argv, "21", &size, &data, &options); if (TYPE(data) != T_ARRAY) rb_raise(rb_eArgError, "data should be an array of arrays"); if (NIL_P(size) || NUM2INT(rb_Integer(size)) > RARRAY_LEN(data)) rb_raise(rb_eArgError, "size should be > 0 and <= data size"); mask = get_value_option(options, "mask", Qnil); if (!NIL_P(mask) && TYPE(mask) != T_ARRAY) rb_raise(rb_eArgError, "mask should be an array of arrays"); int transpose = get_bool_option(options, "transpose", 0); int npass = get_int_option(options, "iterations", DEFAULT_ITERATIONS); // a = average, m = means int method = get_int_option(options, "method", 'a'); // e = euclidian, // b = city-block distance // c = correlation // a = absolute value of the correlation // u = uncentered correlation // x = absolute uncentered correlation // s = spearman's rank correlation // k = kendall's tau int dist = get_int_option(options, "metric", 'e'); // initial assignment int assign = get_int_option(options, "seed", 0); int i,j; int nrows = RARRAY_LEN(data); int ncols = RARRAY_LEN(rb_ary_entry(data, 0)); int nsets = NUM2INT(rb_Integer(size)); double **cdata = (double**)malloc(sizeof(double*)*nrows); int **cmask = (int **)malloc(sizeof(int *)*nrows); double *cweights = (double *)malloc(sizeof(double )*ncols); double **ccentroid; int *ccluster, **ccentroid_mask, dimx = nrows, dimy = ncols, cdimx = nsets, cdimy = ncols; for (i = 0; i < nrows; i++) { cdata[i] = (double*)malloc(sizeof(double)*ncols); cmask[i] = (int *)malloc(sizeof(int )*ncols); for (j = 0; j < ncols; j++) { cdata[i][j] = NUM2DBL(rb_Float(rb_ary_entry(rb_ary_entry(data, i), j))); cmask[i][j] = NIL_P(mask) ? 1 : NUM2INT(rb_Integer(rb_ary_entry(rb_ary_entry(mask, i), j))); } } weights = NIL_P(options) ? Qnil : rb_hash_aref(options, ID2SYM(rb_intern("weights"))); for (i = 0; i < ncols; i++) { cweights[i] = NIL_P(weights) ? 1.0 : NUM2DBL(rb_Float(rb_ary_entry(weights, i))); } if (transpose) { dimx = ncols; dimy = nrows; cdimx = nrows; cdimy = nsets; } ccluster = (int *)malloc(sizeof(int )*dimx); ccentroid = (double**)malloc(sizeof(double*)*cdimx); ccentroid_mask = (int **)malloc(sizeof(int *)*cdimx); for (i = 0; i < cdimx; i++) { ccentroid[i] = (double*)malloc(sizeof(double)*cdimy); ccentroid_mask[i] = (int *)malloc(sizeof(int )*cdimy); } int ifound; double error; kcluster(nsets, nrows, ncols, cdata, cmask, cweights, transpose, npass, method, dist, ccluster, &error, &ifound, assign); getclustercentroids(nsets, nrows, ncols, cdata, cmask, ccluster, ccentroid, ccentroid_mask, transpose, method); VALUE result = rb_hash_new(); VALUE cluster = rb_ary_new(); VALUE centroid = rb_ary_new(); for (i = 0; i < dimx; i++) rb_ary_push(cluster, INT2NUM(ccluster[i])); for (i = 0; i < cdimx; i++) { VALUE point = rb_ary_new(); for (j = 0; j < cdimy; j++) rb_ary_push(point, DBL2NUM(ccentroid[i][j])); rb_ary_push(centroid, point); } rb_hash_aset(result, ID2SYM(rb_intern("cluster")), cluster); rb_hash_aset(result, ID2SYM(rb_intern("centroid")), centroid); rb_hash_aset(result, ID2SYM(rb_intern("error")), DBL2NUM(error)); rb_hash_aset(result, ID2SYM(rb_intern("repeated")), INT2NUM(ifound)); for (i = 0; i < nrows; i++) { free(cdata[i]); free(cmask[i]); } for (i = 0; i < cdimx; i++) { free(ccentroid[i]); free(ccentroid_mask[i]); } free(cdata); free(cmask); free(ccentroid); free(ccentroid_mask); free(cweights); free(ccluster); return result; }
/* @api private */ VALUE rb_do_treecluster(int argc, VALUE *argv, VALUE self) { VALUE size, data, mask, weights, options; rb_scan_args(argc, argv, "21", &size, &data, &options); if (TYPE(data) != T_ARRAY) rb_raise(rb_eArgError, "data should be an array of arrays"); mask = get_value_option(options, "mask", Qnil); if (!NIL_P(mask) && TYPE(mask) != T_ARRAY) rb_raise(rb_eArgError, "mask should be an array of arrays"); if (NIL_P(size) || NUM2INT(rb_Integer(size)) > RARRAY_LEN(data)) rb_raise(rb_eArgError, "size should be > 0 and <= data size"); int transpose = get_int_option(options, "transpose", 0); // s: pairwise single-linkage clustering // m: pairwise maximum- (or complete-) linkage clustering // a: pairwise average-linkage clustering // c: pairwise centroid-linkage clustering int method = get_int_option(options, "method", 'a'); // e = euclidian, // b = city-block distance // c = correlation // a = absolute value of the correlation // u = uncentered correlation // x = absolute uncentered correlation // s = spearman's rank correlation // k = kendall's tau int dist = get_int_option(options, "metric", 'e'); int i,j; int nrows = RARRAY_LEN(data); int ncols = RARRAY_LEN(rb_ary_entry(data, 0)); int nsets = NUM2INT(rb_Integer(size)); double **cdata = (double**)malloc(sizeof(double*)*nrows); int **cmask = (int **)malloc(sizeof(int *)*nrows); double *cweights = (double *)malloc(sizeof(double )*ncols); int *ccluster, dimx = nrows, dimy = ncols; for (i = 0; i < nrows; i++) { cdata[i] = (double*)malloc(sizeof(double)*ncols); cmask[i] = (int *)malloc(sizeof(int )*ncols); for (j = 0; j < ncols; j++) { cdata[i][j] = NUM2DBL(rb_Float(rb_ary_entry(rb_ary_entry(data, i), j))); cmask[i][j] = NIL_P(mask) ? 1 : NUM2INT(rb_Integer(rb_ary_entry(rb_ary_entry(mask, i), j))); } } weights = NIL_P(options) ? Qnil : rb_hash_aref(options, ID2SYM(rb_intern("weights"))); for (i = 0; i < ncols; i++) { cweights[i] = NIL_P(weights) ? 1.0 : NUM2DBL(rb_Float(rb_ary_entry(weights, i))); } if (transpose) { dimx = ncols; dimy = nrows; } ccluster = (int *)malloc(sizeof(int)*dimx); Node *tree = treecluster(nrows, ncols, cdata, cmask, cweights, transpose, dist, method, 0); VALUE result = Qnil, cluster; if (tree) { cuttree(dimx, tree, nsets, ccluster); result = rb_hash_new(); cluster = rb_ary_new(); for (i = 0; i < dimx; i++) rb_ary_push(cluster, INT2NUM(ccluster[i])); rb_hash_aset(result, ID2SYM(rb_intern("cluster")), cluster); } for (i = 0; i < nrows; i++) { free(cdata[i]); free(cmask[i]); } free(cdata); free(cmask); free(cweights); free(ccluster); if (tree) free(tree); else rb_raise(rb_eNoMemError, "treecluster ran out of memory"); return result; }
/* @api private */ VALUE rb_do_self_organizing_map(int argc, VALUE *argv, VALUE self) { VALUE nx, ny, data, mask, weights, options; rb_scan_args(argc, argv, "31", &nx, &ny, &data, &options); if (TYPE(data) != T_ARRAY) rb_raise(rb_eArgError, "data should be an array of arrays"); mask = get_value_option(options, "mask", Qnil); if (!NIL_P(mask) && TYPE(mask) != T_ARRAY) rb_raise(rb_eArgError, "mask should be an array of arrays"); if (NIL_P(nx) || NUM2INT(rb_Integer(nx)) <= 0) rb_raise(rb_eArgError, "nx should be > 0"); if (NIL_P(ny) || NUM2INT(rb_Integer(ny)) <= 0) rb_raise(rb_eArgError, "ny should be > 0"); int nxgrid = NUM2INT(rb_Integer(nx)); int nygrid = NUM2INT(rb_Integer(ny)); int transpose = get_int_option(options, "transpose", 0); int npass = get_int_option(options, "iterations", DEFAULT_ITERATIONS); // e = euclidian, // b = city-block distance // c = correlation // a = absolute value of the correlation // u = uncentered correlation // x = absolute uncentered correlation // s = spearman's rank correlation // k = kendall's tau int dist = get_int_option(options, "metric", 'e'); double tau = get_dbl_option(options, "tau", 1.0); int i, j, k; int nrows = RARRAY_LEN(data); int ncols = RARRAY_LEN(rb_ary_entry(data, 0)); double **cdata = (double**)malloc(sizeof(double*)*nrows); int **cmask = (int **)malloc(sizeof(int *)*nrows); double *cweights = (double *)malloc(sizeof(double )*ncols); int **ccluster; double ***ccelldata; int dimx = nrows, dimy = ncols; if (transpose) { dimx = ncols; dimy = nrows; } ccluster = (int **)malloc(sizeof(int*)*dimx); for (i = 0; i < dimx; i++) ccluster[i] = (int*)malloc(sizeof(int)*2); for (i = 0; i < nrows; i++) { cdata[i] = (double*)malloc(sizeof(double)*ncols); cmask[i] = (int *)malloc(sizeof(int )*ncols); for (j = 0; j < ncols; j++) { cdata[i][j] = NUM2DBL(rb_Float(rb_ary_entry(rb_ary_entry(data, i), j))); cmask[i][j] = NIL_P(mask) ? 1 : NUM2INT(rb_Integer(rb_ary_entry(rb_ary_entry(mask, i), j))); } } weights = NIL_P(options) ? Qnil : rb_hash_aref(options, ID2SYM(rb_intern("weights"))); for (i = 0; i < ncols; i++) { cweights[i] = NIL_P(weights) ? 1.0 : NUM2DBL(rb_Float(rb_ary_entry(weights, i))); } ccelldata = (double***)malloc(sizeof(double**)*nxgrid); for (i = 0; i < nxgrid; i++) { ccelldata[i] = (double **)malloc(sizeof(double*)*nygrid); for (j = 0; j < nygrid; j++) ccelldata[i][j] = (double *)malloc(sizeof(double)*dimy); } somcluster(nrows, ncols, cdata, cmask, cweights, transpose, nxgrid, nygrid, tau, npass, dist, ccelldata, ccluster); VALUE result = rb_hash_new(); VALUE cluster = rb_ary_new(); VALUE centroid = rb_ary_new(); for (i = 0; i < dimx; i++) { VALUE gridpoint = rb_ary_new(); rb_ary_push(gridpoint, INT2NUM(ccluster[i][0])); rb_ary_push(gridpoint, INT2NUM(ccluster[i][1])); rb_ary_push(cluster, gridpoint); } for (i = 0; i < nxgrid; i++) { for (j = 0; j < nygrid; j++) { VALUE point = rb_ary_new(); for (k = 0; k < dimy; k++) rb_ary_push(point, DBL2NUM(ccelldata[i][j][k])); rb_ary_push(centroid, point); } } rb_hash_aset(result, ID2SYM(rb_intern("cluster")), cluster); rb_hash_aset(result, ID2SYM(rb_intern("centroid")), centroid); for (i = 0; i < nrows; i++) { free(cdata[i]); free(cmask[i]); } for (i = 0; i < dimx; i++) free(ccluster[i]); for (i = 0; i < nxgrid; i++) { for (j = 0; j < nygrid; j++) free(ccelldata[i][j]); free(ccelldata[i]); } free(cdata); free(cmask); free(ccelldata); free(cweights); free(ccluster); return result; }
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt) { rb_encoding *enc; const char *p, *end; char *buf; long blen, bsiz; VALUE result; long scanned = 0; int coderange = ENC_CODERANGE_7BIT; int width, prec, flags = FNONE; int nextarg = 1; int posarg = 0; int tainted = 0; VALUE nextvalue; VALUE tmp; VALUE str; volatile VALUE hash = Qundef; #define CHECK_FOR_WIDTH(f) \ if ((f) & FWIDTH) { \ rb_raise(rb_eArgError, "width given twice"); \ } \ if ((f) & FPREC0) { \ rb_raise(rb_eArgError, "width after precision"); \ } #define CHECK_FOR_FLAGS(f) \ if ((f) & FWIDTH) { \ rb_raise(rb_eArgError, "flag after width"); \ } \ if ((f) & FPREC0) { \ rb_raise(rb_eArgError, "flag after precision"); \ } ++argc; --argv; if (OBJ_TAINTED(fmt)) tainted = 1; StringValue(fmt); enc = rb_enc_get(fmt); fmt = rb_str_new4(fmt); p = RSTRING_PTR(fmt); end = p + RSTRING_LEN(fmt); blen = 0; bsiz = 120; result = rb_str_buf_new(bsiz); rb_enc_copy(result, fmt); buf = RSTRING_PTR(result); memset(buf, 0, bsiz); ENC_CODERANGE_SET(result, coderange); for (; p < end; p++) { const char *t; int n; ID id = 0; for (t = p; t < end && *t != '%'; t++) ; PUSH(p, t - p); if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange); ENC_CODERANGE_SET(result, coderange); } if (t >= end) { /* end of fmt string */ goto sprint_exit; } p = t + 1; /* skip `%' */ width = prec = -1; nextvalue = Qundef; retry: switch (*p) { default: if (rb_enc_isprint(*p, enc)) rb_raise(rb_eArgError, "malformed format string - %%%c", *p); else rb_raise(rb_eArgError, "malformed format string"); break; case ' ': CHECK_FOR_FLAGS(flags); flags |= FSPACE; p++; goto retry; case '#': CHECK_FOR_FLAGS(flags); flags |= FSHARP; p++; goto retry; case '+': CHECK_FOR_FLAGS(flags); flags |= FPLUS; p++; goto retry; case '-': CHECK_FOR_FLAGS(flags); flags |= FMINUS; p++; goto retry; case '0': CHECK_FOR_FLAGS(flags); flags |= FZERO; p++; goto retry; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; GETNUM(n, width); if (*p == '$') { if (nextvalue != Qundef) { rb_raise(rb_eArgError, "value given twice - %d$", n); } nextvalue = GETPOSARG(n); p++; goto retry; } CHECK_FOR_WIDTH(flags); width = n; flags |= FWIDTH; goto retry; case '<': case '{': { const char *start = p; char term = (*p == '<') ? '>' : '}'; int len; for (; p < end && *p != term; ) { p += rb_enc_mbclen(p, end, enc); } if (p >= end) { rb_raise(rb_eArgError, "malformed name - unmatched parenthesis"); } #if SIZEOF_INT < SIZEOF_SIZE_T if ((size_t)(p - start) >= INT_MAX) { const int message_limit = 20; len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start); rb_enc_raise(enc, rb_eArgError, "too long name (%"PRIdSIZE" bytes) - %.*s...%c", (size_t)(p - start - 2), len, start, term); } #endif len = (int)(p - start + 1); /* including parenthesis */ if (id) { rb_enc_raise(enc, rb_eArgError, "named%.*s after <%s>", len, start, rb_id2name(id)); } nextvalue = GETNAMEARG((id = rb_check_id_cstr(start + 1, len - 2 /* without parenthesis */, enc), ID2SYM(id)), start, len, enc); if (nextvalue == Qundef) { rb_enc_raise(enc, rb_eKeyError, "key%.*s not found", len, start); } if (term == '}') goto format_s; p++; goto retry; } case '*': CHECK_FOR_WIDTH(flags); flags |= FWIDTH; GETASTER(width); if (width < 0) { flags |= FMINUS; width = -width; } p++; goto retry; case '.': if (flags & FPREC0) { rb_raise(rb_eArgError, "precision given twice"); } flags |= FPREC|FPREC0; prec = 0; p++; if (*p == '*') { GETASTER(prec); if (prec < 0) { /* ignore negative precision */ flags &= ~FPREC; } p++; goto retry; } GETNUM(prec, precision); goto retry; case '\n': case '\0': p--; case '%': if (flags != FNONE) { rb_raise(rb_eArgError, "invalid format character - %%"); } PUSH("%", 1); break; case 'c': { VALUE val = GETARG(); VALUE tmp; unsigned int c; int n; tmp = rb_check_string_type(val); if (!NIL_P(tmp)) { if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) { rb_raise(rb_eArgError, "%%c requires a character"); } c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc); RB_GC_GUARD(tmp); } else { c = NUM2INT(val); n = rb_enc_codelen(c, enc); } if (n <= 0) { rb_raise(rb_eArgError, "invalid character"); } if (!(flags & FWIDTH)) { CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; } else if ((flags & FMINUS)) { CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; FILL(' ', width-1); } else { FILL(' ', width-1); CHECK(n); rb_enc_mbcput(c, &buf[blen], enc); blen += n; } } break; case 's': case 'p': format_s: { VALUE arg = GETARG(); long len, slen; if (*p == 'p') arg = rb_inspect(arg); str = rb_obj_as_string(arg); if (OBJ_TAINTED(str)) tainted = 1; len = RSTRING_LEN(str); rb_str_set_len(result, blen); if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { int cr = coderange; scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr); ENC_CODERANGE_SET(result, (cr == ENC_CODERANGE_UNKNOWN ? ENC_CODERANGE_BROKEN : (coderange = cr))); } enc = rb_enc_check(result, str); if (flags&(FPREC|FWIDTH)) { slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc); if (slen < 0) { rb_raise(rb_eArgError, "invalid mbstring sequence"); } if ((flags&FPREC) && (prec < slen)) { char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str), prec, enc); slen = prec; len = p - RSTRING_PTR(str); } /* need to adjust multi-byte string pos */ if ((flags&FWIDTH) && (width > slen)) { width -= (int)slen; if (!(flags&FMINUS)) { CHECK(width); while (width--) { buf[blen++] = ' '; } } CHECK(len); memcpy(&buf[blen], RSTRING_PTR(str), len); RB_GC_GUARD(str); blen += len; if (flags&FMINUS) { CHECK(width); while (width--) { buf[blen++] = ' '; } } rb_enc_associate(result, enc); break; } } PUSH(RSTRING_PTR(str), len); RB_GC_GUARD(str); rb_enc_associate(result, enc); } break; case 'd': case 'i': case 'o': case 'x': case 'X': case 'b': case 'B': case 'u': { volatile VALUE val = GETARG(); char fbuf[32], nbuf[64], *s; const char *prefix = 0; int sign = 0, dots = 0; char sc = 0; long v = 0; int base, bignum = 0; int len; switch (*p) { case 'd': case 'i': case 'u': sign = 1; break; case 'o': case 'x': case 'X': case 'b': case 'B': if (flags&(FPLUS|FSPACE)) sign = 1; break; } if (flags & FSHARP) { switch (*p) { case 'o': prefix = "0"; break; case 'x': prefix = "0x"; break; case 'X': prefix = "0X"; break; case 'b': prefix = "0b"; break; case 'B': prefix = "0B"; break; } } bin_retry: switch (TYPE(val)) { case T_FLOAT: if (FIXABLE(RFLOAT_VALUE(val))) { val = LONG2FIX((long)RFLOAT_VALUE(val)); goto bin_retry; } val = rb_dbl2big(RFLOAT_VALUE(val)); if (FIXNUM_P(val)) goto bin_retry; bignum = 1; break; case T_STRING: val = rb_str_to_inum(val, 0, TRUE); goto bin_retry; case T_BIGNUM: bignum = 1; break; case T_FIXNUM: v = FIX2LONG(val); break; default: val = rb_Integer(val); goto bin_retry; } switch (*p) { case 'o': base = 8; break; case 'x': case 'X': base = 16; break; case 'b': case 'B': base = 2; break; case 'u': case 'd': case 'i': default: base = 10; break; } if (!bignum) { if (base == 2) { val = rb_int2big(v); goto bin_retry; } if (sign) { char c = *p; if (c == 'i') c = 'd'; /* %d and %i are identical */ if (v < 0) { v = -v; sc = '-'; width--; } else if (flags & FPLUS) { sc = '+'; width--; } else if (flags & FSPACE) { sc = ' '; width--; } snprintf(fbuf, sizeof(fbuf), "%%l%c", c); snprintf(nbuf, sizeof(nbuf), fbuf, v); s = nbuf; } else { s = nbuf; if (v < 0) { dots = 1; } snprintf(fbuf, sizeof(fbuf), "%%l%c", *p == 'X' ? 'x' : *p); snprintf(++s, sizeof(nbuf) - 1, fbuf, v); if (v < 0) { char d = 0; s = remove_sign_bits(s, base); switch (base) { case 16: d = 'f'; break; case 8: d = '7'; break; } if (d && *s != d) { *--s = d; } } } len = (int)strlen(s); } else { if (sign) { tmp = rb_big2str(val, base); s = RSTRING_PTR(tmp); if (s[0] == '-') { s++; sc = '-'; width--; } else if (flags & FPLUS) { sc = '+'; width--; } else if (flags & FSPACE) { sc = ' '; width--; } } else { if (!RBIGNUM_SIGN(val)) { val = rb_big_clone(val); rb_big_2comp(val); } tmp = rb_big2str0(val, base, RBIGNUM_SIGN(val)); s = RSTRING_PTR(tmp); if (*s == '-') { dots = 1; if (base == 10) { rb_warning("negative number for %%u specifier"); } s = remove_sign_bits(++s, base); switch (base) { case 16: if (s[0] != 'f') *--s = 'f'; break; case 8: if (s[0] != '7') *--s = '7'; break; case 2: if (s[0] != '1') *--s = '1'; break; } } } len = rb_long2int(RSTRING_END(tmp) - s); } if (dots) { prec -= 2; width -= 2; } if (*p == 'X') { char *pp = s; int c; while ((c = (int)(unsigned char)*pp) != 0) { *pp = rb_enc_toupper(c, enc); pp++; } } if (prefix && !prefix[1]) { /* octal */ if (dots) { prefix = 0; } else if (len == 1 && *s == '0') { len = 0; if (flags & FPREC) prec--; } else if ((flags & FPREC) && (prec > len)) { prefix = 0; } } else if (len == 1 && *s == '0') { prefix = 0; } if (prefix) { width -= (int)strlen(prefix); } if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) { prec = width; width = 0; } else { if (prec < len) { if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0; prec = len; } width -= prec; } if (!(flags&FMINUS)) { CHECK(width); while (width-- > 0) { buf[blen++] = ' '; } } if (sc) PUSH(&sc, 1); if (prefix) { int plen = (int)strlen(prefix); PUSH(prefix, plen); } CHECK(prec - len); if (dots) PUSH("..", 2); if (!bignum && v < 0) { char c = sign_bits(base, p); while (len < prec--) { buf[blen++] = c; } } else if ((flags & (FMINUS|FPREC)) != FMINUS) { char c; if (!sign && bignum && !RBIGNUM_SIGN(val)) c = sign_bits(base, p); else c = '0'; while (len < prec--) { buf[blen++] = c; } } PUSH(s, len); RB_GC_GUARD(tmp); CHECK(width); while (width-- > 0) { buf[blen++] = ' '; } } break; case 'f': case 'g': case 'G': case 'e': case 'E': case 'a': case 'A': { VALUE val = GETARG(); double fval; int i, need = 6; char fbuf[32]; fval = RFLOAT_VALUE(rb_Float(val)); if (isnan(fval) || isinf(fval)) { const char *expr; if (isnan(fval)) { expr = "NaN"; } else { expr = "Inf"; } need = (int)strlen(expr); if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS)) need++; if ((flags & FWIDTH) && need < width) need = width; CHECK(need + 1); snprintf(&buf[blen], need + 1, "%*s", need, ""); if (flags & FMINUS) { if (!isnan(fval) && fval < 0.0) buf[blen++] = '-'; else if (flags & FPLUS) buf[blen++] = '+'; else if (flags & FSPACE) blen++; memcpy(&buf[blen], expr, strlen(expr)); } else { if (!isnan(fval) && fval < 0.0) buf[blen + need - strlen(expr) - 1] = '-'; else if (flags & FPLUS) buf[blen + need - strlen(expr) - 1] = '+'; else if ((flags & FSPACE) && need > width) blen++; memcpy(&buf[blen + need - strlen(expr)], expr, strlen(expr)); } blen += strlen(&buf[blen]); break; } fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); need = 0; if (*p != 'e' && *p != 'E') { i = INT_MIN; frexp(fval, &i); if (i > 0) need = BIT_DIGITS(i); } need += (flags&FPREC) ? prec : 6; if ((flags&FWIDTH) && need < width) need = width; need += 20; CHECK(need); snprintf(&buf[blen], need, fbuf, fval); blen += strlen(&buf[blen]); } break; } flags = FNONE; } sprint_exit: RB_GC_GUARD(fmt); /* XXX - We cannot validate the number of arguments if (digit)$ style used. */ if (posarg >= 0 && nextarg < argc) { const char *mesg = "too many arguments for format string"; if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg); if (RTEST(ruby_verbose)) rb_warn("%s", mesg); } rb_str_resize(result, blen); if (tainted) OBJ_TAINT(result); return result; }
static VALUE range_bsearch(VALUE range) { VALUE beg, end; int smaller, satisfied = 0; /* Implementation notes: * Floats are handled by mapping them to 64 bits integers. * Apart from sign issues, floats and their 64 bits integer have the * same order, assuming they are represented as exponent followed * by the mantissa. This is true with or without implicit bit. * * Finding the average of two ints needs to be careful about * potential overflow (since float to long can use 64 bits) * as well as the fact that -1/2 can be 0 or -1 in C89. * * Note that -0.0 is mapped to the same int as 0.0 as we don't want * (-1...0.0).bsearch to yield -0.0. */ #define BSEARCH_CHECK(val) \ do { \ VALUE v = rb_yield(val); \ if (FIXNUM_P(v)) { \ if (FIX2INT(v) == 0) return val; \ smaller = FIX2INT(v) < 0; \ } \ else if (v == Qtrue) { \ satisfied = 1; \ smaller = 1; \ } \ else if (v == Qfalse || v == Qnil) { \ smaller = 0; \ } \ else if (rb_obj_is_kind_of(v, rb_cNumeric)) { \ int cmp = rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0)); \ if (!cmp) return val; \ smaller = cmp < 0; \ } \ else { \ rb_raise(rb_eTypeError, "wrong argument type %s" \ " (must be numeric, true, false or nil)", \ rb_obj_classname(v)); \ } \ } while (0) #define BSEARCH(conv) \ do { \ RETURN_ENUMERATOR(range, 0, 0); \ if (EXCL(range)) high--; \ org_high = high; \ while (low < high) { \ mid = ((high < 0) == (low < 0)) ? low + ((high - low) / 2) \ : (low < -high) ? -((-1 - low - high)/2 + 1) : (low + high) / 2; \ BSEARCH_CHECK(conv(mid)); \ if (smaller) { \ high = mid; \ } \ else { \ low = mid + 1; \ } \ } \ if (low == org_high) { \ BSEARCH_CHECK(conv(low)); \ if (!smaller) return Qnil; \ } \ if (!satisfied) return Qnil; \ return conv(low); \ } while (0) beg = RANGE_BEG(range); end = RANGE_END(range); if (FIXNUM_P(beg) && FIXNUM_P(end)) { long low = FIX2LONG(beg); long high = FIX2LONG(end); long mid, org_high; BSEARCH(INT2FIX); } #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T) else if (RB_TYPE_P(beg, T_FLOAT) || RB_TYPE_P(end, T_FLOAT)) { int64_t low = double_as_int64(RFLOAT_VALUE(rb_Float(beg))); int64_t high = double_as_int64(RFLOAT_VALUE(rb_Float(end))); int64_t mid, org_high; BSEARCH(int64_as_double_to_num); } #endif else if (is_integer_p(beg) && is_integer_p(end)) { VALUE low = rb_to_int(beg); VALUE high = rb_to_int(end); VALUE mid, org_high; RETURN_ENUMERATOR(range, 0, 0); if (EXCL(range)) high = rb_funcall(high, '-', 1, INT2FIX(1)); org_high = high; while (rb_cmpint(rb_funcall(low, id_cmp, 1, high), low, high) < 0) { mid = rb_funcall(rb_funcall(high, '+', 1, low), id_div, 1, INT2FIX(2)); BSEARCH_CHECK(mid); if (smaller) { high = mid; } else { low = rb_funcall(mid, '+', 1, INT2FIX(1)); } } if (rb_equal(low, org_high)) { BSEARCH_CHECK(low); if (!smaller) return Qnil; } if (!satisfied) return Qnil; return low; } else { rb_raise(rb_eTypeError, "can't do binary search for %s", rb_obj_classname(beg)); } return range; }
VALUE rb_num_sqrt( VALUE num) { return rb_float_new( sqrt( RFLOAT_VALUE( rb_Float( num)))); }
static void bind_binary_double_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val) { /* val is converted to Float if it isn't Float. */ *(double*)data = RFLOAT_VALUE(rb_Float(val)); }