Don-Reba icon

Vectorized FGT

Don-Reba | PRO | 07/27/16 06:05:42 PM UTC | 0 ⭐ | 10363 👁️ | Never ⏰ | []
C++ (WinAPI) |

0 B

|

None

|

0 👍

/

0 👎

__m256 FgtVolume::operator [] (const Vector3f256 & p) const
{
    __m256 side = _mm256_set1_ps(Side);
 
    // get domain origin
    __m256 minX = _mm256_set1_ps(DomainMin.x());
    __m256 minY = _mm256_set1_ps(DomainMin.y());
    __m256 minZ = _mm256_set1_ps(DomainMin.z());
 
    // get cell coordinates
    __m256 kx = _mm256_floor_ps(_mm256_div_ps(_mm256_sub_ps(p.x, minX), side));
    __m256 ky = _mm256_floor_ps(_mm256_div_ps(_mm256_sub_ps(p.y, minY), side));
    __m256 kz = _mm256_floor_ps(_mm256_div_ps(_mm256_sub_ps(p.z, minZ), side));
 
    // get coefficient addresses
    __m256i indices = _mm256_cvtps_epi32
        ( _mm256_mul_ps
            ( _mm256_fmadd_ps
                    ( _mm256_fmadd_ps(kz, _mm256_set1_ps((float)Count.y()), ky)
                    , _mm256_set1_ps((float)Count.x())
                    , kx
                    )
            , _mm256_set1_ps((float)PD)
            )
        );
 
    // get cell center's position
    __m256 cx = _mm256_fmadd_ps(side, _mm256_add_ps(kx, _mm256_set1_ps(0.5f)), minX);
    __m256 cy = _mm256_fmadd_ps(side, _mm256_add_ps(ky, _mm256_set1_ps(0.5f)), minY);
    __m256 cz = _mm256_fmadd_ps(side, _mm256_add_ps(kz, _mm256_set1_ps(0.5f)), minZ);
 
    // compute distance from cell center in sigmas
    __m256 delta[3] =
        { _mm256_mul_ps(_mm256_sub_ps(p.x, cx), _mm256_set1_ps(1.0f / Sigma))
        , _mm256_mul_ps(_mm256_sub_ps(p.y, cy), _mm256_set1_ps(1.0f / Sigma))
        , _mm256_mul_ps(_mm256_sub_ps(p.z, cz), _mm256_set1_ps(1.0f / Sigma))
        };
 
    __m256 dxx = _mm256_mul_ps(delta[0], delta[0]);
    __m256 dyy = _mm256_mul_ps(delta[1], delta[1]);
    __m256 dzz = _mm256_mul_ps(delta[2], delta[2]);
 
    __m256 dnorm = _mm256_add_ps(_mm256_add_ps(dxx, dyy), dzz);
 
    // gather the polynomial
    assert(PD == 56);
    __m256 polynomial[56];
    polynomial[0] = expf8(_mm256_sub_ps(_mm256_setzero_ps(), dnorm));
 
    Vector3i heads(0, 0, 0);
    int t = 1;
    for (int a = 1; a != Alpha; ++a)
    {
        int tail = t;
        for (int i = 0; i != 3; ++i)
        {
            int head = heads[i];
            heads[i] = t;
            for (int j = head; j != tail; ++j, ++t)
                polynomial[t] = _mm256_mul_ps(delta[i], polynomial[j]);
        }
    }
 
    __declspec(align(32)) int indicesi32[8];
    _mm256_store_si256((__m256i*)indicesi32, indices);
    bool allEqual = true;
    for (size_t i = 1; i != 8; ++i)
        allEqual = allEqual && (indicesi32[0] == indicesi32[i]);
 
    // normalizationFactor * coefficients · polynomial
    __m256 sum = _mm256_setzero_ps();
    if (allEqual)
    {
        // fast path (all indices are the same)
        const float * cp = &Coefficients[indicesi32[0]];
        for (size_t i = 0; i != 56; ++i)
        {
            __m256 coefficients = _mm256_set1_ps(cp[i]);
            sum = _mm256_fmadd_ps(polynomial[i], coefficients, sum);
        }
    }
    else
    {
        // slow path
        for (size_t i = 0; i != 56; ++i)
        {
            __m256 coefficients = _mm256_i32gather_ps(&Coefficients[i], indices, sizeof(float));
            sum = _mm256_fmadd_ps(polynomial[i], coefficients, sum);
        }
    }
    return _mm256_mul_ps(sum, _mm256_set1_ps(normalizationFactor));
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