//------ Begin of function Math::double_poisson -------// //! //! Double Poisson(n, mu) = (exp[-mu]*mu^n)/n! /* Poison probability distribution */ //! float Math::double_poisson(int n, float mu) { int nFactor=1; for (int i=2; i<=n; i++) { nFactor *= i; } return float( exp(-mu) * safe_pow(mu,(float)n) ) / nFactor; }
/// compute power inline CouNumber exprEvenPow::operator () () { // return (currValue_ = safe_pow (base, exponent)); return (safe_pow ((**arglist_) (), (*(arglist_ [1])) ())); }
inline T differentiate( const f * func, const T & in_param, const int_type order = 1, const flt_type & power = 1, const T & factor=SMALL_FACTOR ) { T d_in_param( 0 ); T low_in_param( 0 ); T high_in_param( 0 ); T low_out_param( 0 ); T high_out_param( 0 ); T small_factor_with_units(factor); bool power_flag = false; bool zero_in_flag = false; int_type order_to_use = max( order, 1 ); if ( ( order_to_use > 1 ) ) { throw std::logic_error("IceBRG::differentiate with order > 1 is not currently supported.\n"); } if ( power != 1 ) power_flag = true; else power_flag = false; // Check if any in_params are zero. If so, estimate small factor from other in_params if ( in_param == 0 ) { zero_in_flag = true; } else // if(in_params==0) { small_factor_with_units = in_param * factor; d_in_param = small_factor_with_units; } // else if ( zero_in_flag ) { if ( small_factor_with_units == 0 ) { d_in_param = factor; } else { if ( in_param == 0 ) { d_in_param = small_factor_with_units; } // if(in_params[i]==0) } } bool bad_function_result = false; int_type counter = 0; T Jacobian=0; do { counter++; bad_function_result = false; low_in_param = in_param - d_in_param; high_in_param = in_param + d_in_param; // Run the function to get value at test point try { low_out_param = ( *func )( low_in_param ); high_out_param = ( *func )( high_in_param ); } catch(const std::runtime_error &e) { bad_function_result = true; d_in_param /= 10; // Try again with smaller step continue; } // Record this derivative Jacobian = ( high_out_param - low_out_param ) / (2*d_in_param); if ( power_flag ) Jacobian *= power * safe_pow( ( high_out_param + low_out_param )/2, power - 1 ); if(isbad(Jacobian)) { bad_function_result = true; d_in_param /= 10; // Try again with smaller step continue; } } while ((bad_function_result) && (counter<3)); if(counter>=3) throw std::runtime_error("Cannot differentiate function due to lack of valid nearby points found."); return Jacobian; }
inline std::vector< std::vector< T > > differentiate( const f * func, const std::vector< T > & in_params, const int_type order = 1, const flt_type & power = 1 ) { auto num_in_params = ssize(in_params); std::vector< std::vector< T > > Jacobian; std::vector< T > d_in_params( 0 ); std::vector< T > base_out_params( 0 ); std::vector< T > test_in_params( 0 ); std::vector< T > test_out_params( 0 ); T small_factor_with_units = SMALL_FACTOR; bool power_flag = false; bool zero_in_flag = false; int_type order_to_use = (int_type)max( order, 1 ); if ( ( order_to_use > 1 ) ) { throw std::logic_error("IceBRG::differentiate with order > 1 is not currently supported.\n"); } if ( power != 1 ) power_flag = true; else power_flag = false; // Delete std::vectors we'll be overwriting in case they previously existed Jacobian.clear(); // Set up differentials make_vector_zeroes( d_in_params, num_in_params ); test_in_params = in_params; // Check if any in_params are zero. If so, estimate small factor from other in_params for ( size_t i = 0; i < num_in_params; i++ ) { if ( in_params[i] == 0 ) { zero_in_flag = true; } else // if(in_params[i]==0) { small_factor_with_units = in_params[i] * SMALL_FACTOR; d_in_params[i] = small_factor_with_units; } // else } // for( size_t i = 0; i < num_in_params; i++ ) if ( zero_in_flag ) { if ( small_factor_with_units == 0 ) { // At least try to get the units right for ( size_t i = 0; i < num_in_params; i++ ) { #ifdef _BRG_USE_UNITS_ d_in_params[i].set(SMALL_FACTOR,in_params[i].get_unit_powers()); #else d_in_params[i] = SMALL_FACTOR; #endif } // for( size_t i = 0; i < num_in_params; i++ ) } else { for ( size_t i = 0; i < num_in_params; i++ ) { if ( in_params[i] == 0 ) { #ifdef _BRG_USE_UNITS_ d_in_params[i].set(small_factor_with_units.get_value(),in_params[i].get_unit_powers()); #else d_in_params[i] = small_factor_with_units; #endif } // if(in_params[i]==0) } // for( size_t i = 0; i < num_in_params; i++ ) } } // Get value of function at input parameters base_out_params = ( *func )( in_params ); auto num_out_params=ssize(base_out_params); // Set up Jacobian make_vector_default( Jacobian, num_out_params, num_in_params ); // Loop over input and output dimensions to get Jacobian bool bad_function_result = false; int_type counter = 0; do { counter++; bad_function_result = false; for ( size_t j = 0; j < num_in_params; j++ ) { // Set up test input parameters for ( size_t j2 = 0; j2 < num_in_params; j2++ ) { if ( j2 == j ) { test_in_params[j2] = in_params[j2] + d_in_params[j2]; } // if( j2==j ) else { test_in_params[j2] = in_params[j2]; } // else } // Run the function to get value at test point try { test_out_params = ( *func )( test_in_params ); } catch(const std::exception &e) { bad_function_result = true; for(ssize_t j=0; j< ssize(in_params); j++) d_in_params[j] /= 10; // Try again with smaller step size continue; } // Record this derivative for ( size_t i = 0; i < num_out_params; i++ ) { Jacobian[i][j] = ( test_out_params[i] - base_out_params[i] ) / d_in_params[j]; if ( power_flag ) Jacobian[i][j] *= power * safe_pow( base_out_params[i], power - 1 ); if(isbad(Jacobian[i][j])) { bad_function_result = true; for(size_t j=0; j< ssize(in_params); j++) d_in_params[j] /= 10; // Try again with smaller step size continue; } } // for( int_type i = 0; i < num_out_params; i++) } // for( size_t j = 0; j < num_in_params; j++) } while (bad_function_result && (counter<3)); if(counter>=3) throw std::runtime_error("Cannot differentiate function due to lack of valid nearby points found."); return Jacobian; }