Library Name: lib_math_vector.a
Introduction:

The vector classes provide support for a wide variety of complex mathematical operations. Since vectors are used extensively in signal processing applications, these classes centralize core mathematical functions, and augment the traditional concept of a vector with functions useful for signal processing.

Example:

The following example illustrates how easy it is to do mathematics with the vector classes:

      01  // isip include files
      02  //
      03  #include <VectorFloat.h>
      04  #include <Console.h>
      05
      06  // main program starts here
      07  //
      08  int main() {
      09
      10    // declare two vectors and a scalar
      11    //
      12    VectorFloat u;
      13    VectorFloat v;
      14    Float distance;
      15
      16    // define the elements of the two vectors
      17    //
      18    u.assign(L"3.5, 6.4, 5.9, 0.11, 0.76");
      19    v.assign(L"4.6, 8.9, 11.2, 22.2, 7.7");
      20
      21    // calculate the euclidean distance between two vectors
      22    //
      23    distance = u.norm(v);
      24
      25    // writing the result to the console
      26    //
      27    String output;
      28    String tmp;
      29    output.concat(L"the euclidean distance between u and v is ");
      30    tmp.assign(distance);
      31    output.concat(tmp);
      32    Console::put(output);
      33
      34    // exit gracefully
      35    //
      36    Integral::exit();
      37  }

Explanation:

The above program calculates the Euclidean distance between vectors "u" and "v". This is done in just one step on line 23 using the "norm" function. Since this function returns an integral type, we assign it to a scalar object. The norm function does all of the following in one step:

1. computes the differences element by element for each vector
2. squares these differences
3. computes the sum of the squares
4. computes the square root of the sum

The output generated from the above program is:

the euclidean distance between u and v is 23.9099

The vector classes build upon the scalar classes. The vector classes incorporate many of the methods included in the scalar classes, as well as some interesting higher-level functions.

Example:

Here is another example which demonstrates some of the more advanced functions available in the vector classes:

      01  // isip include files
      02  //
      03  #include <VectorFloat.h>
      04  #include <VectorLong.h>
      05  #include <Console.h>
      06
      07  // main program starts here:
      08  //  this example demonstrates the use of math vector methods to
      09  //  manipulat the values of a vector.
      10  //
      11  int main () {
      12
      13    // define a vector of floats that is 5 elements long
      14    // and a vector of integers
      15    //
      16    VectorFloat signal(5);
      17    VectorLong idx;
      18
      19    // generate a ramp. it will start at 1.0 with a slope of 2.0.
      20    //
      21    signal.ramp(1.0, 2.0);
      22
      23    // print the signal using the debug method
      24    //
      25    signal.debug(L"The signal is ");
      26
      27    // generate an index array for reordering
      28    //
      29    idx.assign(L"4, 3, 2, 1, 0");
      30
      31    // time-reverse the signal via the reorder method.
      32    // another alternative implementation is via the reverse mehtod.
      33    // Ex. signal.reverse();
      34    //
      35    signal.reorder(idx);
      36
      37    // verify that the signal is reversed
      38    //
      39    signal.debug(L"The time-reversed signal is ");
      40
      41    // increase the length of the signal to 10 elements.
      42    //
      43    signal.setLength(10);
      44
      45    // zero-out the new elements. this step is not strictly needed,
      46    // since the values were initially zero and the program has never
      47    // assigned them to other elements. however, the setLength() method
      48    // does NOT zero out new elements, so if this vector was previously
      49    // a longer length with non-zero elements in these new positions
      50    // somewhat unpredictable results could occur.
      51    //
      52    for (long i = 5; i < 10; i++) {
      53      signal(i) = 0;
      54    }
      55
      56    // verify that the signal has been zero-stuffed
      57    //
      58    signal.debug(L"The zero-stuffed signal is ");
      59
      60    // exit gracefully
      61    //
      62    Integral::exit();
      63  }

Explanation:

