A Vells (for value elements) represents a sampling (or integration) of a function on some grid in N-space (as given by a Cells somewhere). A Vells is an array of N1*N2*...*Nk elements. Each axis of the array represents variability over that axis in N-space. The type of the array can be double or complex double (for a regular "value Vells"), or an unsigned 32-bit integer (for a "flag Vells").
Vells Shapes
The shape of a Vells is determined by its axes of variability. For example, a scalar (single element) Vells has no variability along any axis. A time-frequency-variable Vells will have a shape of Ntime*Nfreq (assuming time is axis 0 and frequency is axis 1). A frequency-variable Vells will have a shape of 1*Nfreq. A Vells that is variable along axes 3 and 7 will have a shape of 1*1*1*N*1*1*1*M. As you can see, there is a fixed 1-1 correspondence between the shape of a Vells and its axes of variability; axes with no variation have an extent of 1, and axes beyond the last axis of variability are omitted from the shape altogether (although they can still be thought of as having an implicit extent of 1, so an N*M*1 Vells shape is equivalent to N*M).
C++ Vells
C++ Vells are instances of the Meq::Vells class, which is subclassed from DMI::NumArray. In addition to regular NumArray methods and properties, Vells have the following extra features:
A Vells may hold a read-only reference to a "flag Vells" (normally, all the Vells in a VellSet will share the same flags by-reference).
- Like arrays, copying and assignment of Vells is done via copy-on-write references (i.e. very fast).
- Vells::isNull() and Vells::isUnity() are quick checks for scalar vells of value 0 and 1 (handy for optimizing certain computations).
One or more Vells may appear as arguments in a Vells math expression, to produce another Vells.
Vells Math
Vells math in C++ is enabled by including a using namespace VellsMath declaration. Vells math allows one to work with Vells as if they were simple numbers. The most important feature of Vells math is automatic axis expansion. For example, if an N*1 time-variable Vells (A) is added to a 1*M frequency-variable Vells (B), the result (C) is an N*M Vells, with Cij=Ai+Bj. This expansion happens automatically, and is completely transparent to the programmer.
The following math operations on "value" Vells are defined:
- Unary minus (-)
Binary: + - * /
In-place operators: += -= *= /=
Unary functions of a real or complex argument: exp() log() cos() cosh() sin() sinh() tan() tanh() sqr() sqrt() pow2()...pow8() abs() norm() arg() real() imag() conj()
Unary functions of a real argument: ceil() floor() acos() asin() atan()
Reduction functions (these reduce any array Vells to a scalar): min() max() mean() sum() product() nelements()
Binary functions: posdiff(x,y) tocomplex(re,im) polar(a,ph) pow(x,y) atan2(x,y)
These operations work as intuitively expected. Axis expansion and type promotion/demotion is done as needed. Since a Vells defines an implict constructor from a scalar, all binary operations will take a mix of Vells and numeric arguments. The result of all operations is a Vells returned by value, with the exception of the in-place operators, which return a Vells &. (Since internal Vells storage is implemented via copy-on-write refs, passing them around by value is actually very efficient.)
For flag Vells, only a basic set of bitwise logic operators are defined:
- Unary bitwise NOT (~)
Binary bitwise: | & and ^ (OR, AND, XOR)
In-place bitwise: |= &= and ^=.
Vells in Python
