///| One uniform Loop step, using the old mesh for every stencil.

///|
/// The result owns new storage and retains the original mesh's configured limits.
pub fn Mesh::loop_step(self : Mesh) -> Mesh raise SurfaceError {
  if self.limits.max_levels < 1 {
    raise LimitExceeded("Loop levels")
  }
  let count = self.vertex_count() + self.edge_count()
  if count > self.limits.max_vertices {
    raise LimitExceeded("Loop vertices")
  }
  if self.face_count() * 4 > self.limits.max_output_faces {
    raise LimitExceeded("Loop faces")
  }
  let boundary : Array[(Int, Int)?] = Array::make(self.vertex_count(), None)
  for ring in self.boundary_loops() {
    let n = ring.length()
    for i, v in ring {
      boundary[v] = Some((ring[(i + n - 1) % n], ring[(i + 1) % n]))
    }
  }
  let positions : Array[Vec3] = []
  for v in 0.. [(v, 0.75), (a, 0.125), (b, 0.125)]
      None => {
        let n = self.degrees[v]
        let c = 0.375 + 0.25 * @math.cos(6.283185307179586 / n.to_double())
        let beta = (0.625 - c * c) / n.to_double()
        let entries = [(v, 1.0 - n.to_double() * beta)]
        for other in self.neighbors(v) {
          entries.push((other, beta))
        }
        entries
      }
    }
    positions.push(weighted_position(self.vertices, stencil))
  }
  for e in 0.. Vec3 {
  let mut scale = 0.0
  for (v, _) in stencil {
    let p = points[v]
    scale = Double::max(
      scale,
      Double::max(abs(p.x), Double::max(abs(p.y), abs(p.z))),
    )
  }
  if scale == 0.0 {
    return { x: 0.0, y: 0.0, z: 0.0, }
  }
  let mut x = 0.0
  let mut y = 0.0
  let mut z = 0.0
  for (v, weight) in stencil {
    x += points[v].x / scale * weight
    y += points[v].y / scale * weight
    z += points[v].z / scale * weight
  }
  // Roundoff cannot move a convex combination beyond the input coordinate bound.
  {
    x: Double::max(-1.0, Double::min(1.0, x)) * scale,
    y: Double::max(-1.0, Double::min(1.0, y)) * scale,
    z: Double::max(-1.0, Double::min(1.0, z)) * scale,
  }
}