Example #1
0
void SparseMat::solve_lower_triangle_trans(const DoubleVec &rhs,
					       DoubleVec &x) const
{
  // Solve the transpose of a lower triangular matrix with explicitly
  // stored diagonal elements.  rhs and x can be the same vector.
  
  // x_i = (1/L_ii) (rhs_i - \sum_{j=i+1}^M L_ji x_j)
  assert(is_lower_triangular(true));
  assert(rhs.size() == nrows_);
  assert(x.size() == nrows_);
  assert(nrows_ == ncols_);
  
  // Copy rhs into x.  This does all of the rhs_i terms.
  if(&x[0] != &rhs[0])
    x = rhs;
  for(int j=int(x.size()-1); j>=0; j--) {
    const_row_iterator ji = --end(j);
    if(ji.row() != ji.col() || *ji == 0.0)
      throw ErrSetupError("Zero divisor in solve_lower_triangle_trans!");
    // We're done with the sums for x[j].
    x[j] /= *ji; 
    for(--ji; ji>=begin(j); --ji)
	x[ji.col()] -= (*ji) * x[j];
  }
}
Example #2
0
void SparseMat::axpy(double alpha, const DoubleVec &x, DoubleVec &y) const
{
  if(ncols() != x.size() || nrows() != y.size()) {
    std::string msg = "Incompatible sizes in SparseMat::axpy! [" 
      + to_string(nrows()) + "x" + to_string(ncols()) + "] * [" 
      + to_string(x.size()) + "] + [" + to_string(y.size()) + "]";
    throw ErrProgrammingError(msg, __FILE__, __LINE__);
  }
  if(alpha != 1.0) {
    for(unsigned int r=0; r<nrows_; r++) {
      const SparseMatRow &row = data[r];
      double sum = 0.0;
      for(SparseMatRow::const_iterator j=row.begin(); j<row.end(); ++j)
	sum += (*j).val * x[(*j).col];
      y[r] += alpha*sum;
    }
  }
  else {			// alpha == 1.0
    for(unsigned int r=0; r<nrows_; r++) {
      const SparseMatRow &row = data[r];
      double sum = 0.0;
      for(SparseMatRow::const_iterator j=row.begin(); j<row.end(); ++j)
	sum += (*j).val * x[(*j).col];
      y[r] += sum;
    }
  }
}
Example #3
0
double Stdev(const DoubleVec &val)
{
	double mean=0; 
	double sq=0;
	for(DoubleVec::const_iterator it=val.begin(); it< val.end(); it++)
	{
		mean+=*it;
		sq+=*it*(*it);
	}
	double std= sqrt((val.size()*sq-mean*mean)/((val.size()-1)*val.size()));
	mean/=val.size();
	sq/=val.size();
	return(std);
}
Example #4
0
DoubleVec SparseMat::operator*(const DoubleVec &x) const {
  assert(x.size() == ncols_);
  DoubleVec result(nrows_, 0.0);
  for(unsigned int r=0; r<nrows_; r++) {
    double sum = 0.0;
    const SparseMatRow &row = data[r];
    for(SparseMatRow::const_iterator j=row.begin(); j<row.end(); ++j) {
      assert((*j).col >= 0 && (*j).col < x.size());
      sum += (*j).val * x[(*j).col];
    }
    result[r] = sum;
  }
  return result;
}
Example #5
0
/** Returns the time interval covered by the data.
 * 
 * @param[in] times	Times at which data were taken
 *
 * @return The length of time between the earliest observation in times and 
 *	the latest observation in times, in whatever units @p times is in.
 *
 * @pre @p times.size() &ge; 2
 * @pre @p times contains at least two unique values
 * 
 * @perform O(N) time, where N = @p times.size()
 * 
 * @exception std::invalid_argument Thrown if @p times has at most one element.
 * @exception kpftimes::except::BadLightCurve Thrown if @p times has 
 *	at most one distinct value.
 * 
 * @exceptsafe The function arguments are unchanged in the event 
 *	of an exception.
 * 
 * @test Regular grid, length 1. Expected behavior: throws invalid_argument
 * @test Regular grid, length 2. Expected behavior: returns step
 * @test Regular grid, length 100. Expected behavior: returns 99*step
 * @test Irregular grid, 2 values randomly chosen from [0, 1). Expected behavior: returns max_element()-min_element()
 * @test Irregular grid, 100 values randomly chosen from [0, 1). Expected behavior: returns max_element()-min_element()
 */
