7 #ifndef NUKLEI_GENERIC_KERNEL_H 
    8 #define NUKLEI_GENERIC_KERNEL_H 
   22     struct r3 { 
typedef Vector3 element_t; };
 
   23     struct so3 { 
typedef Quaternion element_t; };
 
   24     struct s2 { 
typedef Vector3 element_t; };
 
   25     struct s2p { 
typedef Vector3 element_t; };
 
   50   namespace value_scaleS
 
   75   template<
class FunctionImpl>
 
   78     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
   80       return (v1-v2).Length();
 
   84   template<
class FunctionImpl>
 
   87     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
   89       return (v1-v2).SquaredLength();
 
   96     static coord_t d(
const Quaternion &q1, 
const Quaternion &q2)
 
   98       coord_t productAbs = std::fabs(q1.Dot(q2));
 
   99       return 2*ACos( productAbs );
 
  106     static coord_t d(
const Quaternion &q1, 
const Quaternion &q2)
 
  108       coord_t productAbs = std::fabs(q1.Dot(q2));
 
  109       return 2*FastACos(productAbs);
 
  116     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
  119       return ACos(product);
 
  126     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
  129       return FastACos(product);
 
  136     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
  138       coord_t product = std::fabs(v1.Dot(v2));
 
  139       return ACos(product);
 
  146     static coord_t d(
const Vector3 &v1, 
const Vector3 &v2)
 
  148       coord_t product = std::fabs(v1.Dot(v2));
 
  149       return FastACos(product);
 
  157   template<
class Group>
 
  163     static Quaternion r()
 
  191   template<
class Shape, 
class FunctionImpl, 
class Squared = squaredS::no>
 
  194   template<
class FunctionImpl>
 
  199       if (std::fabs(d) > h) 
return 0;
 
  208   template<
class FunctionImpl>
 
  214       if (abs_d > gauss_equiv_spread*h) 
return 0;
 
  215       else return 1 - abs_d/(gauss_equiv_spread*h);
 
  219       return gauss_equiv_spread*std::fabs(h);
 
  222     static const coord_t gauss_equiv_spread;
 
  225   template<
class FunctionImpl>
 
  231   >::gauss_equiv_spread = 2;
 
  233   template<
class FunctionImpl>
 
  239       if (abs_d > gauss_equiv_spread*h*gauss_equiv_spread*h) 
return 0;
 
  240       else return 1 - std::sqrt(abs_d)/(gauss_equiv_spread*h);
 
  244       return gauss_equiv_spread*std::fabs(h);
 
  247     static const coord_t gauss_equiv_spread;
 
  250   template<
class FunctionImpl>
 
  256   >::gauss_equiv_spread = 2;
 
  263       return std::exp( - d*d / (2*h*h) );
 
  267       return std::numeric_limits<coord_t>::infinity();
 
  276       return FastNegExp( d*d / (2*h*h) );
 
  280       return std::numeric_limits<coord_t>::infinity();
 
  297     typedef Group group_t;
 
  298     typedef FunctionImpl function_impl_t;
 
  306       return shape_function_t::s(h, dist_t::d(mean, p));
 
  311       return shape_function_t::cut_point(h);
 
  315   template<
class FunctionImpl>
 
  320     typedef FunctionImpl function_impl_t;
 
  330     static coord_t eval(
const Vector3 &mean, 
const coord_t h, 
const Vector3 &p)
 
  332       return shape_function_t::s(h, dist_t::d(mean, p));
 
  337       return shape_function_t::cut_point(h);
 
  349     typedef FunctionImpl function_impl_t;
 
  354       return eval(mean, h, p, ValueScale(), FunctionImpl());
 
  361       coord_t arg = std::pow(mean.Dot(p), 2);
 
  362       return std::exp( h*(arg-1) );
 
  369       coord_t arg = std::pow(mean.Dot(p), 2);
 
  370       return FastNegExp( h*(1-arg) );
 
  379       coord_t arg = std::pow(mean.Dot(p), 2);
 
  380       return std::exp( h*arg ) / confluentHypergeometric1F1(.5, 2, h);
 
  393     typedef Group group_t;
 
  394     typedef typename Group::element_t element_t;
 
  395     typedef FunctionImpl function_impl_t;
 
  401       return eval(mean, h, p, Group(), ValueScale(), FunctionImpl(), HScale());
 
  407       return h_from_angle_h(angle_h, Group());
 
  413       return angle_h_from_h(h, Group());
 
  421       NUKLEI_FAST_ASSERT(0 <= angle_h && angle_h <= M_PI);
 
  422       return 1./( 1-std::cos(angle_h/2) );
 
  428       NUKLEI_FAST_ASSERT(1 <= h);
 
  429       return 2*FastACos(1-1./h);
 
  435       NUKLEI_FAST_ASSERT(0 <= angle_h && angle_h <= M_PI);
 
  436       return 1./( 1-std::cos(angle_h) );
 
  442       NUKLEI_FAST_ASSERT(1 <= h);
 
  443       return FastACos(1-1./h);
 
  449       NUKLEI_FAST_ASSERT(0 <= angle_h && angle_h <= M_PI);
 
  450       return 1./( 1-std::cos(angle_h) );
 
  456       NUKLEI_FAST_ASSERT(1 <= h);
 
  457       return FastACos(1-1./h);
 
  461     template<
class GP, 
class VS, 
class FI>
 
  466       return eval(mean, h_from_angle_h(h), p,
 
  470     static coord_t dist_exponent(
const element_t &mean,
 
  474       return std::fabs(mean.Dot(p));
 
  477     static coord_t dist_exponent(
const element_t &mean,
 
  481       return std::fabs(mean.Dot(p));
 
  484     static coord_t dist_exponent(
const element_t &mean,
 
  510       const coord_t sqrt_alpha = std::sqrt(alpha);
 
  511       const coord_t eta = sqrt_alpha + std::log(h) - std::log(1+sqrt_alpha);
 
  512       const coord_t minus_log_sqrt_2_pi = -0.918938533204673;
 
  513       const coord_t log_bessel_I1_h = (minus_log_sqrt_2_pi + eta -
 
  514                                        .25*std::log(alpha));
 
  515       return std::exp( h*arg - log_bessel_I1_h ) * h / (4 * M_PI * M_PI);
 
  526       return (h / (2 * M_PI * (1-std::exp(-2*h)))) * std::exp( h*(arg-1) );
 
  535       coord_t arg = dist_exponent(mean, p, GP());
 
  536       return std::exp( h*(arg-1) );
 
  545       coord_t arg = dist_exponent(mean, p, GP());
 
  546       return FastNegExp( h*(1-arg) );
 
  555   template<
class Kernel>
 
  556   typename Kernel::group_t::element_t
 
  557   importance_sampling_uniform_proposal(
typename Kernel::group_t::element_t mean,
 
  560     typename Kernel::group_t::element_t q;
 
  561     coord_t kernelMaxPoint = Kernel::eval(mean, h, mean);
 
  565       coord_t e = Kernel::eval(mean, h, q);
 
  567       if (e == 0) 
continue;
 
  574   template<
class Kernel>
 
  575   typename Kernel::group_t::element_t
 
  576   importance_sampling_similar_proposal(
typename Kernel::group_t::element_t mean,
 
  579     typename Kernel::group_t::element_t q;
 
  580     coord_t targetMaxPoint = Kernel::eval(mean, h_target, mean);
 
  581     coord_t proposalMaxPoint = Kernel::eval(mean, h_proposal, mean);
 
  584       q = importance_sampling_uniform_proposal<Kernel>(mean, h_proposal);
 
  585       coord_t e_target = Kernel::eval(mean, h_target, q)/targetMaxPoint;
 
  586       coord_t e_proposal = Kernel::eval(mean, h_proposal, q)/proposalMaxPoint;
 
  589       if (e_target == 0) 
continue;
 
  602   template<
class FunctionImpl>
 
  610       typedef typename kernel_t::group_t group_t;
 
  611       typedef typename kernel_t::function_impl_t function_impl_t;
 
  613       static Vector3 s(
const Vector3 &mean, 
const coord_t h)
 
  616         for (
int i = 0; i < 3; ++i)
 
  622   template<
class Shape, 
class FunctionImpl>
 
  630     typedef typename kernel_t::group_t group_t;
 
  631     typedef typename kernel_t::function_impl_t function_impl_t;
 
  633     static Vector3 s(
const Vector3 &mean, 
const coord_t h)
 
  635       Vector3 zero(Vector3::ZERO);
 
  636       coord_t kernelMaxPoint = kernel_t::eval(zero, h, zero);
 
  637       coord_t cutPoint = kernel_t::cut_point(h);
 
  644         coord_t e = kernel_t::eval(zero, h, r);
 
  646         if (e == 0) 
continue;
 
  650       for (
int i = 0; i < 3; ++i)
 
  658   template<
class Shape, 
class FunctionImpl>
 
  666       typedef typename kernel_t::group_t group_t;
 
  667       typedef typename kernel_t::function_impl_t function_impl_t;
 
  669       static Quaternion s(
const Quaternion &mean, 
const coord_t h)
 
  671         if (h < .1) NUKLEI_WARN(
"S^2 IS with h=" + 
stringify(h) + 
" is slow.");
 
  675         return importance_sampling_uniform_proposal<kernel_t>(mean, h);
 
  691     typedef typename kernel_t::function_impl_t function_impl_t;
 
  693     static Quaternion s(
const Quaternion &mean, 
const coord_t h)
 
  695       return importance_sampling_uniform_proposal<kernel_t>(mean, h);
 
  714     typedef typename kernel_t::group_t group_t;
 
  715     typedef typename group_t::element_t element_t;
 
  716     typedef typename kernel_t::function_impl_t function_impl_t;
 
  718     static element_t s(
const element_t &mean, 
const coord_t h)
 
  720       return s(mean, h, Group(), HScale());
 
  726     static element_t s(
const element_t &mean, 
const coord_t h,
 
  732     static Quaternion s(
const Quaternion &mean, 
const coord_t h,
 
  737       const coord_t t1 = std::sqrt(4*h*h + (d-1)*(d-1));
 
  738       const coord_t b = (-2*h+t1)/(d-1);
 
  739       const coord_t x0 = (1-b)/(1+b);
 
  742       const coord_t c = h*x0 + (d-1) * std::log(1-x0*x0);
 
  747         w = (1-(1+b)*z)/(1-(1-b)*z);
 
  748         coord_t t = h*w + (d-1)*std::log(1-x0*w)-c;
 
  753       Quaternion q(v.X(), v.Y(), v.Z(), w);
 
  754       NUKLEI_FAST_DEBUG_ASSERT(std::fabs(1-q.Length()) < 1e-6);
 
  755       Quaternion sample = (mean * Quaternion(0, 0, 0, 1).Conjugate()) * q;
 
  765     static Vector3 s(
const Vector3 &mean, 
const coord_t h,
 
  769       const coord_t t1 = std::sqrt(4*h*h + (d-1)*(d-1));
 
  770       const coord_t b = (-2*h+t1)/(d-1);
 
  771       const coord_t x0 = (1-b)/(1+b);
 
  774       const coord_t c = h*x0 + (d-1) * std::log(1-x0*x0);
 
  779         w = (1-(1+b)*z)/(1-(1-b)*z);
 
  780         coord_t t = h*w + (d-1)*std::log(1-x0*w)-c;
 
  785       Vector3 q(v.X(), v.Y(), w);
 
  786       NUKLEI_FAST_DEBUG_ASSERT(std::fabs(1-q.Length()) < 1e-6);
 
  787       Vector3 cross = Vector3::UNIT_Z.Cross(mean);
 
  788       Quaternion rotation(1+Vector3::UNIT_Z.Dot(mean),
 
  792       rotation.Normalize();
 
  793       return la::normalized(rotation.Rotate(q));
 
  796     static Vector3 s(
const Vector3 &mean, 
const coord_t h,
 
  811   template<
class Shape, 
class FunctionImpl>
 
  819       typedef typename kernel_t::group_t group_t;
 
  820       typedef typename kernel_t::function_impl_t function_impl_t;
 
  822       static Vector3 s(
const Vector3 &mean, 
const coord_t h)
 
  824         if (h < .1) NUKLEI_WARN(
"S^2 IS with h=" + 
stringify(h) + 
" is slow.");
 
  825         return importance_sampling_uniform_proposal<kernel_t>(mean, h);
 
  832   template<
class Shape, 
class FunctionImpl>
 
  840       typedef typename kernel_t::group_t group_t;
 
  841       typedef typename kernel_t::function_impl_t function_impl_t;
 
  843       static Vector3 s(
const Vector3 &mean, 
const coord_t h)
 
  845         if (h < .1) NUKLEI_WARN(
"S^2 IS with h=" + 
stringify(h) + 
" is slow.");
 
  846         return importance_sampling_uniform_proposal<kernel_t>(mean, h);