abstract class Bottle::BaseArray(T)

Included Modules

Direct Known Subclasses

Defined in:

base/base.cr

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(buffer : Pointer(T), shape : Array(Int32), strides : Array(Int32), flags : Bottle::Internal::ArrayFlags, base : Pointer(T) | Nil, update_flags = true) #

Internal method to create tensors from low level libraries. This does no validation on inputs and is very unsafe unless called by the library.

Should not be used by the external API.


[View source]
def self.new(_shape : Array(Int32), order : ArrayFlags = ArrayFlags::Contiguous, ptr : Pointer(T) | Nil = nil) #

[View source]
def self.new(shape : Array(Int32), order : ArrayFlags = ArrayFlags::Contiguous, &block : Int32 -> T) #

Yields a BaseArray from a provided shape and a block. The block only provides the absolute index, not an index dependent on the shape, so if a user wants to handle an arbitrary shape inside the block they need to do that themselves.

t = BaseArray.new([2, 2, 3]) { |i| i / 2 }
t # =>
Base([[[ 0,  1],
       [ 2,  3]],

      [[ 4,  5],
       [ 6,  7]],

      [[ 8,  9],
       [10, 11]]])

[View source]
def self.new(nrows : Int32, ncols : Int32, &block : Int32, Int32 -> T) #

Yields a Tensor from a provided number of rows and columns. This can quickly create matrices, useful for several Tensor creattion methods such as the underlying implementation of eye, and diag.

This method does provide i and j variables for the passed block, so no offset calculations need to be done by the user.

t = Tensor.new(3, 3) { |i, j| i == j ? 1 : 0 }
t # =>
Tensor([[1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])

[View source]

Class Method Detail

def self.from_array(array : Array) #

[View source]

Instance Method Detail

def [](mask : Tensor(Bool)) #

[View source]
def [](*args) #

Returns a view of a NTensor from a list of indices or ranges.

t = BaseArray.new([2, 4, 4]) { |i| i }

[View source]
def []=(idx : Array, assign : BaseArray(T)) #

Assigns a Tensor to a slice of an array. The provided tensor must be the same shape as the slice in order for this method to work.

t = Tensor.new([3, 2, 2]) { |i| i }
t[[1]] = Tensor.new([2, 2]) { |i| i * 20 }
t # =>
Tensor([[[ 0,  1],
         [ 2,  3]],

        [[ 0, 20],
         [40, 60]],

        [[ 8,  9],
         [10, 11]]])

[View source]
def []=(*args : *U) forall U #

[View source]
def accumulate_along_axis(axis, &) #

[View source]
def aref_set(*args, value : Tensor(T)) #

Assigns a Tensor to a slice of an array. The provided tensor must be the same shape as the slice in order for this method to work.

t = Tensor.new([3, 2, 2]) { |i| i }
t[[1]] = Tensor.new([2, 2]) { |i| i * 20 }
t # =>
Tensor([[[ 0,  1],
         [ 2,  3]],

        [[ 0, 20],
         [40, 60]],

        [[ 8,  9],
         [10, 11]]])

[View source]
def aref_set(*args, value : Number) #

Assigns a scalar value to a slice of a Tensor. The value is tiled along the entire slice.

t = Tensor.new([2, 2, 3]) { |i| i }
t[[1]] = 99
t #=>
Tensor([[[ 0,  1],
         [ 2,  3]],

        [[99, 99],
         [99, 99]],

        [[99, 99],
         [99, 99]]])

[View source]
def as_strided(shape, strides, writeable = false) #

as_strided creates a view into the array given the exact strides and shape. This means it manipulates the internal data structure of a Tensor and, if done incorrectly, the array elements can point to invalid memory and can corrupt results or crash your program. It is advisable to always use the original x.strides when calculating new strides to avoid reliance on a contiguous memory layout.

Furthermore, arrays created with this function often contain self overlapping memory, so that two elements are identical. Vectorized write operations on such arrays will typically be unpredictable. They may even give different results for small, large, or transposed arrays. Since writing to these arrays has to be tested and done with great care, you may want to use writeable=false to avoid accidental write operations.


[View source]
def astype(dtype : U.class) forall U #

[View source]
def base #

[View source]
abstract def basetype #

[View source]
def bc?(axis : Int32) #

[View source]
def broadcast_to(newshape) #

[View source]
def broadcastable(other : BaseArray) #

[View source]
def buffer #

[View source]
def bytesize #

[View source]
abstract def check_type #

[View source]
def diag_view #

Returns a view of the diagonal of a Tensor only valid if the Tensor has two dimensions. Offsets are not supported.

t = Tensor.new([3, 3]) { |i| i }
t.diag_view # => Tensor([0, 4, 8])

[View source]
def dtype #

[View source]
def dup(order : Char | Nil = nil) forall U #

Duplicates a Tensor, respecting the passed order of memory provided. Useful for throwing Tensors down to LAPACK since they must be in Fortran style order

t = B.arange(5)
t.dup # => Tensor([0, 1, 2, 3, 4])

[View source]
def dup_view #

Shallow copies the Tensor. Shape and strides are copied, but the underlying data is not. The returned Tensor does not own its own data, and its base reflects that.


[View source]
def flags #

[View source]
def flat_iter #

[View source]
def index_iter #

[View source]
def is_contiguous #

Asserts if a Tensor is c contiguous, otherwise known as stored in row major order. This is the default memory storage for NDArray


[View source]
def is_fortran_contiguous #

Asserts if a Tensor is fortran contiguous, otherwise known as stored in column major order. This is not the default layout for Tensor's, but can provide performance benefits when passing to LaPACK routines since otherwise the Tensor must be transposed in memory.


[View source]
def nbytes #

Total number of bytes taken up by items in the Tensors data buffer.


[View source]
def ndims #

[View source]
def ravel #

Flatten an array, returning a view if possible. If the array is either fortran or c-contiguous, a view will be returned,

otherwise, the array will be reshaped and copied.


[View source]
def reduce_along_axis(axis, &) #

[View source]
def reshape(newshape : Array(Int32)) #

Fits a Tensor into a new shape, not altering memory if possible. However, the Tensor is usually copied.

t = Tensor.new([2, 4, 3]])

