On 11/06/15 23:51, Sturla Molden wrote:
> On 11/06/15 23:29, Jacob Vanderplas wrote:
>
>> It's not ideal, but I don't see any way around it short of creating
>> explicit flags for every metric. Any thoughts?
>
> Computed goto? But you need to get the code into C or C++. I was
> thinking about adding that was of dispatching between distance metrics
> to cKDTree in SciPy.


The code below did not make any difference to SciPy, neither faster nor 
slower, so I am not going to use it. But if you have a lot of different 
distance metrics, it will still be about as fast as inlining the 
distance metric callback at compile time.

Sturla





/* requires __GNUC__ */

inline npy_float64
_distance_p(const npy_float64 *x, const npy_float64 *y,
             const npy_float64 p, const npy_intp k,
             const npy_float64 upperbound)
{

     void *jmptab[] = {&&minkowski,
                       &&max_coordinate_difference,
                       &&manhattan,
                       NULL,
                       &&euclid};

     int dispatch = (p == infinity) | ((p == 1.)<<1) | ((p == 2.)<<2);
     goto *jmptab[dispatch];

euclid:
     {
         const npy_float64 *u = x;
         const npy_float64 *v = y;
         const npy_intp n = k;
         npy_float64 s;
         npy_intp i;
         npy_float64 acc[4] = {0., 0., 0., 0.};
         for (i = 0; i < n/4; i += 4) {
             npy_float64 _u[4] = {u[i], u[i + 1], u[i + 2], u[i + 3]};
             npy_float64 _v[4] = {v[i], v[i + 1], v[i + 2], v[i + 3]};
             npy_float64 diff[4] = {_u[0] - _v[0],
                                    _u[1] - _v[1],
                                    _u[2] - _v[2],
                                    _u[3] - _v[3]};
             acc[0] += diff[0] * diff[0];
             acc[1] += diff[1] * diff[1];
             acc[2] += diff[2] * diff[2];
             acc[3] += diff[3] * diff[3];
         }
         s = acc[0] + acc[1] + acc[2] + acc[3];
         if (i < n) {
             for(; i<n; ++i) {
                 npy_float64 d = u[i] - v[i];
                 s += d * d;
             }
         }
         return s;
     }

max_coordinate_difference:
     {
         npy_intp i;
         npy_float64 r = 0;
         for (i=0; i<k; ++i) {
             r = dmax(r,dabs(x[i]-y[i]));
             if (r>upperbound)
                 return r;
         }
         return r;
     }

manhattan:
     {
         npy_intp i;
         npy_float64 r = 0;
         for (i=0; i<k; ++i) {
             r += dabs(x[i]-y[i]);
             if (r>upperbound)
                 return r;
         }
         return r;
     }

minkowski:
     {
         npy_intp i;
         npy_float64 r = 0;
         for (i=0; i<k; ++i) {
             r += std::pow(dabs(x[i]-y[i]),p);
             if (r>upperbound)
                  return r;
         }
         return r;
     }
}




------------------------------------------------------------------------------
_______________________________________________
Scikit-learn-general mailing list
Scikit-learn-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/scikit-learn-general

Reply via email to