MathVector.cpp

00001 /*
00002  *  Copyright (C) 2010  Regents of the University of Michigan
00003  *
00004  *   This program is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include "MathVector.h"
00019 #include "MathMatrix.h"
00020 #include "MathConstant.h"
00021 #include "Sort.h"
00022 #include "Error.h"
00023 
00024 #ifdef  _MSC_VER
00025 #define _USE_MATH_DEFINES
00026 #endif
00027 
00028 #include <string.h>
00029 #include <math.h>
00030 
00031 int Vector::alloc = 32;
00032 
00033 void Vector::Init()
00034 {
00035     dim = size = 0;
00036     label = "Unknown";
00037     data = NULL;
00038 }
00039 
00040 Vector::~Vector()
00041 {
00042     // printf(" Deleting vector %s ...\n", (const char *) label);
00043     if (data != NULL) delete [] data;
00044 }
00045 
00046 void Vector::Dimension(int d)
00047 {
00048     if (d > size)
00049     {
00050         if (size < 1024)
00051         {
00052             size = (d + alloc) / alloc * alloc;
00053             double * newData = new double [size];
00054             if (data != NULL)
00055             {
00056                 for (int i = 0; i < dim; i++)
00057                     newData[i] = data[i];
00058                 delete [] data;
00059             }
00060             data = newData;
00061         }
00062         else
00063         {
00064             while (size <= d)
00065                 size *= 2;
00066 
00067             double * newData = new double [size];
00068             if (data != NULL)
00069             {
00070                 for (int i = 0; i < dim; i++)
00071                     newData[i] = data[i];
00072                 delete [] data;
00073             }
00074             data = newData;
00075         }
00076     }
00077     dim = d;
00078 }
00079 
00080 void Vector::Dimension(int d, double value)
00081 {
00082     int original = dim;
00083 
00084     Dimension(d);
00085 
00086     for (int i = original; i < dim; i++)
00087         data[i] = value;
00088 }
00089 
00090 void Vector::Negate()
00091 {
00092     for (int i = 0; i < dim; i++)
00093         data[i] = -data[i];
00094 }
00095 
00096 void Vector::Add(double n)
00097 {
00098     for (int i = 0; i< dim; i++)
00099         data[i] += n;
00100 }
00101 
00102 void Vector::Multiply(double k)
00103 {
00104     for (int i = 0; i < dim; i++)
00105         data[i] *= k;
00106 }
00107 
00108 void Vector::Copy(const Vector & v)
00109 {
00110     Dimension(v.dim);
00111 
00112     if (v.data != NULL)
00113         for (int i=0; i < dim; i++)
00114             data[i] = v.data[i];
00115 }
00116 
00117 Vector & Vector::operator = (const Vector & rhs)
00118 {
00119     Copy(rhs);
00120     return *this;
00121 }
00122 
00123 void Vector::Add(Vector & v)
00124 {
00125     if (dim != v.dim)
00126         error("Vector::Add - vectors have different dimensions\n"
00127               "Vectors     - %s [%d] + %s [%d] ",
00128               (const char *) label, dim, (const char  *) v.label, v.dim);
00129 
00130     for (int i = 0; i < dim; i++)
00131         data[i] += v.data[i];
00132 }
00133 
00134 void Vector::AddMultiple(double k, Vector & v)
00135 {
00136     if (dim != v.dim)
00137         error("Vector::AddMultiple - vectors are incompatible\n"
00138               "Vectors             - %s [%d] + %s [%d] ",
00139               (const char  *) label, dim, (const char  *) v.label, v.dim);
00140 
00141     for (int i = 0; i < dim; i++)
00142         data[i] += k * v.data[i];
00143 }
00144 
00145 
00146 void Vector::Subtract(Vector & v)
00147 {
00148     if (dim != v.dim)
00149         error("Vector::Subtract - vectors have different dimensions\n"
00150               "Vectors          - %s [%d] + %s [%d] ",
00151               (const char  *) label, dim, (const char  *) v.label, v.dim);
00152 
00153     for (int i = 0; i < dim; i++)
00154         data[i] -= v.data[i];
00155 }
00156 
00157 
00158 void Vector::Zero()
00159 {
00160     for (int i = 0; i < dim; i++)
00161         data[i] = 0.0;
00162 }
00163 
00164 void Vector::Set(double k)
00165 {
00166     for (int i = 0; i < dim; i++)
00167         data[i] = k;
00168 }
00169 
00170 void Vector::SetMultiple(double k, Vector & v)
00171 {
00172     Dimension(v.dim);
00173 
00174     for (int i = 0; i < dim; i++)
00175         data[i] = k * v[i];
00176 }
00177 
00178 double Vector::InnerProduct(Vector & v)
00179 {
00180     if (dim != v.dim)
00181         error("Vector::InnerProduct - vectors have different dimensions\n"
00182               "Vectors              - %s[%d] * %s[%d] ",
00183               (const char  *) label, dim, (const char  *) v.label, v.dim);
00184 
00185     double sum = 0.0;
00186     for (int i = 0; i < dim; i++)
00187         sum += data[i] * v.data[i];
00188 
00189     return sum;
00190 }
00191 
00192 void Vector::Insert(int n, double value)
00193 {
00194     Dimension(dim + 1);
00195 
00196     for (int i = dim - 1; i > n; i--)
00197         data[i] = data[i - 1];
00198     data[n] = value;
00199 }
00200 
00201 void Vector::DeleteDimension(int n)
00202 {
00203     for (int i = n; i < dim - 1; i++)
00204         data[i] = data[i + 1];
00205     dim --;
00206 }
00207 
00208 void Vector::Product(Matrix & m, Vector & v)
00209 {
00210     if (m.cols != v.dim)
00211         error("Vector::Product - Cannot Multiply Matrix by Vector\n"
00212               "Vectors         - %s [%d, %d] * %s [%d]\n",
00213               (const char  *) m.label, m.rows, m.cols,
00214               (const char  *) v.label, v.dim);
00215 
00216     Dimension(m.rows);
00217     Zero();
00218 
00219     for (int i = 0; i < m.rows; i++)
00220         for (int j = 0; j < m.cols; j++)
00221             data[i] += m[i][j] * v[j];
00222 }
00223 
00224 double Vector::Average() const
00225 {
00226     if (dim == 0)
00227         error("Average undefined for null vector %s",
00228               (const char  *) label);
00229 
00230     return Sum() / dim;
00231 }
00232 
00233 double Vector::Product() const
00234 {
00235     double product = 1.0;
00236 
00237     for (int j = 0; j < dim; j++)
00238         product *= data[j];
00239 
00240     return product;
00241 }
00242 
00243 double Vector::Sum() const
00244 {
00245     double sum = 0.0;
00246 
00247     for (int j=0; j<dim; j++)
00248         sum += data[j];
00249 
00250     return sum;
00251 }
00252 
00253 double Vector::SumSquares() const
00254 {
00255     double sum = 0.0;
00256 
00257     for (int j=0; j<dim; j++)
00258         sum += data[j] * data[j];
00259 
00260     return sum;
00261 }
00262 
00263 void Vector::AveVar(double & ave, double & var) const
00264 {
00265     // uses a two pass method to correct for
00266     // round-off errors
00267 
00268     if (dim == 0)
00269         error("Average and Variance undefined for null vector %s",
00270               (const char  *) label);
00271 
00272     double s, ep;
00273 
00274     ave = var = ep = 0.0;
00275 
00276     for (int j=0; j<dim; j++)
00277         ave += data[j];
00278 
00279     ave /= dim;
00280 
00281     for (int j=0; j<dim; j++)
00282     {
00283         s = data[j] - ave;
00284         ep += s;
00285         var += s*s;
00286     }
00287 
00288     if (dim > 1)
00289         var = (var - ep*ep/dim)/(dim-1);
00290 }
00291 
00292 double Vector::Var() const
00293 {
00294     double mean, var;
00295     AveVar(mean, var);
00296     return var;
00297 }
00298 
00299 double Vector::StandardDeviation() const
00300 {
00301     double var = Var();
00302 
00303     if (var < 0.0) var = 0.0;
00304 
00305     return sqrt(var);
00306 }
00307 
00308 void Vector::Print(FILE * f, int d)
00309 {
00310     if (d == -1 || d > dim) d = dim;
00311 
00312     fprintf(f, "%.15s : ", (const char  *) label);
00313     for (int i = 0; i < d; i++)
00314         fprintf(f, "%7.3f ", data[i]);
00315     fprintf(f, "\n");
00316 }
00317 
00318 int Vector::CompareDouble(const double * a, const double * b)
00319 {
00320     if (*a < *b) return -1;
00321     if (*a > *b) return 1;
00322     return 0;
00323 }
00324 
00325 void Vector::Sort()
00326 {
00327     QuickSort(data, dim, sizeof(double), COMPAREFUNC CompareDouble);
00328 }
00329 
00330 void Vector::Sort(Vector & freeRider)
00331 {
00332     QuickSort2(data, freeRider.data, dim, sizeof(double),
00333                COMPAREFUNC CompareDouble);
00334 }
00335 
00336 int Vector::BinarySearch(double element)
00337 {
00338     void * pointer = ::BinarySearch
00339                      (&element, data, dim, sizeof(double), COMPAREFUNC CompareDouble);
00340 
00341     if (pointer == NULL)
00342         return -1;
00343 
00344     return ((double *) pointer) - data;
00345 }
00346 
00347 void Vector::RemoveDuplicates()
00348 {
00349     int out = 0;
00350 
00351     for (int in = 1; in < Length(); in++)
00352         if (data[in] != data[out])
00353             data[++out] = data[in];
00354 
00355     Dimension(out + 1);
00356 }
00357 
00358 bool Vector::operator == (const Vector & rhs) const
00359 {
00360     if (rhs.dim != dim) return false;
00361 
00362     for (int i = 0; i < dim; i++)
00363         if (data[i] != rhs[i])
00364             return false;
00365     return true;
00366 }
00367 
00368 // These functions are useful for simulation
00369 //
00370 
00371 int Vector::CountIfGreater(double threshold) const
00372 {
00373     int count = 0;
00374 
00375     for (int i = 0; i < dim; i++)
00376         if (data[i] > threshold)
00377             count++;
00378 
00379     return count;
00380 }
00381 
00382 int Vector::CountIfGreaterOrEqual(double treshold) const
00383 {
00384     int count = 0;
00385 
00386     for (int i = 0; i < dim; i++)
00387         if (data[i] >= treshold)
00388             count++;
00389 
00390     return count;
00391 }
00392 
00393 // Min and max functions
00394 //
00395 
00396 double Vector::Min() const
00397 {
00398     if (dim == 0)
00399         return 0.0;
00400 
00401     double min = data[0];
00402 
00403     for (int i = 1; i < dim; i++)
00404         if (data[i] < min)
00405             min = data[i];
00406 
00407     return min;
00408 }
00409 
00410 double Vector::Max() const
00411 {
00412     if (dim == 0)
00413         return 0.0;
00414 
00415     double max = data[0];
00416 
00417     for (int i = 1; i < dim; i++)
00418         if (data[i] > max)
00419             max = data[i];
00420 
00421     return max;
00422 }
00423 
00424 // Push and Pop functions for using vector as a stack
00425 //
00426 
00427 void Vector::Push(double value)
00428 {
00429     Dimension(dim + 1);
00430     data[dim - 1] = value;
00431 }
00432 
00433 void Vector::Stack(const Vector & v)
00434 {
00435     int end = dim;
00436 
00437     Dimension(dim + v.dim);
00438 
00439     for (int i = 0; i < v.dim; i++)
00440         data[i + end] = v[i];
00441 }
00442 
00443 // Check if all values are in ascending or descending order
00444 //
00445 
00446 bool Vector::isAscending()
00447 {
00448     for (int i = 1; i < dim; i++)
00449         if (data[i] < data[i - 1])
00450             return false;
00451     return true;
00452 }
00453 
00454 bool Vector::isDescending()
00455 {
00456     for (int i = 1; i < dim; i++)
00457         if (data[i] > data[i - 1])
00458             return false;
00459     return true;
00460 }
00461 
00462 // VectorFunc class
00463 //
00464 
00465 VectorFunc::VectorFunc()
00466 {
00467     f = NULL;
00468 }
00469 
00470 VectorFunc::VectorFunc(double(*func)(Vector &))
00471 {
00472     f = func;
00473 }
00474 
00475 double VectorFunc::Evaluate(Vector & v)
00476 {
00477     return f(v);
00478 }
00479 
00480 #ifndef   M_SQRT2
00481 #define   M_SQRT2        1.41421356
00482 #endif
00483 
00484 #define   MAXROUNDS      10
00485 #define   SQRT_HALF      (1.0/M_SQRT2)
00486 #define   TWO            (M_SQRT2 * M_SQRT2)
00487 
00488 void VectorFunc::Derivative(Vector & x, Vector & d, double h_start)
00489 {
00490     double a[MAXROUNDS][MAXROUNDS];
00491 
00492     // Calculate derivatives along each direction ...
00493     for (int k = 0; k < x.dim; k++)
00494     {
00495         double left, right;
00496         double save_x = x[k];
00497         double h = h_start;
00498 
00499         // Evaluate function to the left of x along direction k
00500         x[k] = save_x - h;
00501         left  = Evaluate(x);
00502 
00503         // Initialize or update dfmin if appropriate...
00504         if (k == 0 || left < dfmin)
00505             dfmin = left, dpmin = x;
00506 
00507         // Evaluate function to the right of x along direction k
00508         x[k] = save_x + h;
00509         right = Evaluate(x);
00510 
00511         // Update dfmin
00512         if (right < dfmin)
00513             dfmin = left, dpmin = x;
00514 
00515         // Initial crude estimate
00516         a[0][0] = (right - left) / (2.0 * h);
00517 
00518         // Initial guess of error is large
00519         double err = 1e30;
00520 
00521         // At each round, update Neville tableau with smaller stepsize and higher
00522         // order extrapolation ...
00523         for (int i = 1; i < MAXROUNDS; i++)
00524         {
00525             // Decrease h
00526             h *= SQRT_HALF;
00527 
00528             // Re-evaluate function and update dfmin as required
00529             x[k]  = save_x - h;
00530             left  = Evaluate(x);
00531             if (left < dfmin) dfmin = left, dpmin = x;
00532             x[k]  = save_x + h;
00533             right = Evaluate(x);
00534             if (right < dfmin) dfmin = right, dpmin = x;
00535 
00536             // Improved estimate of derivative
00537             a[0][i] = (right - left) / (2.0 * h);
00538 
00539             // Calculate extrapolations of various orders ...
00540             double factor = TWO;
00541 
00542             for (int j = 1; j <= i; j++)
00543             {
00544                 a[j][i] = (a[j-1][i] * factor - a[j-1][i-1])/(factor - 1.0);
00545 
00546                 factor *= TWO;
00547 
00548                 double error = max(fabs(a[j][i] - a[j-1][i]), fabs(a[j][i] - a[j-1][i-1]));
00549 
00550                 // Did we improve solution?
00551                 if (error < err)
00552                 {
00553                     err = error;
00554                     d[k] = a[j][i];
00555                 }
00556             }
00557 
00558             // Stop if solution is deteriorating ...
00559             if (fabs(a[i][i] - a[i-1][i-1]) >= 2.0 * err)
00560             {
00561                 x[k] = save_x;
00562                 break;
00563             }
00564         }
00565 
00566         x[k] = save_x;
00567     }
00568 }
00569 
00570 int Vector::SafeCount() const
00571 {
00572     int nonMissing = dim;
00573 
00574     for (int i = 0; i < dim; i++)
00575         if (data[i] == _NAN_)
00576             nonMissing--;
00577 
00578     return nonMissing;
00579 }
00580 
00581 double Vector::SafeMin() const
00582 {
00583     double min = _NAN_;
00584     int i;
00585 
00586     for (i = 0; i < dim; i++)
00587         if (data[i] != _NAN_)
00588         {
00589             min = data[i];
00590             break;
00591         }
00592 
00593     for (; i < dim; i++)
00594         if (data[i] != _NAN_ && data[i] < min)
00595             min = data[i];
00596 
00597     return min;
00598 }
00599 
00600 double Vector::SafeMax() const
00601 {
00602     double max = _NAN_;
00603     int i;
00604 
00605     for (i = 0; i < dim; i++)
00606         if (data[i] != _NAN_)
00607         {
00608             max = data[i];
00609             break;
00610         }
00611 
00612     for (; i < dim; i++)
00613         if (data[i] != _NAN_ && data[i] > max)
00614             max = data[i];
00615 
00616     return max;
00617 }
00618 
00619 void Vector::Reverse()
00620 {
00621     for (int i = 0, j = dim - 1; i < j; i++, j--)
00622         Swap(i, j);
00623 }
00624 
00625 void Vector::InsertInSortedList(int value)
00626 {
00627     // Skip through large elements
00628     int pos = dim - 1;
00629 
00630     while (pos >= 0 && data[pos] > value)
00631         pos--;
00632 
00633     // If the value is already in the list, we are done
00634     if (pos >= 0 && data[pos] == value)
00635         return;
00636 
00637     // Otherwise we need to grow array
00638     Dimension(dim + 1);
00639 
00640     // And then shift larger elements to the right
00641     pos++;
00642     for (int i = dim - 1; i > pos; i--)
00643         data[i] = data[i - 1];
00644 
00645     data[pos] = value;
00646 }
00647 
00648 void Vector::Swap(Vector & rhs)
00649 {
00650     double * temp = rhs.data;
00651     rhs.data = data;
00652     data = temp;
00653 
00654     int swap = rhs.dim;
00655     rhs.dim = dim;
00656     dim = swap;
00657 
00658     swap = rhs.size;
00659     rhs.size = size;
00660     size = swap;
00661 }
00662 
00663 double Vector::Average(double returnIfNull)
00664 {
00665     if (Length() == 0)
00666         return returnIfNull;
00667 
00668     return Average();
00669 }
00670 
00671 double Vector::Var(double returnIfNull)
00672 {
00673     if (Length() == 0)
00674         return returnIfNull;
00675 
00676     return Var();
00677 }
00678 
00679 double Vector::StandardDeviation(double returnIfNull)
00680 {
00681     if (Length() == 0)
00682         return returnIfNull;
00683 
00684     return StandardDeviation();
00685 }
Generated on Tue Sep 6 17:52:00 2011 for libStatGen Software by  doxygen 1.6.3