static VALUE string_to_r(VALUE self) { VALUE s = f_gsub(self, underscores_pat, an_underscore); VALUE a = string_to_r_internal(s); if (!NIL_P(RARRAY_AT(a, 0))) return RARRAY_AT(a, 0); return rb_rational_new1(INT2FIX(0)); }
/* * call-seq: * str.to_r -> rational * * Returns a rational which denotes the string form. The parser * ignores leading whitespaces and trailing garbage. Any digit * sequences can be separeted by an underscore. Returns zero for null * or garbage string. * * NOTE: '0.3'.to_r isn't the same as 0.3.to_r. The former is * equivalent to '3/10'.to_r, but the latter isn't so. * * For example: * * ' 2 '.to_r #=> (2/1) * '300/2'.to_r #=> (150/1) * '-9.2'.to_r #=> (-46/5) * '-9.2e2'.to_r #=> (-920/1) * '1_234_567'.to_r #=> (1234567/1) * '21 june 09'.to_r #=> (21/1) * '21/06/09'.to_r #=> (7/2) * 'bwv 1079'.to_r #=> (0/1) */ static VALUE string_to_r(VALUE self, SEL sel) { VALUE s, a, backref; backref = rb_backref_get(); rb_match_busy(backref); s = f_gsub(self, underscores_pat, an_underscore); a = string_to_r_internal(s); rb_backref_set(backref); if (!NIL_P(RARRAY_PTR(a)[0])) return RARRAY_PTR(a)[0]; return rb_rational_new1(INT2FIX(0)); }
static VALUE string_to_r_internal(VALUE self) { VALUE s, m; s = self; if (RSTRING_LEN(s) == 0) return rb_assoc_new(Qnil, self); m = f_match(rat_pat, s); if (!NIL_P(m)) { VALUE v, ifp, exp, ip, fp; VALUE si = f_aref(m, INT2FIX(1)); VALUE nu = f_aref(m, INT2FIX(2)); VALUE de = f_aref(m, INT2FIX(3)); VALUE re = f_post_match(m); { VALUE a; a = f_split(nu, an_e_pat); ifp = RARRAY_PTR(a)[0]; if (RARRAY_LEN(a) != 2) exp = Qnil; else exp = RARRAY_PTR(a)[1]; a = f_split(ifp, a_dot_pat); ip = RARRAY_PTR(a)[0]; if (RARRAY_LEN(a) != 2) fp = Qnil; else fp = RARRAY_PTR(a)[1]; } v = rb_rational_new1(f_to_i(ip)); if (!NIL_P(fp)) { char *p = StringValuePtr(fp); long count = 0; VALUE l; while (*p) { if (rb_isdigit(*p)) count++; p++; } l = f_expt(INT2FIX(10), LONG2NUM(count)); v = f_mul(v, l); v = f_add(v, f_to_i(fp)); v = f_div(v, l); } if (!NIL_P(si) && *StringValuePtr(si) == '-') v = f_negate(v); if (!NIL_P(exp)) v = f_mul(v, f_expt(INT2FIX(10), f_to_i(exp))); #if 0 if (!NIL_P(de) && (!NIL_P(fp) || !NIL_P(exp))) return rb_assoc_new(v, rb_usascii_str_new2("dummy")); #endif if (!NIL_P(de)) v = f_div(v, f_to_i(de)); return rb_assoc_new(v, re); } return rb_assoc_new(Qnil, self); }
/* * call-seq: * int.to_r -> rational * * Returns the value as a rational. * * For example: * * 1.to_r #=> (1/1) * (1<<64).to_r #=> (18446744073709551616/1) */ static VALUE integer_to_r(VALUE self, SEL sel) { return rb_rational_new1(self); }
/* * call-seq: * nil.to_r -> (0/1) * * Returns zero as a rational. */ static VALUE nilclass_to_r(VALUE self, SEL sel) { return rb_rational_new1(INT2FIX(0)); }