diff --git a/common.scad b/common.scad
index 6f4bcfc..30c96fa 100644
--- a/common.scad
+++ b/common.scad
@@ -100,6 +100,21 @@ function is_list_of(list,pattern) =
 	[]==[for(entry=list) if (entry*0 != pattern) entry];
 
 
+// Function: is_consistent()
+// Usage:
+//   is_consistent(list)
+// Description:
+//   Tests whether input is a list of entries which all have the same list structure
+//   and are filled with finite numerical data.
+// Example:
+//   is_consistent([3,4,5]);              // Returns true
+//   is_consistent([[3,4],[4,5],[6,7]]);  // Returns true
+//   is_consistent([[3,4,5],[3,4]]);      // Returns false
+//   is_consistent([[3,[3,4,[5]]], [5,[2,9,[9]]]]); // Returns true
+//   is_consistent([[3,[3,4,[5]]], [5,[2,9,9]]]);   // Returns false
+function is_consistent(list) =
+  is_list(list) && is_list_of(list, list[0]);
+
 
 // Section: Handling `undef`s.
 
diff --git a/coords.scad b/coords.scad
index 500949e..695cfd8 100644
--- a/coords.scad
+++ b/coords.scad
@@ -22,13 +22,19 @@ function point2d(p, fill=0) = [for (i=[0:1]) (p[i]==undef)? fill : p[i]];
 
 // Function: path2d()
 // Description:
-//   Returns a list of 2D vectors/points from a list of 2D or 3D vectors/points.
-//   If given a 3D point list, removes the Z coordinates from each point.
+//   Returns a list of 2D vectors/points from a list of 2D, 3D or higher
+//   dimensional vectors/points. Removes the extra coordinates from
+//   higher dimensional points.  The input must be a path, where
+//   every vector has the same length.  
 // Arguments:
 //   points = A list of 2D or 3D points/vectors.
 //   fill = Value to fill missing values in vectors with.
-function path2d(points, fill=0) = [for (point = points) point2d(point, fill=fill)];
-
+function path2d(points) =
+   assert(is_path(points,dim=undef,fast=true),"Input to path2d is not a path")
+   let (result = points * concat(ident(2), replist([0,0], len(points[0])-2)))
+   assert(is_def(result), "Invalid input to path2d")
+   result;
+                                                                     
 
 // Function: point3d()
 // Description:
@@ -41,11 +47,22 @@ function point3d(p, fill=0) = [for (i=[0:2]) (p[i]==undef)? fill : p[i]];
 
 // Function: path3d()
 // Description:
-//   Returns a list of 3D vectors/points from a list of 2D or 3D vectors/points.
+//   Returns a list of 3D vectors/points from a list of 2D or higher dimensional vectors/points
+//   by removing extra coordinates or adding the z coordinate.  
 // Arguments:
-//   points = A list of 2D or 3D points/vectors.
-//   fill = Value to fill missing values in vectors with.
-function path3d(points, fill=0) = [for (point = points) point3d(point, fill=fill)];
+//   points = A list of 2D, 3D or higher dimensional points/vectors.
+//   fill = Value to fill missing values in vectors with (in the 2D case)
+function path3d(points, fill=0) =
+   assert(is_num(fill))
+   assert(is_path(points, dim=undef, fast=true), "Input to path3d is not a path")
+   let (
+      change = len(points[0])-3,
+      M = change < 0 ? [[1,0,0],[0,1,0]] : 
+                       concat(ident(3), replist([0,0,0],change)),
+      result = points*M
+   )
+   assert(is_def(result), "Input to path3d is invalid")
+   fill == 0 || change>=0 ? result : result + replist([0,0,fill], len(result));
 
 
 // Function: point4d()
@@ -63,7 +80,24 @@ function point4d(p, fill=0) = [for (i=[0:3]) (p[i]==undef)? fill : p[i]];
 // Arguments:
 //   points = A list of 2D or 3D points/vectors.
 //   fill = Value to fill missing values in vectors with.
-function path4d(points, fill=0) = [for (point = points) point4d(point, fill=fill)];
+
+function path4d(points, fill=0) = 
+   assert(is_num(fill) || is_vector(fill))
+   assert(is_path(points, dim=undef, fast=true), "Input to path4d is not a path")
+   let (
+      change = len(points[0])-4,
+      M = change < 0 ? select(ident(4), 0, len(points[0])-1) :
+                       concat(ident(4), replist([0,0,0,0],change)),
+      result = points*M
+   ) 
+   assert(is_def(result), "Input to path4d is invalid")
+   fill == 0 || change >= 0 ? result :
+    let(
+      addition = is_list(fill) ? concat(0*points[0],fill) :
+                                 concat(0*points[0],replist(fill,-change))
+    )
+    assert(len(addition) == 4, "Fill is the wrong length")
+    result + replist(addition, len(result));
 
 
 // Function: translate_points()
diff --git a/math.scad b/math.scad
index 2733f06..f0637a7 100644
--- a/math.scad
+++ b/math.scad
@@ -432,9 +432,11 @@ function lcm(a,b=[]) =
 // Example:
 //   sum([1,2,3]);  // returns 6.
 //   sum([[1,2,3], [3,4,5], [5,6,7]]);  // returns [9, 12, 15]
-function sum(v, dflt=0, _i=0, _acc) =
-	_i>=len(v)? (len(v)? _acc : dflt) :
-	sum(v, dflt=dflt, _i=_i+1, _acc=is_undef(_acc)? v[_i] : _acc+v[_i]);
+function sum(v, dflt=0) =
+    assert(is_consistent(v), "Input to sum is non-numeric or inconsistent")
+    len(v) == 0 ? dflt : _sum(v,v[0]*0);
+
+function _sum(v,_total,_i=0) = _i>=len(v) ? _total : _sum(v,_total+v[_i], _i+1);
 
 
 // Function: cumsum()
diff --git a/paths.scad b/paths.scad
index b4d6889..c496723 100644
--- a/paths.scad
+++ b/paths.scad
@@ -20,6 +20,8 @@ include <BOSL2/triangulation.scad>
 // Description:
 //   Returns true if `list` is a path.  A path is a list of two or more numeric vectors (AKA points).
 //   All vectors must of the same size, and may only contain numbers that are not inf or nan.
+//   By default the vectors in a path must be 2d or 3d.  Set the `dim` parameter to specify a list
+//   of allowed dimensions, or set it to `undef` to allow any dimension.  
 // Examples:
 //   is_path([[3,4],[5,6]]);    // Returns true
 //   is_path([[3,4]]);          // Returns false
@@ -35,6 +37,7 @@ include <BOSL2/triangulation.scad>
 //   is_path([[3,4],"hello"], fast=true); // Returns true
 //   is_path([[3,4],[3,4,5]]);            // Returns false
 //   is_path([[1,2,3,4],[2,3,4,5]]);      // Returns false
+//   is_path([[1,2,3,4],[2,3,4,5]],undef);// Returns true
 // Arguments:
 //   list = list to check
 //   dim = list of allowed dimensions of the vectors in the path.  Default: [2,3]