konovod / linalg

Linear algebra library based on LAPACK

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add "arange" matrix creation

jtanderson opened this issue · comments

This would be useful for creating range-based matrices. The basic functionality is to take a start, end, and delta, and return a row-vector. This should probably mimic the numpy.arange interface.

Here is my first pass at adding this to the Matrix class:

    def self.arange(start_val : T, end_val : T, delta = 1.0)
      unless (end_val - start_val).sign == delta.sign && delta.abs > 0
        raise IndexError.new("Range #{start_val}...#{end_val} invalid with step size #{delta}")
      end
      GeneralMatrix(T).new(1, ((end_val - start_val).abs.ceil / delta.abs).ceil.to_i) do |i,j|
        start_val + j*delta
      end
    end

One complaint I have with this code so far is that if you do Matrix.arange(5,4,1) it will return [[5]] instead of a {1,0} matrix. It's a matter of adding some extra edge-cases, but I'd like to clean it up to avoid clutter.

Update: after reading/experimenting with numpy.arange, this version follows it more closely, and is a bit friendlier in general:

    def self.arange(start_val : T, end_val : T, delta = 1.0)
      return GeneralMatrix(T).new(1,0) unless (end_val - start_val).sign == delta.sign && delta.abs > 0
      GeneralMatrix(T).new(1, ((end_val - start_val).abs.ceil / delta.abs).ceil.to_i) do |i,j|
        start_val + j*delta
      end
    end

One departure from numpy.arange is that if delta: 0 then an empty row will be returned. The numpy version just allows the inner division throw a ZeroDivisionError exception.

I have this code ready with tests and can submit a pull-request is anybody is around to approve!