void dry_revolute_joint_3D::doForce(kte_pass_flag aFlag, const shared_ptr<frame_storage>& aStorage) {
  if((!mEnd) || (!mBase))
    return;
  
  using std::fabs;
  
  if(!mAngle) {
    mBase->Force += mEnd->Force;
    mBase->Torque += mEnd->Torque;
  } else {
    rot_mat_3D<double> R(axis_angle<double>(mAngle->q,mAxis).getRotMat());
    vect<double,3> tmp_f = R * mEnd->Force;
    mBase->Force += tmp_f;
    double tmp_t = mEnd->Torque * mAxis;
    if(fabs(mAngle->q_dot) > mSlipVelocity) 
      mAngle->f += tmp_t - mAngle->q_dot / fabs(mAngle->q_dot) * mSlipCoef * norm_2(tmp_f);
    else {
      mAngle->f += tmp_t - mAngle->q_dot / mSlipVelocity * mStictionCoef * norm_2(tmp_f);
    };
    mBase->Torque += R * ( mEnd->Torque - tmp_t * mAxis );
  };
  
  if((aFlag == store_dynamics) && (aStorage)) {
    if(aStorage->frame_3D_mapping[mEnd]) {
      aStorage->frame_3D_mapping[mEnd]->Force = mEnd->Force;
      aStorage->frame_3D_mapping[mEnd]->Torque = mEnd->Torque;
    };
  };
};
Esempio n. 2
0
//Does the actual calling of Runge Kutta: default precision is TOLERANCE defined in
//def.h
//Returns >0 if there's a problem with the running
int RGE::callRK(double x1, double x2, DoubleVector & v,
		DoubleVector (*derivs)(double, const DoubleVector &), 
		double eps) {
  using std::fabs;
  using std::log;

  double tol;
  if (eps < 0.0) tol = TOLERANCE;
  else if (eps < EPSTOL) tol = EPSTOL;
  else tol = eps;
  // x1 == x2 with high precision
  if (close(fabs(x1), fabs(x2), EPSTOL)) return 0;

  // RGE in terms of natural log of renormalisation scale
  double from = log(fabs(x1));
  double to = log(fabs(x2));

  double guess = (from - to) * 0.1; //first step size
  double hmin = (from - to) * tol * 1.0e-5; 

  int err =
    integrateOdes(v, from, to, tol, guess, hmin, derivs, odeStepper);
  
  setMu(x2);
  return err;
}
Esempio n. 3
0
T hypot_imp(T x, T y, const Policy& pol)
{
   //
   // Normalize x and y, so that both are positive and x >= y:
   //
   using std::fabs; using std::sqrt; // ADL of std names

   x = fabs(x);
   y = fabs(y);

#ifdef BOOST_MSVC
#pragma warning(push) 
#pragma warning(disable: 4127)
#endif
   // special case, see C99 Annex F:
   if(std::numeric_limits<T>::has_infinity
      && ((x == std::numeric_limits<T>::infinity())
      || (y == std::numeric_limits<T>::infinity())))
      return policies::raise_overflow_error<T>("boost::math::hypot<%1%>(%1%,%1%)", 0, pol);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

   if(y > x)
      (std::swap)(x, y);

   if(x * tools::epsilon<T>() >= y)
      return x;

   T rat = y / x;
   return x * sqrt(1 + rat*rat);
} // template <class T> T hypot(T x, T y)
Esempio n. 4
0
TEST(AgradFwdFabs,FvarFvarDouble) {
  using stan::agrad::fvar;
  using std::fabs;

  fvar<fvar<double> > x;
  x.val_.val_ = 1.5;
  x.val_.d_ = 2.0;

  fvar<fvar<double> > a = fabs(x);

  EXPECT_FLOAT_EQ(fabs(1.5), a.val_.val_);
  EXPECT_FLOAT_EQ(2.0, a.val_.d_);
  EXPECT_FLOAT_EQ(0, a.d_.val_);
  EXPECT_FLOAT_EQ(0, a.d_.d_);

  fvar<fvar<double> > y;
  y.val_.val_ = 1.5;
  y.d_.val_ = 2.0;  

  a = fabs(y);
  EXPECT_FLOAT_EQ(fabs(1.5), a.val_.val_);
  EXPECT_FLOAT_EQ(0, a.val_.d_);
  EXPECT_FLOAT_EQ(2.0, a.d_.val_);
  EXPECT_FLOAT_EQ(0, a.d_.d_);
}
 int closestValue(TreeNode* root, double target) {
     stack<TreeNode *> st;
     TreeNode *p = root;
     int res = root->val;
     int val;
     while (true) {
         while (p != NULL) {
             st.push(p);
             p = p->left;
         }
         if (st.empty()) {
             break;
         }
         
         p = st.top()->right;
         val = st.top()->val;
         st.pop();
         
         if (fabs(val - target) < fabs(res - target)) {
             res = val;
         }
         if (val >= target) {
             break;
         }
     }
     while (!st.empty()) {
         st.pop();
     }
     return res;
 }
