packages feed

geomancy-0.4.0.0: cbits/dmat4.c

#if defined(__SSE2__)

#include <emmintrin.h>

void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
  __m128d row0lo = _mm_loadu_pd(&A[0]);
  __m128d row0hi = _mm_loadu_pd(&A[2]);
  __m128d row1lo = _mm_loadu_pd(&A[4]);
  __m128d row1hi = _mm_loadu_pd(&A[6]);
  __m128d row2lo = _mm_loadu_pd(&A[8]);
  __m128d row2hi = _mm_loadu_pd(&A[10]);
  __m128d row3lo = _mm_loadu_pd(&A[12]);
  __m128d row3hi = _mm_loadu_pd(&A[14]);
  for(int i=0; i<4; i++) {
    __m128d brod0 = _mm_set1_pd(B[4*i + 0]);
    __m128d brod1 = _mm_set1_pd(B[4*i + 1]);
    __m128d brod2 = _mm_set1_pd(B[4*i + 2]);
    __m128d brod3 = _mm_set1_pd(B[4*i + 3]);
    __m128d rowlo = _mm_add_pd(
      _mm_add_pd(
        _mm_mul_pd(brod0, row0lo),
        _mm_mul_pd(brod1, row1lo)),
      _mm_add_pd(
        _mm_mul_pd(brod2, row2lo),
        _mm_mul_pd(brod3, row3lo)));
    __m128d rowhi = _mm_add_pd(
      _mm_add_pd(
        _mm_mul_pd(brod0, row0hi),
        _mm_mul_pd(brod1, row1hi)),
      _mm_add_pd(
        _mm_mul_pd(brod2, row2hi),
        _mm_mul_pd(brod3, row3hi)));
    _mm_storeu_pd(&O[4*i], rowlo);
    _mm_storeu_pd(&O[4*i + 2], rowhi);
  }
}

void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
  __m128d row0lo = _mm_loadu_pd(&M[0]);
  __m128d row0hi = _mm_loadu_pd(&M[2]);
  __m128d row1lo = _mm_loadu_pd(&M[4]);
  __m128d row1hi = _mm_loadu_pd(&M[6]);
  __m128d row2lo = _mm_loadu_pd(&M[8]);
  __m128d row2hi = _mm_loadu_pd(&M[10]);
  __m128d row3lo = _mm_loadu_pd(&M[12]);
  __m128d row3hi = _mm_loadu_pd(&M[14]);

  __m128d vec00 = _mm_set1_pd(V[0]);
  __m128d vec01 = _mm_set1_pd(V[1]);
  __m128d vec02 = _mm_set1_pd(V[2]);
  __m128d vec03 = _mm_set1_pd(V[3]);

  __m128d reslo = _mm_mul_pd(row0lo, vec00);
  reslo = _mm_add_pd(reslo, _mm_mul_pd(row1lo, vec01));
  reslo = _mm_add_pd(reslo, _mm_mul_pd(row2lo, vec02));
  reslo = _mm_add_pd(reslo, _mm_mul_pd(row3lo, vec03));

  __m128d reshi = _mm_mul_pd(row0hi, vec00);
  reshi = _mm_add_pd(reshi, _mm_mul_pd(row1hi, vec01));
  reshi = _mm_add_pd(reshi, _mm_mul_pd(row2hi, vec02));
  reshi = _mm_add_pd(reshi, _mm_mul_pd(row3hi, vec03));

  _mm_storeu_pd(&O[0], reslo);
  _mm_storeu_pd(&O[2], reshi);
}

#elif defined(__aarch64__)

#include <arm_neon.h>

void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
  float64x2_t A0lo = vld1q_f64(&A[0]);
  float64x2_t A0hi = vld1q_f64(&A[2]);
  float64x2_t A1lo = vld1q_f64(&A[4]);
  float64x2_t A1hi = vld1q_f64(&A[6]);
  float64x2_t A2lo = vld1q_f64(&A[8]);
  float64x2_t A2hi = vld1q_f64(&A[10]);
  float64x2_t A3lo = vld1q_f64(&A[12]);
  float64x2_t A3hi = vld1q_f64(&A[14]);

  for(int i=0; i<4; i++) {
    float64x2_t Blo = vld1q_f64(&B[4*i]);
    float64x2_t Bhi = vld1q_f64(&B[4*i + 2]);

    float64x2_t Clo = vmovq_n_f64(0);
    Clo = vfmaq_laneq_f64(Clo, A0lo, Blo, 0);
    Clo = vfmaq_laneq_f64(Clo, A1lo, Blo, 1);
    Clo = vfmaq_laneq_f64(Clo, A2lo, Bhi, 0);
    Clo = vfmaq_laneq_f64(Clo, A3lo, Bhi, 1);

    float64x2_t Chi = vmovq_n_f64(0);
    Chi = vfmaq_laneq_f64(Chi, A0hi, Blo, 0);
    Chi = vfmaq_laneq_f64(Chi, A1hi, Blo, 1);
    Chi = vfmaq_laneq_f64(Chi, A2hi, Bhi, 0);
    Chi = vfmaq_laneq_f64(Chi, A3hi, Bhi, 1);

    vst1q_f64(&O[4*i], Clo);
    vst1q_f64(&O[4*i + 2], Chi);
  }
}

void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
  float64x2_t M0lo = vld1q_f64(&M[0]);
  float64x2_t M0hi = vld1q_f64(&M[2]);
  float64x2_t M1lo = vld1q_f64(&M[4]);
  float64x2_t M1hi = vld1q_f64(&M[6]);
  float64x2_t M2lo = vld1q_f64(&M[8]);
  float64x2_t M2hi = vld1q_f64(&M[10]);
  float64x2_t M3lo = vld1q_f64(&M[12]);
  float64x2_t M3hi = vld1q_f64(&M[14]);

  float64x2_t Vlo = vld1q_f64(&V[0]);
  float64x2_t Vhi = vld1q_f64(&V[2]);

  float64x2_t Llo = vmovq_n_f64(0);
  Llo = vfmaq_laneq_f64(Llo, M0lo, Vlo, 0);
  Llo = vfmaq_laneq_f64(Llo, M1lo, Vlo, 1);
  Llo = vfmaq_laneq_f64(Llo, M2lo, Vhi, 0);
  Llo = vfmaq_laneq_f64(Llo, M3lo, Vhi, 1);

  float64x2_t Lhi = vmovq_n_f64(0);
  Lhi = vfmaq_laneq_f64(Lhi, M0hi, Vlo, 0);
  Lhi = vfmaq_laneq_f64(Lhi, M1hi, Vlo, 1);
  Lhi = vfmaq_laneq_f64(Lhi, M2hi, Vhi, 0);
  Lhi = vfmaq_laneq_f64(Lhi, M3hi, Vhi, 1);

  vst1q_f64(&O[0], Llo);
  vst1q_f64(&O[2], Lhi);
}

#else

void DMat4xDMat4_SIMD(double *A, double *B, double *O) {
  for(int i=0; i<4; i++) {
    for(int j=0; j<4; j++) {
      O[4*i + j] =
        (B[4*i + 0] * A[0 + j] + B[4*i + 1] * A[4 + j]) +
        (B[4*i + 2] * A[8 + j] + B[4*i + 3] * A[12 + j]);
    }
  }
}

void DMat4xDVec4_SIMD(double *M, double *V, double *O) {
  for(int j=0; j<4; j++) {
    O[j] =
      M[0 + j] * V[0] +
      M[4 + j] * V[1] +
      M[8 + j] * V[2] +
      M[12 + j] * V[3];
  }
}

#endif