# FlexLinearAlgebra

A typical vector is indexed by integers 1, 2, 3, ..., n. The goal of this package is to create vectors (and eventually matrices) with arbitrary index sets.

## The FlexVector

A FlexVector behaves much like a linear algebra vector, but the index set can be arbitrary. A new, all zero-valued vector is created by calling FlexVector(dom) where dom is the index set. This can be any iterable Julia object (such as an Array, Set, etc.). By default, the zero values in this vector are of type Float64, but one can also invoke FlexVector{Int}(dom) and the resulting vector's values are Ints.

julia> using FlexLinearAlgebra

julia> v = FlexVector(4:7)
FlexVector{Int64,Float64}:
4 => 0.0
5 => 0.0
6 => 0.0
7 => 0.0

julia> w = FlexVector{Int}([1,3,5])
FlexVector{Int64,Int64}:
1 => 0
3 => 0
5 => 0

julia> dom = ["alpha", "bravo", "charlie"]
3-element Array{String,1}:
"alpha"
"bravo"
"charlie"

julia> FlexVector{Complex}(dom)
FlexVector{String,Complex}:
alpha => 0 + 0im
bravo => 0 + 0im
charlie => 0 + 0im


The function FlexOnes can be used to generate a vector of all ones. Use either FlexOnes(dom) or FlexOnes(T,dom) like this:

julia> FlexOnes(3:5)
FlexVector{Int64,Float64}:
3 => 1.0
4 => 1.0
5 => 1.0

julia> FlexOnes(Complex,3:5)
FlexVector{Int64,Complex}:
3 => 1 + 0im
4 => 1 + 0im
5 => 1 + 0im


The function FlexConvert converts an ordinary Vector into a FlexVector. The index set for the result is 1,2,...,n where n is the length of the vector.

julia> FlexConvert([1-2im,2+3im])
FlexVector{Int64,Complex{Int64}}:
1 => 1 - 2im
2 => 2 + 3im


### Accessing elements of a FlexVector

The values held in a FlexVector may be accessed and modified using the usual Julia square-bracket notation:

julia> v[4]=7
7

julia> v
FlexVector{Int64,Float64}:
4 => 7.0
5 => 0.0
6 => 0.0
7 => 0.0


The indices for a FlexVectorv can be recovered using keys(v).

To delete an entry from a FlexVector use delete_entry!(v,k) where k is the index of the entry to be deleted.

Note: It is not an error to access a key that is undefined for a given vector. Even if k is not a key, one may assign to v[k], in which case the vector is modified to include that value. One may also look up the value v[k] in which case zero is returned and the vector is not modified.

### Convert to a Julia Vector

If v is a FlexVector, then Vector(v) converts v into a Julia vector. The keys are lost and we simply have the values of v placed into a one-dimensional array.

## Vector arithmetic

Vector addition/subtraction and scalar multiplication are supported. If the domains of the two vectors are not the same, the resulting vector's domain is the union of the two domains. For example:

julia> v = FlexOnes(Complex{Int},1:4)
FlexVector{Int64,Complex{Int64}}:
1 => 1 + 0im
2 => 1 + 0im
3 => 1 + 0im
4 => 1 + 0im

julia> w = FlexOnes(3:6)
FlexVector{Int64,Float64}:
3 => 1.0
4 => 1.0
5 => 1.0
6 => 1.0

julia> v+w
FlexVector{Int64,Complex{Float64}}:
1 => 1.0 + 0.0im
2 => 1.0 + 0.0im
3 => 2.0 + 0.0im
4 => 2.0 + 0.0im
5 => 1.0 + 0.0im
6 => 1.0 + 0.0im


Notice that the two domains overlap at keys 2 and 3, so the result of the addition at those values is 2.0 + 0.0im. At other keys, there's a tacit zero value taken from the vector that does not have that key.

The sum of the entries in a vector can be computed with sum(v). The dot product of two vectors is computed with dot. If v contains complex values, then dot(v,w) conjugates the values in v.

julia> v
FlexVector{Int64,Float64}:
1 => 2.0
2 => 4.0

julia> w
FlexVector{Int64,Float64}:
1 => 3.0
2 => 5.0

julia> dot(v,w)
26.0

julia> v = FlexConvert([1-2im,2+3im])
FlexVector{Int64,Complex{Int64}}:
1 => 1 - 2im
2 => 2 + 3im

julia> w = FlexConvert([-3im,5+2im])
FlexVector{Int64,Complex{Int64}}:
1 => 0 - 3im
2 => 5 + 2im

julia> dot(v,w)
22 - 14im

julia> dot(w,v)
22 + 14im


## The FlexMatrix

A FlexMatrix is the 2-dimensional analogue of a FlexVector. Important functions include:

• Arithmetic: Addition, subtraction, and multiplication (scalar, matrix-matrix, and matrix-vector).
• Indexing: Usual A[i,j] notation. Also see row_keys and col_keys to get a list for the row/column names.
• FlexConvert to convert a Julia matrix into a FlexMatrix.
• Matrix(A) to convert a FlexMatrixA into a Julia matrix.
• delete_row!(A,r) and delete_col!(A,c) are used to delete the line of A specified.

Note that assigning to a matrix A[i,j]=x will not fail. The set of row and column names will simply be expanded and extra slots filled with zeros.

Can't seem to get .* multiplication working.