void dry_revolute_joint_2D::doForce(kte_pass_flag aFlag, const shared_ptr<frame_storage>& aStorage) {
  if((!mEnd) || (!mBase))
    return;
  
  using std::fabs;
  
  if(!mAngle) {
    mBase->Force += mEnd->Force;
    mBase->Torque += mEnd->Torque;
  } else {
    vect<double,2> tmp_f = rot_mat_2D<double>(mAngle->q) * mEnd->Force;
    mBase->Force += tmp_f;
    if(fabs(mAngle->q_dot) > mSlipVelocity) 
      mAngle->f += mEnd->Torque - mAngle->q_dot / fabs(mAngle->q_dot) * mSlipCoef * norm_2(tmp_f);
    else {
      mAngle->f += mEnd->Torque - mAngle->q_dot / mSlipVelocity * mStictionCoef * norm_2(tmp_f);
    };
  };
  
  if((aFlag == store_dynamics) && (aStorage)) {
    if(aStorage->frame_2D_mapping[mEnd]) {
      aStorage->frame_2D_mapping[mEnd]->Force = mEnd->Force;
      aStorage->frame_2D_mapping[mEnd]->Torque = mEnd->Torque;
    };
  };  
};
Esempio n. 7
0
bool ViewInfo::isOblique() {
    int i;
    double d = 0.0;
    for (i=0; i<3; i++) {
	d += (fabs(m2p[0][i]*m2p[1][i]) + fabs(m2p[0][i]*m2p[2][i]) + fabs(m2p[1][i]*m2p[2][i]));
    }
    if(fabs(d) < 1.0e-4) return false;
    else return true;
}
Esempio n. 8
0
// If the destination is within one delta step away, the object has arrived.
// Set the location to the destination, stop, and return true.
// Otherwise, add the delta to the location, and return false.
bool Moving_object::update_location()
{
	Cartesian_vector diff = destination - location;
	if ((fabs(diff.delta_x) <= fabs(delta.delta_x)) && (fabs(diff.delta_y) <= fabs(delta.delta_y))) {
		location = destination;
		stop_moving();
		return true;
		}
	location = location + delta;
	return false;
}
Esempio n. 9
0
//member function to find maximum absolute value in a given column and range within that column and return the corresponding row indice
int squareMatrix::FindMaxInCol(const int &c, const int &start, const int &end)const{
  double maxVal = 0.0;
  int maxRow = 0;
  for( int ii = start; ii < end+1; ii++ ){
    if( fabs((*this).Data(ii,c)) > maxVal ){
      maxVal = fabs((*this).Data(ii,c));
      maxRow = ii;
    }
  }
  return maxRow;
}
Esempio n. 10
0
void test_grad(const F& fun,
               const std::vector<double>& args) {
  using std::fabs;
  std::vector<double> diffs_finite = finite_diffs(fun,args);
  std::vector<double> diffs_var = grad(fun,args);
  EXPECT_EQ(diffs_finite.size(), diffs_var.size());
  for (size_t i = 0; i < args.size(); ++i) {
    double tolerance = 1e-6 * fmax(fabs(diffs_finite[i]), fabs(diffs_var[i])) + 1e-14;
    EXPECT_NEAR(diffs_finite[i], diffs_var[i], tolerance);
  }
}
Esempio n. 11
0
// get consistent clipping on different platforms by making line
// edges meet clipping box if close
void _Clipper::fixPt(QPointF& pt) const
{
  if( fabs(pt.x() - clip.left()) < 1e-4 )
    pt.setX(clip.left());
  if( fabs(pt.x() - clip.right()) < 1e-4 )
    pt.setX(clip.right());
  if( fabs(pt.y() - clip.top()) < 1e-4 )
    pt.setY(clip.top());
  if( fabs(pt.y() - clip.bottom()) < 1e-4 )
    pt.setY(clip.bottom());
}
Esempio n. 12
0
void CPISwapTest::zciisconsistency() {
    CommonVars common;

    ZeroCouponInflationSwap::Type ztype = ZeroCouponInflationSwap::Payer;
    Real  nominal = 1000000.0;
    Date startDate(common.evaluationDate);
    Date endDate(25, November, 2059);
    Calendar cal = UnitedKingdom();
    BusinessDayConvention paymentConvention = ModifiedFollowing;
    DayCounter dummyDC, dc = ActualActual();
    Period observationLag(2,Months);

    Rate quote = 0.03714;
    ZeroCouponInflationSwap zciis(ztype, nominal, startDate, endDate, cal,
                                  paymentConvention, dc, quote, common.ii,
                                  observationLag);

    // simple structure so simple pricing engine - most work done by index
    ext::shared_ptr<DiscountingSwapEngine>
    dse(new DiscountingSwapEngine(common.nominalTS));

    zciis.setPricingEngine(dse);
    QL_REQUIRE(fabs(zciis.NPV())<1e-3,"zciis does not reprice to zero");

    std::vector<Date> oneDate;
    oneDate.push_back(endDate);
    Schedule schOneDate(oneDate, cal, paymentConvention);

    CPISwap::Type stype = CPISwap::Payer;
    Real inflationNominal = nominal;
    Real floatNominal = inflationNominal * std::pow(1.0+quote,50);
    bool subtractInflationNominal = true;
    Real dummySpread=0.0, dummyFixedRate=0.0;
    Natural fixingDays = 0;
    Date baseDate = startDate - observationLag;
    Real baseCPI = common.ii->fixing(baseDate);

    ext::shared_ptr<IborIndex> dummyFloatIndex;

    CPISwap cS(stype, floatNominal, subtractInflationNominal, dummySpread, dummyDC, schOneDate,
               paymentConvention, fixingDays, dummyFloatIndex,
               dummyFixedRate, baseCPI, dummyDC, schOneDate, paymentConvention, observationLag,
               common.ii, CPI::AsIndex, inflationNominal);

    cS.setPricingEngine(dse);
    QL_REQUIRE(fabs(cS.NPV())<1e-3,"CPISwap as ZCIIS does not reprice to zero");

    for (Size i=0; i<2; i++) {
        QL_REQUIRE(fabs(cS.legNPV(i)-zciis.legNPV(i))<1e-3,"zciis leg does not equal CPISwap leg");
    }
    // remove circular refernce
    common.hcpi.linkTo(ext::shared_ptr<ZeroInflationTermStructure>());
}
Esempio n. 13
0
inline
fvar<T>
fabs(const fvar<T>& x) {
    using std::fabs;
    using stan::math::NOT_A_NUMBER;
    if(x.val_ > 0.0)
        return fvar<T>(fabs(x.val_), x.d_);
    else if(x.val_ == 0.0)
        return fvar<T>(fabs(x.val_), NOT_A_NUMBER);
    else
        return fvar<T>(fabs(x.val_), -x.d_);
}
Esempio n. 14
0
    bool TesterDouble::testEquals( double actualValue, double expectedValue,
            const char * lineText, int lineNumber ) const
    {
        if( fabs(actualValue - expectedValue) < epsilon )
            return true;

        printf( "%s\nat line %i - "
                "Actual: %le - Expected: %le\n"
                "The value is within %le of expected. Epsilon is %le\n\n",
                lineText, lineNumber,
                actualValue, expectedValue,
                fabs(actualValue - expectedValue), epsilon);
        return false;
    }
