diff --git a/envi/EnviClose.h b/envi/EnviClose.h new file mode 100644 index 0000000..bb21076 --- /dev/null +++ b/envi/EnviClose.h @@ -0,0 +1,58 @@ +#ifndef ENVICLOSE_H +#define ENVICLOSE_H + + +#include +#include +#include "EnviHeader.h" +#include "EnviFid.h" +#include "EnviOpen.h" + +// this is to close all the opened files and to create a header file for the written files + +static void EnviClose(EnviFidClass &fid, int dimX=0) +{ + + float* zeroPtr = (float*) malloc(sizeof(float) * fid.header.nF); + memset(zeroPtr, 0, sizeof(float) * fid.header.nF); + + if(fid.mode=="r") + { + fclose(fid.file); + } + + else + { + int totalPixels = fid.header.sX; + int dimY = totalPixels/dimX; + + if(totalPixels % dimX > 0) + { + dimY++; + + int padding = dimY*dimX-totalPixels; + + for(int p=0; p < padding; p++) + fwrite(zeroPtr, sizeof(float), fid.header.nF, fid.file); + } + + //write the calculated values to the header object + fid.header.sX = dimX; + fid.header.sY = dimY; + + + //write the header file to disk + //TODO + + + //close the binary file + fclose(fid.file); + + } + + + + +} +#endif + diff --git a/envi/EnviFid.h b/envi/EnviFid.h new file mode 100644 index 0000000..57d9a4f --- /dev/null +++ b/envi/EnviFid.h @@ -0,0 +1,47 @@ +#ifndef ENVIFID_H +#define ENVIFID_H + +#include +#include +#include +#include +#include +#include "EnviHeader.h" +using namespace std; + +class EnviFidClass +{ +public: + //binary file name + string fileName; + + //header structure + EnviHeaderClass header; + + //valid flag (is the current file valid) + int isValid; + + //file mask (NULL if the whole file is to be read) + char* mask; + + //current position (in pixels) in the file + int filePos; + + //read/write mode ("r" or "w") + string mode; + + //create a variable to store a pointer to the binary file + FILE * file; + + //constructor, set default values + EnviFidClass() + { + isValid = 0; + filePos = 0; + } + + +}; + + +#endif diff --git a/envi/EnviHeader.h b/envi/EnviHeader.h new file mode 100644 index 0000000..b0c93e8 --- /dev/null +++ b/envi/EnviHeader.h @@ -0,0 +1,126 @@ +#ifndef ENVIHEADER_H +#define ENVIHEADER_H +#include +#include +#include +#include +#include +using namespace std; + +enum InterleaveType {bip, bil, bsq}; +class EnviHeaderClass //"EnviheaderClass" will be used to store data into variables sX, sY, etc. +{ +public: + unsigned int sX; //samples = "sX" + unsigned int sY; //lines = "sY" + unsigned int nF; //bands = "nF" + unsigned int headersize; //header offset = "headersize" + unsigned int datatype; //data type = "datatype" + InterleaveType type; + string units; //wavelength units = "units" (Usully in Wavenumber or Wavelength) + int LoadHeader(string filename) + { + ifstream inFile; + //Load the header file in the same directory, for future note, might want to modify code to either "cin" the file name of have a feature in the GUI which take into account different fileneames + inFile.open (filename.c_str()); + + //If or not there is a file + if (!inFile) + { + cout<<"Error"<>result; //converts result from previous line + + return result; + } + //retrieves a string parameter from a line of text + string getString(string line) + { + int position; + position=line.find("="); //Finds the position of the equal sign + + string word; //Creates a string for storing word data called "word" + word=line.substr(position+2); //Moves from the position of "=" 2 spaces to the right + //Note: We do not need to convert word using "istringstream" + + return word; + } +}; +#endif diff --git a/envi/EnviOpen.h b/envi/EnviOpen.h new file mode 100644 index 0000000..7bfb1ee --- /dev/null +++ b/envi/EnviOpen.h @@ -0,0 +1,87 @@ +#ifndef ENVIOPEN_H +#define ENVIOPEN_H +#include +#include +#include +#include +#include +#include +#include "EnviHeader.h" +#include "EnviFid.h" +using namespace std; + + + +//return value is incorrect +static EnviFidClass EnviOpen(string filename, char* mask = NULL, string mode = "r", int nBands = 0, int sX = 0) +{ + //create a file ID object + EnviFidClass fid; + + //set the file read/write mode + fid.mode = mode; + + //set the mask (if specified) + fid.mask = mask; + + // load the header file only while reading + if(mode=="r") + { + //load the header file + int error = fid.header.LoadHeader(filename); + + //if the LoadHeader function is not zero, the header is invalid + if (error != 0) + { + fid.isValid = 0; + return fid; + } + + } + + //default header to be used in case of writing a file + else + { + + fid.header.datatype= 4; + fid.header.nF= nBands; + fid.header.sX=0; + fid.header.sY=1; + fid.header.headersize=0; + } + //load the binary file associated with this header + //get the binary file name + + //find the binary file name + + //locate the position of the extension + int pos = filename.find(".hdr"); + string binaryname = filename.substr(0, pos); + //load the binary file using fopen() + //store the resulting FILE pointer in the EnviFidClass variable + mode += "b"; + fid.file = fopen (binaryname.c_str(), mode.c_str()); + if(fid.file == NULL) + { + cout<<"Error opening binary file."< +#include +#include +#include +#include +#include +#include "EnviHeader.h" +#include "EnviFid.h" +#include "EnviOpen.h" +using namespace std; + + +static int EnviRead(float* ptr, int nPixels, EnviFidClass &fid) +{ + //number of values to read from the file + int totalPixels = fid.header.sX * fid.header.sY; + + //ERROR TEST: make sure that fid.file is a valid file pointer + if (fid.file == NULL) + { + cout<<"Binary file isn't open."< +#include +#include "EnviHeader.h" +#include "EnviFid.h" +#include "EnviOpen.h" + +// Take a memory pointer, and copy all of that data to disk. +static int EnviWrite(float* ptr, int npixels, EnviFidClass &fid) +{ + if(fid.mode == "r") return 0; + + //open a binary file for writing + if (fid.file == NULL) + { + cout<<"Binary file isn't open."< +#include +#include +#include + +/* This is a class for reading and writing ENVI binary files. This class will be updated as needed. + +What this class CAN currently do: + *) Write band images to a BSQ file. + *) Append band images to a BSQ file. + +*/ + +//information from an ENVI header file +//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html +struct EnviHeader +{ + std::string name; + + std::string description; + + unsigned int samples; //x-axis + unsigned int lines; //y-axis + unsigned int bands; //spectral axis + unsigned int header_offset; //header offset for binary file (in bytes) + std::string file_type; //should be "ENVI Standard" + unsigned int data_type; //data representation; common value is 4 (32-bit float) + + enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z + interleaveType interleave; + + std::string sensor_type; //not really used + + enum endianType {endianLittle, endianBig}; + endianType byte_order; //little = least significant bit first (most systems) + + double x_start, y_start; //coordinates of the upper-left corner of the image + std::string wavelength_units; //stored wavelength units + std::string z_plot_titles[2]; + + double pixel_size[2]; //pixel size along X and Y + + std::vector band_names; //name for each band in the image + std::vector wavelength; //wavelength for each band + + EnviHeader() + { + name = ""; + + //specify default values for a new or empty ENVI file + samples = 0; + lines = 0; + bands = 0; + header_offset = 0; + data_type = 4; + interleave = BSQ; + byte_order = endianLittle; + x_start = y_start = 0; + pixel_size[0] = pixel_size[1] = 1; + + //strings + file_type = "ENVI Standard"; + sensor_type = "Unknown"; + wavelength_units = "Unknown"; + z_plot_titles[0] = z_plot_titles[1] = "Unknown"; + } + + std::string trim(std::string line) + { + //trims whitespace from the beginning and end of line + int start_i, end_i; + for(start_i=0; start_i < line.length(); start_i++) + if(line[start_i] != 32) + { + break; + } + + for(end_i = line.length()-1; end_i >= start_i; end_i--) + if(line[end_i] != ' ') + { + break; + } + + return line.substr(start_i, end_i - start_i+1); + } + + + std::string get_token(std::string line) + { + //returns a variable name; in this case we look for the '=' sign + size_t i = line.find_first_of('='); + + std::string result; + if(i != std::string::npos) + result = trim(line.substr(0, i-1)); + + return result; + } + + std::string get_data_str(std::string line) + { + size_t i = line.find_first_of('='); + + std::string result; + if(i != std::string::npos) + result = trim(line.substr(i+1)); + else + { + std::cout<<"ENVI Header error - data not found for token: "< get_string_seq(std::string token, std::string sequence) + { + //this function returns a sequence of comma-delimited strings + std::vector result; + + std::string entry; + size_t i; + do + { + i = sequence.find_first_of(','); + entry = sequence.substr(0, i); + sequence = sequence.substr(i+1); + result.push_back(trim(entry)); + }while(i != std::string::npos); + + return result; + } + + std::vector get_double_seq(std::string token, std::string sequence) + { + //this function returns a sequence of comma-delimited strings + std::vector result; + + std::string entry; + size_t i; + do + { + i = sequence.find_first_of(','); + entry = sequence.substr(0, i); + sequence = sequence.substr(i+1); + result.push_back(atof(entry.c_str())); + }while(i != std::string::npos); + + return result; + } + + void load(std::string filename, std::string mode = "r") + { + name = filename; + + + //open the header file + std::ifstream file(name.c_str()); + + if(!file) + { + //if we are in read mode, throw an exception + if(mode == "r") + { + std::cout<<"ENVI header file not found: "< pxsize = get_double_seq(token, string_sequence); + pixel_size[0] = pxsize[0]; + pixel_size[1] = pxsize[1]; + } + else if(token == "z plot titles") + { + std::string string_sequence = get_brace_str(token, line, file); + std::vector titles = get_string_seq(token, string_sequence); + z_plot_titles[0] = titles[0]; + z_plot_titles[1] = titles[1]; + } + + else if(token == "samples") + samples = atoi(get_data_str(line).c_str()); + else if(token == "lines") + { + lines = atoi(get_data_str(line).c_str()); + std::cout<<"Number of lines loaded: "< 0) + { + outfile<<"band names = {"<0) + return true; + else + return false; + + } + +public: + + EnviFile() + { + init(); + } + + EnviFile(std::string filename, std::string file_mode = "r") + { + init(); + open(filename, filename + ".hdr", file_mode); + } + + void open(std::string file_name, std::string header_name, std::string file_mode = "r") + { + mode = file_mode; + + header.name = header_name; + + //lock the file if we are loading or appending + if(mode == "r" || mode == "a" || mode == "r+" || mode == "a+") + { + //load the ENVI header - failure will cause an exit + set_header(load_header(header_name, file_mode)); + + if(mode == "r" || test_exist(file_name)) + { + locked = true; + } + + } + else + { + header.name = header_name; + } + + //open the data file + data = fopen(file_name.c_str(), (mode + "b").c_str()); + + + } + + void setDescription(std::string desc) + { + readonly(); //if the file is read-only, throw an exception + header.description = desc; + } + + void setZPlotTitles(std::string spectrum, std::string value) + { + readonly(); //if the file is read-only, throw an exception + header.z_plot_titles[0] = spectrum; + header.z_plot_titles[1] = value; + } + + void setPixelSize(double sx, double sy) + { + readonly(); //if the file is read-only, throw an exception + header.pixel_size[0] = sx; + header.pixel_size[1] = sy; + } + + void setWavelengthUnits(std::string units) + { + readonly(); //if the file is read-only, throw an exception + header.wavelength_units = units; + } + + void setCoordinates(double x, double y) + { + readonly(); //if the file is read-only, throw an exception + header.x_start = x; + header.y_start = y; + } + + //FUNCTIONS THAT MAY BE DISALLOWED IN A LOCKED FILE + void setSamples(unsigned int samples) + { + EnviHeader newHeader = header; + newHeader.samples = samples; + set_header(newHeader); + } + + void setLines(unsigned int lines) + { + EnviHeader newHeader = header; + newHeader.lines = lines; + set_header(newHeader); + } + + void setBands(unsigned int bands) + { + EnviHeader newHeader = header; + newHeader.bands = bands; + set_header(newHeader); + } + + //DATA MANIPULATION + void addBand(void* band, unsigned int samples, unsigned int lines, double wavelength, std::string band_name ="") + { + //add a band to the file + + EnviHeader newHeader = header; + newHeader.bands++; + newHeader.samples = samples; + newHeader.lines = lines; + newHeader.wavelength.push_back(wavelength); + if(band_name != "") + newHeader.band_names.push_back(band_name); + set_header(newHeader); + + //copy the data to the file + fwrite(band, header.valsize(), samples * lines, data); + + //since data was written, the file must be locked + locked = true; + } + + //close file + void close() + { + //std::cout<<"ENVI File Mode: "< #include #include -#include "rts/rtcomplex.h" +#include "rts/rtsComplex.h" #define PI 3.14159 @@ -49,7 +49,7 @@ namespace rts{ { //wavelength (in microns) T lambda; - rtcomplex n; + rtsComplex n; }; template @@ -196,6 +196,15 @@ namespace rts{ dispersion.push_back(ri); } + void add(T lambda, rtsComplex n) + { + refIndex ri; + ri.lambda = lambda; + ri.n = n; + + dispersion.push_back(ri); + } + //comparison function for sorting static bool compare(refIndex a, refIndex b) { @@ -234,9 +243,9 @@ namespace rts{ #ifdef FFTW_AVAILABLE //allocate memory for the FFT - rtcomplex* Chi2 = (rtcomplex*)fftw_malloc(sizeof(rtcomplex) * N * pf); - rtcomplex* Chi2FFT = (rtcomplex*)fftw_malloc(sizeof(rtcomplex) * N * pf); - rtcomplex* Chi1 = (rtcomplex*)fftw_malloc(sizeof(rtcomplex) * N * pf); + rtsComplex* Chi2 = (rtsComplex*)fftw_malloc(sizeof(rtsComplex) * N * pf); + rtsComplex* Chi2FFT = (rtsComplex*)fftw_malloc(sizeof(rtsComplex) * N * pf); + rtsComplex* Chi1 = (rtsComplex*)fftw_malloc(sizeof(rtsComplex) * N * pf); //create an FFT plan for the forward and inverse transforms fftw_plan planForward, planInverse; @@ -267,8 +276,8 @@ namespace rts{ } //use linear interpolation between the start and end points to pad the spectrum - //rtcomplex nMin = dispersion.back(); - //rtcomplex nMax = dispersion.front(); + //rtsComplex nMin = dispersion.back(); + //rtsComplex nMax = dispersion.front(); T a; for(int i=N; i j(0, 1); + rtsComplex j(0, 1); for(int i=0; i entry(format); + std::cout<<"Loading material with format: "< entry(format); - for(unsigned int l=0; l 0) ss<=0; l--) + { + if(l < dispersion.size() - 1) ss< 0) ss< getN(T l) + rtsComplex getN(T l) { //declare an iterator typename std::vector< refIndex >::iterator it; @@ -499,16 +550,16 @@ namespace rts{ //std::cout< riMin = (*(it - 1)).n; - rtcomplex riMax = (*it).n; - rtcomplex interp; - interp = rtcomplex(a, 0.0) * riMin + rtcomplex(1.0 - a, 0.0) * riMax; + rtsComplex riMin = (*(it - 1)).n; + rtsComplex riMax = (*it).n; + rtsComplex interp; + interp = rtsComplex(a, 0.0) * riMin + rtsComplex(1.0 - a, 0.0) * riMax; return interp; } } //interpolate the given lambda value and return the index of refraction - rtcomplex operator()(T l) + rtsComplex operator()(T l) { return getN(l); } diff --git a/rts/point.h b/rts/point.h deleted file mode 100644 index 2cdf47b..0000000 --- a/rts/point.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef RTS_POINT_H -#define RTS_POINT_H - -//#include "rts/vector.h" -#include - -namespace rts -{ - -template -struct point -{ - T p[N]; - - CUDA_CALLABLE point() - { - - } - - //efficiency constructor, makes construction easier for 1D-4D vectors - CUDA_CALLABLE point(T x, T y = (T)0.0, T z = (T)0.0, T w = (T)0.0) - { - if(N >= 1) - p[0] = x; - if(N >= 2) - p[1] = y; - if(N >= 3) - p[2] = z; - if(N >= 4) - p[3] = w; - } - - //arithmetic operators - CUDA_CALLABLE rts::point operator+(rts::vector v) - { - rts::point r; - - //calculate the position of the resulting point - for(int i=0; i operator-(rts::vector v) - { - rts::point r; - - //calculate the position of the resulting point - for(int i=0; i operator-(rts::point rhs) - { - rts::vector r; - - //calculate the position of the resulting point - for(int i=0; i operator*(T rhs) - { - rts::point r; - - //calculate the position of the resulting point - for(int i=0; i -std::ostream& operator<<(std::ostream& os, rts::point p) -{ - os< -CUDA_CALLABLE rts::point operator*(T lhs, rts::point rhs) -{ - rts::point r; - - return rhs * lhs; -} - - - -#endif diff --git a/rts/rect.h b/rts/rect.h index 53e07f3..d2d288d 100644 --- a/rts/rect.h +++ b/rts/rect.h @@ -3,8 +3,8 @@ //enable CUDA_CALLABLE macro #include "rts/cuda_callable.h" -#include "rts/vector.h" -#include "rts/point.h" +#include "rts/rtsVector.h" +#include "rts/rtsPoint.h" #include namespace rts{ @@ -27,9 +27,9 @@ struct rect T B[N]; T C[N];*/ - rts::point A; - rts::vector X; - rts::vector Y; + rts::rtsPoint A; + rts::rtsVector X; + rts::rtsVector Y; CUDA_CALLABLE rect() @@ -37,7 +37,7 @@ struct rect } - CUDA_CALLABLE rect(point a, point b, point c) + CUDA_CALLABLE rect(rtsPoint a, rtsPoint b, rtsPoint c) { A = a; @@ -46,27 +46,27 @@ struct rect } - CUDA_CALLABLE rect(rts::point pMin, rts::point pMax, rts::vector normal) + CUDA_CALLABLE rect(rts::rtsPoint pMin, rts::rtsPoint pMax, rts::rtsVector normal) { - //assign the corner point + //assign the corner rtsPoint A = pMin; //compute the vector from pMin to pMax - rts::vector v0; + rts::rtsVector v0; v0 = pMax - pMin; //compute the cross product of A and the plane normal - rts::vector v1; + rts::rtsVector v1; v1 = v0.cross(normal); - //calculate point B - rts::point B; + //calculate rtsPoint B + rts::rtsPoint B; B = A + v0 * 0.5 + v1 * 0.5; - //calculate point C - rts::point C; + //calculate rtsPoint C + rts::rtsPoint C; C = A + v0 * 0.5 - v1 * 0.5; //calculate X and Y @@ -78,7 +78,7 @@ struct rect } - /*CUDA_CALLABLE rect(rts::point p, rts::vector x, rts::vector y, T sx, T sy) + /*CUDA_CALLABLE rect(rts::rtsPoint p, rts::vector x, rts::vector y, T sx, T sy) { //This constructor creates a rect given a position, orientation, and size // p = center position of the rect @@ -100,16 +100,16 @@ struct rect }*/ - CUDA_CALLABLE rts::point p(T a, T b) + CUDA_CALLABLE rts::rtsPoint p(T a, T b) { - rts::point result; + rts::rtsPoint result; //given the two parameters a, b = [0 1], returns the position in world space result = A + X * a + Y * b; return result; } - CUDA_CALLABLE rts::point operator()(T a, T b) + CUDA_CALLABLE rts::rtsPoint operator()(T a, T b) { return p(a, b); } @@ -126,6 +126,23 @@ struct rect return ss.str(); } + + CUDA_CALLABLE rect operator*(T rhs) + { + //scales the plane by a scalar value + + //compute the center rtsPoint + rts::rtsPoint c = A + X*0.5 + Y*0.5; + + //create the new rectangle + rect result; + result.X = X * rhs; + result.Y = Y * rhs; + result.A = c - result.X*0.5 - result.Y*0.5; + + return result; + + } }; } //end namespace rts diff --git a/rts/rtcomplex.h b/rts/rtcomplex.h deleted file mode 100644 index daeaf98..0000000 --- a/rts/rtcomplex.h +++ /dev/null @@ -1,434 +0,0 @@ -/*RTS Complex number class. This class is CUDA compatible, -and can therefore be used in CUDA code and on CUDA devices. -*/ - -#ifndef RTS_COMPLEX -#define RTS_COMPLEX - -#include "cuda_callable.h" -#include -#include -#include -#include - -namespace rts -{ - -template -struct rtcomplex -{ - T r, i; - - //default constructor - CUDA_CALLABLE rtcomplex() - { - r = 0.0; - i = 0.0; - } - - //access methods - T real() - { - return r; - } - - T real(T r_val) - { - r = r_val; - return r_val; - } - - T imag() - { - return i; - } - T imag(T i_val) - { - i = i_val; - return i_val; - } - - - - - - //constructor when given real and imaginary values - CUDA_CALLABLE rtcomplex(T r, T i) - { - this->r = r; - this->i = i; - } - - //return the current value multiplied by i - CUDA_CALLABLE rtcomplex imul() - { - rtcomplex result; - result.r = -i; - result.i = r; - - return result; - } - - //ARITHMETIC OPERATORS-------------------- - - //binary + operator (returns the result of adding two complex values) - CUDA_CALLABLE rtcomplex operator+ (const rtcomplex rhs) - { - rtcomplex result; - result.r = r + rhs.r; - result.i = i + rhs.i; - return result; - } - - CUDA_CALLABLE rtcomplex operator+ (const T rhs) - { - rtcomplex result; - result.r = r + rhs; - result.i = i; - return result; - } - - //binary - operator (returns the result of adding two complex values) - CUDA_CALLABLE rtcomplex operator- (const rtcomplex rhs) - { - rtcomplex result; - result.r = r - rhs.r; - result.i = i - rhs.i; - return result; - } - - //binary - operator (returns the result of adding two complex values) - CUDA_CALLABLE rtcomplex operator- (const T rhs) - { - rtcomplex result; - result.r = r - rhs; - result.i = i; - return result; - } - - //binary MULTIPLICATION operators (returns the result of multiplying complex values) - CUDA_CALLABLE rtcomplex operator* (const rtcomplex rhs) - { - rtcomplex result; - result.r = r * rhs.r - i * rhs.i; - result.i = r * rhs.i + i * rhs.r; - return result; - } - CUDA_CALLABLE rtcomplex operator* (const T rhs) - { - return rtcomplex(r * rhs, i * rhs); - } - - //binary DIVISION operators (returns the result of dividing complex values) - CUDA_CALLABLE rtcomplex operator/ (const rtcomplex rhs) - { - rtcomplex result; - T denom = rhs.r * rhs.r + rhs.i * rhs.i; - result.r = (r * rhs.r + i * rhs.i) / denom; - result.i = (- r * rhs.i + i * rhs.r) / denom; - - return result; - } - CUDA_CALLABLE rtcomplex operator/ (const T rhs) - { - return rtcomplex(r / rhs, i / rhs); - } - - //ASSIGNMENT operators----------------------------------- - CUDA_CALLABLE rtcomplex & operator=(const rtcomplex &rhs) - { - //check for self-assignment - if(this != &rhs) - { - this->r = rhs.r; - this->i = rhs.i; - } - return *this; - } - CUDA_CALLABLE rtcomplex & operator=(const T &rhs) - { - this->r = rhs; - this->i = 0; - - return *this; - } - - //arithmetic assignment operators - CUDA_CALLABLE rtcomplex operator+=(const rtcomplex &rhs) - { - *this = *this + rhs; - return *this; - } - CUDA_CALLABLE rtcomplex operator+=(const T &rhs) - { - *this = *this + rhs; - return *this; - } - - CUDA_CALLABLE rtcomplex operator*=(const rtcomplex &rhs) - { - *this = *this * rhs; - return *this; - } - CUDA_CALLABLE rtcomplex operator*=(const T &rhs) - { - *this = *this * rhs; - return *this; - } - //divide and assign - CUDA_CALLABLE rtcomplex operator/=(const rtcomplex &rhs) - { - *this = *this / rhs; - return *this; - } - CUDA_CALLABLE rtcomplex operator/=(const T &rhs) - { - *this = *this / rhs; - return *this; - } - - //absolute value operator (returns the absolute value of the complex number) - CUDA_CALLABLE T abs() - { - return std::sqrt(r * r + i * i); - } - - CUDA_CALLABLE rtcomplex log() - { - rtcomplex result; - result.r = std::log(std::sqrt(r * r + i * i)); - result.i = std::atan2(i, r); - - - return result; - } - - CUDA_CALLABLE rtcomplex exp() - { - rtcomplex result; - - T e_r = std::exp(r); - result.r = e_r * std::cos(i); - result.i = e_r * std::sin(i); - - return result; - } - - /*CUDA_CALLABLE complex pow(int y) - { - - return pow((double)y); - }*/ - - CUDA_CALLABLE rtcomplex pow(T y) - { - rtcomplex result; - - result = log() * y; - - return result.exp(); - } - - CUDA_CALLABLE rtcomplex sqrt() - { - rtcomplex result; - - //convert to polar coordinates - T a = std::sqrt(r*r + i*i); - T theta = std::atan2(i, r); - - //find the square root - T a_p = std::sqrt(a); - T theta_p = theta/2.0; - - //convert back to cartesian coordinates - result.r = a_p * std::cos(theta_p); - result.i = a_p * std::sin(theta_p); - - return result; - } - - std::string toStr() - { - std::stringstream ss; - ss<<"("< rhs) - { - if(r == rhs.r && i == rhs.i) - return true; - return false; - } - - CUDA_CALLABLE bool operator==(T rhs) - { - if(r == rhs && i == (T)0.0) - return true; - return false; - } - - /*//FRIEND functions - //unary minus operator (for negating the complex number) - template CUDA_CALLABLE friend complex operator-(const complex &rhs); - - //multiplication by T values when the complex number isn't on the left hand side - template CUDA_CALLABLE friend complex operator*(const A a, const complex b); - - //division by T values when the complex number isn't on the left hand side - template CUDA_CALLABLE friend complex operator/(const A a, const complex b); - - //POW function - //template CUDA_CALLABLE friend complex pow(const complex x, T y); - template CUDA_CALLABLE friend complex pow(const complex x, int y); - - //log function - template CUDA_CALLABLE friend complex log(complex x); - - //exp function - template CUDA_CALLABLE friend complex exp(complex x); - - //sqrt function - template CUDA_CALLABLE friend complex sqrt(complex x); - - //trigonometric functions - template CUDA_CALLABLE friend complex sin(complex x); - - template CUDA_CALLABLE friend complex cos(complex x);*/ - -}; - -//addition -template -CUDA_CALLABLE static rtcomplex operator+(const double a, const rtcomplex b) -{ - return rtcomplex(a + b.r, b.i); -} - -//subtraction with a real value -template -CUDA_CALLABLE static rtcomplex operator-(const double a, const rtcomplex b) -{ - return rtcomplex(a - b.r, -b.i); -} - -//minus sign -template -CUDA_CALLABLE static rtcomplex operator-(const rtcomplex &rhs) -{ - return rtcomplex(-rhs.r, -rhs.i); -} - -//multiply a T value by a complex value -template -CUDA_CALLABLE static rtcomplex operator*(const double a, const rtcomplex b) -{ - return rtcomplex(a * b.r, a * b.i); -} - -//divide a T value by a complex value -template -CUDA_CALLABLE static rtcomplex operator/(const double a, const rtcomplex b) -{ - //return complex(a * b.r, a * b.i); - rtcomplex result; - - T denom = b.r * b.r + b.i * b.i; - - result.r = (a * b.r) / denom; - result.i = -(a * b.i) / denom; - - return result; -} - -//POW function -/*template -CUDA_CALLABLE static complex pow(complex x, int y) -{ - return x.pow(y); -}*/ - -template -CUDA_CALLABLE static rtcomplex pow(rtcomplex x, T y) -{ - return x.pow(y); -} - -//log function -template -CUDA_CALLABLE static rtcomplex log(rtcomplex x) -{ - return x.log(); -} - -//exp function -template -CUDA_CALLABLE static rtcomplex exp(rtcomplex x) -{ - return x.exp(); -} - -//sqrt function -template -CUDA_CALLABLE static rtcomplex sqrt(rtcomplex x) -{ - return x.sqrt(); -} - - -template -CUDA_CALLABLE static T abs(rtcomplex a) -{ - return a.abs(); -} - -template -CUDA_CALLABLE static T real(rtcomplex a) -{ - return a.r; -} - -template -CUDA_CALLABLE static T imag(rtcomplex a) -{ - return a.i; -} - -//trigonometric functions -template -CUDA_CALLABLE rtcomplex sin(const rtcomplex x) -{ - rtcomplex result; - result.r = std::sin(x.r) * std::cosh(x.i); - result.i = std::cos(x.r) * std::sinh(x.i); - - return result; -} - -template -CUDA_CALLABLE rtcomplex cos(const rtcomplex x) -{ - rtcomplex result; - result.r = std::cos(x.r) * std::cosh(x.i); - result.i = -(std::sin(x.r) * std::sinh(x.i)); - - return result; -} - - - -} //end RTS namespace - -template -std::ostream& operator<<(std::ostream& os, rts::rtcomplex x) -{ - os< +#include +#include +#include + +namespace rts +{ + +template +struct rtsComplex +{ + T r, i; + + //default constructor + CUDA_CALLABLE rtsComplex() + { + r = 0.0; + i = 0.0; + } + + //access methods + CUDA_CALLABLE T real() + { + return r; + } + + CUDA_CALLABLE T real(T r_val) + { + r = r_val; + return r_val; + } + + CUDA_CALLABLE T imag() + { + return i; + } + CUDA_CALLABLE T imag(T i_val) + { + i = i_val; + return i_val; + } + + //constructor when given real and imaginary values + CUDA_CALLABLE rtsComplex(T r, T i) + { + this->r = r; + this->i = i; + } + + //return the current value multiplied by i + CUDA_CALLABLE rtsComplex imul() + { + rtsComplex result; + result.r = -i; + result.i = r; + + return result; + } + + //ARITHMETIC OPERATORS-------------------- + + //binary + operator (returns the result of adding two complex values) + CUDA_CALLABLE rtsComplex operator+ (const rtsComplex rhs) + { + rtsComplex result; + result.r = r + rhs.r; + result.i = i + rhs.i; + return result; + } + + CUDA_CALLABLE rtsComplex operator+ (const T rhs) + { + rtsComplex result; + result.r = r + rhs; + result.i = i; + return result; + } + + //binary - operator (returns the result of adding two complex values) + CUDA_CALLABLE rtsComplex operator- (const rtsComplex rhs) + { + rtsComplex result; + result.r = r - rhs.r; + result.i = i - rhs.i; + return result; + } + + //binary - operator (returns the result of adding two complex values) + CUDA_CALLABLE rtsComplex operator- (const T rhs) + { + rtsComplex result; + result.r = r - rhs; + result.i = i; + return result; + } + + //binary MULTIPLICATION operators (returns the result of multiplying complex values) + CUDA_CALLABLE rtsComplex operator* (const rtsComplex rhs) + { + rtsComplex result; + result.r = r * rhs.r - i * rhs.i; + result.i = r * rhs.i + i * rhs.r; + return result; + } + CUDA_CALLABLE rtsComplex operator* (const T rhs) + { + return rtsComplex(r * rhs, i * rhs); + } + + //binary DIVISION operators (returns the result of dividing complex values) + CUDA_CALLABLE rtsComplex operator/ (const rtsComplex rhs) + { + rtsComplex result; + T denom = rhs.r * rhs.r + rhs.i * rhs.i; + result.r = (r * rhs.r + i * rhs.i) / denom; + result.i = (- r * rhs.i + i * rhs.r) / denom; + + return result; + } + CUDA_CALLABLE rtsComplex operator/ (const T rhs) + { + return rtsComplex(r / rhs, i / rhs); + } + + //ASSIGNMENT operators----------------------------------- + CUDA_CALLABLE rtsComplex & operator=(const rtsComplex &rhs) + { + //check for self-assignment + if(this != &rhs) + { + this->r = rhs.r; + this->i = rhs.i; + } + return *this; + } + CUDA_CALLABLE rtsComplex & operator=(const T &rhs) + { + this->r = rhs; + this->i = 0; + + return *this; + } + + //arithmetic assignment operators + CUDA_CALLABLE rtsComplex operator+=(const rtsComplex &rhs) + { + *this = *this + rhs; + return *this; + } + CUDA_CALLABLE rtsComplex operator+=(const T &rhs) + { + *this = *this + rhs; + return *this; + } + + CUDA_CALLABLE rtsComplex operator*=(const rtsComplex &rhs) + { + *this = *this * rhs; + return *this; + } + CUDA_CALLABLE rtsComplex operator*=(const T &rhs) + { + *this = *this * rhs; + return *this; + } + //divide and assign + CUDA_CALLABLE rtsComplex operator/=(const rtsComplex &rhs) + { + *this = *this / rhs; + return *this; + } + CUDA_CALLABLE rtsComplex operator/=(const T &rhs) + { + *this = *this / rhs; + return *this; + } + + //absolute value operator (returns the absolute value of the complex number) + CUDA_CALLABLE T abs() + { + return std::sqrt(r * r + i * i); + } + + CUDA_CALLABLE rtsComplex log() + { + rtsComplex result; + result.r = std::log(std::sqrt(r * r + i * i)); + result.i = std::atan2(i, r); + + + return result; + } + + CUDA_CALLABLE rtsComplex exp() + { + rtsComplex result; + + T e_r = std::exp(r); + result.r = e_r * std::cos(i); + result.i = e_r * std::sin(i); + + return result; + } + + /*CUDA_CALLABLE complex pow(int y) + { + + return pow((double)y); + }*/ + + CUDA_CALLABLE rtsComplex pow(T y) + { + rtsComplex result; + + result = log() * y; + + return result.exp(); + } + + CUDA_CALLABLE rtsComplex sqrt() + { + rtsComplex result; + + //convert to polar coordinates + T a = std::sqrt(r*r + i*i); + T theta = std::atan2(i, r); + + //find the square root + T a_p = std::sqrt(a); + T theta_p = theta/2.0; + + //convert back to cartesian coordinates + result.r = a_p * std::cos(theta_p); + result.i = a_p * std::sin(theta_p); + + return result; + } + + std::string toStr() + { + std::stringstream ss; + ss<<"("< rhs) + { + if(r == rhs.r && i == rhs.i) + return true; + return false; + } + + CUDA_CALLABLE bool operator==(T rhs) + { + if(r == rhs && i == (T)0.0) + return true; + return false; + } + + /*//FRIEND functions + //unary minus operator (for negating the complex number) + template CUDA_CALLABLE friend complex operator-(const complex &rhs); + + //multiplication by T values when the complex number isn't on the left hand side + template CUDA_CALLABLE friend complex operator*(const A a, const complex b); + + //division by T values when the complex number isn't on the left hand side + template CUDA_CALLABLE friend complex operator/(const A a, const complex b); + + //POW function + //template CUDA_CALLABLE friend complex pow(const complex x, T y); + template CUDA_CALLABLE friend complex pow(const complex x, int y); + + //log function + template CUDA_CALLABLE friend complex log(complex x); + + //exp function + template CUDA_CALLABLE friend complex exp(complex x); + + //sqrt function + template CUDA_CALLABLE friend complex sqrt(complex x); + + //trigonometric functions + template CUDA_CALLABLE friend complex sin(complex x); + + template CUDA_CALLABLE friend complex cos(complex x);*/ + +}; + +} //end RTS namespace + +//addition +template +CUDA_CALLABLE static rts::rtsComplex operator+(const double a, const rts::rtsComplex b) +{ + return rts::rtsComplex(a + b.r, b.i); +} + +//subtraction with a real value +template +CUDA_CALLABLE static rts::rtsComplex operator-(const double a, const rts::rtsComplex b) +{ + return rts::rtsComplex(a - b.r, -b.i); +} + +//minus sign +template +CUDA_CALLABLE static rts::rtsComplex operator-(const rts::rtsComplex &rhs) +{ + return rts::rtsComplex(-rhs.r, -rhs.i); +} + +//multiply a T value by a complex value +template +CUDA_CALLABLE static rts::rtsComplex operator*(const double a, const rts::rtsComplex b) +{ + return rts::rtsComplex(a * b.r, a * b.i); +} + +//divide a T value by a complex value +template +CUDA_CALLABLE static rts::rtsComplex operator/(const double a, const rts::rtsComplex b) +{ + //return complex(a * b.r, a * b.i); + rts::rtsComplex result; + + T denom = b.r * b.r + b.i * b.i; + + result.r = (a * b.r) / denom; + result.i = -(a * b.i) / denom; + + return result; +} + +//POW function +/*template +CUDA_CALLABLE static complex pow(complex x, int y) +{ + return x.pow(y); +}*/ + +template +CUDA_CALLABLE static rts::rtsComplex pow(rts::rtsComplex x, T y) +{ + return x.pow(y); +} + +//log function +template +CUDA_CALLABLE static rts::rtsComplex log(rts::rtsComplex x) +{ + return x.log(); +} + +//exp function +template +CUDA_CALLABLE static rts::rtsComplex exp(rts::rtsComplex x) +{ + return x.exp(); +} + +//sqrt function +template +CUDA_CALLABLE static rts::rtsComplex sqrt(rts::rtsComplex x) +{ + return x.sqrt(); +} + + +template +CUDA_CALLABLE static T abs(rts::rtsComplex a) +{ + return a.abs(); +} + +template +CUDA_CALLABLE static T real(rts::rtsComplex a) +{ + return a.r; +} + +//template +CUDA_CALLABLE static float real(float a) +{ + return a; +} + +template +CUDA_CALLABLE static T imag(rts::rtsComplex a) +{ + return a.i; +} + +//trigonometric functions +template +CUDA_CALLABLE rts::rtsComplex sin(const rts::rtsComplex x) +{ + rts::rtsComplex result; + result.r = std::sin(x.r) * std::cosh(x.i); + result.i = std::cos(x.r) * std::sinh(x.i); + + return result; +} + +template +CUDA_CALLABLE rts::rtsComplex cos(const rts::rtsComplex x) +{ + rts::rtsComplex result; + result.r = std::cos(x.r) * std::cosh(x.i); + result.i = -(std::sin(x.r) * std::sinh(x.i)); + + return result; +} + + +template +std::ostream& operator<<(std::ostream& os, rts::rtsComplex x) +{ + os< +#include + +namespace rts +{ + +template +struct rtsMatrix +{ + //the matrix will be stored in column-major order (compatible with OpenGL) + T M[N*N]; + + rtsMatrix() + { + for(int r=0; r operator=(T rhs) + { + int Nsq = N*N; + for(int i=0; i operator=(rtsMatrix rhs) + { + for(int i=0; i operator*(rtsVector rhs) + { + rtsVector result; + + for(int r=0; r +std::ostream& operator<<(std::ostream& os, rts::rtsMatrix M) +{ + os< + +namespace rts +{ + +template +struct rtsPoint +{ + T p[N]; + + CUDA_CALLABLE rtsPoint() + { + + } + + //efficiency constructor, makes construction easier for 1D-4D vectors + CUDA_CALLABLE rtsPoint(T x, T y = (T)0.0, T z = (T)0.0, T w = (T)0.0) + { + if(N >= 1) + p[0] = x; + if(N >= 2) + p[1] = y; + if(N >= 3) + p[2] = z; + if(N >= 4) + p[3] = w; + } + + //arithmetic operators + CUDA_CALLABLE rts::rtsPoint operator+(rts::rtsVector v) + { + rts::rtsPoint r; + + //calculate the position of the resulting rtsPoint + for(int i=0; i operator-(rts::rtsVector v) + { + rts::rtsPoint r; + + //calculate the position of the resulting rtsPoint + for(int i=0; i operator-(rts::rtsPoint rhs) + { + rts::rtsVector r; + + //calculate the position of the resulting rtsPoint + for(int i=0; i operator*(T rhs) + { + rts::rtsPoint r; + + //calculate the position of the resulting rtsPoint + for(int i=0; i +std::ostream& operator<<(std::ostream& os, rts::rtsPoint p) +{ + os< +CUDA_CALLABLE rts::rtsPoint operator*(T lhs, rts::rtsPoint rhs) +{ + rts::rtsPoint r; + + return rhs * lhs; +} + + + +#endif diff --git a/rts/rtsProgressBar.h b/rts/rtsProgressBar.h new file mode 100644 index 0000000..f62f7e0 --- /dev/null +++ b/rts/rtsProgressBar.h @@ -0,0 +1,33 @@ +#ifndef RTS_PROGRESSBAR_H +#define RTS_PROGRESSBAR_H + +#include +#include +using namespace std; + +static void rtsProgressBar(int percent) +{ + stringstream bar; + static int x = 0; + string slash[4]; + slash[0] = "\\"; + slash[1] = "-"; + slash[2] = "/"; + slash[3] = "|"; + bar<<"["; + for(int i=0; i<40; i++) + { + if(percent > (float)i/(float)40 *100) + bar << "*"; + else + bar << " "; + } + bar<<"]"; + cout << "\r"; // carriage return back to beginning of line + cout << bar.str() << " " << slash[x] << " " << percent << " %"; // print the bars and percentage + x++; // increment to make the slash appear to rotate + if(x == 4) + x = 0; // reset slash animation +} + +#endif diff --git a/rts/rtsQuad.h b/rts/rtsQuad.h new file mode 100644 index 0000000..1e3f24b --- /dev/null +++ b/rts/rtsQuad.h @@ -0,0 +1,158 @@ +#ifndef RTS_RECT_H +#define RTS_RECT_H + +//enable CUDA_CALLABLE macro +#include "rts/cuda_callable.h" +#include "rts/rtsVector.h" +#include "rts/rtsPoint.h" +#include + +namespace rts{ + +//template for a rtsQuadangle class in ND space +template +struct rtsQuad +{ + /* + C------------------>O + ^ ^ + | | + Y | + | | + | | + A---------X-------->B + */ + + /*T A[N]; + T B[N]; + T C[N];*/ + + rts::rtsPoint A; + rts::rtsVector X; + rts::rtsVector Y; + + + CUDA_CALLABLE rtsQuad() + { + + } + + CUDA_CALLABLE rtsQuad(rtsPoint a, rtsPoint b, rtsPoint c) + { + + A = a; + X = b - a; + Y = c - a; + + } + + CUDA_CALLABLE rtsQuad(rts::rtsPoint pMin, rts::rtsPoint pMax, rts::rtsVector normal) + { + + //assign the corner rtsPoint + A = pMin; + + //compute the vector from pMin to pMax + rts::rtsVector v0; + v0 = pMax - pMin; + + //compute the cross product of A and the plane normal + rts::rtsVector v1; + v1 = v0.cross(normal); + + + //calculate rtsPoint B + rts::rtsPoint B; + B = A + v0 * 0.5 + v1 * 0.5; + + //calculate rtsPoint C + rts::rtsPoint C; + C = A + v0 * 0.5 - v1 * 0.5; + + //calculate X and Y + X = B - A; + Y = C - A; + + + + + } + + /*CUDA_CALLABLE rtsQuad(rts::rtsPoint p, rts::vector x, rts::vector y, T sx, T sy) + { + //This constructor creates a rtsQuad given a position, orientation, and size + // p = center position of the rtsQuad + // x = x-axis for the rtsQuadangle + // y = y-axis for the rtsQuadangle + // sx = size of the rtsQuad along the A-B axis + // sy = size of the rtsQuad along the A-C axis + + //normalize x and y + rts::vector nx = x.norm(); + rts::vector ny = y.norm(); + + //compute X and Y + X = sx * x; + Y = sy * y; + + //compute A + A = p - 0.5 * X - 0.5 * Y; + + }*/ + + CUDA_CALLABLE rts::rtsPoint p(T a, T b) + { + rts::rtsPoint result; + //given the two parameters a, b = [0 1], returns the position in world space + result = A + X * a + Y * b; + + return result; + } + + CUDA_CALLABLE rts::rtsPoint operator()(T a, T b) + { + return p(a, b); + } + + std::string toStr() + { + std::stringstream ss; + + ss<<"A = "< +class rtsQuaternion +{ +public: + T w; + T x; + T y; + T z; + + void normalize(); + void CreateRotation(T theta, T axis_x, T axis_y, T axis_z); + void CreateRotation(T theta, rtsVector axis); + rtsQuaternion operator*(rtsQuaternion &rhs); + rtsMatrix toMatrix(); + + + rtsQuaternion(); + rtsQuaternion(T w, T x, T y, T z); + +}; + +template +void rtsQuaternion::normalize() +{ + double length=sqrt(w*w + x*x + y*y + z*z); + w=w/length; + x=x/length; + y=y/length; + z=z/length; +} + +template +void rtsQuaternion::CreateRotation(T theta, T axis_x, T axis_y, T axis_z) +{ + //assign the given Euler rotation to this quaternion + w = cos(theta/2.0); + x = axis_x*sin(theta/2.0); + y = axis_y*sin(theta/2.0); + z = axis_z*sin(theta/2.0); +} + +template +void rtsQuaternion::CreateRotation(T theta, rtsVector axis) +{ + CreateRotation(theta, axis[0], axis[1], axis[2]); +} + +template +rtsQuaternion rtsQuaternion::operator *(rtsQuaternion ¶m) +{ + float A, B, C, D, E, F, G, H; + + + A = (w + x)*(param.w + param.x); + B = (z - y)*(param.y - param.z); + C = (w - x)*(param.y + param.z); + D = (y + z)*(param.w - param.x); + E = (x + z)*(param.x + param.y); + F = (x - z)*(param.x - param.y); + G = (w + y)*(param.w - param.z); + H = (w - y)*(param.w + param.z); + + rtsQuaternion result; + result.w = B + (-E - F + G + H) /2; + result.x = A - (E + F + G + H)/2; + result.y = C + (E - F + G - H)/2; + result.z = D + (E - F - G + H)/2; + + return result; +} + +template +rtsMatrix rtsQuaternion::toMatrix() +{ + rtsMatrix result; + + + double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; + + + // calculate coefficients + x2 = x + x; y2 = y + y; + z2 = z + z; + xx = x * x2; xy = x * y2; xz = x * z2; + yy = y * y2; yz = y * z2; zz = z * z2; + wx = w * x2; wy = w * y2; wz = w * z2; + + result(0, 0) = 1.0 - (yy + zz); + result(0, 1) = xy - wz; + //m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz; + + result(0, 2) = xz + wy; + //result(0, 3) = 0.0; + //m[2][0] = xz + wy; m[3][0] = 0.0; + + result(1, 0) = xy + wz; + result(1, 1) = 1.0 - (xx + zz); + //m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz); + + result(1, 2) = yz - wx; + //result(1, 3) = 0.0; + //m[2][1] = yz - wx; m[3][1] = 0.0; + + result(2, 0) = xz - wy; + result(2, 1) = yz + wx; + //m[0][2] = xz - wy; m[1][2] = yz + wx; + + result(2, 2) = 1.0 - (xx + yy); + //result(3, 2) = 0.0; + //m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0; + + /*result(3, 0) = 0.0; + result(3, 1) = 0.0; + result(3, 2) = 0.0; + result(3, 3) = 1.0;*/ + //m[0][3] = 0; m[1][3] = 0; + //m[2][3] = 0; m[3][3] = 1; + /* + double* orientationmatrix=(double*)m; + char c; + + + double* result=new double[16]; + double* array=(double*)m; + for(int i=0; i<16; i++) + result[i]=array[i]; + */ + + return result; +} + +template +rtsQuaternion::rtsQuaternion() +{ + w=0.0; x=0.0; y=0.0; z=0.0; +} + +template +rtsQuaternion::rtsQuaternion(T c, T i, T j, T k) +{ + w=c; x=i; y=j; z=k; +} + +} //end rts namespace + +#endif diff --git a/rts/rtsVector.h b/rts/rtsVector.h new file mode 100644 index 0000000..f9a3957 --- /dev/null +++ b/rts/rtsVector.h @@ -0,0 +1,213 @@ +#ifndef RTS_VECTOR_H +#define RTS_VECTOR_H + +#include +//#include "rts/point.h" + +namespace rts +{ + + + +template +struct rtsVector +{ + T v[N]; + + CUDA_CALLABLE rtsVector() + { + //memset(v, 0, sizeof(T) * N); + for(int i=0; i= 1) + v[0] = x; + if(N >= 2) + v[1] = y; + if(N >= 3) + v[2] = z; + if(N >= 4) + v[3] = w; + } + + CUDA_CALLABLE rtsVector(const T(&data)[N]) + { + memcpy(v, data, sizeof(T) * N); + } + + CUDA_CALLABLE T len() + { + //compute and return the vector length + T sum_sq = (T)0; + for(int i=0; i cart2sph() + { + //convert the vector from cartesian to spherical coordinates + //x, y, z -> r, theta, phi (where theta = 0 to 2*pi) + + rtsVector sph; + sph[0] = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); + sph[1] = std::atan2(v[1], v[0]); + sph[2] = std::acos(v[2] / sph[0]); + + return sph; + } + + CUDA_CALLABLE rtsVector sph2cart() + { + //convert the vector from cartesian to spherical coordinates + //r, theta, phi -> x, y, z (where theta = 0 to 2*pi) + + rtsVector cart; + cart[0] = v[0] * std::cos(v[1]) * std::sin(v[2]); + cart[1] = v[0] * std::sin(v[1]) * std::sin(v[2]); + cart[2] = v[0] * std::cos(v[2]); + + return cart; + } + + CUDA_CALLABLE rtsVector norm() + { + //compute and return the vector norm + rtsVector result; + + //compute the vector length + T l = len(); + + //normalize + for(int i=0; i cross(rtsVector rhs) + { + rtsVector result; + + //compute the cross product (only valid for 3D vectors) + result[0] = v[1] * rhs[2] - v[2] * rhs[1]; + result[1] = v[2] * rhs[0] - v[0] * rhs[2]; + result[2] = v[0] * rhs[1] - v[1] * rhs[0]; + + return result; + } + + CUDA_CALLABLE T dot(rtsVector rhs) + { + T result = (T)0; + + for(int i=0; i operator+(rtsVector rhs) + { + rtsVector result; + + for(int i=0; i operator-(rtsVector rhs) + { + rtsVector result; + + for(int i=0; i operator*(T rhs) + { + rtsVector result; + + for(int i=0; i operator/(T rhs) + { + rtsVector result; + + for(int i=0; i +std::ostream& operator<<(std::ostream& os, rts::rtsVector v) +{ + os< +CUDA_CALLABLE rts::rtsVector operator-(rts::rtsVector v) +{ + rts::rtsVector r; + + //negate the vector + for(int i=0; i +CUDA_CALLABLE rts::rtsVector operator*(T lhs, rts::rtsVector rhs) +{ + rts::rtsVector r; + + return rhs * lhs; +} + +#endif diff --git a/rts/sbessel.h b/rts/sbessel.h index 46e0d6f..b432408 100644 --- a/rts/sbessel.h +++ b/rts/sbessel.h @@ -5,10 +5,11 @@ namespace rts{ -#define RTS_BESSEL_CONVERGENCE_FLOAT 0.00045 +#define RTS_BESSEL_CONVERGENCE_FLOAT 0.0145 +#define RTS_BESSEL_MAXIMUM_FLOAT -1e33 template -CUDA_CALLABLE void sbesselj(int n, rtcomplex x, rtcomplex* j) +CUDA_CALLABLE void sbesselj(int n, rtsComplex x, rtsComplex* j) { //compute the first bessel function if(n >= 0) @@ -34,7 +35,7 @@ CUDA_CALLABLE void sbesselj(int n, rtcomplex x, rtcomplex* j) } template -CUDA_CALLABLE void sbessely(int n, rtcomplex x, rtcomplex* y) +CUDA_CALLABLE void sbessely(int n, rtsComplex x, rtsComplex* y) { //compute the first bessel function if(n >= 0) @@ -54,14 +55,14 @@ CUDA_CALLABLE void sbessely(int n, rtcomplex x, rtcomplex* y) //spherical Hankel functions of the first kind template -CUDA_CALLABLE void sbesselh1(int n, rtcomplex x, rtcomplex* h) +CUDA_CALLABLE void sbesselh1(int n, rtsComplex x, rtsComplex* h) { //compute j_0 and j_1 - rtcomplex j[2]; + rtsComplex j[2]; sbesselj(1, x, j); //compute y_0 and y_1 - rtcomplex y[2]; + rtsComplex y[2]; sbessely(1, x, y); //compute the first-order Hhankel function @@ -82,55 +83,60 @@ CUDA_CALLABLE void sbesselh1(int n, rtcomplex x, rtcomplex* h) template CUDA_CALLABLE void init_sbesselj(T x, T* j) { - /*if(x < EPSILON_FLOAT) - { - j[0] = (T)1; - j[1] = (T)0; - return; - }*/ - //compute the first 2 bessel functions - j[0] = std::sin(x) / x; - - j[1] = j[0] / x - std::cos(x) / x; + j[0] = sin(x) / x; - //deal with the degenerate case of x = 0 - /*if(isnan(j[0])) - { - j[0] = (T)1; - j[1] = (T)0; - }*/ - + j[1] = j[0] / x - cos(x) / x; } template -CUDA_CALLABLE void shift_sbesselj(int n, T x, T* j)//, T stability = 1.4) +CUDA_CALLABLE void init_sbessely(T x, T* y) { + //compute the first 2 bessel functions + y[0] = -cos(x) / x; - /*if(x < EPSILON_FLOAT) - { - j[0] = j[1]; - j[1] = (T)0; - return; - }*/ + y[1] = y[0] / x - sin(x) / x; +} - T jnew; +template +CUDA_CALLABLE void shift_sbesselj(int n, T x, T* b)//, T stability = 1.4) +{ + + T bnew; //compute the next (order n) Bessel function - jnew = ((2 * n - 1) * j[1])/x - j[0]; + bnew = ((2 * n - 1) * b[1])/x - b[0]; //if(n > stability*x) - if(n > x) - if(jnew < RTS_BESSEL_CONVERGENCE_FLOAT) - jnew = (T)0; + if(n > real(x)) + if(real(bnew) < RTS_BESSEL_CONVERGENCE_FLOAT) + bnew = 0.0; + + //shift and add the new value to the array + b[0] = b[1]; + b[1] = bnew; +} + +template +CUDA_CALLABLE void shift_sbessely(int n, T x, T* b)//, T stability = 1.4) +{ + + T bnew; + + //compute the next (order n) Bessel function + bnew = ((2 * n - 1) * b[1])/x - b[0]; + + if(bnew < RTS_BESSEL_MAXIMUM_FLOAT || + (n > x && bnew > 0)) + { + bnew = (T)0; + b[1] = (T)0; + } - //deal with the degenerate case of x = 0 - //if(isnan(jnew)) - // jnew = (T)0; //shift and add the new value to the array - j[0] = j[1]; - j[1] = jnew; + b[0] = b[1]; + b[1] = bnew; } diff --git a/rts/vector.h b/rts/vector.h deleted file mode 100644 index 776d9d6..0000000 --- a/rts/vector.h +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef RTS_VECTOR_H -#define RTS_VECTOR_H - -#include -//#include "rts/point.h" - -namespace rts -{ - - - -template -struct vector -{ - T v[N]; - - CUDA_CALLABLE vector() - { - //memset(v, 0, sizeof(T) * N); - } - - //efficiency constructor, makes construction easier for 1D-4D vectors - CUDA_CALLABLE vector(T x, T y = (T)0.0, T z = (T)0.0, T w = (T)0.0) - { - if(N >= 1) - v[0] = x; - if(N >= 2) - v[1] = y; - if(N >= 3) - v[2] = z; - if(N >= 4) - v[3] = w; - } - - CUDA_CALLABLE vector(const T(&data)[N]) - { - memcpy(v, data, sizeof(T) * N); - } - - CUDA_CALLABLE T len() - { - //compute and return the vector length - T sum_sq = (T)0; - for(int i=0; i cart2sph() - { - //convert the vector from cartesian to spherical coordinates - //x, y, z -> r, theta, phi - - vector sph; - sph[0] = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); - sph[1] = std::atan2(v[1], v[0]); - sph[2] = std::acos(v[2] / sph[0]); - - return sph; - } - - CUDA_CALLABLE vector sph2cart() - { - //convert the vector from cartesian to spherical coordinates - //r, theta, phi -> x, y, z - - vector cart; - cart[0] = v[0] * std::cos(v[1]) * std::sin(v[2]); - cart[1] = v[0] * std::sin(v[1]) * std::sin(v[2]); - cart[2] = v[0] * std::cos(v[2]); - - return cart; - } - - CUDA_CALLABLE vector norm() - { - //compute and return the vector norm - vector result; - - //compute the vector length - T l = len(); - - //normalize - for(int i=0; i cross(vector rhs) - { - vector result; - - //compute the cross product (only valid for 3D vectors) - result[0] = v[1] * rhs[2] - v[2] * rhs[1]; - result[1] = v[2] * rhs[0] - v[0] * rhs[2]; - result[2] = v[0] * rhs[1] - v[1] * rhs[0]; - - return result; - } - - CUDA_CALLABLE T dot(vector rhs) - { - T result = (T)0; - - for(int i=0; i operator+(vector rhs) - { - vector result; - - for(int i=0; i operator-(vector rhs) - { - vector result; - - for(int i=0; i operator*(T rhs) - { - vector result; - - for(int i=0; i operator/(T rhs) - { - vector result; - - for(int i=0; i -std::ostream& operator<<(std::ostream& os, rts::vector v) -{ - os< -CUDA_CALLABLE rts::vector operator-(rts::vector v) -{ - rts::vector r; - - //negate the vector - for(int i=0; i -CUDA_CALLABLE rts::vector operator*(T lhs, rts::vector rhs) -{ - rts::vector r; - - return rhs * lhs; -} - -#endif -- libgit2 0.21.4