#
# = Tensor manipulations
# The tensor library is developed by J. Burguet and distributed
# as an add-on package of GSL. See {here}[https://sourceware.org/ml/gsl-discuss/2004-q4/msg00053.html] and {here}[https://sourceware.org/ml/gsl-discuss/2004-q4/msg00055.html].
#
# == Class methods
# ---
# * GSL::Tensor.new(rank, dimention)
# * GSL::Tensor.alloc(rank, dimention)
# * GSL::Tensor[rank, dimention]
#
#   Create a tensor of rank <tt>rank</tt> and dimension <tt>dimention</tt>.
#
# ---
# * GSL::Tensor.calloc(rank, dimention)
#
#   Creates a tensor of rank <tt>rank</tt> and dimension <tt>dimention</tt>,
#   and initializes all the elements to zero.
#
# ---
# * GSL::Tensor.copy(tensor)
#
#   Create a tensor copying the existing tensor <tt>tensor</tt>.
#
# ---
# * GSL::Tensor.memcpy(dest, src)
#
#   Copies the tensor <tt>src</tt> to another <tt>dest</tt>. The two
#   tensors must have the same shape.
#
# ---
# * GSL::Tensor.swap(a, b)
#
#   Exchanges the elements of the tensor <tt>a</tt> and <tt>b</tt>.
#
# == Instance methods
# === Accessing tensor elements
# ---
# * GSL::Tensor#set_zero
#
#   Sets all the element of the tensor <tt>self</tt> to zero.
# ---
# * GSL::Tensor#set_all(x)
#
#   Sets all the element of the tensor <tt>self</tt> to <tt>x</tt>.
# ---
# * GSL::Tensor#set(indices, x)
# * \GSL::Tensor#[indices]=x
#
#   Sets the element of the given indices to <tt>x</tt>.
#
# ---
# * GSL::Tensor#get(indices)
# * \GSL::Tensor#[indices]
#
#   Returns the tensor element. If the number of indices given is smaller than the
#   rank of the tensor, the method GSL::Tensor#subtensor is called.
#
#   Ex:
#       >> t = Tensor.new(2, 3)
#       => #<GSL::Tensor:0x762ae8>
#       >> t.set(1, 2, 2, 123)
#       => #<GSL::Tensor:0x762ae8>
#       >> t.get(1, 2, 2)
#       => 123.0
#       >> t[0, 0, 2] = 456
#       => 456
#       >> t[0, 0, 2]
#       => 456.0
#
# ---
# * GSL::Tensor#subtensor(indices)
# * \GSL::Tensor#[indices]
#
#   Return a subtensor.
#
#   Ex:
#       >> require("gsl")
#       => true
#       >> t = Vector[1..125].to_tensor(3, 5)
#       => GSL::Tensor:
#       [ 1.000e+00 2.000e+00 3.000e+00 4.000e+00 5.000e+00 6.000e+00 7.000e+00 ... ]
#       >> t[0]
#       => GSL::Tensor::View:
#       [ 1.000e+00 2.000e+00 3.000e+00 4.000e+00 5.000e+00
#         6.000e+00 7.000e+00 8.000e+00 9.000e+00 1.000e+01
#         1.100e+01 1.200e+01 1.300e+01 1.400e+01 1.500e+01
#         1.600e+01 1.700e+01 1.800e+01 1.900e+01 2.000e+01
#         2.100e+01 2.200e+01 2.300e+01 2.400e+01 2.500e+01 ]
#       >> t[0,2]
#       => GSL::Tensor::View:
#       [ 1.100e+01 1.200e+01 1.300e+01 1.400e+01 1.500e+01 ]
#       >> t[3,1]
#       => GSL::Tensor::View:
#       [ 8.100e+01 8.200e+01 8.300e+01 8.400e+01 8.500e+01 ]
#       >> t[1][2]
#       => GSL::Tensor::View:
#       [ 3.600e+01 3.700e+01 3.800e+01 3.900e+01 4.000e+01 ]
#
# ---
# * GSL::Tensor#swap_indices(i, j)
# * GSL::Tensor#data
#
#   Returns the data as <tt>GSL::Vector::View</tt>.
# ---
# * GSL::Tensor#to_v
#
#   Creates a new vector from the tensor.
#
# ---
# * GSL::Tensor#to_vector
#
#   Converts the tensor of rank 1 into a <tt>GSL::Vector::View</tt> object.
# ---
# * GSL::Tensor#to_matrix
#
#   Converts the tensor of rank 2 into a <tt>GSL::Matrix::View</tt> object.
#
# === IO
# ---
# * GSL::Tensor#fwrite(io)
# * GSL::Tensor#fwrite(filename)
# * GSL::Tensor#fread(io)
# * GSL::Tensor#fread(filename)
# * GSL::Tensor#fprintf(io, format="%g")
# * GSL::Tensor#fprintf(filename, format="%g")
# * GSL::Tensor#fscanf(io)
# * GSL::Tensor#fscanf(filename)
#
#
# === Max, min
# ---
# * GSL::Tensor#max
# * GSL::Tensor#min
# * GSL::Tensor#minmax
# * GSL::Tensor#max_index
# * GSL::Tensor#min_index
# * GSL::Tensor#minmax_index
#
#
# === Tensor operations
# ---
# * GSL::Tensor#add(b)
# * GSL::Tensor#+(b)
#
#   Creates a new tensor adding two tensors <tt>self</tt> and <tt>b</tt>.
# ---
# * GSL::Tensor#add!(b)
#
#   Adds the element of tensor <tt>b</tt> to the elements of <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#sub(b)
# * GSL::Tensor#+(b)
#
#   Creates a new tensor subtracting the tensors <tt>b</tt> from <tt>self</tt>.
# ---
# * GSL::Tensor#sub!(b)
#
#   Subtracts the element of tensor <tt>b</tt> from the elements of <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#mul_elements(b)
#
#   This calculate element-by-element multiplication of <tt>self</tt> and <tt>b</tt>,
#   and returns a new tensor.
# ---
# * GSL::Tensor#mul_elements!(b)
#
#   Multiplies the elements of tensor <tt>self</tt> to the elements of <tt>b</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#div_elements(b)
# * GSL::Tensor#/(b)
#
#   This calculate element-by-element division of <tt>self</tt> and <tt>b</tt>,
#   and returns a new tensor.
#   Multiplies the elements of tensor <tt>b</tt> to the elements of <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#div_elements!(b)
#
#   Divides the elements of tensor <tt>self</tt> to the elements of <tt>b</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#add_constant(x)
#
#   Creates a new tensor adding the constant <tt>x</tt> to the tensor <tt>self</tt>.
# ---
# * GSL::Tensor#add_constant!(x)
#
#   Adds the constant <tt>x</tt> to the elements of tensor <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#scale(x)
#
#   Creates a new tensor scaling the tensor <tt>self</tt> by the constant <tt>x</tt>.
# ---
# * GSL::Tensor#scale!(x)
#
#   Multiplies the constant <tt>x</tt> to the elements of tensor <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#add_diagonal(x)
#
#   Creates a new tensor adding the constant <tt>x</tt> to the diagonal elements
#   of the tensor <tt>self</tt>.
# ---
# * GSL::Tensor#add_diagonal!(x)
#
#   Adds the constant <tt>x</tt> to the diagonal elements of tensor <tt>self</tt> , <tt>in-place</tt>.
# ---
# * GSL::Tensor#product(b)
# * GSL::Tensor#*(b)
#
#   Calculate tensorian product of <tt>self</tt> and <tt>b</tt>.
# ---
# * GSL::Tensor#contract(i, j)
#
#
# ---
# * GSL::Tensor#equal?(b, eps = 1e-10)
# * GSL::Tensor#==(b)
#
#   Returns <tt>true</tt> if the tensors have same size and elements
#   equal to absolute accurary <tt>eps</tt> for all the indices,
#   and <tt>false</tt> otherwise.
#
# === Tensor properties
# ---
# * GSL::Tensor#isnull
#
#   Returns 1 if all the elements of the tensor are zero, and 0 otherwise.
# ---
# * GSL::Tensor#isnull?
#
#   Returns <tt>true</tt> if all the elements of the tensor are zero, and <tt>false</tt> otherwise.
#
# ---
# * GSL::Tensor#rank
#
#   Returns the rank
# ---
# * GSL::Tensor#dimension
#
#   Returns the dimension
# ---
# * GSL::Tensor#size
#
#   Returns the size
#
# {prev}[link:rdoc/rng_rdoc.html#label-Random+number+generator+initialization]
# {next}[link:rdoc/narray_rdoc.html]
#
# {Reference index}[link:rdoc/ref_rdoc.html]
# {top}[link:index.html]
#
#
