[svn] r5976: nemerle/trunk/snippets/raytracer/ray-hand-opt.n

malekith svnadmin at nemerle.org
Mon Nov 28 13:01:23 CET 2005


Log:
Transform matching to vcalls, this gives 10% speedup (vs optimized matching).

Author: malekith
Date: Mon Nov 28 13:01:22 2005
New Revision: 5976

Modified:
   nemerle/trunk/snippets/raytracer/ray-hand-opt.n

Modified: nemerle/trunk/snippets/raytracer/ray-hand-opt.n
==============================================================================
--- nemerle/trunk/snippets/raytracer/ray-hand-opt.n	(original)
+++ nemerle/trunk/snippets/raytracer/ray-hand-opt.n	Mon Nov 28 13:01:22 2005
@@ -21,16 +21,40 @@
     (1 / Sqrt (this ** this)) * this
 
 
-variant Scene
-  | Sphere { m : Vec; r : double; }
-  | Group { m : Vec; r : double; l : list [Scene]; }
+abstract class Scene
+  public abstract intersect (orig : Vec, dir : Vec, first : double * Vec) : double * Vec
+  
+  [Record] \
+  internal sealed class Sphere : Scene
+    public center : Vec
+    public radius : double
+    public override intersect (orig : Vec, dir : Vec, first : double * Vec) : double * Vec
+      def l = first [0]
+      def l' = M.ray_sphere (orig, dir, center, radius)
+      if (l' >= l) first
+      else (l', (orig + l' * dir - center).Unitise ())
+  
+  [Record] \
+  internal sealed class Group : Scene
+    public center : Vec
+    public radius : double
+    public scenes : list [Scene]
+    
+    public override intersect (orig : Vec, dir : Vec, first : double * Vec) : double * Vec
+        def l = first [0]
+        def l' = M.ray_sphere (orig, dir, center, radius)
+        if (l' >= l) first
+        else
+          mutable acc = first
+          foreach (s in scenes)
+            acc = s.intersect (orig, dir, acc)
+          acc
 
 module M
   delta = 1.49011611938476562e-08
   inf : double = 1.0 / 0.0
 
-
-  ray_sphere (orig : Vec, dir : Vec, center : Vec, radius : double) : double
+  internal ray_sphere (orig : Vec, dir : Vec, center : Vec, radius : double) : double
     def v = center - orig
     def b = v ** dir
     def disc = b * b - (v ** v) + radius * radius
@@ -43,36 +67,15 @@
       else if (t1 > 0) t1
       else t2
 
-  intersect (orig : Vec, dir : Vec, scene : Scene, first : double * Vec) : double * Vec
-    def l = first [0]
-    match (scene)
-      | Scene.Sphere as s =>
-        def center = s.m
-        def radius = s.r
-        def l' = ray_sphere (orig, dir, center, radius)
-        if (l' >= l) first
-        else (l', (orig + l' * dir - center).Unitise ())
-      | Scene.Group as g =>
-        def center = g.m
-        def radius = g.r
-        def scenes = g.l
-        def l' = ray_sphere (orig, dir, center, radius)
-        if (l' >= l) first
-        else
-          mutable acc = first
-          foreach (s in scenes)
-            acc = intersect (orig, dir, s, acc)
-          acc
-
   ray_trace (light:Vec, orig:Vec, dir:Vec, scene:Scene) : double
-    def (lambda, normal) = intersect (orig, dir, scene, (inf, Vec()))
+    def (lambda, normal) = scene.intersect (orig, dir, (inf, Vec()))
     if (lambda == inf) 0.0
     else
       def g = normal ** light
       if (g >= 0) 0.0
       else
         def p = orig + lambda * dir + delta * normal
-        if ((intersect (p, -1 * light, scene, (inf,Vec()))) [0] < inf) 0.0
+        if ((scene.intersect (p, -1 * light, (inf,Vec()))) [0] < inf) 0.0
         else -g
 
   internal main (level : int, n : int) : void



More information about the svn mailing list