## Introduction

The header file attached to this article implements the `EVector`

class. In order to remove confusion from the start, this class is not a data structure, or an STL container. It does, however, resemble the `std::vector`

class that's provided as part of STL even though their purposes are quite different.

`std::vector`

is basically a container for objects of type `T`

. This class, however, is an implementation of a vector in the mathematical sense. Therefore, it contains operators like `+`

, `-`

, `*`

, etc.. as well as other functions that are used to manipulate vectors.

## Background

This class was written as part of a library I've been writing. I wanted to create some mathematical infrastructure that will be used by other parts of the library. Up till now, I've used this class to write a matrix class and to specialize the case of 2D and 3D vectors for graphics and computational geometry algorithms. Even though I haven't provided those classes (I might in the future, though...) I think it's very easy to use/extend/specialize this class for such purposes by any user.

## Implementation

While writing this class, I followed these guidelines:

- This class is really low-level and will be used almost everywhere. This is why it has to be well written and conform to widely-used notation.
- Future changes will be addition of functionality and not changes in already existing behavior.
- Portability.
- This class should conform to standard behavior in order to be used by other 3
^{rd}-party libraries or replace similar classes. - Other people might use this class and therefore it must be well documented. This will also facilitate changes in the future.

To adhere to the above, the code is documented using Doxygen. In addition, it is STL-compliant. This means that it has an allocator object and appropriate iterators that can be used to traverse the elements of the vector. The elements of the vector are allocated and deallocated using the allocator.

One of the intentions of this class is to be used for graphics and code that is run-time critical. Any of you who have used OpenGL or Direct3D are familiar with vertex arrays. A vertex array is just what its name implies - an array of (usually) 3D vectors. Such arrays can be cached, or optimized, and for such reasons there's no need to impose the use of an allocator instance for each instance of `EVector`

. In this example, an array of `EVector`

s can be easily used as a vertex array that can be passed to OpenGL and the programmer doesn't even need to calculate the offset between consecutive instances of `EVector`

s (even though it's easy...). Such an array will definitely occupy less memory if there's no allocator instance for each `EVector`

instance. This is why I make use of the `E_VECTOR_USE_ALLOCATOR`

flag.

If you take a look at the code, you'll see the `E_VECTOR_USE_ALLOCATOR`

flag. If this flag is defined, `EVector`

has a template parameter `A`

that determines the type of the allocator (which is by default `std::allocator`

). In addition, each instance of an `EVector`

object will hold an instance of an allocator - just like `std::vector`

(or any other STL container). If, however, it isn't defined, all instances of `EVector`

of the same type (meaning, having the same `T`

and `n`

) will share the same allocator instance. To make a long story short - `E_VECTOR_USE_ALLOCATOR`

determines whether the allocator is a static member of `EVector`

or not. This still allows the flexibility of providing different ways of allocating objects without the overhead of complexity and memory usage that might arise in most cases. It is important to emphasis that whether `E_VECTOR_USE_ALLOCATOR`

is defined or not, `EVector`

can be used identically. This is because if `E_VECTOR_USE_ALLOCATOR`

isn't defined, `A`

becomes a typedef of the class, and `get_allocator()`

simply returns the static member.

Unfortunately, I can't get into the skinny math details, so I assume that most users of this class know some linear algebra. It really isn't complicated. As mentioned above, the class contains the standard functions that manipulate vectors. If anything is missing and should be in - let me know. :-)

As I mentioned above, the class is STL-compliant - which allows it to be used by STL algorithms. I've demonstrated this in the small test program for the case of `std::reverse`

but, of course, it can be used with other algorithms as well. It also includes simple serialization to and from a stream.

An important thing to notice. The size of the vector is static!! It can't be changed at run-time and is determined completely by the template parameter `n`

. This is in contrast to some other classes I've seen. There are several reasons for this. The main two are simplicity and performance. Like I said, this class is intended to be used for performance-critical tasks. If the size was changeable at run-time, simple operations like addition, subtraction, dot product, and so forth would have to be validated at run-time by checking that vectors have the same size and otherwise throwing an exception. Keeping the size static and part of the template parameters removes all such problems because these are simply verified during compilation. If one tries to define:

EVector< float, 5 > v; EVector< float, 3 > u; cout << u+v << endl; // compilation error!

one would get a compilation error because the operators mentioned above are defined for vectors of the same size.

## Using the code

This is simple. All you have to do is to include *EVector.h* in your source code. Then you can define:

EVector< double, 4 > v; // creates an invalid vector of 4 doubles EVector< int, 2 > p; // creates an invalid vector of 2 integers v.fill(0.1); // v = (0.1, 0.1, 0.1, 0.1) p[0] = 1; p[1] = 5; // p = (1, 5) v.normalize(); // |v| = v.length() = 1 std::reverse(p.begin(), p.end()); // p = (5, 1)

And start having fun with them...

Please look at the (Doxygen) comments in the code to find out what are the operators and functions that are defined for the class.

## Points of Interest

Please notice that the default constructor creates an invalid vector. An invalid vector is a vector one of whose arguments is NaN (Not a Number). To check for the validity of a vector one should use the `isValid()`

member function.

You'll see that for some of the functions there's an optional epsilon argument. This is provided because some computations (actually, most computations...) result in numerical errors. For example, two vectors are considered orthogonal if their dot product is 0. Since the computer has only finite accuracy, two vectors which would be practically orthogonal might not yield an exact 0 when calculating their dot product. The epsilon argument solves this problem by considering vectors whose dot product is less or equal to epsilon orthogonal, and vectors whose dot product is greater than epsilon - not orthogonal. The same principle applies for other kinds of tests.

## History

No history yet...