Skip to content
John Prince edited this page Dec 10, 2010 · 5 revisions

Rough documentation of the behavior of Masahiro Tanaka's redesign of NArray. Right now, this code is highly experimental and expected to change.

NArray is now housed under the Num module. The rest of this document will refer to the Num library rather than NArray so there is no confusion as to which version I am referring to. Focus will be on new features, but also how Num differs from NArray.

ATTRIBUTION: most code examples are copied or modified from Masahiro Tanaka's test suite.

Indexing

Index order

By default, Num follows the indexing order convention of Matlab, Numpy, C, Ruby Matrix and Ruby multidimensional arrays (opposite NArray, PDL, and Fortran). This is a good thing for consistency.

  >> x = Num::Int32.new([2,3]).seq
  => Num::Int32#shape=[2,3]:
  [[0, 1, 2], 
   [3, 4, 5]]
  >> x[0,2]
  => 2
  >> x[1,2]
  => 5
  # same order as a ruby multidimensional array:
  a = [[0,1,2],
       [3,4,5]]
  a[1][2]  # => 5
  # same order as a ruby Matrix
  require 'matrix'
  b = Matrix[[0,1,2],[3,4,5]] ;
  b[1,2]   # => 5

Numpy style indexing with a string

The format is simple, 'start:stop:step'

  >> a = Num::DFloat.new([5,5]).seq
  => Num::DFloat#shape=[5,5]:
  [[0, 1, 2, 3, 4], 
   [5, 6, 7, 8, 9], 
   [10, 11, 12, 13, 14], 
   [15, 16, 17, 18, 19], 
   [20, 21, 22, 23, 24]]
  >> a['1:3,::2']
  => Num::DFloat#shape=[3,3]:
  [[5, 7, 9], 
   [10, 12, 14], 
   [15, 17, 19]]
  >> a['1:3,1::2']
  => Num::DFloat#shape=[3,2]:
  [[6, 8], 
   [11, 13], 
   [16, 18]]
  >> a['1:3,:']
  => Num::DFloat#shape=[3,5]:
  [[5, 6, 7, 8, 9], 
   [10, 11, 12, 13, 14], 
   [15, 16, 17, 18, 19]]

Shallow copy when indexing

NArray makes a deep copy upon indexing, but Num makes a shallow copy (like Numpy) when indexing:

  >> a = Num::DFloat.new([5,5]).seq
  => Num::DFloat#shape=[5,5]:
  [[0, 1, 2, 3, 4], 
   [5, 6, 7, 8, 9], 
   [10, 11, 12, 13, 14], 
   [15, 16, 17, 18, 19], 
   [20, 21, 22, 23, 24]]
  >> b = a['1:3,::2']
  => Num::DFloat#shape=[3,3]:
  [[5, 7, 9], 
   [10, 12, 14], 
   [15, 17, 19]]
  >> b.fill(10000)
  => Num::DFloat#shape=[3,3]:
  [[10000, 10000, 10000], 
   [10000, 10000, 10000], 
   [10000, 10000, 10000]]
  >> a
  => Num::DFloat#shape=[5,5]:
  [[0, 1, 2, 3, 4], 
   [10000, 6, 10000, 8, 10000], 
   [10000, 11, 10000, 13, 10000], 
   [10000, 16, 10000, 18, 10000], 
   [20, 21, 22, 23, 24]]

Custom types

Num allows the definition of custom types. A serious feature.

  Hoge = Num::NStruct.new() do |m|
    add_type(Num::DFloat, :f64)
    add_type(Num::Int32, :i32)
  end
  Hoge.byte_size  # => 12
  x = Hoge.new([3,4])
  x.byte_size   # => 144
  >> x.definition(0)
  => [:f64, Num::DFloat, 0, 8]
  >> x.definition(:f64)
  => [:f64, Num::DFloat, 0, 8]
  >> x.definition(1)
  => [:i32, Num::Int32, 8, 4]
  >> x.definitions
  => [[:f64, Num::DFloat, 0, 8], [:i32, Num::Int32, 8, 4]]
  >> x.field(:f64).seq.inplace * 2.4 + 0.5
  => Num::DFloat#shape=[3,4]:
  [[0.5, 2.9, 5.3, 7.7], 
   [10.1, 12.5, 14.9, 17.3], 
   [19.7, 22.1, 24.5, 26.9]]
  >> x.field(:i32).seq.inplace * 2 + 3
  => Num::Int32#shape=[3,4]:
  [[3, 5, 7, 9], 
   [11, 13, 15, 17], 
   [19, 21, 23, 25]]
  >> x[0,1].field(:f64)
  => Num::DFloat#shape=[]:
  (scalar)2.9
  >> x[0,1].field(:i32)
  => Num::Int32#shape=[]:
  (scalar)5