| 138 | } |
| 139 | #ifdef SSE_PERMUTOHEDRAL |
| 140 | void Permutohedral::init ( const MatrixXf & feature ) |
| 141 | { |
| 142 | // Compute the lattice coordinates for each feature [there is going to be a lot of magic here |
| 143 | N_ = feature.cols(); |
| 144 | d_ = feature.rows(); |
| 145 | HashTable hash_table( d_, N_/**(d_+1)*/ ); |
| 146 | |
| 147 | const int blocksize = sizeof(__m128) / sizeof(float); |
| 148 | const __m128 invdplus1 = _mm_set1_ps( 1.0f / (d_+1) ); |
| 149 | const __m128 dplus1 = _mm_set1_ps( d_+1 ); |
| 150 | const __m128 Zero = _mm_set1_ps( 0 ); |
| 151 | const __m128 One = _mm_set1_ps( 1 ); |
| 152 | |
| 153 | // Allocate the class memory |
| 154 | offset_.resize( (d_+1)*(N_+16) ); |
| 155 | std::fill( offset_.begin(), offset_.end(), 0 ); |
| 156 | barycentric_.resize( (d_+1)*(N_+16) ); |
| 157 | std::fill( barycentric_.begin(), barycentric_.end(), 0 ); |
| 158 | rank_.resize( (d_+1)*(N_+16) ); |
| 159 | |
| 160 | // Allocate the local memory |
| 161 | __m128 * scale_factor = (__m128*) _mm_malloc( (d_ )*sizeof(__m128) , 16 ); |
| 162 | __m128 * f = (__m128*) _mm_malloc( (d_ )*sizeof(__m128) , 16 ); |
| 163 | __m128 * elevated = (__m128*) _mm_malloc( (d_+1)*sizeof(__m128) , 16 ); |
| 164 | __m128 * rem0 = (__m128*) _mm_malloc( (d_+1)*sizeof(__m128) , 16 ); |
| 165 | __m128 * rank = (__m128*) _mm_malloc( (d_+1)*sizeof(__m128), 16 ); |
| 166 | float * barycentric = new float[(d_+2)*blocksize]; |
| 167 | short * canonical = new short[(d_+1)*(d_+1)]; |
| 168 | short * key = new short[d_+1]; |
| 169 | |
| 170 | // Compute the canonical simplex |
| 171 | for( int i=0; i<=d_; i++ ){ |
| 172 | for( int j=0; j<=d_-i; j++ ) |
| 173 | canonical[i*(d_+1)+j] = i; |
| 174 | for( int j=d_-i+1; j<=d_; j++ ) |
| 175 | canonical[i*(d_+1)+j] = i - (d_+1); |
| 176 | } |
| 177 | |
| 178 | // Expected standard deviation of our filter (p.6 in [Adams etal 2010]) |
| 179 | float inv_std_dev = sqrt(2.0 / 3.0)*(d_+1); |
| 180 | // Compute the diagonal part of E (p.5 in [Adams etal 2010]) |
| 181 | for( int i=0; i<d_; i++ ) |
| 182 | scale_factor[i] = _mm_set1_ps( 1.0 / sqrt( (i+2)*(i+1) ) * inv_std_dev ); |
| 183 | |
| 184 | // Setup the SSE rounding |
| 185 | #ifndef __SSE4_1__ |
| 186 | const unsigned int old_rounding = _mm_getcsr(); |
| 187 | _mm_setcsr( (old_rounding&~_MM_ROUND_MASK) | _MM_ROUND_NEAREST ); |
| 188 | #endif |
| 189 | |
| 190 | // Compute the simplex each feature lies in |
| 191 | for( int k=0; k<N_; k+=blocksize ){ |
| 192 | // Load the feature from memory |
| 193 | float * ff = (float*)f; |
| 194 | for( int j=0; j<d_; j++ ) |
| 195 | for( int i=0; i<blocksize; i++ ) |
| 196 | ff[ j*blocksize + i ] = k+i < N_ ? feature(j,k+i) : 0.0; |
| 197 | |