Skip to content

Loading…

Float specs #54

Merged
merged 5 commits into from

2 participants

@gglresearchanddevelopment

Updates to pass various minor float specs, and implements Float#round(decimalPlaces) which is not in rubyspec (but MRI has it).

Float is now compatible with MRI except for Rational, which looks like it might be a big job?

@tmat tmat merged commit 6f02ff4 into IronLanguages:master
@tmat
IronLanguages member

Merged. Needs a follow up for Languages/Ruby/Libraries/Extensions/ClrFloat.cs:L569 comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 1, 2012
  1. Update Float#<=> as per rubyspec

    Orion Edwards [GGL] committed
  2. Update Float#divmod as per rubyspec

    Orion Edwards [GGL] committed
  3. Implement Float#fdiv (it's just float#/) as per rubyspec

    Orion Edwards [GGL] committed
  4. Update Float#% and Float#modulo to raise ZeroDivisionError as per rub…

    Orion Edwards [GGL] committed
    …yspec
  5. Implement Float#round(decimalPlaces). There is no rubyspec for this b…

    Orion Edwards [GGL] committed
    …ut it's very useful and MRI has it
This page is out of date. Refresh to see the latest.
View
7 Languages/Ruby/Libraries/Extensions/ClrBigInteger.cs
@@ -579,7 +579,12 @@ public sealed class ClrBigInteger {
/// </remarks>
[RubyMethod("<=>")]
public static object Compare(RubyContext/*!*/ context, BigInteger/*!*/ self, double other) {
- return ClrFloat.Compare(ToFloat(context, self), other);
+ var result = ClrFloat.Compare(context, other, self);
+ if (result == null) {
+ return null;
+ } else {
+ return ((int)result) * -1;
+ }
}
/// <summary>
View
72 Languages/Ruby/Libraries/Extensions/ClrFloat.cs
@@ -18,6 +18,7 @@
using Microsoft.Scripting.Math;
using IronRuby.Runtime;
using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Utils;
namespace IronRuby.Builtins {
/// <summary>
@@ -197,6 +198,7 @@ public static class ClrFloat {
/// </summary>
/// <returns>Float</returns>
[RubyMethod("/")]
+ [RubyMethod("fdiv")]
public static double Divide(double self, int other) {
return self / (double)other;
}
@@ -206,6 +208,7 @@ public static class ClrFloat {
/// </summary>
/// <returns>Float</returns>
[RubyMethod("/")]
+ [RubyMethod("fdiv")]
public static double Divide(RubyContext/*!*/ context, double self, [NotNull]BigInteger/*!*/ other) {
return self / Protocols.ConvertToDouble(context, other);
}
@@ -215,6 +218,7 @@ public static class ClrFloat {
/// </summary>
/// <returns>Float</returns>
[RubyMethod("/")]
+ [RubyMethod("fdiv")]
public static double Divide(double self, double other) {
return self / other;
}
@@ -224,6 +228,7 @@ public static class ClrFloat {
/// </summary>
/// <returns></returns>
[RubyMethod("/")]
+ [RubyMethod("fdiv")]
public static object Divide(BinaryOpStorage/*!*/ coercionStorage, BinaryOpStorage/*!*/ binaryOpSite, double self, object other) {
return Protocols.CoerceAndApply(coercionStorage, binaryOpSite, "/", self, other);
}
@@ -238,6 +243,9 @@ public static class ClrFloat {
/// <returns>Float</returns>
[RubyMethod("%"), RubyMethod("modulo")]
public static double Modulo(double self, int other) {
+ if (other == 0) {
+ throw CreateZeroDivisionError();
+ }
return (double)InternalDivMod(self, (double)other)[1];
}
@@ -247,6 +255,9 @@ public static class ClrFloat {
/// <returns>Float</returns>
[RubyMethod("%"), RubyMethod("modulo")]
public static double Modulo(RubyContext/*!*/ context, double self, [NotNull]BigInteger/*!*/ other) {
+ if (other == BigInteger.Zero) {
+ throw CreateZeroDivisionError();
+ }
return (double)InternalDivMod(self, Protocols.ConvertToDouble(context, other))[1];
}
@@ -256,6 +267,9 @@ public static class ClrFloat {
/// <returns>Float</returns>
[RubyMethod("%"), RubyMethod("modulo")]
public static double Modulo(double self, double other) {
+ if (other == 0.0) {
+ throw CreateZeroDivisionError();
+ }
return (double)InternalDivMod(self, other)[1];
}
@@ -365,6 +379,10 @@ public static class ClrFloat {
/// </remarks>
[RubyMethod("divmod")]
public static RubyArray DivMod(double self, double other) {
+ if (other == 0.0) {
+ throw CreateZeroDivisionError();
+ }
+
RubyArray result = InternalDivMod(self, other);
// Unlike modulo, divmod blows up if the quotient or modulus are not finite, so we can't put this inside InternalDivMod
// We only need to test if the quotient is double since it should have been converted to Integer (Fixnum or Bignum) if it was OK.
@@ -521,6 +539,39 @@ public static class ClrFloat {
return 0;
}
+ /// <summary>
+ /// Rounds <code>self</code> to the <code>decimalPlaces</code> places.
+ /// </summary>
+ /// <remarks>
+ /// This is equivalent to:
+ /// <code>
+ /// def round
+ /// return (self+0.5).floor if self &gt; 0.0
+ /// return (self-0.5).ceil if self &lt; 0.0
+ /// return 0
+ /// end
+ /// </code>
+ /// </remarks>
+ /// <example>
+ /// 312.12570.round(1) == 312.1
+ /// 312.12570.round(2) == 312.13
+ /// 312.12570.round(3) == 312.126
+ /// 312.12570.round(4) == 312.1257
+ /// 312.12570.round(5) == 312.12570
+ /// 312.12570.round(10) == 312.12570
+ /// </example>
+ [RubyMethod("round")]
+ public static object Round(double self, int decimalPlaces) {
+ if (decimalPlaces == 0) {
+ return Round(self);
+ }
+
+ double exponent = Math.Pow(10.0, decimalPlaces);
+ if (self > 0) { return Math.Floor(self * exponent + 0.5) / exponent; }
+ if (self < 0) { return Math.Ceiling(self * exponent - 0.5) / exponent; }
+ return 0;
+ }
+
#endregion
#region inspect, to_s
@@ -646,7 +697,18 @@ public static class ClrFloat {
if (Double.IsNaN(self)) {
return null;
}
- return self.CompareTo(Protocols.ConvertToDouble(context, other));
+
+ double otherFloat;
+ if (!other.TryToFloat64(out otherFloat)) { // out of range, treat it as positive or negative infinity
+ otherFloat = other.Sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
+
+ if (self == double.NegativeInfinity) {
+ return -1;
+ } else if (self == double.PositiveInfinity) {
+ return 1;
+ }
+ }
+ return self.CompareTo(otherFloat);
}
/// <summary>
@@ -930,6 +992,14 @@ public static class ClrFloat {
return new FloatDomainError("NaN");
}
+ public static Exception CreateZeroDivisionError(string message) {
+ return new DivideByZeroException(message);
+ }
+
+ public static Exception CreateZeroDivisionError() {
+ return new DivideByZeroException("divided by 0");
+ }
+
public static Exception CreateFloatDomainError(string message, Exception inner) {
return new FloatDomainError("NaN", inner);
}
View
49 Languages/Ruby/Libraries/Initializers.Generated.cs
@@ -3024,11 +3024,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "readlines", 0x51,
- 0x00000000U, 0x00020004U, 0x00060000U, 0x00000000U,
+ 0x00000000U, 0x00000000U, 0x00020004U, 0x00060000U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, Microsoft.Scripting.Runtime.DynamicNull, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Runtime.Union<IronRuby.Builtins.MutableString, System.Int32>, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.MutableString, System.Int32, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines)
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.MutableString, System.Int32, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines)
);
DefineLibraryMethod(module, "readpartial", 0x51,
@@ -3567,6 +3567,14 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, System.Double, System.Object, System.Object>(IronRuby.Builtins.ClrFloat.DivMod)
);
+ DefineLibraryMethod(module, "fdiv", 0x51,
+ 0x00000000U, 0x00000004U, 0x00000000U, 0x00000000U,
+ new Func<System.Double, System.Int32, System.Double>(IronRuby.Builtins.ClrFloat.Divide),
+ new Func<IronRuby.Runtime.RubyContext, System.Double, Microsoft.Scripting.Math.BigInteger, System.Double>(IronRuby.Builtins.ClrFloat.Divide),
+ new Func<System.Double, System.Double, System.Double>(IronRuby.Builtins.ClrFloat.Divide),
+ new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, System.Double, System.Object, System.Object>(IronRuby.Builtins.ClrFloat.Divide)
+ );
+
DefineLibraryMethod(module, "finite?", 0x51,
0x00000000U,
new Func<System.Double, System.Boolean>(IronRuby.Builtins.ClrFloat.IsFinite)
@@ -3601,8 +3609,9 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "round", 0x51,
- 0x00000000U,
- new Func<System.Double, System.Object>(IronRuby.Builtins.ClrFloat.Round)
+ 0x00000000U, 0x00000000U,
+ new Func<System.Double, System.Object>(IronRuby.Builtins.ClrFloat.Round),
+ new Func<System.Double, System.Int32, System.Object>(IronRuby.Builtins.ClrFloat.Round)
);
DefineLibraryMethod(module, "to_f", 0x51,
@@ -4250,15 +4259,15 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "define_singleton_method", 0x51,
- new[] { 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0004000aU, 0x0000000aU, 0x0002000cU},
- new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
+ new[] { 0x0002000cU, 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0004000aU, 0x0000000aU, 0x0002000cU, 0x0000000cU},
new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.RubyMethod, IronRuby.Builtins.RubyMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.RubyMethod, IronRuby.Builtins.RubyMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.UnboundMethod, IronRuby.Builtins.UnboundMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.UnboundMethod, IronRuby.Builtins.UnboundMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, System.Object, System.String, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
- new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod)
+ new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
+ new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod)
);
DefineLibraryMethod(module, "display", 0x51,
@@ -6850,11 +6859,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "each_line", 0x51,
- 0x00000002U, 0x00010000U, 0x00020001U, 0x00000000U,
+ 0x00000000U, 0x00000002U, 0x00010000U, 0x00020001U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine)
+ new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine)
);
DefineLibraryMethod(module, "empty?", 0x51,
@@ -6965,11 +6974,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "lines", 0x51,
- 0x00000002U, 0x00010000U, 0x00020001U, 0x00000000U,
+ 0x00000000U, 0x00000002U, 0x00010000U, 0x00020001U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine)
+ new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine)
);
DefineLibraryMethod(module, "ljust", 0x51,
@@ -7030,10 +7039,10 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "rindex", 0x51,
- 0x00010002U, 0x00030002U, 0x00040004U,
+ 0x00040004U, 0x00010002U, 0x00030002U,
+ new Func<IronRuby.Runtime.RubyScope, IronRuby.Builtins.MutableString, IronRuby.Builtins.RubyRegex, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
- new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
- new Func<IronRuby.Runtime.RubyScope, IronRuby.Builtins.MutableString, IronRuby.Builtins.RubyRegex, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf)
+ new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf)
);
DefineLibraryMethod(module, "rjust", 0x51,
@@ -11520,12 +11529,12 @@ public sealed class BigDecimalLibraryInitializer : IronRuby.Builtins.LibraryInit
);
DefineLibraryMethod(module, "<=>", 0x11,
- new[] { 0x00000000U, 0x00000002U, 0x00000004U, 0x00000000U, 0x00000000U},
- new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
+ new[] { 0x00000002U, 0x00000004U, 0x00000000U, 0x00000000U, 0x00000000U},
new Func<IronRuby.StandardLibrary.BigDecimal.BigDecimal, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, Microsoft.Scripting.Math.BigInteger, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Int32, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Double, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare)
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Double, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
+ new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare)
);
DefineLibraryMethod(module, "==", 0x11,
Something went wrong with that request. Please try again.