https://github.com/cran/tgp
Tip revision: 9b4a3bcc59be4ea56fdbd635e201ac2aabc94354 authored by Robert B. Gramacy on 17 October 2008, 00:00:00 UTC
version 2.1-4
version 2.1-4
Tip revision: 9b4a3bc
matrix.c
/********************************************************************************
*
* Bayesian Regression and Adaptive Sampling with Gaussian Process Trees
* Copyright (C) 2005, University of California
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Questions? Contact Robert B. Gramacy (rbgramacy@ams.ucsc.edu)
*
********************************************************************************/
#include "rhelp.h"
/* #include "rand_draws.h" */
#include "matrix.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/* #define DEBUG */
/*
* get_data_rect:
*
* compute and return the rectangle implied by the X data
*/
double **get_data_rect(double **X, unsigned int N, unsigned int d)
{
unsigned int i,j;
double ** rect = new_matrix(2, d);
for(i=0; i<d; i++) {
rect[0][i] = X[0][i];
rect[1][i] = X[0][i];
for(j=1; j<N; j++) {
if(X[j][i] < rect[0][i]) rect[0][i] = X[j][i];
else if(X[j][i] > rect[1][i]) rect[1][i] = X[j][i];
}
}
return(rect);
}
/*
* replace matrix with zeros
*/
void zero(double **M, unsigned int n1, unsigned int n2)
{
unsigned int i, j;
for(i=0; i<n1; i++) for(j=0; j<n2; j++) M[i][j] = 0;
}
/*
* replace square matrix with identitiy
*/
void id(double **M, unsigned int n)
{
unsigned int i;
zero(M, n, n);
for(i=0; i<n; i++) M[i][i] = 1.0;
}
/*
* same as new_matrix below, but for creating
* n x n identity matrices
*/
double ** new_id_matrix(unsigned int n)
{
unsigned int i;
double** m = new_zero_matrix(n, n);
for(i=0; i<n; i++) m[i][i] = 1.0;
return m;
}
/*
* same as new_matrix below, but zeros out the matrix
*/
double ** new_zero_matrix(unsigned int n1, unsigned int n2)
{
unsigned int i, j;
double **m = new_matrix(n1, n2);
for(i=0; i<n1; i++) for(j=0; j<n2; j++) m[i][j] = 0.0;
return m;
}
/*
* create a new n1 x n2 matrix which is allocated like
* and n1*n2 array, but can be referenced as a 2-d array
*/
double ** new_matrix(unsigned int n1, unsigned int n2)
{
int i;
double **m;
if(n1 == 0 || n2 == 0) return NULL;
m = (double**) malloc(sizeof(double*) * n1);
assert(m);
m[0] = (double*) malloc(sizeof(double) * (n1*n2));
assert(m[0]);
for(i=1; i<n1; i++) m[i] = m[i-1] + n2;
return m;
}
/*
* create a double ** Matrix from a double * vector
* should be freed with the free command, rather than
* delete_matrix
*/
double ** new_matrix_bones(double *v, unsigned int n1, unsigned int n2)
{
double **M;
int i;
M = (double **) malloc(sizeof(double*) * n1);
M[0] = v;
for(i=1; i<n1; i++) M[i] = M[i-1] + n2;
return(M);
}
/*
* create a new n1 x n2 matrix which is allocated like
* and n1*n2 array, and copy the of n1 x n2 M into it.
*/
double ** new_dup_matrix(double** M, unsigned int n1, unsigned int n2)
{
double **m;
if(n1 <= 0 || n2 <= 0) {
/* assert(M == NULL); */
return NULL;
}
m = new_matrix(n1, n2);
dup_matrix(m, M, n1, n2);
return m;
}
/*
* create a new n1 x (n2-1) matrix which is allocated like
* an n1*(n2-1) array, and copy M[n1][2:n2] into it.
*/
double ** new_shift_matrix(double** M, unsigned int n1, unsigned int n2)
{
double **m;
unsigned int i, j;
if(n1 <= 0 || n2 <= 1) {
assert(M == NULL);
return NULL;
}
m = new_matrix(n1, (n2-1));
/* printMatrix(M, n1, n2, stdout); */
for(i=0; i<n1; i++) for(j=0; j<(n2-1); j++) m[i][j] = M[i][j+1];
/* printMatrix(m, n1, (n2-1), stdout); */
return m;
}
/*
* copy M2 to M1
*/
void dup_matrix(double** M1, double **M2, unsigned int n1, unsigned int n2)
{
unsigned int i;
if(n1 == 0 || n2 == 0) return;
assert(M1 && M2);
for(i=0; i<n1; i++) dupv(M1[i], M2[i], n2);
}
/*
* swap the pointers of M2 to M1, and vice-versa
* (tries to aviod dup_matrix when unnecessary)
*/
void swap_matrix(double **M1, double **M2, unsigned int n1, unsigned int n2)
{
unsigned int i;
double *temp;
temp = M1[0];
M1[0] = M2[0];
M2[0] = temp;
for(i=1; i<n1; i++) {
M1[i] = M1[i-1] + n2;
M2[i] = M2[i-1] + n2;
}
}
/*
* create a bigger n1 x n2 matrix which is allocated like
* and n1*n2 array, and copy the of n1 x n2 M into it.
* deletes the old matrix
*/
double ** new_bigger_matrix(double** M, unsigned int n1, unsigned int n2,
unsigned int n1_new, unsigned int n2_new)
{
int i;
double **m;
assert(n1_new >= n1);
assert(n2_new >= n2);
if(n1_new <= 0 || n2_new <= 0) {
assert(M == NULL);
return NULL;
}
if(M == NULL) {
assert(n1 == 0 || n2 == 0);
return new_zero_matrix(n1_new, n2_new);
}
if(n2 == n2_new) {
m = (double**) malloc(sizeof(double*) * n1_new);
assert(m);
m[0] = realloc(M[0], sizeof(double) * n1_new * n2_new);
free(M);
assert(m[0]);
for(i=1; i<n1_new; i++) m[i] = m[i-1] + n2_new;
zerov(m[n1], (n1_new-n1)*n2_new);
} else {
m = new_zero_matrix(n1_new, n2_new);
dup_matrix(m, M, n1, n2);
delete_matrix(M);
}
return m;
}
/*
* create a new n1 x n2 matrix which is allocated like
* and n1*n2 array, and copy the of n1 x n2 M into it.
*/
double ** new_normd_matrix(double** M, unsigned int n1, unsigned int n2,
double **rect, double normscale)
{
double **m;
m = new_dup_matrix(M, n1, n2);
normalize(m, rect, n1, n2, normscale);
return m;
}
/*
* create a new n2 x n1 matrix which is allocated like
* and n1*n2 array, and copy the TRANSPOSE of n1 x n2 M into it.
*/
double ** new_t_matrix(double** M, unsigned int n1, unsigned int n2)
{
int i,j;
double **m;
if(n1 <= 0 || n2 <= 0) {
assert(M == NULL);
return NULL;
}
m = new_matrix(n2, n1);
for(i=0; i<n1; i++) for(j=0; j<n2; j++) m[j][i] = M[i][j];
return m;
}
/*
* delete a matrix allocated as above
*/
void delete_matrix(double** m)
{
if(m == NULL) return;
assert(*m);
free(*m);
assert(m);
free(m);
}
/*
* delete a matrix allocated as above
*/
void delete_imatrix(int** m)
{
if(m == NULL) return;
assert(*m);
free(*m);
assert(m);
free(m);
}
/*
* print an n x col matrix allocated as above out an opened outfile.
* actually, this routine can print any double**
*/
void printMatrix(double **M, unsigned int n, unsigned int col, FILE *outfile)
{
int i,j;
assert(outfile);
if(n > 0 && col > 0) assert(M);
for(i=0; i<n; i++) {
for(j=0; j<col; j++) {
#ifdef DEBUG
if(j==col-1) myprintf(outfile, "%.20f\n", M[i][j]);
else myprintf(outfile, "%.20f ", M[i][j]);
#else
if(j==col-1) myprintf(outfile, "%g\n", M[i][j]);
else myprintf(outfile, "%g ", M[i][j]);
#endif
}
}
}
/*
* print an n x col integer matrix allocated as above out an opened outfile.
* actually, this routine can print any double**
*/
void printIMatrix(int **M, unsigned int n, unsigned int col, FILE *outfile)
{
int i,j;
assert(outfile);
if(n > 0 && col > 0) assert(M);
for(i=0; i<n; i++) {
for(j=0; j<col; j++) {
#ifdef DEBUG
if(j==col-1) myprintf(outfile, "%d\n", M[i][j]);
else myprintf(outfile, "%d ", M[i][j]);
#else
if(j==col-1) myprintf(outfile, "%d\n", M[i][j]);
else myprintf(outfile, "%d ", M[i][j]);
#endif
}
}
}
/*
* print the transpose of an n x col matrix allocated as above out an
* opened outfile. actually, this routine can print any double**
*/
void printMatrixT(double **M, unsigned int n, unsigned int col, FILE *outfile)
{
int i,j;
assert(outfile);
if(n > 0 && col > 0) assert(M);
for(i=0; i<col; i++) {
for(j=0; j<n; j++) {
if(j==n-1) myprintf(outfile, "%g\n", M[j][i]);
else myprintf(outfile, "%g ", M[j][i]);
}
}
}
/*
* add two matrices of the same size
* M1 = a*M1 + b*M2
*/
void add_matrix(double a, double **M1, double b, double **M2,
unsigned int n1, unsigned int n2)
{
unsigned int i,j;
assert(n1 > 0 && n2 > 0);
assert(M1 && M2);
for(i=0; i<n1; i++)
for(j=0; j<n2; j++)
M1[i][j] = a*M1[i][j] + b*M2[i][j];
}
/*
* add_p_matrix:
*
* add v[n1][n2] to V into the positions specified by p1[n1] and
* p2[n2]
*/
void add_p_matrix(double a, double **V, int *p1, int *p2, double b, double **v,
unsigned int n1, unsigned int n2)
{
int i,j;
assert(V); assert(p1); assert(p2); assert(n1 > 0 && n2 > 0);
for(i=0; i<n1; i++) for(j=0; j<n2; j++)
V[p1[i]][p2[j]] = a*V[p1[i]][p2[j]] + b*v[i][j];
}
/*
* subtract off (element-wise) the center[n2] vector from each
* column of the M[n1][n2] matrix
*/
void center_columns(double **M, double *center, unsigned int n1, unsigned int n2)
{
unsigned int i,j;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(center && M);
for(i=0; i<n2; i++)
for(j=0; j<n1; j++)
M[j][i] -= center[i];
}
/*
* subtract off (element-wise) the center[n1] vector from each
* row of the M[n1][n2] matrix
*/
void center_rows(double **M, double *center, unsigned int n1, unsigned int n2)
{
unsigned int i;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(center && M);
for(i=0; i<n1; i++) centerv(M[i], n2, center[i]);
}
/*
* subtract off (element-wise) the center[n2] vector from each
* column of the M[n1][n2] matrix
*/
void norm_columns(double **M, double *norm, unsigned int n1, unsigned int n2)
{
unsigned int i,j;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(norm && M);
for(i=0; i<n2; i++)
for(j=0; j<n1; j++)
M[j][i] /= norm[i];
}
/*
* wmean_of_columns:
*
* fill mean[n1] with the weighted mean of the columns of M (n1 x n2);
* weight vector should have length n1;
*/
void wmean_of_columns(double *mean, double **M, unsigned int n1, unsigned int n2,
double *weight)
{
unsigned int i,j;
double sw;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(mean && M);
/* find normailzation constant */
if(weight) sw = sumv(weight, n1);
else sw = (double) n1;
/* calculate mean of columns */
for(i=0; i<n2; i++) {
mean[i] = 0;
if(weight) for(j=0; j<n1; j++) mean[i] += weight[j] * M[j][i];
else for(j=0; j<n1; j++) mean[i] += M[j][i];
mean[i] = mean[i] / sw;
}
}
/*
* sum_of_columns_f:
*
* fill sum[n1] with the sum of the columns of M (n1 x n2);
* each element of which is sent through function f() first;
*/
void sum_of_columns_f(double *s, double **M, unsigned int n1, unsigned int n2,
double(*f)(double))
{
unsigned int i,j;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(s && M);
/* calculate mean of columns */
for(i=0; i<n2; i++) {
s[i] = 0;
for(j=0; j<n1; j++) s[i] += f(M[j][i]);
}
}
/*
* sum_of_each_column_f:
*
* fill sum[n1] with the sum of the columns of M (n1[i] x n2);
* each element of which is sent through function f() first;
* n1 must have n2 entries
*/
void sum_of_each_column_f(double *s, double **M, unsigned int *n1,
unsigned int n2, double(*f)(double))
{
unsigned int i,j;
/* sanity checks */
if(n2 <= 0) {return;}
assert(s && M);
/* calculate mean of columns */
for(i=0; i<n2; i++) {
s[i] = 0;
for(j=0; j<n1[i]; j++) s[i] += f(M[j][i]);
}
}
/*
* wmean_of_columns_f:
*
* fill mean[n1] with the weighted mean of the columns of M (n1 x n2);
* weight vector should have length n1 -- each element of which is
* sent through function f() first;
*/
void wmean_of_columns_f(double *mean, double **M, unsigned int n1, unsigned int n2,
double *weight, double(*f)(double))
{
unsigned int i,j;
double sw;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(mean && M);
/* find normailzation constant */
if(weight) sw = sumv(weight, n1);
else sw = (double) n1;
/* calculate mean of columns */
for(i=0; i<n2; i++) {
mean[i] = 0;
if(weight) for(j=0; j<n1; j++) mean[i] += weight[j] * f(M[j][i]);
else for(j=0; j<n1; j++) mean[i] += f(M[j][i]);
mean[i] = mean[i] / sw;
}
}
/*
* wmean_of_rows_f:
*
* fill mean[n1] with the weighted mean of the rows of M (n1 x n2);
* weight vector should have length n2 -- each element of which is
* sent through function f() first;
*/
void wmean_of_rows_f(double *mean, double **M, unsigned int n1, unsigned int n2,
double *weight, double(*f)(double))
{
unsigned int i,j;
double sw;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(mean && M);
/* calculate the normalization constant */
if(weight) sw = sumv(weight, n2);
else sw = (double) n2;
/* calculate the mean of rows */
for(i=0; i<n1; i++) {
mean[i] = 0;
if(weight) for(j=0; j<n2; j++) mean[i] += weight[j] * f(M[i][j]);
else for(j=0; j<n2; j++) mean[i] += f(M[i][j]);
mean[i] = mean[i] / sw;
}
}
/*
* wmean_of_rows_f:
*
* fill mean[n1] with the weighted mean of the rows of M (n1 x n2);
* weight vector should have length n2;
*/
void wmean_of_rows(double *mean, double **M, unsigned int n1, unsigned int n2,
double *weight)
{
unsigned int i,j;
double sw;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(mean && M);
/* calculate the normalization constant */
if(weight) sw = sumv(weight, n2);
else sw = (double) n2;
/* calculate the mean of rows */
for(i=0; i<n1; i++) {
mean[i] = 0;
if(weight) for(j=0; j<n2; j++) mean[i] += weight[j] * M[i][j];
else for(j=0; j<n2; j++) mean[i] += M[i][j];
mean[i] = mean[i] / sw;
}
}
/*
* wcov_of_columns:
*
* fill cov[n1,n1] with the weighted covariance of the columns of M (n1 x n2);
* weight vector should have length n1;
*/
void wcov_of_columns(double **cov, double **M, double *mean, unsigned int n1,
unsigned int n2, double *weight)
{
unsigned int i,j,t;
double sw;
/* sanity checks */
if(n1 <= 0 || n2 <= 0) {return;}
assert(cov && M && mean);
/* find normailzation constant */
if(weight) sw = sumv(weight, n1);
else sw = (double) n1;
/* calculate mean of columns */
for(i=0; i<n2; i++) {
zerov(cov[i], n2);
if(weight) {
for(t=0; t<n1; t++) {
for(j=i; j<n2; j++) /* using weights */
cov[i][j] += weight[t]*(M[t][i]*M[t][j] - M[t][i]*mean[j] -
M[t][j]*mean[i]) + mean[i]*mean[j];
}
} else {
for(t=0; t<n1; t++) {
for(j=i; j<n2; j++) /* not using weights */
cov[i][j] += (M[t][i]*M[t][j] - M[t][i]*mean[j] -
M[t][j]*mean[i] + mean[i]*mean[j]);
}
}
scalev(cov[i], n2, 1.0/sw);
/* fill in the other half */
for(j=0; j<i; j++) cov[i][j] = cov[j][i];
}
}
/*
* wcovx_of_columns:
*
* fill mean[n1] with the weighted covariance of the columns of M1 (T x n1)
* to those of M2 (T x n2); weight vector should have length T;
*/
void wcovx_of_columns(double **cov, double **M1, double **M2, double *mean1,
double *mean2, unsigned int T, unsigned int n1,
unsigned int n2, double *weight)
{
unsigned int i,j,t;
double sw;
/* sanity checks */
if(T <= 0 || n1 <= 0 || n2 <= 0) {return;}
assert(cov && M1 && M2 && mean1 && mean2);
/* find normailzation constant */
if(weight) sw = sumv(weight, T);
else sw = (double) T;
/* calculate mean of columns */
for(i=0; i<n1; i++) {
zerov(cov[i], n2);
if(weight) {
for(t=0; t<T; t++) {
for(j=0; j<n2; j++) /* using weights */
cov[i][j] += weight[t] * (M1[t][i]*M2[t][j] - M1[t][i]*mean2[j] -
M2[t][j]*mean1[i]) + mean1[i]*mean2[j];
}
} else {
for(t=0; t<T; t++) {
for(j=0; j<n2; j++) /* not using weights */
cov[i][j] += (M1[t][i]*M2[t][j] - M1[t][i]*mean2[j] -
M2[t][j]*mean1[i] + mean1[i]*mean2[j]);
}
}
scalev(cov[i], n2, 1.0/sw);
}
}
/*
* fill the q^th quantile for each column of M (n1 x n2)
* if non-null, the w argument should contain NORMALIZED
* weights to be used in a bootstrap calculation of the
* quantiles
*/
void quantiles_of_columns(double **Q, double *q, unsigned int m,
double **M, unsigned int n1, unsigned int n2,
double *w)
{
unsigned int i,j;
double *Mc, *wnorm, *qs;
double W;
/* check if there is anything to do */
if(n1 == 0) return;
/* allocate vector representing the current column,
* and for storing the m quantiles */
Mc = new_vector(n1);
qs = new_vector(m);
/* if non-null, create a normalized weight vector */
if(w != NULL) {
W = sumv(w, n1);
wnorm = new_dup_vector(w, n1);
scalev(wnorm, n1, 1.0/W);
} else {
wnorm = NULL;
}
/* for each column */
for(i=0; i<n2; i++) {
/* copy the column into a vector */
for(j=0; j<n1; j++) Mc[j] = M[j][i];
quantiles(qs, q, m, Mc, wnorm, n1);
for(j=0; j<m; j++) Q[j][i] = qs[j];
}
/* clean up */
if(w != NULL) { assert(wnorm); free(wnorm); }
free(Mc);
free(qs);
}
/*
* data structure for sorting weighted samples
* to estimate quantiles
*/
typedef struct wsamp
{
double w;
double x;
} Wsamp;
/*
* comparison function for weighted samples
*/
int compareWsamp(const void* a, const void* b)
{
Wsamp* aa = (Wsamp*)(*(Wsamp **)a);
Wsamp* bb = (Wsamp*)(*(Wsamp **)b);
if(aa->x < bb->x) return -1;
else return 1;
}
/*
* calculate the quantiles of v[1:n] specified in q[1:m], and store them
* in qs[1:m]; If non-null weights, then use the sorting method; assume
* that the weights are NORMALIZED, it is also assumed that the q[1:m]
* is specified in increasing order
*/
void quantiles(double *qs, double *q, unsigned int m, double *v,
double *w, unsigned int n)
{
unsigned int i, k, j;
double wsum;
Wsamp **wsamp;
/* create and fill pointers to weighted sample structures */
if(w != NULL) {
wsamp = (Wsamp**) malloc(sizeof(struct wsamp*) * n);
for(i=0; i<n; i++) {
wsamp[i] = malloc(sizeof(struct wsamp));
wsamp[i]->w = w[i];
wsamp[i]->x = v[i];
}
/* sort by v; and implicity report the associated weights w */
qsort((void*)wsamp, n, sizeof(Wsamp*), compareWsamp);
} else wsamp = NULL;
/* for each quantile in q */
wsum = 0.0;
for(i=0, j=0; j<m; j++) {
/* check to make sure the j-th quantile requested is valid */
assert(q[j] > 0 && q[j] <1);
/* find the (non-weighted) quantile using select */
if(w == NULL) {
/* calculate the index-position of the quantile */
k = (unsigned int) n*q[j];
qs[j] = quick_select(v, n, k);
} else { /* else using sorting method */
/* check to make sure the qs are ordered */
assert(wsamp);
if(j > 0) assert(q[j] > q[j-1]);
/* find the next quantile in the q-array */
for(; i<n; i++) {
/* to cover the special case where n<=m */
if(i > 0 && wsum >= q[j]) { qs[j] = wsamp[i-1]->x; break; }
/* increment with the next weight */
wsum += wsamp[i]->w;
/* see if we've found the next quantile */
if(wsum >= q[j]) { qs[j] = wsamp[i]->x; break; }
}
/* check to make sure we actually had founda quantile */
if(i == n) warning("unable to find quanile q[%d]=%g", j, q[j]);
}
}
/* clean up */
if(w) {
assert(wsamp);
for(i=0; i<n; i++) free(wsamp[i]);
free(wsamp);
}
}
/*
* allocate and return an array of length n with scale*1 at
* each entry
*/
double* ones(unsigned int n, double scale)
{
double *o;
unsigned int i;
/* o = (double*) malloc(sizeof(double) * n); */
o = new_vector(n);
/* assert(o); */
for(i=0; i<n; i++) o[i] = scale;
return o;
}
/*
* allocate and return an array containing
* the seqence of doubles [from...to] with steps of
* size by
*/
double* dseq(double from, double to, double by)
{
unsigned int n,i;
double *s = NULL;
by = abs(by);
if(from <= to) n = (unsigned int) (to - from)/abs(by) + 1;
else n = (unsigned int) (from - to)/abs(by) + 1;
if( n == 0 ) return NULL;
s = (double*) malloc(sizeof(double) * n);
assert(s);
s[0] = from;
for(i=1; i<n; i++) {
s[i] = s[i-1] + by;
}
return s;
}
/*
* allocate and return an array containing
* the integer seqence [from...to]
*/
int* iseq(double from, double to)
{
unsigned int n,i;
int by;
int *s = NULL;
if(from <= to) {
n = (unsigned int) (to - from) + 1;
by = 1;
} else {
assert(from > to);
n = (unsigned int) (from - to) + 1;
by = -1;
}
if(n == 0) return NULL;
s = new_ivector(n);
s[0] = from;
for(i=1; i<n; i++) {
s[i] = s[i-1] + by;
}
return s;
}
/*
* find:
*
* return an integer of length (*len) with indexes into V which
* satisfy the relation "V op val" where op is one of
* LT(<) GT(>) EQ(==) LEQ(<=) GEQ(>=) NE(!=)
*/
int* find(double *V, unsigned int n, FIND_OP op, double val, unsigned int* len)
{
unsigned int i,j;
int *tf;
int *found;
tf = new_ivector(n);
(*len) = 0;
switch (op) {
case GT:
for(i=0; i<n; i++) {
if(V[i] > val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case GEQ:
for(i=0; i<n; i++) {
if(V[i] >= val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case EQ:
for(i=0; i<n; i++) {
if(V[i] == val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case LEQ:
for(i=0; i<n; i++) {
if(V[i] <= val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case LT:
for(i=0; i<n; i++) {
if(V[i] < val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case NE:
for(i=0; i<n; i++) {
if(V[i] != val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
default: error("OP not supported");
}
if(*len == 0) found = NULL;
else {
found = new_ivector(*len);
for(i=0,j=0; i<n; i++) {
if(tf[i]) {
found[j] = i;
j++;
}
}
}
free(tf);
return found;
}
/*
* return an integer of length (*len) wih indexes into V[][col] which
* satisfy the relation "V op val" where op is one of LT(<) GT(>)
* EQ(==) LEQ(<=) GEQ(>=) NE(!=)
*/
int* find_col(double **V, unsigned int n, unsigned int var,
FIND_OP op, double val, unsigned int* len)
{
unsigned int i,j;
int *tf;
int *found;
tf = new_ivector(n);
(*len) = 0;
switch (op) {
case GT:
for(i=0; i<n; i++) {
if(V[i][var] > val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case GEQ:
for(i=0; i<n; i++) {
if(V[i][var] >= val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case EQ:
for(i=0; i<n; i++) {
if(V[i][var] == val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case LEQ:
for(i=0; i<n; i++) {
if(V[i][var] <= val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case LT:
for(i=0; i<n; i++) {
if(V[i][var] < val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
case NE:
for(i=0; i<n; i++) {
if(V[i][var] != val) tf[i] = 1;
else tf[i] = 0;
if(tf[i] == 1) (*len)++;
}
break;
default: error("OP not supported");
}
if(*len == 0) found = NULL;
else {
found = new_ivector(*len);
for(i=0,j=0; i<n; i++) {
if(tf[i]) {
found[j] = i;
j++;
}
}
}
free(tf);
return found;
}
/*
* Returns the kth smallest value in the array arr[1..n]. The input
* array will be rearranged to have this value in location arr[k] ,
* with all smaller elements moved to arr[1..k-1] (in arbitrary order)
* and all larger elements in arr[k+1..n] (also in arbitrary order).
* (from Numerical Recipies in C)
*
* This Quickselect routine is based on the algorithm described in
* "Numerical recipes in C", Second Edition, Cambridge University
* Press, 1992, Section 8.5, ISBN 0-521-43108-5 This code by Nicolas
* Devillard - 1998. Public domain.
*/
#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
double quick_select(double arr[], int n, int k)
{
int low, high ;
int middle, ll, hh;
low = 0 ; high = n-1 ;
assert(k >= low && k <= high);
for (;;) {
if (high <= low) /* One element only */
return arr[k] ;
if (high == low + 1) { /* Two elements only */
if (arr[low] > arr[high])
ELEM_SWAP(arr[low], arr[high]) ;
return arr[k] ;
}
/* Find kth of low, middle and high items; swap into position low */
middle = (low + high) / 2;
if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ;
if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ;
if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ;
/* Swap low item (now in position middle) into position (low+1) */
ELEM_SWAP(arr[middle], arr[low+1]) ;
/* Nibble from each end towards middle, swapping items when stuck */
ll = low + 1;
hh = high;
for (;;) {
do ll++; while (arr[low] > arr[ll]) ;
do hh--; while (arr[hh] > arr[low]) ;
if (hh < ll)
break;
ELEM_SWAP(arr[ll], arr[hh]) ;
}
/* Swap middle item (in position low) back into correct position */
ELEM_SWAP(arr[low], arr[hh]) ;
/* Re-set active partition */
if (hh <= k)
low = ll;
if (hh >= k)
high = hh - 1;
}
}
/*
* same as the quick_select algorithm above, but less
* efficient. Not currently used in tgp
*/
double kth_smallest(double a[], int n, int k)
{
int i,j,l,m ;
double x ;
l=0 ; m=n-1 ;
while (l<m) {
x=a[k] ;
i=l ;
j=m ;
do {
while (a[i]<x) i++ ;
while (x<a[j]) j-- ;
if (i<=j) {
ELEM_SWAP(a[i],a[j]) ;
i++ ; j-- ;
}
} while (i<=j) ;
if (j<k) l=i ;
if (k<i) m=j ;
}
return a[k] ;
}
#undef ELEM_SWAP
/*
* send mean of the columns of the matrix M
* out to a file
*/
void mean_to_file(const char *file_str, double **M, unsigned int T, unsigned int n)
{
double *Mm;
FILE *MmOUT;
unsigned int i;
Mm = (double*) malloc(sizeof(double) * n);
wmean_of_columns(Mm, M, T, n, NULL);
MmOUT = fopen(file_str, "w");
assert(MmOUT);
for(i=0; i<n; i++) myprintf(MmOUT, "%g\n", Mm[i]);
fclose(MmOUT);
free(Mm);
}
/*
* send a vector
* of the matrix M out to a file
*/
void vector_to_file(const char* file_str, double* vector, unsigned int n)
{
FILE* VOUT;
unsigned int i;
VOUT = fopen(file_str, "w");
assert(VOUT);
for(i=0; i<n; i++) myprintf(VOUT, "%g\n", vector[i]);
fclose(VOUT);
}
/*
* open file with the given name
* and print the passed matrix to it
*/
void matrix_to_file(const char* file_str, double** matrix, unsigned int n1, unsigned int n2)
{
FILE* MOUT;
MOUT = fopen(file_str, "w");
assert(MOUT);
printMatrix(matrix, n1, n2, MOUT);
fclose(MOUT);
}
/*
* open file with the given name
* and print the passed integer matrix to it
*/
void intmatrix_to_file(const char* file_str, int** matrix, unsigned int n1, unsigned int n2)
{
FILE* MOUT;
MOUT = fopen(file_str, "w");
assert(MOUT);
printIMatrix(matrix, n1, n2, MOUT);
fclose(MOUT);
}
/*
* open file with the given name
* and print transpose of the passed matrix to it
*/
void matrix_t_to_file(const char* file_str, double** matrix, unsigned int n1,
unsigned int n2)
{
FILE* MOUT;
MOUT = fopen(file_str, "w");
assert(MOUT);
printMatrixT(matrix, n1, n2, MOUT);
fclose(MOUT);
}
/*
* sub_pcols_matrix:
*
* copy the cols v[1:n1][p[n2]] to V.
* must have nrow(v) == nrow(V) and ncol(V) >= lenp
* and ncol(v) >= max(p)
*/
void sub_p_matrix(double **V, int *p, double **v,
unsigned int nrows, unsigned int lenp)
{
int i,j;
assert(V); assert(p); assert(v); assert(nrows > 0 && lenp > 0);
for(i=0; i<nrows; i++) for(j=0; j<lenp; j++)
V[i][j] = v[i][p[j]];
}
/*
* new_p_matrix::
*
* create a new matrix from the columns of v, specified
* by p. Must have have nrow(v) == nrow(V) and ncol(V) >= ncols
* and ncol(v) >= max(p)
*/
double **new_p_submatrix(int *p, double **v, unsigned int nrows,
unsigned int ncols)
{
double **V;
if(nrows == 0 || ncols == 0) return NULL;
assert(p); assert(v);
V = new_matrix(nrows, ncols);
sub_p_matrix(V, p, v, nrows, ncols);
return(V);
}
/*
* copy_p_matrix:
*
* copy v[n1][n2] to V into the positions specified by p1[n1] and p2[n2]
*/
void copy_p_matrix(double **V, int *p1, int *p2, double **v,
unsigned int n1, unsigned int n2)
{
int i,j;
assert(V); assert(p1); assert(p2); assert(n1 > 0 && n2 > 0);
for(i=0; i<n1; i++) for(j=0; j<n2; j++)
V[p1[i]][p2[j]] = v[i][j];
}
/*
* enforce that means should lie within the quantiles,
* to guard agains numerical instabilities arising in
* prediction. when violated, replace with median
*/
void check_means(double *mean, double *q1, double *median,
double *q2, unsigned int n)
{
unsigned int i;
int replace = 0;
for(i=0; i<n; i++) {
if(mean[i] > q2[i] || mean[i] < q1[i]) {
myprintf(stdout, "replacing %g with (%g,%g,%g)\n",
mean[i], q1[i], median[i], q2[i]);
mean[i] = median[i];
replace++;
}
}
/* let us know what happened */
if(replace > 0)
myprintf(stdout, "NOTICE: %d predictive means replaced with medians\n",
replace);
}
/*
* pass back the indices (through p) into the matrix X which lie
* within the boundaries described by rect; return the number of true
* indices. X is treated as n1 x n2, and p is an n1 (preallocated)
* array
*/
unsigned int matrix_constrained(int *p, double **X, unsigned int n1,
unsigned int n2, Rect *rect)
{
unsigned int i,j, count;
count = 0;
/* printRect(stderr, rect->d, rect->boundary); */
for(i=0; i<n1; i++) {
p[i] = 1;
for(j=0; j<n2; j++) {
if(rect->opl[j] == GT) {
assert(rect->opr[j] == LEQ);
p[i] = (int) (X[i][j] > rect->boundary[0][j] &&
X[i][j] <= rect->boundary[1][j]);
}
else if(rect->opl[j] == GEQ) {
if(rect->opr[j] == LEQ)
p[i] = (int) (X[i][j] >= rect->boundary[0][j] &&
X[i][j] <= rect->boundary[1][j]);
else if(rect->opr[j] == LT)
p[i] = (int) (X[i][j] >= rect->boundary[0][j] &&
X[i][j] < rect->boundary[1][j]);
else assert(0);
}
else assert(0);
if(p[i] == 0) break;
}
if(p[i] == 1) count++;
}
return count;
}
/*
* create a new rectangle structure without any of the fields filled
* in
*/
Rect* new_rect(unsigned int d)
{
Rect* rect = (Rect*) malloc(sizeof(struct rect));
rect->d = d;
rect->boundary = new_matrix(2, d);
rect->opl = (FIND_OP *) malloc(sizeof(FIND_OP) * d);
rect->opr = (FIND_OP *) malloc(sizeof(FIND_OP) * d);
return rect;
}
/*
* return a pointer to a duplicated rectangle structure
*/
Rect* new_dup_rect(Rect* oldR)
{
unsigned int i;
Rect* rect = (Rect*) malloc(sizeof(struct rect));
rect->d = oldR->d;
rect->boundary = new_dup_matrix(oldR->boundary, 2, oldR->d);
rect->opl = (FIND_OP *) malloc(sizeof(FIND_OP) * rect->d);
rect->opr = (FIND_OP *) malloc(sizeof(FIND_OP) * rect->d);
for(i=0; i<rect->d; i++) {
rect->opl[i] = oldR->opl[i];
rect->opr[i] = oldR->opr[i];
}
return rect;
}
/*
* calculate and return the area depicted by
* the rectangle boundaries
*/
double rect_area(Rect* rect)
{
unsigned int i;
double area;
area = 1.0;
for(i=0; i<rect->d; i++)
area *= rect->boundary[1][i] - rect->boundary[0][i];
return area;
}
/*
* calculate and return the area depicted by
* the rectangle boundaries, using only dimensions 0,...,maxd-1
*/
double rect_area_maxd(Rect* rect, unsigned int maxd)
{
unsigned int i;
double area;
assert(maxd <= rect->d);
area = 1.0;
for(i=0; i<maxd; i++)
area *= rect->boundary[1][i] - rect->boundary[0][i];
return area;
}
/*
* print a rectangle structure out to
* the file denoted by "outfile"
*/
void print_rect(Rect *r, FILE* outfile)
{
unsigned int i;
myprintf(outfile, "# %d dim rect (area=%g) with boundary:\n",
r->d, rect_area(r));
printMatrix(r->boundary, 2, r->d, outfile);
myprintf(outfile, "# opl and opr\n");
for(i=0; i<r->d; i++) myprintf(outfile, "%d ", r->opl[i]);
myprintf(outfile, "\n");
for(i=0; i<r->d; i++) myprintf(outfile, "%d ", r->opr[i]);
myprintf(outfile, "\n");
}
/*
* free the memory associated with a
* rectangle structure
*/
void delete_rect(Rect *rect)
{
delete_matrix(rect->boundary);
free(rect->opl);
free(rect->opr);
free(rect);
}
/*
* make it so that the data lives in
* [0,1]^d.
*/
void normalize(double **X, double **rect, int N, int d, double normscale)
{
int i, j;
double norm;
if(N == 0) return;
assert(d != 0);
for(i=0; i<d; i++) {
norm = fabs(rect[1][i] - rect[0][i]);
if(norm == 0) norm = fabs(rect[0][i]);
for(j=0; j<N; j++) {
if(rect[0][i] < 0)
X[j][i] = (X[j][i] + fabs(rect[0][i])) / norm;
else
X[j][i] = (X[j][i] - rect[0][i]) / norm;
X[j][i] = normscale * X[j][i];
assert(X[j][i] >=0 && X[j][i] <= normscale);
}
}
}
/*
* put Rect r on the scale of double rect
* r should be form 0 to NORMSCALE
*/
void rect_unnorm(Rect* r, double **rect, double normscale)
{
int i;
double norm;
for(i=0; i<r->d; i++) {
assert(r->boundary[0][i] >= 0 && r->boundary[1][i] <= normscale);
norm = fabs(rect[1][i] - rect[0][i]);
if(norm == 0) norm = fabs(rect[0][i]);
r->boundary[1][i] = normscale * r->boundary[1][i];
r->boundary[0][i] = rect[0][i] + norm * r->boundary[0][i];
r->boundary[1][i] = rect[1][i] - norm * (1.0 - r->boundary[1][i]);
}
}
/*
* allocates a new double array of size n1
*/
double* new_vector(unsigned int n)
{
double *v;
if(n == 0) return NULL;
v = (double*) malloc(sizeof(double) * n);
return v;
}
/*
* allocates a new double array of size n1
* and fills it with zeros
*/
double* new_zero_vector(unsigned int n)
{
double *v;
v = new_vector(n);
zerov(v, n);
return v;
}
/*
* allocates a new double array of size n1
* and fills it with the contents of vold
*/
double* new_dup_vector(double* vold, unsigned int n)
{
double *v;
v = new_vector(n);
dupv(v, vold, n);
return v;
}
/*
* copies vold to v
* (assumes v has already been allcocated)
*/
void dupv(double *v, double* vold, unsigned int n)
{
unsigned int i;
for(i=0; i<n; i++) v[i] = vold[i];
}
/*
* copies v into the col-th column of M
* (assumes M and v are properly allocated already)
*/
void dup_col(double **M, unsigned int col, double *v, unsigned int n)
{
unsigned int i;
for(i=0; i<n; i++) M[i][col] = v[i];
}
/*
* sumv:
*
* return the sum of the contents of the vector
*/
double sumv(double *v, unsigned int n)
{
unsigned int i;
double s;
if(n==0) return 0;
assert(v);
s = 0;
for(i=0; i<n; i++) s += v[i];
return(s);
}
/*
* meanv:
*
* return the mean of the contents of the vector
*/
double meanv(double *v, unsigned int n)
{
return(sumv(v, n)/n);
}
/*
* sumiv:
*
* return the sum of the contents of the integer vector
*/
int sumiv(int *iv, unsigned int n)
{
unsigned int i;
int s;
if(n==0) return 0;
assert(iv);
s = 0;
for(i=0; i<n; i++) s += iv[i];
return(s);
}
/*
* meaniv:
*
* return the mean of the contents of the integer vector
*/
int meaniv(int *iv, unsigned int n)
{
return((int) (sumiv(iv, n)/n));
}
/*
* sum_fv:
*
* return the sum of the contents of the vector
* each entry of which is applied to function f
*/
double sum_fv(double *v, unsigned int n, double(*f)(double))
{
unsigned int i;
double s;
if(n==0) return 0;
assert(v);
s = 0;
for(i=0; i<n; i++) s += f(v[i]);
return(s);
}
/*
* swaps the pointer of v2 to v1, and vice-versa
* (avoids copying via dupv)
*/
void swap_vector(double **v1, double **v2)
{
double* temp;
temp = (double*) *v1;
*v1 = *v2;
*v2 = (double*) temp;
}
/*
* zeros out v
* (assumes that it has already been allocated)
*/
void zerov(double*v, unsigned int n)
{
unsigned int i;
for(i=0; i<n; i++) v[i] = 0;
}
/*
* multiple the contents of vector v[n]
* by the scale parameter
*/
void scalev(double *v, unsigned int n, double scale)
{
int i;
assert(v);
for(i=0; i<n; i++) v[i] = v[i]*scale;
}
/*
* multiple the contents of vector v[n]
* by the scale[n] parameter
*/
void scalev2(double *v, unsigned int n, double *scale)
{
int i;
assert(v);
assert(scale);
for(i=0; i<n; i++) v[i] = v[i]*scale[i];
}
/*
* subtract the center value from each component
* of v[n]
*/
void centerv(double *v, unsigned int n, double center)
{
int i;
assert(v);
for(i=0; i<n; i++) v[i] = v[i] - center;
}
/*
* divide off the norm[n] value from each component
* of v[n]
*/
void normv(double *v, unsigned int n, double* norm)
{
int i;
assert(v);
assert(norm);
for(i=0; i<n; i++) v[i] /= norm[i];
}
/*
* copy v[n] to V into the positions specified by p[n]
*/
void copy_p_vector(double *V, int *p, double *v, unsigned int n)
{
int i;
assert(V); assert(p); assert(n > 0);
for(i=0; i<n; i++) V[p[i]] = v[i];
}
/*
* copy v[p[i]] to V[n]
*/
void copy_sub_vector(double *V, int *p, double *v, unsigned int n)
{
int i;
if(n == 0) return;
assert(V); assert(p); assert(n > 0);
for(i=0; i<n; i++) V[i] = v[p[i]];
}
/*
* new n-vector V; copy v[p[i]] to V [n]
*/
double* new_sub_vector(int *p, double *v, unsigned int n)
{
double *V = new_vector(n);
copy_sub_vector(V, p, v, n);
return V;
}
/*
* add two vectors of the same size
* v1 = a*v1 + b*v2
*/
void add_vector(double a, double *v1, double b, double *v2, unsigned int n)
{
if(n == 0) return;
assert(n > 0);
assert(v1 && v2);
add_matrix(a, &v1, b, &v2, 1, n);
}
/*
* add_p_vector:
*
* add v[n1] to V into the positions specified by p[n1]
*/
void add_p_vector(double a, double *V, int *p, double b, double *v, unsigned int n)
{
int i = 0;
if(n == 0) return;
assert(V); assert(p);
add_p_matrix(a, &V, &i, p, b, &v, 1, n);
}
/*
* printing a vector out to outfile
*/
void printVector(double *v, unsigned int n, FILE *outfile, PRINT_PREC type)
{
unsigned int i;
if(type==HUMAN) for(i=0; i<n; i++) myprintf(outfile, "%g ", v[i]);
else if(type==MACHINE) for(i=0; i<n; i++) myprintf(outfile, "%.20f ", v[i]);
else error("bad PRINT_PREC type");
myprintf(outfile, "\n");
}
/*
* printing a symmetric matrix in vector format out to outfile
*/
void printSymmMatrixVector(double **m, unsigned int n, FILE *outfile,
PRINT_PREC type)
{
unsigned int i,j;
if(type==HUMAN)
for(i=0; i<n; i++)
for(j=i; j<n; j++)
myprintf(outfile, "%g ", m[i][j]);
else if(type==MACHINE)
for(i=0; i<n; i++)
for(j=i; j<n; j++)
myprintf(outfile, "%.20f ", m[i][j]);
else error("bad PRINT_PREC type");
myprintf(outfile, "\n");
}
/*
* return the minimum element in the vector.
* pass back the index of the minimum through
* the which pointer
*/
double min(double *v, unsigned int n, unsigned int *which)
{
unsigned int i;
double min;
*which = 0;
min = v[0];
for(i=1; i<n; i++) {
if(v[i] < min) {
min = v[i];
*which = i;
}
}
return min;
}
/*
* return the maximum element in the vector. pass back the index of
* the maximum through the which pointer
*/
double max(double *v, unsigned int n, unsigned int *which)
{
unsigned int i;
double max;
*which = 0;
max = v[0];
for(i=1; i<n; i++) {
if(v[i] > max) {
max = v[i];
*which = i;
}
}
return max;
}
/*
* new vector of integers of length n
*/
int *new_ivector(unsigned int n)
{
int *iv;
if(n == 0) return NULL;
iv = (int*) malloc(sizeof(int) * n);
assert(iv);
return iv;
}
/*
* duplicate the integer contents of iv of length n into the already
* allocated vector iv_new, also of length n
*/
void dupiv(int *iv_new, int *iv, unsigned int n)
{
unsigned int i;
if(n > 0) assert(iv && iv_new);
for(i=0; i<n; i++) iv_new[i] = iv[i];
}
/*
* zeros out v
* (assumes that it has already been allocated)
*/
void zeroiv(int*v, unsigned int n)
{
unsigned int i;
for(i=0; i<n; i++) v[i] = 0;
}
/*
* swaps the pointer of v2 to v1, and vice-versa
* (avoids copying via dupv)
*/
void swap_ivector(int **v1, int **v2)
{
int* temp;
temp = (int*) *v1;
*v1 = *v2;
*v2 = (int*) temp;
}
/*
* allocate a new integer vector of length n and copy the integer
* contents of iv into it
*/
int *new_dup_ivector(int *iv, unsigned int n)
{
int* iv_new = new_ivector(n);
dupiv(iv_new, iv, n);
return iv_new;
}
/*
* create a new integer vector of length n, fill it with ones,
* multiplied by the scale parameter-- for a vector of 5's, use
* scale=5
*/
int *new_ones_ivector(unsigned int n, int scale)
{
int *iv = new_ivector(n);
iones(iv, n, scale);
return iv;
}
/*
* create a new integer vector of length n, fill it with zeros
*/
int *new_zero_ivector(unsigned int n)
{
int *iv = new_ivector(n);
zeroiv(iv, n);
return iv;
}
/*
* write n ones into iv (pre-allocated), and then multiply by the
* scale parameter-- for a vector of 5's, use scale=5
*/
void iones(int *iv, unsigned int n, int scale)
{
unsigned int i;
if(n > 0) assert(iv);
for(i=0; i<n; i++) iv[i] = scale;
}
/*
* printing an integer vector out to outfile
*/
void printIVector(int *iv, unsigned int n, FILE *outfile)
{
unsigned int i;
for(i=0; i<n; i++) myprintf(outfile, "%d ", iv[i]);
myprintf(outfile, "\n");
}
/*
* send an integer vector
* of the matrix M out to a file
*/
void ivector_to_file(const char* file_str, int* vector, unsigned int n)
{
FILE* VOUT;
unsigned int i;
VOUT = fopen(file_str, "w");
assert(VOUT);
for(i=0; i<n; i++) myprintf(VOUT, "%d\n", vector[i]);
fclose(VOUT);
}
/*
* copy v[n] to V into the positions specified by p[n]
*/
void copy_p_ivector(int *V, int *p, int *v, unsigned int n)
{
int i;
assert(V); assert(p); assert(n > 0);
for(i=0; i<n; i++) V[p[i]] = v[i];
}
/*
* copy v[p[i]] to V[n]
*/
void copy_sub_ivector(int *V, int *p, int *v, unsigned int n)
{
int i;
assert(V); assert(p); assert(n > 0);
for(i=0; i<n; i++) V[i] = v[p[i]];
}
/*
* new n-vector V; copy v[p[i]] to V [n]
*/
int* new_sub_ivector(int *p, int *v, unsigned int n)
{
int *V = new_ivector(n);
copy_sub_ivector(V, p, v, n);
return V;
}
/*
* casting used on above function for vectors
* of UNSIGNED integers.
*/
unsigned int *new_uivector(unsigned int n)
{ return (unsigned int*) new_ivector(n); }
void dupuiv(unsigned int *iv_new, unsigned int *iv, unsigned int n)
{ dupiv((int *) iv_new, (int*) iv, n); }
unsigned int *new_dup_uivector(unsigned int *iv, unsigned int n)
{ return (unsigned int*) new_dup_ivector((int*) iv, n); }
unsigned int *new_ones_uivector(unsigned int n, unsigned int scale)
{ return (unsigned int*) new_ones_ivector(n, (int) scale); }
unsigned int *new_zero_uivector(unsigned int n)
{ return (unsigned int*) new_zero_ivector(n); }
void uiones(unsigned int *iv, unsigned int n, unsigned int scale)
{ iones((int*) iv, n, (int) scale); }
void zerouiv(unsigned int *iv, unsigned int n)
{ zeroiv((int*) iv, n); }
void printUIVector(unsigned int *iv, unsigned int n, FILE *outfile)
{ printIVector((int*) iv, n, outfile); }
void uivector_to_file(const char *file_str, unsigned int *iv, unsigned int n)
{ ivector_to_file(file_str, (int*) iv, n); }
void copy_p_uivector(unsigned int *V, int *p, unsigned int *v, unsigned int n)
{ copy_p_ivector((int*)V, p, (int*)v, n); }
void copy_sub_uivector(unsigned int *V, int *p, unsigned int *v, unsigned int n)
{ copy_sub_ivector((int*)V, p, (int*)v, n); }
unsigned int* new_sub_uivector(int *p, unsigned int *v, unsigned int n)
{ return (unsigned int*) new_sub_ivector(p, (int*)v, n); }
unsigned int sumuiv(unsigned int *v, unsigned int n)
{ return (unsigned int) sumiv((int*)v, n); }
unsigned int meanuiv(unsigned int *v, unsigned int n)
{ return (unsigned int) meaniv((int*)v, n); }
/*
* sq:
*
* calculate the square of x
*/
double sq(double x)
{
return x*x;
}
/*
* myfmax:
*
* seems like some systems are missing the prototype
* for the fmax function which should be in math.h --
* so I wrote my own
*/
double myfmax(double a, double b)
{
if(a >= b) return a;
else return b;
}
/*
* myfmin:
*
* seems like some systems are missing the prototype
* for the fmin function which should be in math.h --
* so I wrote my own
*/
double myfmin(double a, double b)
{
if(a <= b) return a;
else return b;
}
/*
* vmult:
*
* returns the product of its arguments
*/
double vmult(double *v1, double *v2, int n)
{
double v = 0.0;
int i;
for(i=0; i<n; i++) v += v1[i]*v2[i];
return v;
}