libStatGen Software
1
|
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 }