Skip to content
Rodrigo Botafogo edited this page May 1, 2013 · 17 revisions

MDArrays can be of the following types:

  • boolean, byte, short, int, long, float, double, string, structure.

To create a new MDArray one needs to inform at least the type and shape of the array. It is also possible to pass to the array factory initialization data, but this is not required. When no initialization data is provided, the array is initialized with 0. For instance, to create a byte array of shape [2, 2, 3] and all values equal to 0 (zero). No initialization data is given:

> require `mdarray`
> @a = MDArray.byte([2, 2, 3])

We can now check some basic informatin about array a:

Shape of the array:

> puts @a.shape
[2, 2, 3]

Number of dimensions:

> puts @a.ndim
3

Size of the array, the number of elements in it:

> puts @a.size
12

The type of the array:

> puts @a.dtype
"byte"

Accessing elements of an array is done by using [] to index the element.

> puts @a[0, 0, 0]
0

> puts @a[1, 1, 2]
0

Unlike Ruby arrays, an MDArray has a uniform and fixed type, so trying to add values from a different type in an MDArray will raise an exception. In this case a RuntimeError.

> a[0, 0, 0] = true
RuntimeError

Writing a double value on byte array will cast double to byte:

> a[0, 0, 0] = 10.25
> puts a[0, 0, 0]
10

> a[0, 0, 0] = 200
> puts a[0, 0, 0] 
-56

Now, lets build a "short" array. Both MDArray.build("short", ) or MDArray.short() can be used:

> short = MDArray.build("short", [2, 2, 3])

All other types can be build the same way:

> int = MDArray.int([5,5,5,5])

Now lets create a float array with some data:

> float = MDArray.float([2, 3], [0, 1, 2, 3, 4, 5, 6])

Note that the data is shaped according to the given shape, so, in this case the array is:

[[0.0 1.0 2.0]
 [3.0 4.0 5.0]]

Note also that although the initialization data is in "int" format the resulting array is of type float

> puts float.dtype
"float"

  assert_equal(1.0, b[0, 1])

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create arrays from arange functions" do 

  # use method arange to build an int array with a sequence of numbers
  # d = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
  d = MDArray.arange(15)
  counter = 0
  d.each do |elmt|
    assert_equal(counter, elmt)
    counter += 1
  end

  # with 2 arguments we have the begining and ending values for arange
  # e = [5 6 7 8 9 10 11 12 13 14]
  e = MDArray.arange(5, 15)
  counter = 5
  e.each do |elmt|
    assert_equal(counter, elmt)
    counter += 1
  end

  # with 3 arguments we have the begining, ending and step arguments
  # f = [10 15 20 25]
  f = MDArray.arange(10, 30, 5)
  counter = 10
  f.each do |elmt|
    assert_equal(counter, elmt)
    counter += 5
  end

  # typed_arange does the same as arange but for arrays of other type
  g = MDArray.typed_arange("double", 10, 30)

  # h = [10.0 12.5 15.0 17.5 20.0 22.5 25.0 27.5]
  h = MDArray.typed_arange("double", 10, 30, 2.5)
  counter = 10
  h.each do |elmt|
    assert_equal(counter, elmt)
    counter += 2.5
  end

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create array from fromfunction" do

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5]) do |x|
    x
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5, 5]) do |x, y|
    x + y
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [2, 3, 4]) do |x, y, z|
    3.21 * x + y + z
  end
  assert_equal("double", arr.type)
  assert_equal(0, arr[0, 0, 0])
  assert_equal(4.21, arr[1, 1, 0])

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("int", [2, 3, 4]) do |x, y, z|
    x + y + z
  end
  assert_equal("int", arr.type)

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5, 5, 5, 5]) do |x, y, z, k|
    x + y + z + k
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5, 5, 5, 5, 5]) do |x, y, z, k, w|
    x + y + z + k + w
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5, 5, 5, 5, 5, 5]) do |x, y, z, k, w, i|
    x + y + z + k + w + i
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  arr = MDArray.fromfunction("double", [5, 5, 5, 5, 5, 5, 5]) do |x, y, z, k, w, i, l|
    x + y + z + k + w + i + l
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  # Arrays with dimension larger than 7, the data is treated as an array, and we
  # cannot use the same notation as before.
  arr = MDArray.fromfunction("double", [5, 5, 5, 5, 5, 5, 5, 5]) do |x|
    x.inject(:+)
  end

  # creates an array from a function (actually a block).  The name fromfunction
  # is preserved to maintain API compatibility with NumPy (is it necessary?)
  # A similar notation as the array can be used for lower dimensions using ruby *
  # operator.  This is a little less efficient though.
  arr = MDArray.fromfunction("double", [5, 5, 5, 5, 5]) do |*x|
    x.inject(:+)
  end

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create array from arange" do

  arr = MDArray.arange(10)
  assert_equal("0 1 2 3 4 5 6 7 8 9 ", arr.to_string)
  arr = MDArray.arange(2, 30)
  assert_equal("2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ", 
               arr.to_string)
  arr = MDArray.arange(2, 30, 3)
  assert_equal("2 5 8 11 14 17 20 23 26 29 ", arr.to_string)
  # inconsistent result, better to use linspace
  arr = MDArray.arange(2, 30, 2.5)

end


#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create array from linspace" do

  arr = MDArray.linspace("double", 0, 2, 9)
  assert_equal(0.0, arr[0])
  assert_equal(0.5, arr[2])
  assert_equal(1.0, arr[4])
  assert_equal(1.5, arr[6])
  assert_equal(2.0, arr[8])

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create array with ones" do

  # creates an array with all 1's
  ones = MDArray.ones("byte", [2, 2, 2, 2])
  assert_equal(1, ones[1, 1, 1, 1])
  assert_equal(1, ones[1, 0, 1, 0])

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create array with given value" do

  # creates an array with a given value and type
  fives = MDArray.init_with("double", [3, 3], 5.34)
  assert_equal(5.34, fives[2, 1])
  assert_equal(5.34, fives[0, 2])

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "allow filling the array with data" do

  # fill b with a given value
  b = MDArray.double([2, 3], [0, 1, 2, 3, 4, 5])
  b.fill(5.47)
  b.each do |elmt|
    assert_equal(5.47, elmt)
  end

  # typed_arange does the same as arange but for arrays of other type
  g = MDArray.typed_arange("double", 6)
  g.reshape!([2, 3])
  b.fill(g)
  assert_equal(b.to_string, g.to_string)

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create boolean arrays" do

  bool = MDArray.boolean([2, 2])
  bool[0, 0] = true
  assert_raise ( RuntimeError ) { bool[0, 1] = 10.0 }
  assert_equal(bool[0, 0], true)
  bool[0, 1] = false
  assert_equal(bool[0, 1], false)

end

#-------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------

should "create string arrays" do

  sarray = MDArray.string([2, 3], ["hello", "this", "is", "a", "string", "array"])
  assert_equal(6, sarray.size)
  assert_equal("hello", sarray.get([0, 0]))
  assert_equal("hello this is a string array ", sarray.to_string)

end

#-------------------------------------------------------------------------------------
# A struct array is an array of pointers to structures
#-------------------------------------------------------------------------------------

should "create struct arrays" do

  m = Hash.new
  m[:hello] = "world"
  m[:test] = 1.23

  struct = MDArray.structure([10])
  struct[0] = m
  struct.print

end

Clone this wiki locally