double deltaT(const DoubleVec &times) {
	if (times.size() < 2) {
		throw std::invalid_argument("Parameter 'times' in deltaT() contains fewer than 2 observations");
	}
	
	// In C++11, this entire body can be replaced with a call to std::minmax_element()

	// Scanning the array to verify that it's sorted would take just as 
	//	long as scanning it for min and max
	double tMin = times.front();
	double tMax = tMin;
	
	for (DoubleVec::const_iterator i = times.begin(); i != times.end(); i++) {
		if (*i < tMin) {
			tMin = *i;
		}
		if (*i > tMax) {
			tMax = *i;
		}
	}
	
	if (tMax <= tMin) {
		throw except::BadLightCurve("Parameter 'times' in deltaT() contains only one unique value");
	}
	else {
		return (tMax - tMin);
	}
}
Example #6
0
/** Returns the highest frequency that can be probed by the data. This is 
 * defined as 1/2dt, where dt > 0 is the @b smallest time interval between 
 * any two observations.
 * 
 * @param[in] times	Times at which data were taken
 *
 * @return The highest meaningful frequency, in the inverse of whatever units 
 *	@p times is in.
 *
 * @pre @p times.size() &ge; 2
 * @pre @p times contains at least two unique values
 * @pre @p times is sorted in ascending order
 * 
 * @perform O(N) time, where N = @p times.size()
 * 
 * @exception std::invalid_argument Thrown if @p times has at most one element.
 * @exception kpftimes::except::BadLightCurve Thrown if @p times has 
 *	at most one distinct value.
 * @exception kpfutils::except::NotSorted Thrown if @p times is not in 
 *	ascending order.
 * 
 * @exceptsafe The function arguments are unchanged in the event 
 *	of an exception.
 * 
 * @test Regular grid, length 1. Expected behavior: throws invalid_argument
 * @test Regular grid, length 2. Expected behavior: returns PNF = 1/(2*step)
 * @test Regular grid, length 100. Expected behavior: returns PNF = 1/(2*step)
 * @todo How to test this for irregular grids?
 */