void test_grad_multi_student_t(const F& fun,
               const std::vector<T_y> & vec_y,
               const std::vector<T_mu> & vec_mu,
               const std::vector<T_sigma> & vec_sigma,
               const T_nu & nu) {
  using std::fabs;
  std::vector<double> diffs_finite = finite_diffs_multi_normal(fun,vec_y,vec_mu,vec_sigma,nu);
  std::vector<double> diffs_var = grad_multi_normal(fun,vec_y,vec_mu,vec_sigma,nu);
  EXPECT_EQ(diffs_finite.size(), diffs_var.size());
  for (size_t i = 0; i < diffs_finite.size(); ++i) {
    double tolerance = 1e-6 * fmax(fabs(diffs_finite[i]), fabs(diffs_var[i])) + 1e-14;
    EXPECT_NEAR(diffs_finite[i], diffs_var[i], tolerance);
  }
}
Esempio n. 16
0
void broyden_good_method(const Vector& x_prev, Vector& x0, RootedFunction f, const T& tol = std::numeric_limits<T>::epsilon(), std::size_t max_iter = 50) 
{
  using std::fabs;
  typedef typename vect_traits<Vector>::value_type ValueType;
  typedef typename vect_traits<Vector>::size_type SizeType;
  
  Vector dx = x0 - x_prev;
  Vector y0 = f(x0);
  Vector dy = y0 - f(x_prev);
  std::size_t iter = 0;
  
  mat<ValueType, mat_structure::square> J_inv = mat<ValueType, mat_structure::identity>(dx.size());
  Vector Jdy = dy;
  ValueType denom = dx * dy;
  if( fabs(denom) < tol )
    throw singularity_error("Broyden's good method failed due to a stationary point!");
  Vector dxJ = dx;
  for(SizeType i = 0; i < dx.size(); ++i)
    for(SizeType j = 0; j < dx.size(); ++j)
      J_inv(i,j) += (dx[i] - dy[i]) * dx[j] / denom;
  
  while(true) {
    
    dx = -J_inv * y0;
    x0 += dx;
    
    if(norm_2(dx) < tol)
      return;
  
    if( ++iter > max_iter ) 
      throw maximum_iteration("Broyden's good method diverged, as detected by reaching the maximum iteration limit!");
  
    dy = f(x0) - y0;
    y0 += dy;
    
    Jdy = J_inv * dy;
    denom = dx * Jdy;
    if( fabs(denom) < tol )
      throw singularity_error("Broyden's good method failed due to a stationary point!");
    dxJ = dx * J_inv;
    
    for(SizeType i = 0; i < dx.size(); ++i)
      for(SizeType j = 0; j < dx.size(); ++j)
        J_inv(i,j) += (dx[i] - Jdy[i]) * dxJ[j] / denom;
    
  };
  
  return x0;
};
Esempio n. 17
0
typename boost::enable_if_c< is_readable_matrix<Matrix>::value, 
 bool >::type is_diagonal(const Matrix& A, typename mat_traits<Matrix>::value_type NumTol = typename mat_traits<Matrix>::value_type(1E-8) ) {
  if(A.get_row_count() != A.get_col_count())
    return false;
  
  typedef typename mat_traits< Matrix >::size_type SizeType;
  using std::fabs;
  
  for(SizeType i=0;i<A.get_row_count();i++)
    for(SizeType j=0;j<i;j++)
      if((fabs(A(j,i)) > NumTol) || (fabs(A(i,j)) > NumTol))
        return false;
  
  return true;
};
Esempio n. 18
0
int AxisInfo::mapIndex(spViewInfo_t view, int i) {

   if(i<0 || i>2) return i;
   if(view == nullView) return i;

   double d=0.0;
   int ind=i;
   for(int j=0;j<3;j++) {
     if(fabs(view->p2m[j][i]) > d) {
	d=fabs(view->p2m[j][i]);
	ind = j;
     }
   }
   return ind;
}
Esempio n. 19
0
TEST(prob_transform,cov_matrix_jacobian) {
  using stan::math::var;
  using stan::math::determinant;
  using std::log;
  using std::fabs;

  int K = 4;
  //unsigned int K = 4;
  unsigned int K_choose_2 = 6;
  Matrix<var,Dynamic,1> X(K_choose_2 + K);
  X << 1.0, 2.0, -3.0, 1.7, 9.8, 
    -12.2, 0.4, 0.2, 1.2, 2.7;
  std::vector<var> x;
  for (int i = 0; i < X.size(); ++i)
    x.push_back(X(i));
  var lp = 0.0;
  Matrix<var,Dynamic,Dynamic> Sigma = stan::math::cov_matrix_constrain(X,K,lp);
  std::vector<var> y;
  for (int m = 0; m < K; ++m)
    for (int n = 0; n <= m; ++n)
      y.push_back(Sigma(m,n));

  std::vector<std::vector<double> > j;
  stan::math::jacobian(y,x,j);

  Matrix<double,Dynamic,Dynamic> J(10,10);
  for (int m = 0; m < 10; ++m)
    for (int n = 0; n < 10; ++n)
      J(m,n) = j[m][n];

  double log_abs_jacobian_det = log(fabs(determinant(J)));
  EXPECT_FLOAT_EQ(log_abs_jacobian_det,lp.val());
}
Esempio n. 20
0
int
compute_residual(const int n, const double * const v1, const double * const v2,
    double * const residual)
{
  double local_residual = 0.0;
  PERFLOG(compute_residual,IN(n));
  for (int i = 0; i < n; i++)
  {
    double diff = fabs(v1[i] - v2[i]);
    if (diff > local_residual)
      local_residual = diff;
  }
#ifdef USING_SSTMAC
  // a little compute modeling
  SSTMAC_compute_loop(0, n, 2/3.0/1.5);
#endif


  PERFSTOP(compute_residual,IN(n));
  // Use MPI's reduce function to collect all partial sums

  double global_residual = 0;


  MPI_Allreduce(&local_residual, &global_residual, 1, MPI_DOUBLE, MPI_SUM,
      MPI_COMM_WORLD);
  *residual = global_residual;


  return (0);
}
Esempio n. 21
0
    inline
    fvar<T>
    gamma_q(const fvar<T>& x1, const double x2){
      using stan::math::gamma_q;
      using std::log;
      using std::exp;
      using std::pow;
      using std::fabs;
      using boost::math::tgamma;
      using boost::math::digamma;

      T u = gamma_q(x1.val_, x2);
      
      T S = 0;
      double s = 1;
      double l = log(x2);
      T g = tgamma(x1.val_);
      T dig = digamma(x1.val_);
      
      int k = 0;
      T delta = s / (x1.val_ * x1.val_);
      
      while (fabs(delta) > 1e-6) {
        S += delta;
        ++k;
        s *= -x2 / k;
        delta = s / ((k + x1.val_) * (k + x1.val_));
      }
      
      T der1 = (1.0 - u) * ( dig - l ) + exp( x1.val_ * l ) * S / g;
      
      return fvar<T>(u, x1.d_ * der1);
    }
Esempio n. 22
0
void bisection_method(T& low, T& hi, RootedFunction f, const T& tol = std::numeric_limits<T>::epsilon()) 
{
  using std::fabs;
  
  T low_value = f(low);
  T hi_value = f(hi);
  
  if( low_value * hi_value > 0.0 )
    return;
  
  while(fabs(hi - low) > tol) {
    
    T mid = 0.5 * (hi + low);
    T mid_value = f(mid);
    
    if(mid_value * hi_value > 0.0) {
      hi = mid;
      hi_value = mid_value;
    } else {
      low = mid;
      low_value = mid_value;
    };
    
  };
  
};
Esempio n. 23
0
int test_error_vec (const DualVector& random_vec,
                    const Vector& error_vec)
{
  using std::max;
  using std::fabs;

  typedef typename ValueType<Vector>::type Scalar;

  static const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 10;

  Scalar max_abs_error = 0;

  for (unsigned int i=0; i != error_vec.size(); ++i)
    {
      max_abs_error = max(max_abs_error, fabs(error_vec.raw_at(i)));

      // Handle NaNs properly.  Testing max_abs_error for NaN is
      // impossible because IEEE sucks:
      // https://en.wikipedia.org/wiki/IEEE_754_revision#min_and_max
      if (max_abs_error > tol || error_vec[i] != error_vec[i])
        {
	  std::cerr << "Value " << random_vec.raw_at(i) <<
		       "\nError " << error_vec.raw_at(i) <<
		       "\nTol   " << tol << std::endl;
	  return 1;
        }
    }

  return 0;
}
Esempio n. 24
0
int test_error_vec (const DualVector& random_vec,
                    const Vector& error_vec)
{
  using std::max;
  using std::fabs;

  typedef typename ValueType<Vector>::type Scalar;

  static const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 10;

  Scalar max_abs_error = 0;

  for (unsigned int i=0; i != error_vec.size(); ++i)
    {
      max_abs_error = max(max_abs_error, fabs(error_vec.raw_at(i)));

      if (max_abs_error > tol)
        {
	  std::cerr << "Value " << random_vec.raw_at(i) <<
		       "\nError " << error_vec.raw_at(i) <<
		       "\nTol   " << tol << std::endl;
	  return 1;
        }
    }

  return 0;
}
Esempio n. 25
0
void grad_2F1(T& gradA, T& gradC, T a, T b, T c, T z, T precision = 1e-6) {
    using std::fabs;

    gradA = 0;
    gradC = 0;

    T gradAold = 0;
    T gradCold = 0;

    int k = 0;
    T tDak = 1.0 / (a - 1);

    while (fabs(tDak * (a + (k - 1)) ) > precision || k == 0) {
        const T r = ( (a + k) / (c + k) ) * ( (b + k) / (T)(k + 1) ) * z;
        tDak = r * tDak * (a + (k - 1)) / (a + k);

        if (r == 0) break;

        gradAold = r * gradAold + tDak;
        gradCold = r * gradCold - tDak * ((a + k) / (c + k));

        gradA += gradAold;
        gradC += gradCold;

        ++k;

        if (k > 200) break;
    }
}
 static 
 double get_proper_distance(const BaseTopology& b_space, const rt_metric_type& rt_dist, const point_type& a, const point_type& b) {
   using std::fabs;
   svp_reach_time_metric< base_time_topo, true > p_rt_dist(rt_dist);
   double reach_time = p_rt_dist(a.pt, b.pt, b_space.get_space_topology());
   return fabs(b.time - a.time) + reach_time;
 };
// TODO Check for reference passing or const reference passing
double canberra_location(long nl, long ne, std::vector<std::vector<long> >& lists, long k, std::vector<long>& i1, std::vector<long>& i2, std::vector<double>& dist)
{
	long		i, idx1, idx2, l1, l2, count;
	double		distance, indicator;

	indicator = 0.0;
	count = 0;

	for (idx1 = 1; idx1 <= nl - 1; idx1++)
		for (idx2 = idx1 + 1; idx2 <= nl; idx2++) 
		{
			distance = 0.0;
			for (i = 1; i <= ne; i++) 
			{
				l1 = lists[idx1 - 1][i - 1] + 1 <= k + 1 ? lists[idx1 - 1][i - 1] + 1 : k + 1;
				l2 = lists[idx2 - 1][i - 1] + 1 <= k + 1 ? lists[idx2 - 1][i - 1] + 1 : k + 1;
				distance += fabs(l1 - l2) / (l1 + l2);
			}

			i1[count] = idx1 - 1;
			i2[count] = idx2 - 1;
			dist[count] = distance;
			count++;

			indicator += 2.0 * distance / (nl * (nl - 1));
		}

	return (indicator);
}
Esempio n. 28
0
    inline
    fvar<typename stan::return_type<T,double>::type>
    gamma_p(const fvar<T>& x1, double x2){
      using stan::math::gamma_p;
      using std::log;
      using std::exp;
      using std::pow;
      using std::fabs;
      using boost::math::tgamma;
      using boost::math::digamma;

      typename stan::return_type<T,double>::type u = gamma_p(x1.val_, x2);
      
      T S = 0.0;
      double s = 1.0;
      double l = log(x2);
      T g = tgamma(x1.val_);
      T dig = digamma(x1.val_);
      
      int k = 0;
      T delta = s / (x1.val_ * x1.val_);
      
      while (fabs(delta) > 1e-6) {
        S += delta;
        ++k;
        s *= -x2 / k;
        delta = s / ((k + x1.val_) * (k + x1.val_));
      }
      
      T der1 = (u) * ( dig - l ) + exp( x1.val_ * l ) * S / g;

      return fvar<typename 
                  stan::return_type<T,double>::type>(u,x1.d_ * -der1);
    }
Esempio n. 29
0
    inline
    fvar<T>
    gamma_p(const fvar<T>& x1, const fvar<T>& x2){
      using stan::math::gamma_p;
      using std::log;
      using std::exp;
      using std::pow;
      using std::fabs;
      using boost::math::tgamma;
      using boost::math::digamma;

      T u = gamma_p(x1.val_, x2.val_);
      
      T S = 0;
      T s = 1;
      T l = log(x2.val_);
      T g = tgamma(x1.val_);
      T dig = digamma(x1.val_);
      
      int k = 0;
      T delta = s / (x1.val_ * x1.val_);
      
      while (fabs(delta) > 1e-6) {
        S += delta;
        ++k;
        s *= -x2.val_ / k;
        delta = s / ((k + x1.val_) * (k + x1.val_));
      }
      
      T der1 = (u) * ( dig - l ) + exp( x1.val_ * l ) * S / g;
      T der2 = exp(-x2.val_) * pow(x2.val_, x1.val_ - 1.0) / g;
      
      return fvar<T>(u,x1.d_ * -der1 + x2.d_ * der2);
    }
 static 
 double get_proper_norm(const BaseTopology& b_space, const rt_metric_type& rt_dist, const point_difference_type& dp) {
   using std::fabs;
   svp_reach_time_metric< base_time_topo, true > p_rt_dist(rt_dist);
   double reach_time = p_rt_dist(dp.pt, b_space.get_space_topology());
   return fabs(dp.time) + reach_time;
 };