t.reshape([2, 2, 2, 3]) # =>
Tensor([[[[ 0,  1,  2],
          [ 6,  7,  8]],

         [[ 3,  4,  5],
          [ 9, 10, 11]]],


        [[[12, 13, 14],
          [18, 19, 20]],

         [[15, 16, 17],
          [21, 22, 23]]]])

[View source]
def shape #

[View source]
def shape=(shape : Array(Int32)) #

[View source]
def size #

[View source]
def slice(idx : Array(Int32 | Range(Int32, Int32))) #

Slices a Tensor from an array of integers or ranges Primarily used when you can't pass *args to the index method but still need the functionality.

t = Tensor.new([2, 2, 3]) { |i| i }
t.slice([0, 0...1, 0...2]) #=>
Tensor([[0, 1]])

[View source]
def strides #

[View source]
def strides=(strides : Array(Int32)) #

[View source]
def to_s(io) #

[View source]
def transpose(order : Array(Int32) = [] of Int32) #

Permute the dimensions of a Tensor. If no order is provided, the dimensions will be reversed, a "true transpose". Otherwise, the dimensions will be permutated in the order provided.

t = Tensor.new([2, 4, 3]) { |i| i }
t.transpose([2, 0, 1])
Tensor([[[ 0,  3,  6,  9],
         [12, 15, 18, 21]],

        [[ 1,  4,  7, 10],
         [13, 16, 19, 22]],

        [[ 2,  5,  8, 11],
         [14, 17, 20, 23]]])

[View source]
def unsafe_iter #

[View source]
def value #

[View source]
def view(dtype : U.class) forall U #

[View source]