JDFTx  1.2.0
vector3.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------
2 Copyright 2011 Ravishankar Sundararaman
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx. If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #ifndef JDFTX_CORE_VECTOR3_H
21 #define JDFTX_CORE_VECTOR3_H
22 
25 
26 #include <core/scalar.h>
27 #include <vector>
28 #include <cstdio>
29 
30 #define LOOP3(code) { for(int k=0; k<3; k++) { code } }
31 
33 template<typename scalar=double> class vector3
34 {
35  scalar v[3];
36 public:
37  //Accessors
38  __hostanddev__ scalar& operator[](int k) { return v[k]; }
39  __hostanddev__ const scalar& operator[](int k) const { return v[k]; }
40  __hostanddev__ scalar& x() { return v[0]; }
41  __hostanddev__ scalar& y() { return v[1]; }
42  __hostanddev__ scalar& z() { return v[2]; }
43  __hostanddev__ const scalar& x() const { return v[0]; }
44  __hostanddev__ const scalar& y() const { return v[1]; }
45  __hostanddev__ const scalar& z() const { return v[2]; }
46 
47  //Constructor
48  __hostanddev__ explicit vector3(scalar a=0, scalar b=0, scalar c=0) { v[0]=a; v[1]=b; v[2]=c; }
49  vector3(std::vector<scalar> a) { LOOP3(v[k]=a[k];) }
50  template<typename scalar2> __hostanddev__ explicit vector3(const vector3<scalar2>& a) { LOOP3(v[k]=a[k];) }
51 
52  //Arithmetic:
53  __hostanddev__ vector3 operator+(const vector3 &a) const { return vector3(v[0]+a[0], v[1]+a[1], v[2]+a[2]); }
54  __hostanddev__ vector3 operator+=(const vector3 &a) { LOOP3( v[k]+=a[k]; ) return *this; }
55  __hostanddev__ vector3 operator+(const scalar a) const { return vector3(v[0]+a, v[1]+a, v[2]+a); }
56  __hostanddev__ vector3 operator+=(const scalar a) { LOOP3( v[k]+=a; ) return *this; }
57 
58  __hostanddev__ vector3 operator-() const { return vector3(-v[0],-v[1],-v[2]); }
59  __hostanddev__ vector3 operator-(const vector3 &a) const { return vector3(v[0]-a[0], v[1]-a[1], v[2]-a[2]); }
60  __hostanddev__ vector3 operator-=(const vector3 &a) { LOOP3( v[k]-=a[k]; ) return *this; }
61 
62  __hostanddev__ vector3 operator/(scalar s) const { return (*this)*(1.0/s); }
63  __hostanddev__ vector3& operator/=(scalar s) { return (*this)*=(1.0/s); }
64 
65  __hostanddev__ scalar length_squared() const { return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; }
66  __hostanddev__ scalar length() const { return sqrt(length_squared()); }
67 
68  void print(FILE* fp, const char *format) const { std::fprintf(fp, "[ "); LOOP3( fprintf(fp, format, v[k]); ) std::fprintf(fp, " ]\n"); }
69  __hostanddev__ bool operator==(const vector3& w) const { LOOP3( if(v[k] != w[k]) return false; ) return true; }
70  __hostanddev__ bool operator<(const vector3& w) const { LOOP3( if(v[k]!=w[k]) return v[k]<w[k]; ) return false; }
71 };
72 
73 template<typename scalar> __hostanddev__ vector3<scalar> operator+(scalar s, const vector3<scalar>& a) { return vector3<scalar>(a[0]+s, a[1]+s, a[2]+s); }
74 __hostanddev__ vector3<int> operator+(int s, const vector3<int>& a) { return vector3<int>(a[0]+s, a[1]+s, a[2]+s); }
75 __hostanddev__ vector3<int> operator+(const vector3<int>& a, int s) { return vector3<int>(a[0]+s, a[1]+s, a[2]+s); }
76 //Mixed additions (special cases)
77 template<typename scalar> __hostanddev__ vector3<scalar> operator+(const vector3<scalar>& a, int s) { return vector3<scalar>(a[0]+s, a[1]+s, a[2]+s); }
78 template<typename scalar> __hostanddev__ vector3<scalar> operator+(int s, const vector3<scalar>& a) { return vector3<scalar>(a[0]+s, a[1]+s, a[2]+s); }
79 __hostanddev__ vector3<> operator+(vector3<> a, vector3<int> b) { return vector3<>(a[0]+b[0], a[1]+b[1], a[2]+b[2]); }
80 __hostanddev__ vector3<> operator+(vector3<int> a, vector3<> b) { return vector3<>(a[0]+b[0], a[1]+b[1], a[2]+b[2]); }
81 
82 template<typename scalar> __hostanddev__ vector3<scalar>& operator*=(vector3<scalar>& a, scalar s) { LOOP3(a[k]*=s;) return a; }
83 template<typename scalar> __hostanddev__ vector3<scalar>& operator*=(vector3<scalar>& a, double s) { LOOP3(a[k]*=s;) return a; }
84 template<typename scalar> __hostanddev__ vector3<scalar>& operator*=(vector3<scalar>& a, int s) { LOOP3(a[k]*=s;) return a; }
85 __hostanddev__ vector3<>& operator*=(vector3<>& a, double s) { LOOP3(a[k]*=s;) return a; }
86 __hostanddev__ vector3<>& operator*=(vector3<>& a, int s) { LOOP3(a[k]*=s;) return a; }
87 __hostanddev__ vector3<int>& operator*=(vector3<int>& a, int s) { LOOP3(a[k]*=s;) return a; }
88 
89 template<typename scalar> __hostanddev__ vector3<scalar> operator*(scalar s, const vector3<scalar> &a) { vector3<scalar> v; LOOP3(v[k]=a[k]*s;) return v; }
90 template<typename scalar> __hostanddev__ vector3<scalar> operator*(double s, const vector3<scalar> &a) { vector3<scalar> v; LOOP3(v[k]=a[k]*s;) return v; }
91 template<typename scalar> __hostanddev__ vector3<scalar> operator*(const vector3<scalar> &a, double s) { vector3<scalar> v; LOOP3(v[k]=a[k]*s;) return v; }
92 template<typename scalar> __hostanddev__ vector3<scalar> operator*(int s, const vector3<scalar> &a) { vector3<scalar> v; LOOP3(v[k]=a[k]*s;) return v; }
93 template<typename scalar> __hostanddev__ vector3<scalar> operator*(const vector3<scalar> &a, int s) { vector3<scalar> v; LOOP3(v[k]=a[k]*s;) return v; }
94 __hostanddev__ vector3<> operator*(double s, const vector3<> &a) { vector3<> v; LOOP3(v[k]=a[k]*s;) return v; }
95 __hostanddev__ vector3<> operator*(const vector3<> &a, double s) { vector3<> v; LOOP3(v[k]=a[k]*s;) return v; }
96 __hostanddev__ vector3<> operator*(double s, const vector3<int> &a) { vector3<> v; LOOP3(v[k]=a[k]*s;) return v; }
97 __hostanddev__ vector3<> operator*(const vector3<int> &a, double s) { vector3<> v; LOOP3(v[k]=a[k]*s;) return v; }
98 __hostanddev__ vector3<complex> operator*(complex s, const vector3<> &a) { vector3<complex> v; LOOP3(v[k]=a[k]*s;) return v; }
99 __hostanddev__ vector3<complex> operator*(const vector3<> &a, complex s) { vector3<complex> v; LOOP3(v[k]=a[k]*s;) return v; }
100 __hostanddev__ vector3<complex> operator*(complex s, const vector3<int> &a) { vector3<complex> v; LOOP3(v[k]=a[k]*s;) return v; }
101 __hostanddev__ vector3<complex> operator*(const vector3<int> &a, complex s) { vector3<complex> v; LOOP3(v[k]=a[k]*s;) return v; }
102 
103 //dot product of similar generic vectors, and all combinations with real vectors
104 template<typename scalar> __hostanddev__ scalar dot(const vector3<scalar>& a, const vector3<scalar>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
105 template<typename scalar> __hostanddev__ scalar dot(const vector3<double>& a, const vector3<scalar>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
106 template<typename scalar> __hostanddev__ scalar dot(const vector3<int>& a, const vector3<scalar>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
107 template<typename scalar> __hostanddev__ scalar dot(const vector3<scalar>& a, const vector3<double>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
108 template<typename scalar> __hostanddev__ scalar dot(const vector3<scalar>& a, const vector3<int>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
109 __hostanddev__ double dot(const vector3<double>& a, const vector3<double>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
110 __hostanddev__ double dot(const vector3<int>& a, const vector3<double>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
111 __hostanddev__ double dot(const vector3<double>& a, const vector3<int>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
112 __hostanddev__ int dot(const vector3<int>& a, const vector3<int>& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
113 
115 template<typename scalar> __hostanddev__ vector3<scalar> cross(const vector3<scalar> &a, const vector3<scalar> &b)
116 { return vector3<scalar>(
117  a[1]*b[2] - a[2]*b[1],
118  a[2]*b[0] - a[0]*b[2],
119  a[0]*b[1] - a[1]*b[0] );
120 }
121 
123 template<typename scalar> __hostanddev__ scalar box(const vector3<scalar>& a, const vector3<scalar>& b, const vector3<scalar>& c)
124 { return dot(a,cross(b,c));
125 }
126 
128 __hostanddev__ vector3<int> round(const vector3<>& v, double* err=0)
129 { vector3<int> out;
130  LOOP3( out[k] = round(v[k]); )
131  if(err) *err = (v+(-out)).length();
132  return out;
133 }
134 
138 __hostanddev__ double circDistanceSquared(const vector3<>& a, const vector3<>& b)
139 { return (cis(2*M_PI*a[0]) - cis(2*M_PI*b[0])).norm()
140  + (cis(2*M_PI*a[1]) - cis(2*M_PI*b[1])).norm()
141  + (cis(2*M_PI*a[2]) - cis(2*M_PI*b[2])).norm();
142 }
143 
144 
146 template<typename T> T gcd(T x, T y)
147 { while(y != 0)
148  { T yPrev = y;
149  y = x % y;
150  x = yPrev;
151  }
152  return x;
153 }
154 
156 template<typename T> vector3<T> gcdReduce(const vector3<T>& d)
157 { T g = gcd(gcd(d[0], d[1]), d[2]);
158  return vector3<T>(d[0]/g, d[1]/g, d[2]/g);
159 }
160 
161 
163 template<typename scalar> __hostanddev__ vector3<scalar> loadVector(const vector3<const scalar*>& vArr, int i)
164 { return vector3<scalar>( vArr[0][i], vArr[1][i], vArr[2][i] );
165 }
167 template<typename scalar> __hostanddev__ vector3<scalar> loadVector(const vector3<scalar*>& vArr, int i)
168 { return vector3<scalar>( vArr[0][i], vArr[1][i], vArr[2][i] );
169 }
171 template<typename scalar> __hostanddev__ void storeVector(const vector3<scalar>& v, vector3<scalar*>& vArr, int i)
172 { LOOP3( vArr[k][i] = v[k]; )
173 }
175 template<typename scalar> __hostanddev__ void accumVector(const vector3<scalar>& v, vector3<scalar*>& vArr, int i)
176 { LOOP3( vArr[k][i] += v[k]; )
177 }
178 
179 #undef LOOP3
180 #endif // JDFTX_CORE_VECTOR3_H
ScalarField sqrt(const ScalarField &)
Elementwise square root (preserve input)
complex dot(const Tptr &X, const Tptr &Y)
Definition: Operators.h:196
__hostanddev__ vector3< scalar > cross(const vector3< scalar > &a, const vector3< scalar > &b)
cross product
Definition: vector3.h:115
vector3< T > gcdReduce(const vector3< T > &d)
Reduce an integer vector by its gcd.
Definition: vector3.h:156
T gcd(T x, T y)
GCD of integers, templated over integer types.
Definition: vector3.h:146
__hostanddev__ void storeVector(const vector3< scalar > &v, vector3< scalar * > &vArr, int i)
Store vector to a vector field.
Definition: vector3.h:171
__hostanddev__ void accumVector(const vector3< scalar > &v, vector3< scalar * > &vArr, int i)
Accumulate vector onto a vector field.
Definition: vector3.h:175
__hostanddev__ scalar box(const vector3< scalar > &a, const vector3< scalar > &b, const vector3< scalar > &c)
box product / triple product
Definition: vector3.h:123
__hostanddev__ vector3< scalar > loadVector(const vector3< const scalar * > &vArr, int i)
Load vector from a constant vector field.
Definition: vector3.h:163
__hostanddev__ vector3< int > round(const vector3<> &v, double *err=0)
Round vector3<> to vector3<int> (and optionally retrieve error)
Definition: vector3.h:128
__hostanddev__ double circDistanceSquared(const vector3<> &a, const vector3<> &b)
Definition: vector3.h:138
Complex number (need to define our own because we need operators for gpu code as well) ...
Definition: scalar.h:49
Generic 3-vector.
Definition: vector3.h:33