Something went wrong on our end
useful.h 11.64 KiB
///////////////////////////////////////////////////////////////////////
// Useful classes.
// Author: Jeff Comer <jcomer2@illinois.edu>
#ifndef USEFUL_H
#define USEFUL_H
#ifdef __CUDACC__
#define HOST __host__
#define DEVICE __device__
#else
#define HOST
#define DEVICE
#endif
#if defined(__CUDACC__) // NVCC
#define MY_ALIGN(n) __align__(n)
#elif defined(__GNUC__) // GCC
#define MY_ALIGN(n) __attribute__((aligned(n)))
#elif defined(_MSC_VER) // MSVC
#define MY_ALIGN(n) __declspec(align(n))
#else
#error "Please provide a definition for MY_ALIGN macro for your host compiler!"
#endif
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cuda_runtime.h>
// using namespace std;
bool isReal(char c);
bool isInt(char c);
int firstSpace(const char* s, int max);
/*class int2 {
public:
int2(int x, int y) : x(x), y(y) {}
int x, y;
}*/
// A classic growable string class.
class String {
public:
HOST DEVICE inline String() {
cap = 16;
c = new char[cap];
c[0] = '\0';
len = 1;
}
HOST DEVICE inline String(const char* s) {
len = strlen(s) + 1;
cap = len;
c = new char[len];
for (int i = 0; i < len; i++)
c[i] = s[i];
}
HOST DEVICE inline String(const String& s) {
len = s.len;
cap = s.len;
c = new char[cap];
for (int i = 0; i < s.len; i++)
c[i] = s.c[i];
}
HOST DEVICE inline static size_t strlen(const char * s) {
size_t i;
for (i = 0; s[i] != '\0'; i++);
return i;
}
HOST DEVICE inline ~String() {
delete[] c;
}
String& operator=(const String& s);
void add(char c0);
void add(const char* s);
void add(String& s);
void printInline() const;
void print() const;
int length() const;
// Negative indices go from the end.
String range(int first, int last) const;
String trim();
static bool isWhite(char c);
int tokenCount() const;
int tokenCount(char delim) const;
int tokenize(String* tokenList) const;
int tokenize(String* tokenList, char delim) const;
void lower();
void upper();
char operator[](int i) const;
bool operator==(const String& s) const;
bool operator==(const char* s) const;
bool operator!=(const String& s) const;
operator const char*() const {
return c;
}
const char* val() const;
String getNumbers() const;
private:
char* c;
int cap, len;
void grow(int n);
};
String operator+(String s, int i);
String operator+(String s, const char* c);
String operator+(String s1, String s2);
// class Vector3
// Operations on 3D float vectors
//
class MY_ALIGN(16) Vector3 {
public:
HOST DEVICE inline Vector3() : x(0), y(0), z(0), w(0) {}
HOST DEVICE inline Vector3(float s):x(s), y(s), z(s), w(s) {}
HOST DEVICE inline Vector3(const Vector3& v):x(v.x), y(v.y), z(v.z), w(v.w) {}
HOST DEVICE inline Vector3(float x0, float y0, float z0) : x(x0), y(y0), z(z0), w(0) {}
HOST DEVICE inline Vector3(const float* d) : x(d[0]), y(d[1]), z(d[2]), w(0) {}
DEVICE inline Vector3(const float4 a) : x(a.x ), y(a.y ), z(a.z ), w(a.w) {}
static Vector3 random(float s);
HOST DEVICE inline Vector3 cross(const Vector3& w) const {
Vector3 v;
v.x = y*w.z - z*w.y;
v.y = z*w.x - x*w.z;
v.z = x*w.y - y*w.x;
return v;
}
HOST DEVICE inline Vector3& operator=(const Vector3& v) {
x = v.x;
y = v.y;
z = v.z;
return *this;
}
HOST DEVICE inline Vector3& operator+=(const Vector3& v) {
x += v.x;
y += v.y;
z += v.z;
return *this;
}
HOST DEVICE inline Vector3& operator-=(const Vector3& v) {
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
HOST DEVICE inline Vector3& operator*=(float s) {
x *= s;
y *= s;
z *= s;
return *this;
}
HOST DEVICE inline Vector3& operator/=(float s) {
const float sinv = 1.0f/s;
x *= sinv;
y *= sinv;
z *= sinv;
return *this;
}
HOST DEVICE inline Vector3 operator-() const {
Vector3 v;
v.x = -x;
v.y = -y;
v.z = -z;
return v;
}
HOST DEVICE inline Vector3 operator+(const Vector3& w ) const {
Vector3 v;
v.x = x + w.x;
v.y = y + w.y;
v.z = z + w.z;
return v;
}
HOST DEVICE inline Vector3 operator-(const Vector3& w ) const {
Vector3 v;
v.x = x - w.x;
v.y = y - w.y;
v.z = z - w.z;
return v;
}
HOST DEVICE inline Vector3 operator*(float s) const {
Vector3 v;
v.x = s*x;
v.y = s*y;
v.z = s*z;
return v;
}
HOST DEVICE inline float dot(const Vector3& w) const { return x*w.x + y*w.y + z*w.z; }
HOST DEVICE inline float length() const { return sqrtf(x*x + y*y + z*z); }
HOST DEVICE inline float length2() const { return x*x + y*y + z*z; }
HOST DEVICE inline float rLength() const {
float l = length();
if (l != 0.0f)
return 1.0f / l;
return 0.0f;
}
HOST DEVICE inline float rLength2() const {
float l2 = length2();
if (l2 != 0.0f) return 1.0f / l2;
return 0.0f;
}
HOST DEVICE static inline Vector3 element_mult(const Vector3 v, const Vector3 w) {
Vector3 ret(
v.x*w.x,
v.y*w.y,
v.z*w.z);
return ret;
}
HOST DEVICE static inline Vector3 element_sqrt(const Vector3 w) {
Vector3 ret(
sqrt(w.x),
sqrt(w.y),
sqrt(w.z));
return ret;
}
HOST DEVICE inline void print() const {
printf("%0.3f %0.3f %0.3f\n", x,y,z);
}
float x, y, z, w; //append a member w
String toString() const;
};
HOST DEVICE inline Vector3 operator*(float s, Vector3 v) {
v.x *= s;
v.y *= s;
v.z *= s;
return v;
}
HOST DEVICE inline Vector3 operator/(Vector3 v, float s) {
const float sinv = 1.0f/s;
return v*sinv;
}
HOST DEVICE inline Vector3 operator/(float s, Vector3 v) {
v.x = s / v.x;
v.y = s / v.y;
v.z = s / v.z;
return v;
}
// class Matrix3
// Operations on 3D float matrices
class MY_ALIGN(16) Matrix3 {
friend class TrajectoryWriter;
friend class BaseGrid;
friend class RigidBodyController; /* for trajectory writing */
public:
HOST DEVICE inline Matrix3() : isDiag(false) {}
HOST DEVICE Matrix3(float s);
HOST DEVICE Matrix3(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz);
HOST DEVICE Matrix3(float x, float y, float z);
HOST DEVICE Matrix3(const Vector3& ex, const Vector3& ey, const Vector3& ez);
HOST DEVICE Matrix3(const float* d);
// Operators
HOST DEVICE inline const Matrix3 operator*(float s) const {
Matrix3 m;
m.exx = s*exx; m.exy = s*exy; m.exz = s*exz;
m.eyx = s*eyx; m.eyy = s*eyy; m.eyz = s*eyz;
m.ezx = s*ezx; m.ezy = s*ezy; m.ezz = s*ezz;
m.isDiag = isDiag;
return m;
}
HOST DEVICE friend inline Matrix3 operator*(float s, Matrix3 m) { return m*s; }
HOST DEVICE friend inline Matrix3 operator/(Matrix3 m, float s) {
const float sinv = 1.0f/s;
return m*sinv;
}
HOST DEVICE inline const Vector3 operator*(const Vector3& v) const { return this->transform(v); }
HOST DEVICE inline Matrix3 operator*(const Matrix3& m) const {
Matrix3 ret;
ret.exx = exx*m.exx + exy*m.eyx + exz*m.ezx;
ret.eyx = eyx*m.exx + eyy*m.eyx + eyz*m.ezx;
ret.ezx = ezx*m.exx + ezy*m.eyx + ezz*m.ezx;
ret.exy = exx*m.exy + exy*m.eyy + exz*m.ezy;
ret.eyy = eyx*m.exy + eyy*m.eyy + eyz*m.ezy;
ret.ezy = ezx*m.exy + ezy*m.eyy + ezz*m.ezy;
ret.exz = exx*m.exz + exy*m.eyz + exz*m.ezz;
ret.eyz = eyx*m.exz + eyy*m.eyz + eyz*m.ezz;
ret.ezz = ezx*m.exz + ezy*m.eyz + ezz*m.ezz;
ret.setIsDiag();
return ret;
}
HOST DEVICE inline Matrix3 operator-() const {
Matrix3 m;
m.exx = -exx;
m.exy = -exy;
m.exz = -exz;
m.eyx = -eyx;
m.eyy = -eyy;
m.eyz = -eyz;
m.ezx = -ezx;
m.ezy = -ezy;
m.ezz = -ezz;
m.isDiag = isDiag;
return m;
}
HOST DEVICE inline Matrix3 transpose() const {
Matrix3 m;
m.exx = exx;
m.exy = eyx;
m.exz = ezx;
m.eyx = exy;
m.eyy = eyy;
m.eyz = ezy;
m.ezx = exz;
m.ezy = eyz;
m.ezz = ezz;
m.isDiag = isDiag;
return m;
}
HOST DEVICE inline Vector3 transform(const Vector3& v) const {
Vector3 w;
if (isDiag) {
w.x = exx*v.x;
w.y = eyy*v.y;
w.z = ezz*v.z;
} else {
w.x = exx*v.x + exy*v.y + exz*v.z;
w.y = eyx*v.x + eyy*v.y + eyz*v.z;
w.z = ezx*v.x + ezy*v.y + ezz*v.z;
}
return w;
}
HOST DEVICE inline Matrix3 transform(const Matrix3& m) const {
Matrix3 ret;
ret.exx = exx*m.exx + exy*m.eyx + exz*m.ezx;
ret.eyx = eyx*m.exx + eyy*m.eyx + eyz*m.ezx;
ret.ezx = ezx*m.exx + ezy*m.eyx + ezz*m.ezx;
ret.exy = exx*m.exy + exy*m.eyy + exz*m.ezy;
ret.eyy = eyx*m.exy + eyy*m.eyy + eyz*m.ezy;
ret.ezy = ezx*m.exy + ezy*m.eyy + ezz*m.ezy;
ret.exz = exx*m.exz + exy*m.eyz + exz*m.ezz;
ret.eyz = eyx*m.exz + eyy*m.eyz + eyz*m.ezz;
ret.ezz = ezx*m.exz + ezy*m.eyz + ezz*m.ezz;
ret.setIsDiag();
return ret;
}
HOST DEVICE
Matrix3 inverse() const;
HOST DEVICE
float det() const;
//Han-Yi Chou
HOST DEVICE inline Matrix3 normalized() const {
Vector3 x = this->ex();
Vector3 y = this->ey();
/*
x = x / x.length();
float error = x.dot(y);
y = y-(error*x);
y = y / y.length();
Vector3 z = x.cross(y);
z = z / z.length();*/
//x = (0.5*(3-x.dot(x)))*x; /* approximate normalization */
//y = (0.5*(3-y.dot(y)))*y;
//z = (0.5*(3-z.dot(z)))*z;
//return Matrix3(x,y,z);
Vector3 z = x.cross(y);
z = z / z.length();
x = x / x.length();
y = z.cross(x);
y = y / y.length();
return Matrix3(x,y,z);
}
HOST DEVICE void setIsDiag() {
isDiag = (exy == 0 && exz == 0 &&
eyx == 0 && eyz == 0 &&
ezx == 0 && ezy == 0) ? true : false;
}
HOST DEVICE inline Vector3 ex() const { return Vector3(exx,eyx,ezx); }
HOST DEVICE inline Vector3 ey() const { return Vector3(exy,eyy,ezy); }
HOST DEVICE inline Vector3 ez() const { return Vector3(exz,eyz,ezz); }
String toString() const;
String toString1() const;
HOST DEVICE inline void print() const {
printf("%0.3f %0.3f %0.3f\n", exx,exy,exz);
printf("%0.3f %0.3f %0.3f\n", eyx,eyy,eyz);
printf("%0.3f %0.3f %0.3f\n", ezx,ezy,ezz);
}
HOST DEVICE inline bool isDiagonal() const { return isDiag; }
private:
float exx, exy, exz;
float eyx, eyy, eyz;
float ezx, ezy, ezz;
bool isDiag;
};
// class IndexList
// A growable list of integers.
class MY_ALIGN(16) IndexList {
public:
IndexList();
IndexList(const IndexList& l);
IndexList(const int* a, int n);
~IndexList();
IndexList& operator=(const IndexList& l);
void add(const int val);
void add(const IndexList& l);
HOST DEVICE inline int length() const {
return num;
}
HOST DEVICE inline int get(const int i) const {
#ifdef DEBUG
if (i < 0 || i >= num) {
printf("Warning! IndexList::get out of bounds.\n");
return 0;
}
#endif
return lis[i];
}
int* getList();
void setList(int* list) { lis = list; }
void clear();
String toString() const;
int find(int key);
IndexList range(int i0, int i1);
public:
int num, maxnum;
int* lis;
};
class ForceEnergy {
public:
HOST DEVICE ForceEnergy() : f(0.f), e(0.f) {};
HOST DEVICE ForceEnergy(Vector3 &f, float &e) :
f(f), e(e) {};
HOST DEVICE explicit ForceEnergy(float e) : f(e), e(e) {};
HOST DEVICE ForceEnergy(float f, float e) :
f(f), e(e) {};
HOST DEVICE ForceEnergy(const ForceEnergy& src)
{
f = src.f;
e = src.e;
}
HOST DEVICE ForceEnergy& operator=(const ForceEnergy& src)
{
if(&src != this)
{
this->f = src.f;
this->e = src.e;
}
return *this;
}
HOST DEVICE ForceEnergy operator+(const ForceEnergy& src)
{
ForceEnergy fe;
fe.f = this->f + src.f;
fe.e = this->e + src.e;
return fe;
}
HOST DEVICE ForceEnergy& operator+=(ForceEnergy& src)
{
this->f += src.f;
this->e += src.e;
return *this;
}
Vector3 f;
float e;
};
#endif