Skip to content
Browse files

Some C# love for the numeric range hot path

  • Loading branch information...
1 parent 1d0c020 commit c85099ac197eeb3d7671716282e80ea1af573619 @sorear committed
Showing with 59 additions and 23 deletions.
  1. +20 −16 lib/Builtins.cs
  2. +1 −7 lib/CORE.setting
  3. +38 −0 lib/Kernel.cs
View
36 lib/Builtins.cs
@@ -1229,14 +1229,13 @@ public partial class Builtins {
return c.setting.MakeInt(Kernel.UnboxAny<FatRat>(a1.Fetch()).den);
}
- const int O_IS_GREATER = 1;
- const int O_IS_LESS = 2;
- const int O_IS_EQUAL = 4;
- const int O_IS_UNORD = 8;
- const int O_COMPLEX_OK = 16;
+ internal const int O_IS_GREATER = 1;
+ internal const int O_IS_LESS = 2;
+ internal const int O_IS_EQUAL = 4;
+ internal const int O_IS_UNORD = 8;
+ internal const int O_COMPLEX_OK = 16;
public static Variable numcompare(Constants c, Variable a1, Variable a2, int mask,
Func<Constants,Variable,Variable,Variable> dl) {
- int r1, r2, res=0;
var s = c.setting;
P6any o1 = a1.Fetch(), o2 = a2.Fetch();
if (!(o1.mo.is_any && o2.mo.is_any)) {
@@ -1246,27 +1245,35 @@ public partial class Builtins {
return jr.Fetch().mo.mro_raw_Bool.Get(jr) ? s.FalseV : s.TrueV;
return jr;
}
+ int res = numcompare_core(s, a1, o1, a2, o2, (mask & O_COMPLEX_OK) != 0);
+
+ return ((mask & res) != 0) ? s.TrueV : s.FalseV;
+ }
+
+ internal static int numcompare_core(Compartment s, Variable a1, P6any o1,
+ Variable a2, P6any o2, bool complex_ok) {
+ int r1, r2;
P6any n1 = GetNumber(a1, o1, out r1);
P6any n2 = GetNumber(a2, o2, out r2);
if (r1 == NR_COMPLEX || r2 == NR_COMPLEX) {
- if ((mask & O_COMPLEX_OK) == 0)
+ if (!complex_ok)
throw new NieczaException("Complex numbers are not arithmetically ordered; use cmp if you want an arbitrary order");
Complex v1 = PromoteToComplex(r1, n1);
Complex v2 = PromoteToComplex(r2, n2);
if (double.IsNaN(v1.re) || double.IsNaN(v1.im) ||
double.IsNaN(v2.re) || double.IsNaN(v2.im))
- res = O_IS_UNORD;
+ return O_IS_UNORD;
else if (v1.re != v2.re)
- res = v1.re > v2.re ? O_IS_GREATER : O_IS_LESS;
+ return v1.re > v2.re ? O_IS_GREATER : O_IS_LESS;
else
- res = v1.im > v2.im ? O_IS_GREATER : v1.im < v2.im ? O_IS_LESS : O_IS_EQUAL;
+ return v1.im > v2.im ? O_IS_GREATER : v1.im < v2.im ? O_IS_LESS : O_IS_EQUAL;
}
else if (r1 == NR_FLOAT || r2 == NR_FLOAT) {
double d1 = PromoteToFloat(r1, n1);
double d2 = PromoteToFloat(r2, n2);
- if (double.IsNaN(d1) || double.IsNaN(d2)) res = O_IS_UNORD;
- else res =d1 > d2 ? O_IS_GREATER : d1 < d2 ? O_IS_LESS : O_IS_EQUAL;
+ if (double.IsNaN(d1) || double.IsNaN(d2)) return O_IS_UNORD;
+ else return d1 > d2 ? O_IS_GREATER : d1 < d2 ? O_IS_LESS : O_IS_EQUAL;
}
else if (r1 == NR_FATRAT || r2 == NR_FATRAT) {
FatRat v1 = PromoteToFatRat(r1, n1);
@@ -1287,10 +1294,7 @@ public partial class Builtins {
else
r1 = PromoteToFixInt(r1, n1).CompareTo(PromoteToFixInt(r2, n2));
- if (res == 0)
- res = (r1 > 0) ? O_IS_GREATER : (r1 < 0) ? O_IS_LESS : O_IS_EQUAL;
-
- return ((mask & res) != 0) ? s.TrueV : s.FalseV;
+ return (r1 > 0) ? O_IS_GREATER : (r1 < 0) ? O_IS_LESS : O_IS_EQUAL;
}
static readonly Func<Constants,Variable,Variable,Variable> mul_d = mul;
View
8 lib/CORE.setting
@@ -2922,13 +2922,7 @@ my class NumericRangeIter is IterCursor {
has $.limit;
has $.exclusive;
- method reify() {
- my $c ::= $!current;
- my \l = $!limit;
-
- $c < l ?? ($c, NumericRangeIter.new(current => $c.succ, limit => l, exclusive => $!exclusive)) !!
- ($c > l || $!exclusive) ?? () !! ($c,);
- }
+ # reify implemented in lower-level code
}
my class RangeIter is IterCursor {
View
38 lib/Kernel.cs
@@ -3849,6 +3849,39 @@ class CtxStrNativeNum2Str : ContextHandler<Variable> {
}
}
+ class CtxNumRangeReify : ContextHandler<Variable[]> {
+ public override Variable[] Get(Variable obj) {
+ var nrmo = setting.NumericRangeIterMO;
+ P6any o = obj.Fetch();
+ var curv = (Variable)o.GetSlot(nrmo, "$!current");
+ var endv = (Variable)o.GetSlot(nrmo, "$!limit");
+ var excl = (Variable)o.GetSlot(nrmo, "$!exclusive");
+
+ var curo = curv.Fetch();
+ var endo = endv.Fetch();
+
+ int cmp = Builtins.numcompare_core(setting, curv, curo, endv, endo, false);
+
+ if (cmp == Builtins.O_IS_LESS) {
+ P6opaque newobj = new P6opaque(setting.NumericRangeIterMO);
+ newobj.slots[0] = curo.mo.mro_succ.Get(curv);
+ newobj.slots[1] = endo;
+ newobj.slots[2] = excl;
+
+ return new Variable[] {
+ curo,
+ newobj
+ };
+ }
+ else if (cmp == Builtins.O_IS_GREATER || excl.Fetch().mo.mro_raw_Bool.Get(excl)) {
+ return new Variable[0];
+ }
+ else {
+ return new Variable[] { curo };
+ }
+ }
+ }
+
class IxCallMethod : IndexHandler {
string name;
string adv;
@@ -4586,6 +4619,7 @@ public class Compartment {
[CORESaved] public BoxObject<int> TrueV;
[CORESaved] public BoxObject<int> FalseV;
+ [NewSaved] [CORESaved] public STable NumericRangeIterMO;
internal ObjectRegistry reg;
public string[] obj_dirs = new string[] { AppDomain.CurrentDomain.BaseDirectory };
@@ -6456,6 +6490,10 @@ class LastFrameNode {
s.ScalarMO = new STable(s, "Scalar");
s.ScalarMO.FillProtoClass(s.AnyMO);
+
+ s.NumericRangeIterMO = new STable(s, "NumericIterCursor");
+ Handler_PandBox(s.NumericRangeIterMO, "reify", new CtxNumRangeReify(), s.ParcelMO);
+ s.NumericRangeIterMO.FillProtoClass(s.AnyMO);
}
// This is a library function in .NET 4

0 comments on commit c85099a

Please sign in to comment.
Something went wrong with that request. Please try again.