ruby-changes:35132
From: nobu <ko1@a...>
Date: Mon, 18 Aug 2014 17:07:00 +0900 (JST)
Subject: [ruby-changes:35132] nobu:r47214 (trunk): sprintf.c: rational 'f' format
nobu 2014-08-18 17:06:48 +0900 (Mon, 18 Aug 2014) New Revision: 47214 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47214 Log: sprintf.c: rational 'f' format * sprintf.c (rb_str_format): support rational 'f' format. [ruby-core:64382] [Bug #10136] Modified files: trunk/ChangeLog trunk/common.mk trunk/sprintf.c trunk/test/ruby/test_sprintf.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 47213) +++ ChangeLog (revision 47214) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Aug 18 17:06:27 2014 Nobuyoshi Nakada <nobu@r...> + + * sprintf.c (rb_str_format): support rational 'f' format. + [ruby-core:64382] [Bug #10136] + Mon Aug 18 08:03:46 2014 SHIBATA Hiroshi <shibata.hiroshi@g...> * spec/default.mspec: use 2.2 definition. Index: common.mk =================================================================== --- common.mk (revision 47213) +++ common.mk (revision 47214) @@ -771,7 +771,7 @@ ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_ https://github.com/ruby/ruby/blob/trunk/common.mk#L771 safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h -sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ +sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h {$(VPATH)}id.h \ {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ Index: sprintf.c =================================================================== --- sprintf.c (revision 47213) +++ sprintf.c (revision 47214) @@ -15,6 +15,7 @@ https://github.com/ruby/ruby/blob/trunk/sprintf.c#L15 #include "ruby/re.h" #include "ruby/encoding.h" #include "internal.h" +#include "id.h" #include <math.h> #include <stdarg.h> @@ -1022,12 +1023,78 @@ rb_str_format(int argc, const VALUE *arg https://github.com/ruby/ruby/blob/trunk/sprintf.c#L1023 break; case 'f': + { + VALUE val = GETARG(), num, den; + int sign = (flags&FPLUS) ? 1 : 0, zero = 0; + long len; + 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 (width > len) { + width -= (int)len; + if (!(flags&FMINUS)) { + FILL(' ', width); + width = 0; + } + } + if (sign || (flags&FSPACE)) buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' '; + len = RSTRING_LEN(val) + zero; + t = RSTRING_PTR(val); + if (len > prec) + memcpy(&buf[blen], t, len - prec); + else + buf[blen++] = '0'; + blen += len - prec; + if (prec > 0) buf[blen++] = '.'; + if (zero) FILL('0', zero); + else if (prec > 0) { + memcpy(&buf[blen], t + len - prec, prec); + blen += prec; + } + if (width > 0) FILL(' ', width); + 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; Index: test/ruby/test_sprintf.rb =================================================================== --- test/ruby/test_sprintf.rb (revision 47213) +++ test/ruby/test_sprintf.rb (revision 47214) @@ -148,6 +148,11 @@ class TestSprintf < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_sprintf.rb#L148 assert_equal(" Inf", sprintf("% e", inf), '[ruby-dev:34002]') end + def test_rational + assert_match(/\A0\.10+\z/, sprintf("%.60f", 0.1r)) + assert_match(/\A0\.3+\z/, sprintf("%.60f", 1/3r)) + end + def test_hash options = {:capture=>/\d+/} assert_equal("with options {:capture=>/\\d+/}", sprintf("with options %p" % options)) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/