/* Operations on vectors of floats or doubles. * * Can operate on vectors of doubles, floats, or integers - appropriate * routine is prefixed with D, F, or I. For example, esl_vec_DSet() is * the Set routine for a vector of doubles; esl_vec_ISet() is for integers. * * Contents: * 1. The vectorops API. * 2. Unit tests. * 3. Test driver. * 4. Examples. * 5. Copyright and license information. * */ #include "esl_config.h" #include #include #include "easel.h" #include "esl_vectorops.h" /* Function: esl_vec_DSet() * Synopsis: Set all items in vector to scalar value. * * Purpose: Sets all items in to . * * and do the same, * for float and integer vectors. */ void esl_vec_DSet(double *vec, int n, double value) { int x; for (x = 0; x < n; x++) vec[x] = value; } void esl_vec_FSet(float *vec, int n, float value) { int x; for (x = 0; x < n; x++) vec[x] = value; } void esl_vec_ISet(int *vec, int n, int value) { int x; for (x = 0; x < n; x++) vec[x] = value; } /* Function: esl_vec_DScale() * Synopsis: Multiply all items in vector by scalar value. * * Purpose: Multiplies all items in by . * * and do the same, * for float and integer vectors. * * Essentially the same as BLAS1's xSCAL(). */ void esl_vec_DScale(double *vec, int n, double scale) { int x; for (x = 0; x < n; x++) vec[x] *= scale; } void esl_vec_FScale(float *vec, int n, float scale) { int x; for (x = 0; x < n; x++) vec[x] *= scale; } void esl_vec_IScale(int *vec, int n, int scale) { int x; for (x = 0; x < n; x++) vec[x] *= scale; } /* Function: esl_vec_DIncrement() * Synopsis: Add a scalar to all items in a vector. * Incept: SRE, Mon Mar 21 11:56:57 2005 [St. Louis] * * Purpose: Adds scalar to all items in the -vector . * * and do the * same, for float and integer vectors. */ void esl_vec_DIncrement(double *v, int n, double x) { int i; for (i = 0; i < n; i++) v[i] += x; } void esl_vec_FIncrement(float *v, int n, float x) { int i; for (i = 0; i < n; i++) v[i] += x; } void esl_vec_IIncrement(int *v, int n, int x) { int i; for (i = 0; i < n; i++) v[i] += x; } /* Function: esl_vec_DSum() * Synopsis: Returns $\sum_i x_i$. * * Purpose: Returns the scalar sum of the items in . * * and do the same, * but for float and integer vectors. */ double esl_vec_DSum(double *vec, int n) { double sum = 0.; int x; for (x = 0; x < n; x++) sum += vec[x]; return sum; } float esl_vec_FSum(float *vec, int n) { float sum = 0.; int x; for (x = 0; x < n; x++) sum += vec[x]; return sum; } int esl_vec_ISum(int *vec, int n) { int sum = 0; int x; for (x = 0; x < n; x++) sum += vec[x]; return sum; } /* Function: esl_vec_DAdd() * Synopsis: Vector addition of two vectors. * * Purpose: Vector addition. Adds to , leaving * result in . ( is unchanged.). * Both vectors are of size . * * and do the same, * for float and integer vectors. */ void esl_vec_DAdd(double *vec1, const double *vec2, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x]; } void esl_vec_FAdd(float *vec1, const float *vec2, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x]; } void esl_vec_IAdd(int *vec1, const int *vec2, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x]; } /* Function: esl_vec_DAddScaled() * Synopsis: Scale and add it to . * * Purpose: Scales by scalar , and adds that * to . Both vectors are of size . * * and do the same, * for float and integer vectors. * * Essentially the same as BLAS1 xAXPY(). */ void esl_vec_DAddScaled(double *vec1, double *vec2, double a, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x] * a; } void esl_vec_FAddScaled(float *vec1, float *vec2, float a, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x] * a; } void esl_vec_IAddScaled(int *vec1, int *vec2, int a, int n) { int x; for (x = 0; x < n; x++) vec1[x] += vec2[x] * a; } /* Function: esl_vec_DCopy() * Synopsis: Set vector to same values as . * * Purpose: Copies to . is * unchanged. Both vectors are of size . * * and do the same, * for float and integer vectors. * * Essentially the same as BLAS1 xCOPY(). */ void esl_vec_DCopy(const double *src, const int n, double *dest) { int x; for (x = 0; x < n; x++) dest[x] = src[x]; } void esl_vec_FCopy(const float *src, const int n, float *dest) { int x; for (x = 0; x < n; x++) dest[x] = src[x]; } void esl_vec_ICopy(const int *src, const int n, int *dest) { int x; for (x = 0; x < n; x++) dest[x] = src[x]; } /* Function: esl_vec_DCompare() * Synopsis: Return if two vectors are equal. * Incept: SRE, Mon Nov 6 10:20:28 2006 [Janelia] * * Purpose: Compare to for equality, by * comparing each cognate element pair. Both vectors * are of size . Equality of elements is * defined by being $\leq$ fractional tolerance * for floating point comparisons, and strict equality * for integer comparisons. Return * if the vectors are equal, and if not. * * If , the test always succeeds. In this case, either * and (or both) may be . This * accommodates an occasional convention of leaving empty * vectors . * * and do the same, * for float and integer vectors. */ int esl_vec_DCompare(const double *vec1, const double *vec2, int n, double tol) { int i; for (i = 0; i < n; i++) if (esl_DCompare(vec1[i], vec2[i], tol) == eslFAIL) return eslFAIL; return eslOK; } int esl_vec_FCompare(const float *vec1, const float *vec2, int n, float tol) { int i; for (i = 0; i < n; i++) if (esl_DCompare(vec1[i], vec2[i], tol) == eslFAIL) return eslFAIL; return eslOK; } int esl_vec_ICompare(const int *vec1, const int *vec2, int n) { int i; for (i = 0; i < n; i++) if (vec1[i] != vec2[i]) return eslFAIL; return eslOK; } /* Function: esl_vec_DSwap() * Synopsis: Swap two vectors. * * Purpose: Swaps and . * Both vectors are of size . * * and do the same, * for float and integer vectors. * * Essentially the same as BLAS1 xSWAP(). * * You will be better off swapping the pointers to * the vectors, if that's feasible. */ void esl_vec_DSwap(double *vec1, double *vec2, int n) { int x; double tmp; for (x = 0; x < n; x++) { tmp = vec1[x]; vec1[x] = vec2[x]; vec2[x] = tmp; } } void esl_vec_FSwap(float *vec1, float *vec2, int n) { int x; float tmp; for (x = 0; x < n; x++) { tmp = vec1[x]; vec1[x] = vec2[x]; vec2[x] = tmp; } } void esl_vec_ISwap(int *vec1, int *vec2, int n) { int x; int tmp; for (x = 0; x < n; x++) { tmp = vec1[x]; vec1[x] = vec2[x]; vec2[x] = tmp; } } /* Function: esl_vec_DReverse() * Synopsis: Reverse a vector (possibly in place). * * Purpose: Put the values from vector in reversed order in * . Caller provides storage in for at least * values. * * and can be the same, in which case is * reversed in place. * * and * do the same, for float and integer values. */ void esl_vec_DReverse(double *vec, double *rev, int n) { int i; double x; for (i = 0; i < n/2; i++) { x = vec[n-i-1]; rev[n-i-1] = vec[i]; rev[i] = x; } if (n%2) rev[i] = vec[i]; } void esl_vec_FReverse(float *vec, float *rev, int n) { int i; float x; for (i = 0; i < n/2; i++) { x = vec[n-i-1]; rev[n-i-1] = vec[i]; rev[i] = x; } if (n%2) rev[i] = vec[i]; } void esl_vec_IReverse(int *vec, int *rev, int n) { int i; int x; for (i = 0; i < n/2; i++) { x = vec[n-i-1]; rev[n-i-1] = vec[i]; rev[i] = x; } if (n%2) rev[i] = vec[i]; } /* Function: esl_vec_DDot() * Synopsis: Return the dot product of two vectors. * * Purpose: Returns the scalar dot product $\cdot$ . * Both vectors are of size . * * and do the same, * for float and integer vectors. */ double esl_vec_DDot(double *vec1, double *vec2, int n) { double result = 0.; int x; for (x = 0; x < n; x++) result += vec1[x] * vec2[x]; return result; } float esl_vec_FDot(float *vec1, float *vec2, int n) { float result = 0.; int x; for (x = 0; x < n; x++) result += vec1[x] * vec2[x]; return result; } int esl_vec_IDot(int *vec1, int *vec2, int n) { int result = 0; int x; for (x = 0; x < n; x++) result += vec1[x] * vec2[x]; return result; } /* Function: esl_vec_DMax() * Synopsis: Return value of the maximum element in a vector. * * Purpose: Returns the maximum value of the values * in . * * and do the same, * for float and integer vectors. */ double esl_vec_DMax(const double *vec, int n) { int i; double best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] > best) best = vec[i]; return best; } float esl_vec_FMax(const float *vec, int n) { int i; float best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] > best) best = vec[i]; return best; } int esl_vec_IMax(const int *vec, int n) { int i; int best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] > best) best = vec[i]; return best; } /* Function: esl_vec_DMin() * Synopsis: Return value of the minimum element in a vector. * * Purpose: Returns the minimum value of the values * in . * * and do the same, * for float and integer vectors. */ double esl_vec_DMin(const double *vec, int n) { int i; double best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] < best) best = vec[i]; return best; } float esl_vec_FMin(const float *vec, int n) { int i; float best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] < best) best = vec[i]; return best; } int esl_vec_IMin(const int *vec, int n) { int i; int best; best = vec[0]; for (i = 1; i < n; i++) if (vec[i] < best) best = vec[i]; return best; } /* Function: esl_vec_DArgMax() * Synopsis: Return index of maximum element in a vector. * * Purpose: Returns the index of the maximum value in the values * in . In case of ties, the element with the smallest index * is returned. * * can be 0 and can be , in which case the * function returns 0. * * and do the same, * for float and integer vectors. * * Note: Do not change the behavior that the smallest index is * returned in case of ties. Some functions rely on this * behavior: optimal accuracy tracebacks in HMMER for example. */ int esl_vec_DArgMax(const double *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] > vec[best]) best = i; return best; } int esl_vec_FArgMax(const float *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] > vec[best]) best = i; return best; } int esl_vec_IArgMax(const int *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] > vec[best]) best = i; return best; } /* Function: esl_vec_DArgMin() * Synopsis: Return index of minimum element in a vector. * * Purpose: Returns the index of the minimum value in the values * in . * * and do the same, * for float and integer vectors. */ int esl_vec_DArgMin(const double *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] < vec[best]) best = i; return best; } int esl_vec_FArgMin(const float *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] < vec[best]) best = i; return best; } int esl_vec_IArgMin(const int *vec, int n) { int i; int best = 0; for (i = 1; i < n; i++) if (vec[i] < vec[best]) best = i; return best; } /* some static functions to pass to qsort() that the * upcoming Sort() functions will call */ static int qsort_DIncreasing(const void *xp1, const void *xp2) { double x1 = * (double *) xp1; double x2 = * (double *) xp2; if (x1 < x2) return -1; if (x1 > x2) return 1; return 0; } static int qsort_FIncreasing(const void *xp1, const void *xp2) { float x1 = * (float *) xp1; float x2 = * (float *) xp2; if (x1 < x2) return -1; if (x1 > x2) return 1; return 0; } static int qsort_IIncreasing(const void *xp1, const void *xp2) { int x1 = * (int *) xp1; int x2 = * (int *) xp2; if (x1 < x2) return -1; if (x1 > x2) return 1; return 0; } static int qsort_DDecreasing(const void *xp1, const void *xp2) { double x1 = * (double *) xp1; double x2 = * (double *) xp2; if (x1 > x2) return -1; if (x1 < x2) return 1; return 0; } static int qsort_FDecreasing(const void *xp1, const void *xp2) { float x1 = * (float *) xp1; float x2 = * (float *) xp2; if (x1 > x2) return -1; if (x1 < x2) return 1; return 0; } static int qsort_IDecreasing(const void *xp1, const void *xp2) { int x1 = * (int *) xp1; int x2 = * (int *) xp2; if (x1 > x2) return -1; if (x1 < x2) return 1; return 0; } /* Function: esl_vec_DSortIncreasing() * Synopsis: Sort vector from smallest to largest. * Incept: SRE, Wed Aug 17 10:44:31 2005 [St. Louis] * * Purpose: Sorts in place, from smallest to largest value. * (That is, is the minimum and is * the maximum.) * * and * do the same, for float and integer vectors. */ void esl_vec_DSortIncreasing(double *vec, int n) { qsort((void *) vec, n, sizeof(double), qsort_DIncreasing); } void esl_vec_FSortIncreasing(float *vec, int n) { qsort((void *) vec, n, sizeof(float), qsort_FIncreasing); } void esl_vec_ISortIncreasing(int *vec, int n) { qsort((void *) vec, n, sizeof(int), qsort_IIncreasing); } /* Function: esl_vec_DSortDecreasing() * Synopsis: Sort vector from largest to smallest. * Incept: SRE, Wed Aug 17 10:44:31 2005 [St. Louis] * * Purpose: Sorts in place, from largest to smallest value. * (That is, is the maximum and is * the minimum.) * * and * do the same, for float and integer vectors. */ void esl_vec_DSortDecreasing(double *vec, int n) { qsort((void *) vec, n, sizeof(double), qsort_DDecreasing); } void esl_vec_FSortDecreasing(float *vec, int n) { qsort((void *) vec, n, sizeof(float), qsort_FDecreasing); } void esl_vec_ISortDecreasing(int *vec, int n) { qsort((void *) vec, n, sizeof(int), qsort_IDecreasing); } /* Function: esl_vec_DDump() * Synopsis: Output vector to a stream as text. * Incept: ER, Thu Jul 21 12:54:56 CDT 2005 [St. Louis] * * Purpose: Given a vector, dump it to stream . * * If