On line 21 in this program, we generate a ramp signal using the "ramp" method available in the VectorFloat class. The first input argument to the ramp method is the offset value of the ramp (1.0) and the second argument (2.0) specifies the increment of the ramp. The debug method is used to verify the contents of the signal. All classes have a debug method - these are particularly useful during program development.
Next, on line 29, we generate a vector of indices that will be used to time-reverse the signal. The function call on line 35 time reverses the signal using a reordering method (also available in all vector classes). The result is again verified on line 39 using the debug method.
The length of a vector can automatically be resized by simply changing the length of the vector. This is demonstrated on line 41, where the vector's dimension is increased to 10. This is verified on line 56. Vectors have both a length (the current size of the vector) and a capacity (the current maximum size of the vector). If the length is set to a number greater than the capacity, the vector's capacity is automatically increased. Hence, vectors can grow as needed, and capacity is used to ensure this growth is done in an efficient manner.
The output for the above program is shown below:

      <VectorFloat:: The signal is> length_d = 5
      <VectorFloat:: The signal is> capacity_d = 5
      <VectorFloat:: The signal is> v_d = 1, 3, 5, 7, 9
      <VectorFloat:: The time-reversed signal is> length_d = 5
      <VectorFloat:: The time-reversed signal is> capacity_d = 5
      <VectorFloat:: The time-reversed signal is> v_d = 9, 7, 5, 3, 1
      <VectorFloat:: The zero-stuffed signal is> length_d = 10
      <VectorFloat:: The zero-stuffed signal is> capacity_d = 10
      <VectorFloat:: The zero-stuffed signal is> v_d = 9, 7, 5, 3, 1, 0, 0, 0, 0, 0

Example:

The following example illustrates how easy it is to do a conversion from a Real type to a Complex type assuming zero imaginary parts, with the vector classes:

      01  // isip include files
      02  //
      03  #include <VectorFloat.h>
      04  #include <VectorComplexFloat.h>
      05
      06  // main program starts here
      07  //
      08  int main() {
      09
      10    // declare a real vector and a complex vector
      11    //
      12    VectorFloat real;
      13    VectorComplexFloat complex;
      14
      15    // define the elements of the real vector
      16    //
      17    real.assign(L"3.5, 6.4, 5.9, 0.11, 0.76");
      18
      19    // convert the real to a complex type assuming zero imaginary parts
      20    //
      21    complex.assign(real);
      22
      23    // writing the result
      24    //
      25    real.debug(L"the real vector is ");
      26    complex.debug(L"the equivalent complex vector is ");
      27
      28    // exit gracefully
      29    //
      30    Integral::exit();
      31  }

Explanation:

The above program converts a real vector float type to a complex vector float type assuming zero imaginary parts. This is done in just one step on line 21 using the "assign" function. The assign function does all of the following in one step. It loops through each scalar in the vectors and assigns the real type to the real part of complex type with imaginary part as zero.
The output generated from the above program is:

<VectorFloat::the real vector is > length_d = 5
<VectorFloat::the real vector is > capacity_d = 5
<VectorFloat::the real vector is > v_d = 3.5, 6.4, 5.9, 0.11, 0.76
<VectorComplexFloat::the equivalent complex vector is > length_d = 5
<VectorComplexFloat::the equivalent complex vector is > capacity_d = 5
<VectorComplexFloat::the equivalent complex vector is > v_d = 3.5+0j, 6.4+0j, 5.9+0j, 0.11+0j, 0.76+0j

A detailed listing of all the relational, logical and mathematical operations for the vectors can be found in the template header file documentation (for functions shared across all classes) or the individual class documentation (for example, see the VectorFloat class). The vector classes that are available include:

VectorByte | VectorComplexDouble | VectorComplexFloat | VectorComplexLong
VectorDouble | VectorFloat | VectorLlong | VectorLong
VectorShort | VectorUllong | VectorUlong | VectorUshort

The next level in the ISIP class hierarchy is matrix which provides a means of creating a matrix of ISIP scalar objects. The software corresponding to the examples demonstrated in this document can be found in our documentation directory under class/math/vector/.