double maxFreq(const DoubleVec &times) {
	if (times.size() < 2) {
		throw std::invalid_argument("Parameter 'times' in maxFreq() contains fewer than 2 observations");
	}

	// Test for sort in O(N)
	// Faster than sorting, O(N log N), or unsorted test, O(N^2)
	if(!kpfutils::isSorted(times.begin(), times.end())) {
		throw kpfutils::except::NotSorted("Parameter 'times' in maxFreq() is unsorted");
	}

	// Look for the smallest interval
	DoubleVec::const_iterator t1 = times.begin();
	DoubleVec::const_iterator t2 = t1 + 1;
	double minDeltaT = 0.0;
	
	while(t2 != times.end()) {
		if (*t2 > *t1 && (*t2 - *t1 < minDeltaT || minDeltaT == 0.0)) {
			minDeltaT = *t2 - *t1;
		}
		t1++;
		t2++;
	}
	
	// Report the results
	if (minDeltaT == 0.0) {
		throw except::BadLightCurve("Parameter 'times' in maxFreq() contains only one unique value");
	} else {
		return 0.5 / minDeltaT;
	}
}
Example #7
0
double VectorOutputVal::dot(const DoubleVec &other) const {
  assert(size() == other.size());
  double sum = 0;
  for(unsigned int i=0; i<size(); i++)
    sum += data[i]*other[i];
  return sum;
}
Example #8
0
void SparseMat::solve_lower_triangle_unitd(const DoubleVec &rhs,
					       DoubleVec &x)
  const
{
  // Solve a lower triangular matrix assuming that the diagonal
  // elements are 1.0.  rhs and x can be the same vector.
  assert(is_lower_triangular(false)); // diags aren't stored explicitly
  // x_n = rhs_n - \sum{i=0}^{n-1} L_ni x_i
  for(unsigned int rowno=0; rowno<rhs.size(); rowno++) {
    double sum = 0.0;
    for(const_row_iterator ij=begin(rowno); ij<end(rowno); ++ij)
      sum += (*ij)*x[ij.col()];
    x[rowno] = rhs[rowno] - sum;
  }
}
Example #9
0
void SparseMat::solve_lower_triangle(const DoubleVec &rhs, DoubleVec &x)
  const
{
  // Solve a lower triangular matrix. rhs and x can be the same
  // vector.
  assert(is_lower_triangular(true)); // diag elements are stored explicitly
  // x_n = (1/L_nn) (rhs_n - \sum{i=0}^{n-1} L_ni x_i)
  for(unsigned int rowno=0; rowno<rhs.size(); rowno++) {
    double sum = 0.0;
    const_row_iterator ij=--end(rowno);
    double diag = *ij;
    if(diag == 0.0)
      throw ErrSetupError("Zero divisor in solve_lower_triangle");
    for(--ij; ij>=begin(rowno); --ij)
      sum += (*ij)*x[ij.col()];
    x[rowno] = (rhs[rowno] - sum)/diag;
  }
}
Example #10
0
void
SparseMat::solve_lower_triangle_trans_unitd(const DoubleVec &rhs,
						DoubleVec &x) const
{
  // Solve the transpose of a lower triangular matrix with implicit
  // ones on the diagonal.  rhs and x can be the same vector.

  // x_i = rhs_i - \sum_{j=i+1}^M L_ji x_j

  assert(is_lower_triangular(false));
  if(&x[0] != &rhs[0])
    x = rhs;
  for(int j=int(x.size()-1); j>=0; j--) {
    if(is_nonempty_row(j)) {
      for(const_row_iterator ji=begin(j); ji<end(j); ++ji) {
        x[ji.col()] -= (*ji) * x[j];
      }
    }
  }
}
Example #11
0
void SparseMat::solve_upper_triangle(const DoubleVec &rhs, DoubleVec &x)
  const
{
  // Solve an upper triangular matrix with explicit diagonal elements.
  // rhs and x can be the same vector.
  assert(is_upper_triangular(true));
  
  // x_i = (1/U_ii) (rhs_i - \sum_{n=i+1}^M U_in x_n )
  // rowno must be an int, not an unsigned int, or else rowno>=0 will
  // always be true.
  for(int rowno=int(rhs.size())-1; rowno>=0; rowno--) {
    const_row_iterator ij=begin(rowno);
    double diagterm = *ij;
    if(ij.row() != ij.col() || diagterm == 0.0)
      throw ErrSetupError("Zero divisor in solve_upper_triangle!");
    double sum = rhs[rowno];
    for(++ij; ij<end(rowno); ++ij)
      sum -= (*ij)*x[ij.col()];
    x[rowno] = sum/diagterm;
  }
}
Example #12
0
void SparseMat::solve_upper_triangle_trans(const DoubleVec &rhs,
					       DoubleVec &x) const
{
  // Solve the transpose of an upper triangular matrix with explicit
  // diagonal elements.  rhs and x can be the same vector.
  assert(is_upper_triangular(true));

  // x_i = (1/U_ii) (rhs_i - \sum_{j=0}^{i-1} U_ji x_j)

  // Copy rhs into x. This does all of the rhs_i terms.
  if(&x[0] != &rhs[0])
    x = rhs;
  for(unsigned int i=0; i<x.size(); i++) {
    const_row_iterator ji=begin(i); // loop over i^th col of the transpose
    // We're already done with the sums for x_i.
    if(ji.row() != ji.col() || *ji == 0.0)
      throw ErrSetupError("Zero divisor in solve_upper_triangle_trans!");
    x[i] /= *ji; 		// divide by the diagonal
    // Accumulate contributions to later x[i]'s.
    for(++ji; ji<end(i); ++ji)
      x[ji.col()] -= (*ji) * x[i];
  }
}
Example #13
0
double ROC(const DoubleVec & _score_pos, const DoubleVec & _score_neg, DoubleVec &sens_vec, DoubleVec &spec_vec, DoubleVec &cutoffs)
{
	if(_score_pos.size()==0 || _score_neg.size()==0)
	{
		cout << "Error: No positive or negative scores";
		return(-1);
	}
	sens_vec.clear();
	spec_vec.clear();
	cutoffs.clear();

	DoubleVec score_pos=_score_pos;
	DoubleVec score_neg=_score_neg;
	std::sort(score_pos.begin(),score_pos.end());
	std::sort(score_neg.begin(),score_neg.end());

	double integral=0;
	sens_vec.push_back(0);
	spec_vec.push_back(1);
	cutoffs.push_back(min(score_neg.front(),score_pos.front()));


	DoubleVec::const_iterator cut_neg=score_neg.begin();
	DoubleVec::const_iterator cut_pos=score_pos.begin();

	while(cut_pos<score_pos.end())
	{

		while(cut_neg<score_neg.end()) // Move cut_neg to first value >= cut_pos
		{
			if(*cut_neg<*cut_pos)
				cut_neg++;
			else
				break;
		}

		unsigned TP=unsigned(cut_pos-score_pos.begin());
		unsigned FP=unsigned(cut_neg-score_neg.begin());
		unsigned TN=score_neg.size()-FP;
		unsigned FN=score_pos.size()-TP;
		double sens=double(TP)/score_pos.size();
		double spec=double(TN)/score_neg.size();
		integral+=(sens-sens_vec.back())*(spec+spec_vec.back())/2.0;
		sens_vec.push_back(sens);
		spec_vec.push_back(spec);
		cutoffs.push_back(*cut_pos);

		double last_cutoff=*cut_pos;
		while(cut_pos<score_pos.end()) // Advance cut_pos while = last cutoff !!Change that to move cut_pos to first value >= cut_neg, perfect symmetry
		{
			if(*cut_pos==last_cutoff)
				cut_pos++;
			else
				break;
		}
		while(cut_neg<score_neg.end()) // Advance cut_pos while = last cutoff
		{
			if(*cut_neg==last_cutoff)
				cut_neg++;
			else
				break;
		}

		TP=unsigned(cut_pos-score_pos.begin());
		FP=unsigned(cut_neg-score_neg.begin());
		TN=score_neg.size()-FP;
		FN=score_pos.size()-TP;

		sens=double(TP)/score_pos.size();
		spec=double(TN)/score_neg.size();
		integral+=(sens-sens_vec.back())*(spec+spec_vec.back())/2.0;
		sens_vec.push_back(sens);
		spec_vec.push_back(spec);

		double cp=score_pos.back();
		double cn=score_neg.back();
		if(cut_pos<score_pos.end())
			cp=*cut_pos;
		if(cut_neg<score_neg.end())
			cn=*cut_neg;
		cutoffs.push_back(min(cp,cn));
	}
	integral+=(1-sens_vec.back())*(spec_vec.back()+0)/2.0;
	sens_vec.push_back(1);
	spec_vec.push_back(0);
	cutoffs.push_back(max(score_neg.back(),score_pos.back()));
	return(integral);
}
Example #14
0
/** Returns the pseudo-Nyquist frequency for a grid of observations.
 * 
 * The pseudo-Nyquist frequency is defined as N/2T, where N is the number of 
 * observations and T is the length of the time interval covered by the data.
 * 
 * @param[in] times	Times at which data were taken
 * 
 * @return The pseudo-Nyquist frequency, in the inverse of whatever units 
 *	times is in.
 *
 * @pre @p times.size() &ge; 2
 * @pre @p times contains at least two unique values
 * 
 * @perform O(N) time, where N = @p times.size()
 * 
 * @exception std::invalid_argument Thrown if @p times has at most one element.
 * @exception kpftimes::except::BadLightCurve Thrown if @p times has 
 *	at most one distinct value.
 * 
 * @exceptsafe The function arguments are unchanged in the event 
 *	of an exception.
 *
 * @test Regular grid, length 1. Expected behavior: throws invalid_argument
 * @test Regular grid, length 2. Expected behavior: returns PNF = 1/(2*step)
 * @test Regular grid, length 100. Expected behavior: returns PNF = 1/(2*step)
 * 
 * @todo Come up with test cases for an irregular grid.
 */
double pseudoNyquistFreq(const DoubleVec &times) {
	// Delegate input validation to deltaT
	return 0.5 * times.size() / deltaT(times);
}
Example #15
0
VectorOutputVal::VectorOutputVal(const DoubleVec &vec)
  : size_(vec.size()),
    data(new double[vec.size()])
{
  (void) memcpy(data, &vec[0], size_*sizeof(double));
}
Example #16
0
void CNumVec::SetTo(const DoubleVec &v)
{
	resize(v.size());
	for(unsigned i=0; i<v.size(); i++)
		gsl_vector_set(m_vec,i,v[i]);
}