#ifndef RTS_FUNCTION_H #define RTS_FUNCTION_H #include namespace stim{ //template class for a one-dimensional function template class function { protected: std::vector X; std::vector Y; Ty range[2]; Ty bounding[2]; //comparison function for searching lambda static bool findCeiling(Tx ax, Tx bx){ return (ax > bx); } //process a string to extract a function (generally delimited by tabs, commas, spaces, etc.) void process_string(std::string s){ std::stringstream ss(s); Tx x; Ty y; std::string line; while(!ss.eof()){ std::getline(ss, line); if(line[0] == '#') continue; std::stringstream lstream(line); lstream>>x; //read the x value lstream>>y; //read the y value if(ss.eof()) break; insert(x, y); //insert the read value into the function } } void update_range(Ty y){ //if the function is empty, just set the range to the given value if(X.size() == 0){ range[0] = range[1] = y; } //otherwise compare the values and set them appropriately if(y < range[0]) range[0] = y; if(y > range[1]) range[1] = y; } public: function(){ range[0] = range[1] = 0; bounding[0] = bounding[1] = 0; } //linear interpolation Ty linear(Tx x) const { if(X.size() == 0) return bounding[0]; //return zero if the function is empty //return bounding values if x is outside the sample domain if(x < X[0]) return bounding[0]; if(x > X.back()) return bounding[1]; unsigned int N = X.size(); //number of sample points //declare an iterator typedef typename std::vector< Tx >::iterator f_iter; //declare an iterator f_iter it; //find the first X-coordinate that is greater than x unsigned int i; for(i = 0; i x) break; } //i currently holds the ceiling //if the wavelength is past the end of the list, return the last sample point if(i == N) return Y.back(); //if the wavelength is before the beginning of the list, return the front else if(i == 0) return Y[0]; //otherwise interpolate else{ Tx xMax = X[i]; Tx xMin = X[i-1]; Tx a = (x - xMin) / (xMax - xMin); Ty riMin = Y[i - 1]; Ty riMax = Y[i]; Ty interp = riMax * a + riMin * (1 - a); return interp; } } ///add a data point to a function void insert(Tx x, Ty y) { unsigned int N = X.size(); //number of sample points update_range(y); //update the range of the function if(N == 0 || X[N-1] < x){ X.push_back(x); Y.push_back(y); return; } //declare an iterator and search for the x value typename std::vector< Tx >::iterator it; it = search(X.begin(), X.end(), &x, &x + 1, &function::findCeiling); //if the function value is past the end of the vector, add it to the back if(*it == N){ X.push_back(x); Y.push_back(y); } //otherwise add the value at the iterator position else{ X.insert(it, x); Y.insert(Y.begin() + *it, y); } } Tx getX(unsigned int i) const{ return X[i]; } Ty getY(unsigned int i) const{ return Y[i]; } ///get the number of data points in the function unsigned int getN() const{ return X.size(); } //look up an indexed component Ty operator[](int i) const{ if(i <= X.size()){ std::cout<<"ERROR: accessing non-existing sample point in 'function'"< operator+(Ty r) const{ function result; //if there are points in the function if(X.size() > 0){ //add r to every point in f for(unsigned int i=0; i & operator= (const Ty & rhs){ X.clear(); Y.clear(); bounding[0] = bounding[1] = rhs; //set the boundary values to rhs if(rhs != 0) //if the RHS is zero, just clear, otherwise add one value of RHS insert(0, rhs); return *this; } //output a string description of the function (used for console output and debugging) std::string str(){ unsigned int N = X.size(); std::stringstream ss; ss<<"# of samples: "<(t)), std::istreambuf_iterator()); process_string(str); } }; } //end namespace rts #endif