docs: def ctimes(*args):
      '''
      ctimes(a, b...) returns the product of all the values as a numpy array object. Like numpy's
        multiply function or a*b syntax, times will thread over the latest dimension possible; thus
        if a.shape is (4,2) and b.shape is 2, times(a,b) is a equivalent to a * b.
  
      Unlike numpy's multiply function, ctimes works with sparse matrices and will reify them.
      '''
      n = len(args)
      if   n == 0: return np.asarray(0)
      elif n == 1: return np.asarray(args[0])
      elif n >  2: return reduce(plus, args)
      (a,b) = args
      if   sps.issparse(a): return a.multiply(b)
      elif sps.issparse(b): return b.multiply(a)
      else:                 return np.asarray(a) * b