top of page

CVector

The CVector object represents a real dense vector that is backed by a primitive double Java array. Because the vector is backed by a Java array of Complex128's, the elements of the vector are stored contiguously in memory and uses zero-based indexing. CVector's may have undesirable cache performance as the backing array is an object array which will contain references to the objects locations in the heap (this will likely change in a future release when value objects are fully supported). The maximum number of entries in a vector is limited by the maximum Java array size of 2,147,483,647.


A CVector is essentially a rank 1 CTensor. However, the vector objects in Flag4j have specialized algorithms and operations which may yield additional performance and ease of use over a 1D tensor.


Vector objects in Flag4j do not have an inherent notion of orientation (e.g. row or column vector). However, some methods will treat the vector as if it were a row or column vector. For example, the matrix-vector multiplication method provided in the CMatrix class (via the AbstractDenseSemiringMatrix) operates as if the vector is a column vector.

Initialization

The CVector class contain several constructors that can be used to initialize an instance. The most basic constructor takes a single Complex128[] Java array which will be used as the data of the vector. Note that when using this constructor, the Complex128[] Java array backing the vector will be the same instance passed as a parameter to the constructor. This means manipulating entries in the original array will be reflected in the CVector object instance.

Passing a sequence of Complex128s will also initialize a vector in the same manner as a passing a Complex128[] Java array as the values will be implicitly wrapped. It is similar when passing a primitive Java double[] or int[] array as well but in this case these arrays will not be the same object as the CVector's data array so changes in the original array will not be reflected in the vector object instance.


There are a few possible gotchas with the available constructors we will discuss. The CVector class also offers some constructors to initialize zero vectors or single value vectors of a specified size. Passing a single integer will create a zero vector of that size while passing a single double (or float or Complex128) will result in a vector with a single entry with that value. Passing an integer followed by a single double (or float or Complex128) will result in a vector of size equal to the integer with all values set to the passed double value. However, passing two doubles (or floats) will result in a vector of length 2 with those two entries. Users should be carful and note the difference between the constructor which accepts an integer then a double and the varargs double constructor.


The snippet below provides examples of using all major constructors available in Flag4j's CVector class.

As with all array objects in Flag4j, you may create a copy of a CVector using the copy() method.

This will be a deep copy in the sense that changing the elements in the copy vector will have no effect on the elements of the original vector.

Core Attributes

The CVector object maintains its most important properties as public final fields. This includes size/shape and data (i.e. the entries) of the vector as well as the rank which will trivially be 1 for any vector. The rank is provided to be consistent with Flag4j's array API.


There are also several getters provided as part of Flag4j's array API. For vectors, the totalEntries() getter will always be equal to the length/size of the vector.


Element Access &
Slicing

There are several methods available in the CVector object for setting and accessing data.


Users can get a single element, get a slice (i.e., a continuous range of values), or get items at a specific list of indices. Getting a slice or multiple items will return a CVector object containing all of the specified items.


Similarly, users may set a single item, set a slice, or set multiple items at specific indices. When setting a slice or multiple items, the new values may be specified in an array or as another vector. All set methods take the new value(s) to set first, then the index/indices to be set second. This is done to allow for varargs to be used when setting values in CTensors while maintaining a consistent API across all array objects in Flag4j.


Reshaping & Manipulating

Because vectors are 1D arrays they cannot be reshaped (and remain a 1D array). However, the reshape and flatten methods are still supported as part of Flag4j's array API. These methods are effectively just a copy and only support the shape/size parameter to be exactly the same as the shape/size of the vector exactly.

It is still possible to convert the CVector to a CMatrix or CTensor which can be reshaped. See the section on interoperability for examples.

Attributes & Comparisons

CVectors support the basic element-wise comparisons defined by Flag4j's array API including equality and approximate equality: equals(...) and allClose(...) respectively. CVector objects also support checking for parallelism and perpendicularity.


As with any real dense array object in Flag4j, users can check if a CVector contains only finite values, contains a NaN, or if all entries are all positive, negative, zeros, or ones.


Standard Operations

As part of Flag4j's array API, CVectors support all basic arithmetic operations. Users can compute element-wise addition, subtraction, multiplication and division with two vector objects or with a scalar value.


For all operations in the example code snippet below, the vectors `a` and `b` may contain arbitrary elements provided they are the same size. Each operation may also be done in-place using the accompanying [operation]Eq() method.

For any of the binary element-wise operations, if the two vectors are not the same size, an error will be thrown.

Linear Algebra &
Tensor Operations

There are a few "vector-specific" operations supported by the CVector object. Specifically, vector products, and vector norms/magnitudes.


Vector Products

  1. For complex vectors, the inner and dot products are not equivalent. The dot product will not take the complex conjugate of elements of the second vector while the inner product will take the complex conjugate of elements of the second vector.

  2. The outer product will return a CMatrix.

  3. The cross product is only defined for vectors of length 3. If vectors of a different length are used, an exception will be thrown. It will return a CVector of length 3.

Vector Norms

Flag4j supports the standard norms such as L1, L2, Lp, and maximum norms. Arbitrary p-values may be specified when computing the Lp norm, even negative values. Strictly speaking, p-values less than 1 are not true norms in the sense that they may not satisfy all formal requirements of a norm. However, they can still be useful for numerical purposes and are supported by Flag4j. Computing the magnitude of a vector is equivalent to the L2 (Euclidian) norm.


Passing a p-value of Double.POSITIVE_INFINITY will result in the maximum norm while Double.NEGATIVE_INFINITY will return in the minimum "norm" (which is not a true norm).

Note: While p-values less than 1 are supported, setting p equal to exactly zero will raise an error to avoid division by zero.

Reductions &
Aggregations

Interoperability

Array objects in Flag4j are very flexible and support a wide range of overloaded operations and conversions. For instance, a complex dense vector may be converted to/from a real dense vector or a complex sparse COO vector. Most binary operations also support passing other vector types such as real dense vectors, real sparse vectors, and complex sparse vectors.


Conversions

CVectors can be converted to sparse COO vectors if desired. This should be done with some caution as sparse vectors are only more efficient if the vector is very sparse.


CVectors may also be converted to matrices or tensors with optionally specified shapes. If a shape is specified, then the total number of entries specified by the shape (i.e., the product of each dimension) must exactly equal the number of elements in the vector.

Overloaded Operations

Most binary operations support passing other vector types as arguments. For instance, the CVector class has several overloaded methods for vector addition supporting  real dense vectors, real sparse vectors, and complex sparse vectors. Most other basic binary operations also implement similar overloaded methods. An exception is element-wise division which does not support passing a sparse vector as the denominator since it would almost certainly result in division by zero.


The code snippet below demonstrates some of these overloaded methods as well as their return type.

For a full list of overloaded methods see the API reference.

bottom of page