mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	sprintf.c: improve rational 'f' format
* sprintf.c (rb_str_format): rational 'f' format works for more values. [fix GH-717] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47588 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									7b09deef51
								
							
						
					
					
						commit
						230b845fa2
					
				
					 3 changed files with 58 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,8 @@
 | 
			
		|||
Mon Sep 15 08:13:40 2014  Matthew Draper  <matthew@trebex.net>
 | 
			
		||||
 | 
			
		||||
	* sprintf.c (rb_str_format): rational 'f' format works for more
 | 
			
		||||
	  values.  [fix GH-717]
 | 
			
		||||
 | 
			
		||||
Sun Sep 14 16:57:27 2014  Eric Wong  <e@80x24.org>
 | 
			
		||||
 | 
			
		||||
	* template/vm.inc.tmpl: "insns.c" => "insns.def"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										52
									
								
								sprintf.c
									
										
									
									
									
								
							
							
						
						
									
										52
									
								
								sprintf.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1027,6 +1027,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
 | 
			
		|||
		VALUE val = GETARG(), num, den;
 | 
			
		||||
		int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
 | 
			
		||||
		long len;
 | 
			
		||||
		int i, done = 0, prefix = 0;
 | 
			
		||||
		if (!RB_TYPE_P(val, T_RATIONAL)) {
 | 
			
		||||
		    nextvalue = val;
 | 
			
		||||
		    goto float_value;
 | 
			
		||||
| 
						 | 
				
			
			@ -1062,28 +1063,53 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
 | 
			
		|||
		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 ? '-' : ' ';
 | 
			
		||||
		    prefix++;
 | 
			
		||||
		    done++;
 | 
			
		||||
		}
 | 
			
		||||
		if (sign || (flags&FSPACE)) buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
 | 
			
		||||
		len = RSTRING_LEN(val) + zero;
 | 
			
		||||
		t = RSTRING_PTR(val);
 | 
			
		||||
		if (len > prec)
 | 
			
		||||
		if (len > prec) {
 | 
			
		||||
		    memcpy(&buf[blen], t, len - prec);
 | 
			
		||||
		else
 | 
			
		||||
		    blen += len - prec;
 | 
			
		||||
		    done += len - prec;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
		    buf[blen++] = '0';
 | 
			
		||||
		blen += len - prec;
 | 
			
		||||
		if (prec > 0) buf[blen++] = '.';
 | 
			
		||||
		if (zero) FILL('0', zero);
 | 
			
		||||
		    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) {
 | 
			
		||||
		    if (!(flags&FMINUS)) {
 | 
			
		||||
			int shifting = (flags&FZERO) ? done - prefix : done;
 | 
			
		||||
			for (i = 1; i <= shifting; i++)
 | 
			
		||||
			    buf[width - i] = buf[done - i];
 | 
			
		||||
			blen -= shifting;
 | 
			
		||||
			FILL((flags&FZERO) ? '0' : ' ', width - done);
 | 
			
		||||
			blen += shifting;
 | 
			
		||||
		    } else {
 | 
			
		||||
			FILL(' ', width - done);
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
		if (width > 0) FILL(' ', width);
 | 
			
		||||
		RB_GC_GUARD(val);
 | 
			
		||||
		break;
 | 
			
		||||
	    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -150,8 +150,22 @@ class TestSprintf < Test::Unit::TestCase
 | 
			
		|||
 | 
			
		||||
  def test_rational
 | 
			
		||||
    assert_match(/\A0\.10+\z/, sprintf("%.60f", 0.1r))
 | 
			
		||||
    assert_match(/\A0\.010+\z/, sprintf("%.60f", 0.01r))
 | 
			
		||||
    assert_match(/\A0\.0010+\z/, sprintf("%.60f", 0.001r))
 | 
			
		||||
    assert_match(/\A0\.3+\z/, sprintf("%.60f", 1/3r))
 | 
			
		||||
    assert_match(/\A1\.20+\z/, sprintf("%.60f", 1.2r))
 | 
			
		||||
 | 
			
		||||
    0.upto(9) do |len|
 | 
			
		||||
      -1.upto(9) do |prec|
 | 
			
		||||
        ['', '+', '-', ' ', '0', '+0', '-0', ' 0', '+ ', '- ', '+ 0', '- 0'].each do |flags|
 | 
			
		||||
          fmt = "%#{flags}#{len > 0 ? len : ''}#{prec >= 0 ? ".#{prec}" : ''}f"
 | 
			
		||||
          [0, 0.1, 0.01, 0.001, 1.001, 100.0, 100.001, 10000000000.0, 0.00000000001, 1/3r, 2/3r, 1.2r, 10r].each do |num|
 | 
			
		||||
            assert_equal(sprintf(fmt, num.to_f), sprintf(fmt, num.to_r), "sprintf(#{fmt.inspect}, #{num.inspect}.to_r)")
 | 
			
		||||
            assert_equal(sprintf(fmt, -num.to_f), sprintf(fmt, -num.to_r), "sprintf(#{fmt.inspect}, #{(-num).inspect}.to_r)") if num > 0
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_hash
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue