Category : C++ Source Code
Archive   : JCOOL01.ZIP
Filename : M_VECTOR.C

 
Output of file : M_VECTOR.C contained in archive : JCOOL01.ZIP
//
// Copyright (C) 1991 Texas Instruments Incorporated.
// Copyright (C) 1992 General Electric Company.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated, General Electric Company,
// provides this software "as is" without express or implied warranty.
//

#include // header of vector and its envelope

//## hack to workaround BC++ 3.1 Envelope bug
#define CoolEnvelope CoolEnvelope_M_Vector

// compare_s -- Function used by == test
template
Boolean (*CoolM_Vector::compare_s)(const Type&, const Type&) = &CoolM_Vector_is_data_equal;

// CoolM_Vector -- constructor specifiying size of CoolM_Vector
// Input: Length
// Output: None

template
CoolM_Vector::CoolM_Vector(unsigned int len)
: CoolBase_M_Vector(len)
{
this->data = new Type[len]; // Allocate the elements
}


// CoolM_Vector -- constructor specifiying size of vector and initial value
// Input: Length and initial value
// Output: None

template
CoolM_Vector::CoolM_Vector(unsigned int len, const Type& value)
: CoolBase_M_Vector(len)
{
this->data = new Type[len]; // Allocate the elements
for (int i = 0; i < len; i ++) { // For each elmt in the CoolM_Vector
this->data[i] = value; // Assign initial value
}
}

// CoolM_Vector -- constructor specifiying size of vector and initial values
// Input: Length and initial values
// Output: None
// Note: Arguments in ... can only be pointers, primitive types like int,
// and NOT OBJECTS, passed by reference or value, like vectors, matrices;
// because constructors must be known and called at compile time!!!
// Cannot have char in ..., because char is 1 instead of 4 bytes, and
// va_arg expects sizeof(Type) a multiple of 4 bytes.

template
CoolM_Vector::CoolM_Vector(unsigned int len, int n, Type v00, ...)
: CoolBase_M_Vector(len)
{
#if ERROR_CHECKING
if (((sizeof(Type) % 4) != 0) || // Cause alignment problems
(sizeof(Type) > 8)) // User defined classes?
this->va_arg_error("Type", sizeof(Type)); // So, cannot use this constructor
#endif
this->data = new Type[len]; // Allocate the elements
if (n > 0) { // If user specified values
va_list argp; // Declare argument list
va_start (argp, v00); // Initialize macro
for (int i = 0; i < len && n; i++, n--) // For remaining values given
if (i == 0)
this->data[0] = v00; // Hack for v00 ...
else
this->data[i] = va_arg(argp, Type); // Extract and assign
va_end(argp);
}
}


// CoolM_Vector -- constructor for reference to another CoolM_Vector object
// Input: CoolM_Vector reference
// Output: None

template
CoolM_Vector::CoolM_Vector(const CoolM_Vector& v)
: CoolBase_M_Vector(v)
{
this->data = new Type[this->num_elmts]; // Allocate the elements
for (int i = 0; i < this->num_elmts; i ++) { // For each element in the CoolM_Vector
this->data[i] = v.data[i]; // Copy value
}
}


// ~CoolM_Vector -- Destructor for CoolM_Vector class that frees up storage
// Input: *this
// Output: None

template
CoolM_Vector::~CoolM_Vector() {
delete this->data; // Free up the data space
}

// fill -- Set all elements of a vector to a specified fill value
// Input: *this, reference to fill value
// Output: None

template
void CoolM_Vector::fill (const Type& value) {
for (int i = 0; i < this->num_elmts; i++) // For each index in the CoolM_Vector
this->data[i] = value; // Assign fill value
}

// operator= -- Overload the assignment operator to assign a single
// value to the elements of a CoolM_Vector.
// Input: *this, reference to a value
// Output: Reference to updated CoolM_Vector object

template
CoolM_Vector& CoolM_Vector::operator= (const Type& value) {
for (int i = 0; i < this->num_elmts; i++) // For each index in CoolM_Vector
this->data[i] = value; // Assign value
return *this; // Return CoolM_Vector reference
}


// operator= -- Overload the assignment operator to copy the elements
// in one CoolM_Vector to another. The existing storage for the
// destination vector is freed up and new storage of the same
// size as the source is allocated.
// Input: *this, reference to CoolM_Vector
// Output: Reference to copied CoolM_Vector object

template
CoolM_Vector& CoolM_Vector::operator= (const CoolM_Vector& v) {
if (this != &v) { // make sure *this != m
if (this->num_elmts != v.num_elmts) {
delete this->data; // Free up the data space
this->num_elmts = v.num_elmts; // Copy index specification
this->data = new Type[this->num_elmts]; // Allocate the elements
}
for (int i = 0; i < this->num_elmts; i++) // For each index
this->data[i] = v.data[i]; // Copy value
}
return *this; // Return CoolM_Vector reference
}

// operator== -- Compare the elements of two Matrices of Type Type using
// the Compare pointer to funtion (default is ==). If one
// CoolM_Vector has more elements than the other, the
// result is FALSE
// Input: Reference to CoolM_Vector of Type Type
// Output: TRUE/FALSE

template
Boolean CoolM_Vector::operator== (const CoolM_Vector& v) const {
if (this->num_elmts != v.num_elmts) // Size?
return FALSE; // Then not equal
for (int i = 0; i < this->num_elmts; i++) // For each index
if ((*this->compare_s)(this->data[i],v.data[i]) == FALSE) // Same?
return FALSE; // Then no match
return TRUE; // Else same, so return TRUE
}

// is_data_equal -- Default data comparison function if user has not provided
// another one. Note that this is not inline because we need
// to take the address of it for the compare static variable
// Input: Two Type references
// Output: TRUE/FALSE

template
Boolean CoolM_Vector_is_data_equal (const Type& t1, const Type& t2) {
return (t1 == t2);
}

// set_compare -- Specify the comparison function to be used
// in logical tests of vector elements
// Input: Pointer to a compare function
// Output: None

template
void CoolM_Vector::set_compare (Boolean (*c) (const Type&, const Type&)) {
if (c == NULL) // If no argument supplied
this->compare_s = &CoolM_Vector_is_data_equal; // Default is_equal
else
this->compare_s = c; // Else set to user function
}


// operator<< -- Overload the output operator to print a vector

// Input: ostream reference, CoolM_Vector reference
// Output: ostream reference

template
ostream& operator<< (ostream& s, const CoolM_Vector& v) {
for (int i = 0; i < v.num_elmts; i++) { // For each index in vector
s << v.data[i] << " "; // Output data element
}
return (s); // Return ostream reference
}

// operator+= -- Destructive vector addition of a scalar.
// Input: *this, scalar value
// Output: New vector reference

template
CoolM_Vector& CoolM_Vector::operator+= (const Type& value) {
for (int i = 0; i < this->num_elmts; i++) // For each index
this->data[i] += value; // Add scalar
return *this;
}

// operator*= -- Destructive vector multiplication by a scalar.
// Input: *this, scalar value
// Output: New vector reference


template
CoolM_Vector& CoolM_Vector::operator*= (const Type& value) {
for (int i = 0; i < this->num_elmts; i++) // For each index
this->data[i] *= value; // Multiply by scalar
return *this;
}

// operator/= -- Destructive vector division by a scalar.
// Input: *this, scalar value
// Output: New vector reference

template
CoolM_Vector& CoolM_Vector::operator/= (const Type& value) {
for (int i = 0; i < this->num_elmts; i++) // For each index
this->data[i] /= value; // division by scalar
return *this;
}


// operator+= -- Destructive vector addition with assignment. Note that the
// dimensions of each vector must be identical
// Input: *this, vector reference
// Output: Updated *this vector reference

template
CoolM_Vector& CoolM_Vector::operator+= (const CoolM_Vector& v) {
if (this->num_elmts != v.num_elmts) // Size?
this->dimension_error ("operator+=", "Type",
this->num_elmts, v.num_elmts);
for (int i = 0; i < this->num_elmts; i++) // For each index
this->data[i] += v.data[i]; // Add elements
return *this;
}


// operator-= -- Destructive vector subtraction with assignment. Note that the
// dimensions of each vector must be identical
// Input: *this, vector reference
// Output: Updated *this vector reference

template
CoolM_Vector& CoolM_Vector::operator-= (const CoolM_Vector& v) {
if (this->num_elmts != v.num_elmts) // Size?
this->dimension_error ("operator-=", "Type",
this->num_elmts, v.num_elmts);
for (int i = 0; i < this->num_elmts; i++)
this->data[i] -= v.data[i];
return *this;
}



// pre_multiply -- Destructive pre_multiply vector with matrix. v = m * v
// num_cols of matrix must match num_elmts of vector
// Input: *this, matrix reference
// Output: Updated *this vector reference

template
CoolM_Vector& CoolM_Vector::pre_multiply (const CoolMatrix& m) {
if (m.columns() != this->num_elmts) // dimensions do not match?
this->dimension_error ("operator*=", "Type",
this->num_elmts, m.columns());
Type* temp= new Type[m.rows()]; // Temporary
CoolMatrix& mm = (CoolMatrix&) m; // Drop const for get()
for (int i = 0; i < m.rows(); i++) { // For each index
temp[i] = (Type) 0.0; // Initialize element value
for (int k = 0; k < this->num_elmts; k++) // Loop over column values
temp[i] += (mm.get(i,k) * this->data[k]); // Multiply
}
delete this->data; // Free up the data space
num_elmts = m.rows(); // Set new num_elmts
this->data = temp; // Pointer to new storage
return *this; // Return vector reference
}

// post_multiply -- Destructive post_multiply vector with matrix. v = v * m
// num_elmts of vector must match num_rows of matrix
// Input: *this, matrix reference
// Output: Updated *this vector reference

template
CoolM_Vector& CoolM_Vector::post_multiply (const CoolMatrix& m) {
if (this->num_elmts != m.rows()) // dimensions do not match?
this->dimension_error ("operator*=", "Type",
this->num_elmts, m.rows());
Type* temp= new Type[m.columns()]; // Temporary
CoolMatrix& mm = (CoolMatrix&) m; // Drop const for get()
for (int i = 0; i < m.columns(); i++) { // For each index
temp[i] = (Type) 0.0; // Initialize element value
for (int k = 0; k < this->num_elmts; k++) // Loop over column values
temp[i] += (this->data[k] * mm.get(k,i)); // Multiply
}
delete this->data; // Free up the data space
num_elmts = m.columns(); // Set new num_elmts
this->data = temp; // Pointer to new storage
return *this; // Return vector reference
}


// operator- -- Non-destructive vector negation. a = -b;
// Input: *this
// Output: New vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::operator- () const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++)
temp.data[i] = - this->data[i]; // negate element
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// operator+ -- Non-destructive vector addition of a scalar.
// Input: *this, scalar value
// Output: New vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::operator+ (const Type& value) const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++) // For each index
temp.data[i] = (this->data[i] + value); // Add scalar
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}


// operator* -- Non-destructive vector multiply by a scalar.
// Input: *this, scalar value
// Output: New vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::operator* (const Type& value) const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++) // For each index
temp.data[i] = (this->data[i] * value); // Multiply
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}


// operator/ -- Non-destructive vector division by a scalar.
// Input: *this, scalar value
// Output: New vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::operator/ (const Type& value) const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++) // For each index
temp.data[i] = (this->data[i] / value); // Divide
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// operator* -- Non-destructive multiply matrix with vector: vb = m * va
// num_cols of first matrix must match num_elmts of second vector.
// Input: matrix, vector reference
// Output: New vector

template
CoolEnvelope< CoolM_Vector > operator* (const CoolMatrix& m, const CoolM_Vector& v) {
if (m.columns() != v.num_elmts) // dimensions do not match?
v.dimension_error ("operator*", "Type",
m.columns(), v.num_elmts);
CoolM_Vector temp(m.rows()); // Temporary
CoolMatrix& mm = (CoolMatrix&) m; // Drop const for get()
for (int i = 0; i < m.rows(); i++) { // For each index
temp.data[i] = (Type) 0.0; // Initialize element value
for (int k = 0; k < v.num_elmts; k++) // Loop over column values
temp.data[i] += (mm.get(i,k) * v.data[k]); // Multiply
}
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}


// operator* -- Non-destructive multiply vector with matrix: vb = va * m
// num_elmts of first vector must match num_rows of second matrix.
// Input: vector, matrix reference
// Output: New vector

template
CoolEnvelope< CoolM_Vector > operator* (const CoolM_Vector& v, const CoolMatrix&m) {
if (v.num_elmts != m.rows()) // dimensions do not match?
v.dimension_error ("operator*", "Type",
v.num_elmts, m.rows());
CoolM_Vector temp(m.columns()); // Temporary
CoolMatrix& mm = (CoolMatrix&) m; // Drop const for get()
for (int i = 0; i < m.columns(); i++) { // For each index
temp.data[i] = (Type) 0.0; // Initialize element value
for (int k = 0; k < v.num_elmts; k++) // Loop over column values
temp.data[i] += (v.data[k] * mm.get(k,i)); // Multiply
}
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}


// update -- replace a subvector of this, by the actual argument.
// Input: *this, starting corner specified by top and left.
// Ouput: mutated reference.

template
CoolM_Vector& CoolM_Vector::update (const CoolM_Vector& v,
unsigned int start) {
unsigned int end = start + v.num_elmts;
if (this->num_elmts < end)
this->dimension_error ("update", "Type",
end-start, v.num_elmts);
for (int i = start; i < end; i++)
this->data[i] = v.data[i-start];
return *this;
}


// extract -- Return a subvector specified by the start-left corner and size.
// Input: *this, starting corner specified by start and left, and size.
// Ouput: new vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::extract (unsigned int len, unsigned int start) const{
unsigned int end = start + len;
if (this->num_elmts < end)
this->dimension_error ("extract", "Type",
end-start, len);
CoolM_Vector temp(len);
for (int i = 0; i < len; i++)
temp.data[i] = data[start+i];
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// abs -- Return vector of absolute values. v[i] = abs(v[i])
// Input: *this
// Ouput: new vector

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::abs() const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++)
if (this->data[i] < 0)
temp.data[i] = - this->data[i];
else
temp.data[i] = this->data[i];
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// sign -- Mutate *this to store signs, either -1,1 or 0, depending on
// whether the corresponding values are negative, positive, or 0.
// Input: *this
// Ouput: *this mutated.

template
CoolEnvelope< CoolM_Vector > CoolM_Vector::sign () const {
CoolM_Vector temp(this->num_elmts);
for (int i = 0; i < this->num_elmts; i++)
if (this->data[i] == 0) // test fuzz equality to 0
temp.data[i] = 0; // first.
else
if (this->data[i] < 0)
temp.data[i] = -1;
else
temp.data[i] = 1;
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// element_product -- return the vector whose elements are the products
// Input: 2 vectors v1, v2 by reference
// Output: New vector, whose elements are v1[i]*v2[i].

template
CoolEnvelope< CoolM_Vector > element_product (const CoolM_Vector& v1, const CoolM_Vector& v2) {
if (v1.num_elmts != v2.num_elmts) // Size?
v1.dimension_error ("element_product", "Type",
v1.num_elmts, v2.num_elmts);
CoolM_Vector temp(v1.num_elmts);
for (int i = 0; i < v1.num_elmts; i++)
temp.data[i] = v1.data[i] * v2.data[i];
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

// element_quotient -- return the vector whose elements are the quotients
// Input: 2 vectors v1, v2 by reference
// Output: New vector, whose elements are v1[i]/v2[i].

template
CoolEnvelope< CoolM_Vector > element_quotient (const CoolM_Vector& v1, const CoolM_Vector& v2) {
if (v1.num_elmts != v2.num_elmts) // Size?
v1.dimension_error ("element_quotient", "Type",
v1.num_elmts, v2.num_elmts);
CoolM_Vector temp(v1.num_elmts);
for (int i = 0; i < v1.num_elmts; i++)
temp.data[i] = v1.data[i] / v2.data[i];
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}


// dot_product -- Return the dot product of the vectors
// Input: 2 vectors by reference
// Ouput: dot product value

template
Type dot_product (const CoolM_Vector& v1, const CoolM_Vector& v2) {
if (v1.num_elmts != v2.num_elmts) // Size?
v1.dimension_error ("dot_product", "Type",
v1.num_elmts, v2.num_elmts);
Type dot = 0;
for (int i = 0; i < v1.num_elmts; i++)
dot += v1.data[i] * v2.data[i]; // of vectors
return dot;
}

// cross_2d -- Return the 2X1 cross-product of 2 2d-vectors
// Input: 2 vectors by reference
// Ouput: cross product value

template
Type cross_2d (const CoolM_Vector& v1, const CoolM_Vector& v2) {
if (v1.num_elmts != 2 || v2.num_elmts != 2)
v1.dimension_error ("cross_2d", "Type",
v1.num_elmts, v2.num_elmts);

return (v1.x() * v2.y()
-
v1.y() * v2.x());
}

// cross_3d -- Return the 3X1 cross-product of 2 3d-vectors
// Input: 2 vectors by reference
// Ouput: 3d cross product vector

template
CoolEnvelope< CoolM_Vector > cross_3d (const CoolM_Vector& v1, const CoolM_Vector& v2) {
if (v1.num_elmts != 3 || v2.num_elmts != 3)
v1.dimension_error ("cross_3d", "Type",
v1.num_elmts, v2.num_elmts);
CoolM_Vector temp(v1.num_elmts);

temp.x() = v1.y() * v2.z() - v1.z() * v2.y(); // work for both col/row
temp.y() = v1.z() * v2.x() - v1.x() * v2.z(); // representation
temp.z() = v1.x() * v2.y() - v1.y() * v2.x();
CoolEnvelope< CoolM_Vector >& result = (CoolEnvelope< CoolM_Vector >&) temp; // same physical object
return result; // copy of envelope
}

//## hack to workaround BC++ 3.1 Envelope bug
#undef CoolEnvelope



  3 Responses to “Category : C++ Source Code
Archive   : JCOOL01.ZIP
Filename : M_VECTOR.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/