def matrix_rank(m, tol:nil, driver:'svd')
    m = Numo::NArray.asarray(m)
    if m.ndim < 2
      m.ne(0).any? ? 1 : 0
    else
      case driver.to_s
      when /^(ge)?sdd$/, "turbo"
        s = Lapack.call(:gesdd, m, jobz:'N')[0]
      when /^(ge)?svd$/
        s = Lapack.call(:gesvd, m, jobu:'N', jobvt:'N')[0]
      else
        raise ArgumentError, "invalid driver: #{driver}"
      end
      tol ||= s.max(axis:-1, keepdims:true) *
        (m.shape[-2..-1].max * s.class::EPSILON)
      (s > tol).count(axis:-1)
    end
  end
def matrix_rank(m, tol:nil, driver:'svd')
    m = Numo::NArray.asarray(m)
    if m.ndim < 2
      m.ne(0).any? ? 1 : 0
    else
      case driver.to_s
      when /^(ge)?sdd$/, "turbo"
        s = Lapack.call(:gesdd, m, jobz:'N')[0]
      when /^(ge)?svd$/
        s = Lapack.call(:gesvd, m, jobu:'N', jobvt:'N')[0]
      else
        raise ArgumentError, "invalid driver: #{driver}"
      end
      tol ||= s.max(axis:-1, keepdims:true) *
        (m.shape[-2..-1].max * s.class::EPSILON)
      (s > tol).count(axis:-1)
    end
  end
Compute matrix rank of array using SVD
 *Rank* is the number of singular values greater than *tol*.

 @param m [Numo::NArray] matrix (>= 2-dimensional NArray)
 @param tol [Float] threshold below which singular values are
   considered to be zero. If *tol* is nil,
   `tol = sing_vals.max() * m.shape.max * EPSILON`.
 @param driver [String or Symbol] choose LAPACK solver from 'svd',
   'sdd'. (optional, default='svd')