- Main Page
- Related Pages
- Classes
- Files

- File List

# vectorize_pnacl.h

    00001 #ifndef OPENMM_VECTORIZE_PNACL_H_
    00002 #define OPENMM_VECTORIZE_PNACL_H_
    00003
    00004 /* -------------------------------------------------------------------------- *
    00005  *                                   OpenMM                                   *
    00006  * -------------------------------------------------------------------------- *
    00007  * This is part of the OpenMM molecular simulation toolkit originating from   *
    00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
    00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
    00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
    00011  *                                                                            *
    00012  * Portions copyright (c) 2013-2014 Stanford University and the Authors.      *
    00013  * Authors: Peter Eastman                                                     *
    00014  * Contributors:                                                              *
    00015  *                                                                            *
    00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
    00017  * copy of this software and associated documentation files (the "Software"), *
    00018  * to deal in the Software without restriction, including without limitation  *
    00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
    00020  * and/or sell copies of the Software, and to permit persons to whom the      *
    00021  * Software is furnished to do so, subject to the following conditions:       *
    00022  *                                                                            *
    00023  * The above copyright notice and this permission notice shall be included in *
    00024  * all copies or substantial portions of the Software.                        *
    00025  *                                                                            *
    00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
    00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
    00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
    00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
    00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
    00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
    00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
    00033  * -------------------------------------------------------------------------- */
    00034
    00035 #include <cmath>
    00036 #include <cstdlib>
    00037
    00038 // This file defines classes and functions to simplify vectorizing code with portable SIMD vectors.
    00039
    00043 static bool isVec4Supported() {
    00044     return true;
    00045 }
    00046
    00047 typedef float __m128 __attribute__((vector_size(16), aligned(4)));
    00048 typedef int __m128i __attribute__((vector_size(16), aligned(4)));
    00049
    00050 class ivec4;
    00051
    00055 class fvec4 {
    00056 public:
    00057     __m128 val;
    00058
    00059     fvec4() {}
    00060     fvec4(float v) {
    00061         val = {v, v, v, v};
    00062     }
    00063     fvec4(float v1, float v2, float v3, float v4) {
    00064         val = {v1, v2, v3, v4};
    00065     }
    00066     fvec4(__m128 v) : val(v) {}
    00067     fvec4(const float* v) {
    00068         val = *((__m128*) v);
    00069     }
    00070     operator __m128() const {
    00071         return val;
    00072     }
    00073     float operator[](int i) const {
    00074         return val[i];
    00075     }
    00076     void store(float* v) const {
    00077         *((__m128*) v) = val;
    00078     }
    00079     fvec4 operator+(const fvec4& other) const {
    00080         return val+other;
    00081     }
    00082     fvec4 operator-(const fvec4& other) const {
    00083         return val-other;
    00084     }
    00085     fvec4 operator*(const fvec4& other) const {
    00086         return val*other;
    00087     }
    00088     fvec4 operator/(const fvec4& other) const {
    00089         return val/other;
    00090     }
    00091     void operator+=(const fvec4& other) {
    00092         val = val+other;
    00093     }
    00094     void operator-=(const fvec4& other) {
    00095         val = val-other;
    00096     }
    00097     void operator*=(const fvec4& other) {
    00098         val = val*other;
    00099     }
    00100     void operator/=(const fvec4& other) {
    00101         val = val/other;
    00102     }
    00103     fvec4 operator-() const {
    00104         return -val;
    00105     }
    00106     fvec4 operator&(const fvec4& other) const {
    00107         return (fvec4) (((__m128i)val)&((__m128i)other.val));
    00108     }
    00109     fvec4 operator|(const fvec4& other) const {
    00110         return (fvec4) (((__m128i)val)|((__m128i)other.val));
    00111     }
    00112     fvec4 operator==(const fvec4& other) const {
    00113         return (val==other.val);
    00114     }
    00115     fvec4 operator!=(const fvec4& other) const {
    00116         return (val!=other.val);
    00117     }
    00118     fvec4 operator>(const fvec4& other) const {
    00119         return (val>other.val);
    00120     }
    00121     fvec4 operator<(const fvec4& other) const {
    00122         return (val<other.val);
    00123     }
    00124     fvec4 operator>=(const fvec4& other) const {
    00125         return (val>=other.val);
    00126     }
    00127     fvec4 operator<=(const fvec4& other) const {
    00128         return (val<=other.val);
    00129     }
    00130     operator ivec4() const;
    00131 };
    00132
    00136 class ivec4 {
    00137 public:
    00138     __m128i val;
    00139
    00140     ivec4() {}
    00141     ivec4(int v) {
    00142         val = {v, v, v, v};
    00143     }
    00144     ivec4(int v1, int v2, int v3, int v4) {
    00145         val = {v1, v2, v3, v4};
    00146     }
    00147     ivec4(__m128i v) : val(v) {}
    00148     ivec4(const int* v) {
    00149         val = *((__m128*) v);
    00150     }
    00151     operator __m128i() const {
    00152         return val;
    00153     }
    00154     int operator[](int i) const {
    00155         return val[i];
    00156     }
    00157     void store(int* v) const {
    00158         *((__m128*) v) = val;
    00159     }
    00160     ivec4 operator+(const ivec4& other) const {
    00161         return val+other;
    00162     }
    00163     ivec4 operator-(const ivec4& other) const {
    00164         return val-other;
    00165     }
    00166     ivec4 operator*(const ivec4& other) const {
    00167         return val*other;
    00168     }
    00169     void operator+=(const ivec4& other) {
    00170         val = val+other;
    00171     }
    00172     void operator-=(const ivec4& other) {
    00173         val = val-other;
    00174     }
    00175     void operator*=(const ivec4& other) {
    00176         val = val*other;
    00177     }
    00178     ivec4 operator-() const {
    00179         return -val;
    00180     }
    00181     ivec4 operator&(const ivec4& other) const {
    00182         return val&other.val;
    00183     }
    00184     ivec4 operator|(const ivec4& other) const {
    00185         return val|other.val;
    00186     }
    00187     ivec4 operator==(const ivec4& other) const {
    00188         return (val==other.val);
    00189     }
    00190     ivec4 operator!=(const ivec4& other) const {
    00191         return (val!=other.val);
    00192     }
    00193     ivec4 operator>(const ivec4& other) const {
    00194         return (val>other.val);
    00195     }
    00196     ivec4 operator<(const ivec4& other) const {
    00197         return (val<other.val);
    00198     }
    00199     ivec4 operator>=(const ivec4& other) const {
    00200         return (val>=other.val);
    00201     }
    00202     ivec4 operator<=(const ivec4& other) const {
    00203         return (val<=other.val);
    00204     }
    00205     operator fvec4() const;
    00206 };
    00207
    00208 // Conversion operators.
    00209
    00210 inline fvec4::operator ivec4() const {
    00211     return __builtin_convertvector(val, __m128i);
    00212 }
    00213
    00214 inline ivec4::operator fvec4() const {
    00215     return __builtin_convertvector(val, __m128);
    00216 }
    00217
    00218 // Functions that operate on fvec4s.
    00219
    00220 static inline fvec4 floor(const fvec4& v) {
    00221     return fvec4(std::floor(v[0]), std::floor(v[1]), std::floor(v[2]), std::floor(v[3]));
    00222 }
    00223
    00224 static inline fvec4 ceil(const fvec4& v) {
    00225     return fvec4(std::ceil(v[0]), std::ceil(v[1]), std::ceil(v[2]), std::ceil(v[3]));
    00226 }
    00227
    00228 static inline fvec4 round(const fvec4& v) {
    00229     return fvec4(std::round(v[0]), std::round(v[1]), std::round(v[2]), std::round(v[3]));
    00230 }
    00231
    00232 static inline fvec4 min(const fvec4& v1, const fvec4& v2) {
    00233     return fvec4(std::min(v1[0], v2[0]), std::min(v1[1], v2[1]), std::min(v1[2], v2[2]), std::min(v1[3], v2[3]));
    00234 }
    00235
    00236 static inline fvec4 max(const fvec4& v1, const fvec4& v2) {
    00237     return fvec4(std::max(v1[0], v2[0]), std::max(v1[1], v2[1]), std::max(v1[2], v2[2]), std::max(v1[3], v2[3]));
    00238 }
    00239
    00240 static inline fvec4 abs(const fvec4& v) {
    00241     return fvec4(std::abs(v[0]), std::abs(v[1]), std::abs(v[2]), std::abs(v[3]));
    00242 }
    00243
    00244 static inline fvec4 sqrt(const fvec4& v) {
    00245     return fvec4(std::sqrt(v[0]), std::sqrt(v[1]), std::sqrt(v[2]), std::sqrt(v[3]));
    00246 }
    00247
    00248 static inline float dot3(const fvec4& v1, const fvec4& v2) {
    00249     fvec4 r = v1*v2;
    00250     return r[0]+r[1]+r[2];
    00251 }
    00252
    00253 static inline float dot4(const fvec4& v1, const fvec4& v2) {
    00254     fvec4 r = v1*v2;
    00255     return r[0]+r[1]+r[2]+r[3];
    00256 }
    00257
    00258 static inline fvec4 cross(const fvec4& v1, const fvec4& v2) {
    00259     __m128 temp = v2.val*__builtin_shufflevector(v1.val, v1.val, 2, 0, 1, 3) -
    00260                   v1.val*__builtin_shufflevector(v2.val, v2.val, 2, 0, 1, 3);
    00261     return __builtin_shufflevector(temp, temp, 2, 0, 1, 3);
    00262 }
    00263
    00264 static inline void transpose(fvec4& v1, fvec4& v2, fvec4& v3, fvec4& v4) {
    00265     __m128 a1 = __builtin_shufflevector(v1.val, v2.val, 0, 4, 2, 6);
    00266     __m128 a2 = __builtin_shufflevector(v1.val, v2.val, 1, 5, 3, 7);
    00267     __m128 a3 = __builtin_shufflevector(v3.val, v4.val, 0, 4, 2, 6);
    00268     __m128 a4 = __builtin_shufflevector(v3.val, v4.val, 1, 5, 3, 7);
    00269     v1 = __builtin_shufflevector(a1, a3, 0, 1, 4, 5);
    00270     v2 = __builtin_shufflevector(a2, a4, 0, 1, 4, 5);
    00271     v3 = __builtin_shufflevector(a1, a3, 2, 3, 6, 7);
    00272     v4 = __builtin_shufflevector(a2, a4, 2, 3, 6, 7);
    00273 }
    00274
    00275 // Functions that operate on ivec4s.
    00276
    00277 static inline ivec4 min(const ivec4& v1, const ivec4& v2) {
    00278     return ivec4(std::min(v1[0], v2[0]), std::min(v1[1], v2[1]), std::min(v1[2], v2[2]), std::min(v1[3], v2[3]));
    00279 }
    00280
    00281 static inline ivec4 max(const ivec4& v1, const ivec4& v2) {
    00282     return ivec4(std::max(v1[0], v2[0]), std::max(v1[1], v2[1]), std::max(v1[2], v2[2]), std::max(v1[3], v2[3]));
    00283 }
    00284
    00285 static inline ivec4 abs(const ivec4& v) {
    00286     return ivec4(abs(v[0]), abs(v[1]), abs(v[2]), abs(v[3]));
    00287 }
    00288
    00289 static inline bool any(const __m128i& v) {
    00290     return (v[0] || v[1] || v[2] || v[3]);
    00291 }
    00292
    00293 // Mathematical operators involving a scalar and a vector.
    00294
    00295 static inline fvec4 operator+(float v1, const fvec4& v2) {
    00296     return fvec4(v1)+v2;
    00297 }
    00298
    00299 static inline fvec4 operator-(float v1, const fvec4& v2) {
    00300     return fvec4(v1)-v2;
    00301 }
    00302
    00303 static inline fvec4 operator*(float v1, const fvec4& v2) {
    00304     return fvec4(v1)*v2;
    00305 }
    00306
    00307 static inline fvec4 operator/(float v1, const fvec4& v2) {
    00308     return fvec4(v1)/v2;
    00309 }
    00310
    00311 // Operations for blending fvec4s based on an ivec4.
    00312
    00313 static inline fvec4 blend(const fvec4& v1, const fvec4& v2, const __m128i& mask) {
    00314     return fvec4(mask[0] ? v2[0] : v1[0], mask[1] ? v2[1] : v1[1], mask[2] ? v2[2] : v1[2], mask[3] ? v2[3] : v1[3]);
    00315 }
    00316
    00317 #endif /*OPENMM_VECTORIZE_PNACL_H_*/
    00318