Project

General

Profile

Backport #6044 ยป fixmodulo.patch

marcandre (Marc-Andre Lafortune), 02/18/2012 09:26 AM

View differences:

insns.def
1620 1620
		 BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
1621 1621
	    double x = RFLOAT_VALUE(recv);
1622 1622
	    double y = RFLOAT_VALUE(obj);
1623
	    double div, mod;
1624

  
1625
	    {
1623
	    double mod;
1624
#ifdef HAVE_FMOD
1625
	    mod = fmod(x, y);
1626
#else
1627
	    if((x == -0.0) || (isinf(y) && !isinf(x)))
1628
	        mod = x;
1629
	    else {
1626 1630
		double z;
1627 1631

  
1628
		modf(x / y, &z);
1632
		modf(x/y, &z);
1629 1633
		mod = x - z * y;
1630 1634
	    }
1631

  
1632
	    div = (x - mod) / y;
1635
#endif
1633 1636
	    if (y * mod < 0) {
1634 1637
		mod += y;
1635
		div -= 1.0;
1636 1638
	    }
1637 1639
	    val = DBL2NUM(mod);
1638 1640
	}
numeric.c
811 811
static void
812 812
flodivmod(double x, double y, double *divp, double *modp)
813 813
{
814
    /******
815
    Modifications to this implementation should be mirrored in insns.def
816
    *******/
817

  
814 818
    double div, mod;
815 819

  
816 820
    if (y == 0.0) rb_num_zerodiv();
821

  
817 822
#ifdef HAVE_FMOD
818 823
    mod = fmod(x, y);
819 824
#else
820
    {
825
    if((x == -0.0) || (isinf(y) && !isinf(x)))
826
        mod = x;
827
    else {
821 828
	double z;
822 829

  
823 830
	modf(x/y, &z);
824 831
	mod = x - z * y;
825 832
    }
826 833
#endif
834

  
827 835
    if (isinf(x) && !isinf(y) && !isnan(y))
828 836
	div = x;
829 837
    else
test/ruby/envutil.rb
206 206
        assert_equal([true, ""], [status.success?, err], message)
207 207
        assert_operator(after.fdiv(before), :<, limit, message)
208 208
      end
209

  
210
      def assert_is_minus_zero(f)
211
        assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
212
      end
209 213
    end
210 214
  end
211 215
end
test/ruby/test_float.rb
195 195
    assert_raise(TypeError) { 2.0.send(:%, nil) }
196 196
  end
197 197

  
198
  def test_modulo3
199
    assert_equal(4.2, 4.2.send(:%, Float::INFINITY))
200
    assert_equal(4.2, 4.2 % Float::INFINITY)
201
    assert_is_minus_zero(-0.0 % 4.2)
202
    assert_is_minus_zero(-0.0.send :%, 4.2)
203
  end
204

  
198 205
  def test_divmod2
199 206
    assert_equal([1.0, 0.0], 2.0.divmod(2))
200 207
    assert_equal([1.0, 0.0], 2.0.divmod((2**32).coerce(2).first))