Update series_expansion methods to use armadillo and std:: components.

This commit is contained in:
Ryan Curtin
2011-01-31 19:16:13 +00:00
parent 6bd0293fa2
commit 4e98f49684
13 changed files with 626 additions and 803 deletions
@@ -12,7 +12,8 @@
#ifndef FARFIELD_EXPANSION
#define FARFIELD_EXPANSION
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include "kernel_aux.h"
#include "series_expansion_aux.h"
@@ -38,10 +39,10 @@ class FarFieldExpansion {
////////// Private Member Variables //////////
/** @brief The center of the expansion. */
Vector center_;
arma::vec center_;
/** @brief The coefficients. */
Vector coeffs_;
arma::vec coeffs_;
/** @brief The order of the expansion. */
int order_;
@@ -61,12 +62,6 @@ class FarFieldExpansion {
*/
const typename TKernelAux::TSeriesExpansionAux *sea_;
OT_DEF(FarFieldExpansion) {
OT_MY_OBJECT(center_);
OT_MY_OBJECT(coeffs_);
OT_MY_OBJECT(order_);
}
public:
////////// Getters/Setters //////////
@@ -82,16 +77,16 @@ class FarFieldExpansion {
*
* @return The center of expansion for the current far-field expansion.
*/
Vector* get_center() { return &center_; }
const Vector* get_center() const { return &center_; }
arma::vec& get_center() { return center_; }
const arma::vec& get_center() const { return center_; }
/** @brief Gets the set of far-field coefficients.
*
* @return The const reference to the vector containing the
* far-field coefficients.
*/
const Vector& get_coeffs() const { return coeffs_; }
arma::vec& get_coeffs() { return coeffs_; }
const arma::vec& get_coeffs() const { return coeffs_; }
/** @brief Gets the approximation order.
*
@@ -122,11 +117,8 @@ class FarFieldExpansion {
* will be copied to the center of the given far-field
* expansion object.
*/
void set_center(const Vector &center) {
for(index_t i = 0; i < center.length(); i++) {
center_[i] = center[i];
}
void set_center(const arma::vec& center) {
center_ = center;
}
////////// User-level Functions //////////
@@ -151,7 +143,7 @@ class FarFieldExpansion {
* @param order The order up to which the far-field moments should be
* accumulated up to.
*/
void Accumulate(const Vector &reference_point, double weight, int order);
void Accumulate(const arma::vec& reference_point, double weight, int order);
/** @brief Accumulates the far field moment represented by the given
* reference data into the coefficients.
@@ -178,24 +170,24 @@ class FarFieldExpansion {
* @param order The order up to which the far-field moments should be
* accumulated up to.
*/
void AccumulateCoeffs(const Matrix& data, const Vector& weights,
void AccumulateCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/** @brief Refine the far field moment that has been computed before
* up to a new order.
*/
void RefineCoeffs(const Matrix& data, const Vector& weights,
void RefineCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/** @brief Evaluates the far-field coefficients at the given point.
*/
double EvaluateField(const Matrix& data, int row_num, int order) const;
double EvaluateField(const arma::mat& data, int row_num, int order) const;
double EvaluateField(const double *x_q, int order) const;
/** @brief Evaluates the two-way convolution mixed with exhaustive
* computations with two other far field expansions.
*/
double MixField(const Matrix &data, int node1_begin, int node1_end,
double MixField(const arma::mat& data, int node1_begin, int node1_end,
int node2_begin, int node2_end, const FarFieldExpansion &fe2,
const FarFieldExpansion &fe3, int order2, int order3) const;
@@ -214,14 +206,14 @@ class FarFieldExpansion {
/** @brief Initializes the current far field expansion object with
* the given center.
*/
void Init(const Vector& center, const TKernelAux &ka);
void Init(const arma::vec& center, const TKernelAux &ka);
void Init(const TKernelAux &ka);
template<typename TBound>
int OrderForConvolving(const TBound &far_field_region,
const Vector &far_field_region_centroid,
const arma::vec &far_field_region_centroid,
const TBound &local_field_region,
const Vector &local_field_region_centroid,
const arma::vec &local_field_region_centroid,
double min_dist_sqd_regions,
double max_dist_dsqd_regons,
double max_error, double *actual_error) const;
@@ -6,33 +6,31 @@
#define FARFIELD_EXPANSION_IMPL_H
template<typename TKernelAux>
void FarFieldExpansion<TKernelAux>::Accumulate(const Vector &v, double weight,
void FarFieldExpansion<TKernelAux>::Accumulate(const arma::vec& v, double weight,
int order) {
int dim = v.length();
int dim = v.n_elem;
int total_num_coeffs = sea_->get_total_num_coeffs(order);
Vector tmp;
arma::vec tmp;
int r, i, j, k, t, tail;
GenVector<short int> heads;
Vector x_r;
arma::Col<short int> heads;
arma::vec x_r;
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// initialize temporary variables
tmp.Init(total_num_coeffs);
heads.Init(dim + 1);
x_r.Init(dim);
Vector pos_coeffs;
Vector neg_coeffs;
pos_coeffs.Init(total_num_coeffs);
pos_coeffs.SetZero();
neg_coeffs.Init(total_num_coeffs);
neg_coeffs.SetZero();
tmp.set_size(total_num_coeffs);
heads.set_size(dim + 1);
x_r.set_size(dim);
arma::vec pos_coeffs;
arma::vec neg_coeffs;
pos_coeffs.zeros(total_num_coeffs);
neg_coeffs.zeros(total_num_coeffs);
// set to new order if greater
if(order_ < order) {
order_ = order;
}
Vector C_k;
arma::vec& C_k;
// Calculate the coordinate difference between the ref point and the
// centroid.
@@ -41,7 +39,7 @@ void FarFieldExpansion<TKernelAux>::Accumulate(const Vector &v, double weight,
}
// initialize heads
heads.SetZero();
heads.zeros();
heads[dim] = SHRT_MAX;
tmp[0] = 1.0;
@@ -70,7 +68,7 @@ void FarFieldExpansion<TKernelAux>::Accumulate(const Vector &v, double weight,
}
// get multiindex factors
C_k.Alias(sea_->get_inv_multiindex_factorials());
C_k = sea_->get_inv_multiindex_factorials();
for(r = 0; r < total_num_coeffs; r++) {
coeffs_[r] += (pos_coeffs[r] + neg_coeffs[r]) * C_k[r];
@@ -78,47 +76,44 @@ void FarFieldExpansion<TKernelAux>::Accumulate(const Vector &v, double weight,
}
template<typename TKernelAux>
void FarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
const Vector& weights,
void FarFieldExpansion<TKernelAux>::AccumulateCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
int dim = data.n_rows();
int dim = data.n_rows;
int total_num_coeffs = sea_->get_total_num_coeffs(order);
Vector tmp;
arma::vec tmp;
int r, i, j, k, t, tail;
GenVector<short int> heads;
Vector x_r;
arma::Col<short int> heads;
arma::vec x_r;
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// initialize temporary variables
tmp.Init(total_num_coeffs);
heads.Init(dim + 1);
x_r.Init(dim);
Vector pos_coeffs;
Vector neg_coeffs;
pos_coeffs.Init(total_num_coeffs);
pos_coeffs.SetZero();
neg_coeffs.Init(total_num_coeffs);
neg_coeffs.SetZero();
tmp.set_size(total_num_coeffs);
heads.set_size(dim + 1);
x_r.set_size(dim);
arma::vec pos_coeffs;
arma::vec neg_coeffs;
pos_coeffs.zeros(total_num_coeffs);
neg_coeffs.zeros(total_num_coeffs);
// set to new order if greater
if(order_ < order) {
order_ = order;
}
Vector C_k;
// Repeat for each reference point in this reference node.
for(r = begin; r < end; r++) {
// Calculate the coordinate difference between the ref point and the
// centroid.
for(i = 0; i < dim; i++) {
x_r[i] = (data.get(i, r) - center_[i]) / bandwidth_factor;
x_r[i] = (data(i, r) - center_[i]) / bandwidth_factor;
}
// initialize heads
heads.SetZero();
heads.zeros();
heads[dim] = SHRT_MAX;
tmp[0] = 1.0;
@@ -149,7 +144,7 @@ void FarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
} // End of looping through each reference point
// get multiindex factors
C_k.Alias(sea_->get_inv_multiindex_factorials());
const arma::vec& C_k = sea_->get_inv_multiindex_factorials();
for(r = 0; r < total_num_coeffs; r++) {
coeffs_[r] += (pos_coeffs[r] + neg_coeffs[r]) * C_k[r];
@@ -157,8 +152,8 @@ void FarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
}
template<typename TKernelAux>
void FarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
const Vector& weights,
void FarFieldExpansion<TKernelAux>::RefineCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
@@ -168,22 +163,19 @@ void FarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
return;
}
int dim = data.n_rows();
int dim = data.n_rows;
int old_total_num_coeffs = sea_->get_total_num_coeffs(order_);
int total_num_coeffs = sea_->get_total_num_coeffs(order);
double tmp;
int r, i, j;
Vector x_r;
arma::vec x_r(dim);
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// initialize temporary variables
x_r.Init(dim);
Vector pos_coeffs;
Vector neg_coeffs;
pos_coeffs.Init(total_num_coeffs);
pos_coeffs.SetZero();
neg_coeffs.Init(total_num_coeffs);
neg_coeffs.SetZero();
arma::vec pos_coeffs;
arma::vec neg_coeffs;
pos_coeffs.zeros(total_num_coeffs);
neg_coeffs.zeros(total_num_coeffs);
// if we already have the order of approximation, then return.
if(order_ >= order) {
@@ -193,7 +185,7 @@ void FarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
order_ = order;
}
Vector C_k;
const arma::vec& C_k = sea_->get_inv_multiindex_factorials();
// Repeat for each reference point in this reference node.
for(r = begin; r < end; r++) {
@@ -201,12 +193,12 @@ void FarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
// Calculate the coordinate difference between the ref point and the
// centroid.
for(i = 0; i < dim; i++) {
x_r[i] = (data.get(i, r) - center_[i]) / bandwidth_factor;
x_r[i] = (data(i, r) - center_[i]) / bandwidth_factor;
}
// compute in bruteforce way
for(i = old_total_num_coeffs; i < total_num_coeffs; i++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(i);
const std::vector<short int> &mapping = sea_->get_multiindex(i);
tmp = 1;
for(j = 0; j < dim; j++) {
@@ -225,19 +217,16 @@ void FarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
} // End of looping through each reference point
// get multiindex factors
C_k.Alias(sea_->get_inv_multiindex_factorials());
for(r = old_total_num_coeffs; r < total_num_coeffs; r++) {
coeffs_[r] = (pos_coeffs[r] + neg_coeffs[r]) * C_k[r];
}
}
template<typename TKernelAux>
double FarFieldExpansion<TKernelAux>::EvaluateField(const Matrix& data,
double FarFieldExpansion<TKernelAux>::EvaluateField(const arma::mat& data,
int row_num,
int order) const {
return EvaluateField(data.GetColumnPtr(row_num), order);
return EvaluateField(data.unsafe_col(row_num).memptr(), order);
}
template<typename TKernelAux>
@@ -259,16 +248,14 @@ double FarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
double multipole_sum = 0;
// computed derivative map
Matrix derivative_map;
ka_->AllocateDerivativeMap(dim, order, &derivative_map);
arma::mat derivative_map;
ka_->AllocateDerivativeMap(dim, order, derivative_map);
// temporary variable
Vector arrtmp;
arrtmp.Init(total_num_coeffs);
arma::vec arrtmp(total_num_coeffs);
// (x_q - x_R) scaled by bandwidth
Vector x_q_minus_x_R;
x_q_minus_x_R.Init(dim);
arma::vec x_q_minus_x_R(dim);
// compute (x_q - x_R) / (sqrt(2h^2))
for(index_t d = 0; d < dim; d++) {
@@ -276,11 +263,11 @@ double FarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
}
// compute deriative maps based on coordinate difference.
ka_->ComputeDirectionalDerivatives(x_q_minus_x_R, &derivative_map, order);
ka_->ComputeDirectionalDerivatives(x_q_minus_x_R, derivative_map, order);
// compute h_{\alpha}((x_q - x_R)/sqrt(2h^2)) ((x_r - x_R)/h)^{\alpha}
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(j);
const std::vector<short int> &mapping = sea_->get_multiindex(j);
double arrtmp = ka_->ComputePartialDerivative(derivative_map, mapping);
double prod = coeffs_[j] * arrtmp;
@@ -297,7 +284,7 @@ double FarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
}
template<typename TKernelAux>
double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
double FarFieldExpansion<TKernelAux>::MixField(const arma::mat &data,
int node1_begin, int node1_end,
int node2_begin, int node2_end,
const FarFieldExpansion &fe2,
@@ -307,18 +294,17 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
// bandwidth factor and multiindex mapping stuffs
double result;
double bandwidth_factor = ka_->BandwidthFactor(bandwidth_sq());
const ArrayList<short int> *multiindex_mapping =
const std::vector<short int>& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList<short int> *lower_mapping_index =
const std::vector<short int>& lower_mapping_index =
sea_->get_lower_mapping_index();
// get the total number of coefficients and coefficients
int total_num_coeffs2 = sea_->get_total_num_coeffs(order2);
int total_num_coeffs3 = sea_->get_total_num_coeffs(order3);
int dim = sea_->get_dimension();
Vector coeffs2, coeffs3;
coeffs2.Alias(fe2.get_coeffs());
coeffs3.Alias(fe3.get_coeffs());
arma::vec& coeffs2 = fe2.get_coeffs();
arma::vec& coeffs3 = fe3.get_coeffs();
// actual accumulated sum
double neg_sum = 0;
@@ -330,65 +316,58 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
double xi_xI, xj_xJ, diff;
// temporary array
ArrayList<short int> beta_gamma_nu_eta_mapping;
ArrayList<short int> beta_nu_mapping;
ArrayList<short int> gamma_eta_mapping;
beta_nu_mapping.Init(dim);
gamma_eta_mapping.Init(dim);
beta_gamma_nu_eta_mapping.Init(dim);
std::vector<short int> beta_gamma_nu_eta_mapping;
std::vector<short int> beta_nu_mapping;
std::vector<short int> gamma_eta_mapping;
beta_nu_mapping.reserve(dim);
gamma_eta_mapping.reserve(dim);
beta_gamma_nu_eta_mapping.reserve(dim);
// partial derivatives table
Matrix derivative_map_beta;
ka_->AllocateDerivativeMap(dim, order2, &derivative_map_beta);
Matrix derivative_map_gamma;
ka_->AllocateDerivativeMap(dim, order3, &derivative_map_gamma);
arma::mat derivative_map_beta;
ka_->AllocateDerivativeMap(dim, order2, derivative_map_beta);
arma::mat derivative_map_gamma;
ka_->AllocateDerivativeMap(dim, order3, derivative_map_gamma);
// compute center differences and complete the table of partial derivatives
Vector xI_xK, xJ_xK;
xI_xK.Init(dim);
xJ_xK.Init(dim);
Vector xJ_center, xK_center;
xJ_center.Alias(*(fe2.get_center()));
xK_center.Alias(*(fe3.get_center()));
arma::vec xI_xK(dim), xJ_xK(dim);
arma::vec& xJ_center = fe2.get_center();
arma::vec& xK_center = fe3.get_center();
for(index_t d = 0; d < dim; d++) {
xI_xK[d] = (center_[d] - xK_center[d]) / bandwidth_factor;
xJ_xK[d] = (xJ_center[d] - xK_center[d]) / bandwidth_factor;
}
ka_->ComputeDirectionalDerivatives(xI_xK, &derivative_map_beta, order2);
ka_->ComputeDirectionalDerivatives(xJ_xK, &derivative_map_gamma, order3);
ka_->ComputeDirectionalDerivatives(xI_xK, derivative_map_beta, order2);
ka_->ComputeDirectionalDerivatives(xJ_xK, derivative_map_gamma, order3);
// inverse factorials
Vector inv_multiindex_factorials;
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
arma::vec& inv_multiindex_factorials = sea_->get_inv_multiindex_factorials();
// precompute pairwise kernel values between node i and node j
Matrix exhaustive_ij;
exhaustive_ij.Init(node1_end - node1_begin, node2_end - node2_begin);
arma::mat exhaustive_ij(node1_end - node1_begin, node2_end - node2_begin);
for(index_t i = node1_begin; i < node1_end; i++) {
const double *i_col = data.GetColumnPtr(i);
arma::vec i_col = data.unsafe_col(i);
for(index_t j = node2_begin; j < node2_end; j++) {
const double *j_col = data.GetColumnPtr(j);
arma::vec j_col = data.unsafe_col(j);
exhaustive_ij.set
(i - node1_begin, j - node2_begin,
kernel_->EvalUnnormOnSq(la::DistanceSqEuclidean(data.n_rows(),
i_col, j_col)));
exhaustive_ij(i - node1_begin, j - node2_begin) =
kernel_->EvalUnnormOnSq(la::DistanceSqEuclidean(i_col, j_col));
}
}
// main loop
for(index_t beta = 0; beta < total_num_coeffs2; beta++) {
const ArrayList <short int> &beta_mapping = multiindex_mapping[beta];
const ArrayList <short int> &lower_mappings_for_beta =
const std::vector<short int> &beta_mapping = multiindex_mapping[beta];
const std::vector<short int> &lower_mappings_for_beta =
lower_mapping_index[beta];
double beta_derivative = ka_->ComputePartialDerivative
(derivative_map_beta, beta_mapping);
for(index_t nu = 0; nu < lower_mappings_for_beta.size(); nu++) {
const ArrayList<short int> &nu_mapping =
const std::vector<short int> &nu_mapping =
multiindex_mapping[lower_mappings_for_beta[nu]];
// beta - nu
@@ -398,19 +377,19 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
for(index_t gamma = 0; gamma < total_num_coeffs3; gamma++) {
const ArrayList <short int> &gamma_mapping = multiindex_mapping[gamma];
const ArrayList <short int> &lower_mappings_for_gamma =
const std::vector<short int> &gamma_mapping = multiindex_mapping[gamma];
const std::vector<short int> &lower_mappings_for_gamma =
lower_mapping_index[gamma];
double gamma_derivative = ka_->ComputePartialDerivative
(derivative_map_gamma, gamma_mapping);
for(index_t eta = 0; eta < lower_mappings_for_gamma.size();
eta++){
eta++) {
// add up alpha, mu, eta and beta, gamma, nu, eta
int sign = 0;
const ArrayList<short int> &eta_mapping =
const std::vector<short int> &eta_mapping =
multiindex_mapping[lower_mappings_for_gamma[eta]];
for(index_t d = 0; d < dim; d++) {
@@ -439,7 +418,7 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
inv_multiindex_factorials
[sea_->ComputeMultiindexPosition(nu_mapping)];
for(index_t d = 0; d < dim; d++) {
diff = (data.get(d, i) - center_[d]) / bandwidth_factor;
diff = (data(d, i) - center_[d]) / bandwidth_factor;
xi_xI *= pow(diff, nu_mapping[d]);
}
@@ -448,7 +427,7 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
xj_xJ = inv_multiindex_factorials
[sea_->ComputeMultiindexPosition(eta_mapping)];
for(index_t d = 0; d < dim; d++) {
diff = (data.get(d, j) - xJ_center[d]) / bandwidth_factor;
diff = (data(d, j) - xJ_center[d]) / bandwidth_factor;
xj_xJ *= pow(diff, eta_mapping[d]);
}
@@ -457,8 +436,7 @@ double FarFieldExpansion<TKernelAux>::MixField(const Matrix &data,
(sea_->ComputeMultiindexPosition(beta_gamma_nu_eta_mapping),
sea_->ComputeMultiindexPosition(beta_nu_mapping)) *
beta_derivative * gamma_derivative * xi_xI * xj_xJ *
moment_k * exhaustive_ij.get
(i - node1_begin, j - node2_begin);
moment_k * exhaustive_ij(i - node1_begin, j - node2_begin);
if(result > 0) {
pos_sum += result;
@@ -485,16 +463,15 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
// The bandwidth factor and the multiindex mapping stuffs.
double bandwidth_factor = ka_->BandwidthFactor(bandwidth_sq());
const ArrayList<short int> *multiindex_mapping =
const std::vector<short int>& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList<short int> *lower_mapping_index =
const std::vector<short int>& lower_mapping_index =
sea_->get_lower_mapping_index();
// Get the total number of coefficients and the coefficient themselves.
int total_num_coeffs = sea_->get_total_num_coeffs(order);
int dim = sea_->get_dimension();
Vector coeffs2;
coeffs2.Alias(fe.get_coeffs());
arma::vec& coeffs2 = fe.get_coeffs();
// Actual accumulated sum.
double neg_sum = 0;
@@ -502,41 +479,38 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
double sum = 0;
// The partial derivatives table.
Matrix derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order, &derivative_map_alpha);
arma::mat derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order, derivative_map_alpha);
// Compute the center difference and its table of partial
// derivatives.
Vector xI_xJ;
xI_xJ.Init(dim);
Vector xJ_center;
xJ_center.Alias(*(fe.get_center()));
arma::vec xI_xJ(dim);
arma::vec& xJ_center = fe.get_center();
for(index_t d = 0; d < dim; d++) {
xI_xJ[d] = (center_[d] - xJ_center[d]) / bandwidth_factor;
}
ka_->ComputeDirectionalDerivatives(xI_xJ, &derivative_map_alpha, order);
ka_->ComputeDirectionalDerivatives(xI_xJ, derivative_map_alpha, order);
// The inverse factorials.
Vector inv_multiindex_factorials;
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
arma::vec& inv_multiindex_factorials = sea_->get_inv_multiindex_factorials();
// The temporary space for computing the difference of two mappings.
ArrayList<short int> alpha_minus_beta_mapping;
alpha_minus_beta_mapping.Init(dim);
std::vector<short int> alpha_minus_beta_mapping;
alpha_minus_beta_mapping.reserve(dim);
// The main loop.
for(index_t alpha = 0; alpha < total_num_coeffs; alpha++) {
const ArrayList <short int> &alpha_mapping = multiindex_mapping[alpha];
const ArrayList <short int> &lower_mappings_for_alpha =
const std::vector<short int> &alpha_mapping = multiindex_mapping[alpha];
const std::vector<short int> &lower_mappings_for_alpha =
lower_mapping_index[alpha];
double alpha_derivative = ka_->ComputePartialDerivative
(derivative_map_alpha, alpha_mapping);
for(index_t beta = 0; beta < lower_mappings_for_alpha.size(); beta++) {
const ArrayList <short int> &beta_mapping =
const std::vector<short int> &beta_mapping =
multiindex_mapping[lower_mappings_for_alpha[beta]];
double n_choose_k_factor = sea_->get_n_multichoose_k_by_pos
@@ -583,9 +557,9 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
// bandwidth factor and multiindex mapping stuffs
double result;
double bandwidth_factor = ka_->BandwidthFactor(bandwidth_sq());
const ArrayList<short int> *multiindex_mapping =
const std::vector<short int>& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList<short int> *lower_mapping_index =
const std::vector<short int>& lower_mapping_index =
sea_->get_lower_mapping_index();
// get the total number of coefficients and coefficients
@@ -593,9 +567,8 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
int total_num_coeffs2 = sea_->get_total_num_coeffs(order2);
int total_num_coeffs3 = sea_->get_total_num_coeffs(order3);
int dim = sea_->get_dimension();
Vector coeffs2, coeffs3;
coeffs2.Alias(fe2.get_coeffs());
coeffs3.Alias(fe3.get_coeffs());
arma::vec& coeffs2 = fe2.get_coeffs();
arma::vec& coeffs3 = fe3.get_coeffs();
// actual accumulated sum
double neg_sum = 0;
@@ -606,61 +579,56 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
double moment_i, moment_j, moment_k;
// temporary array
ArrayList<short int> mu_nu_mapping;
ArrayList<short int> alpha_mu_eta_mapping;
ArrayList<short int> beta_gamma_nu_eta_mapping;
ArrayList<short int> alpha_mu_mapping;
ArrayList<short int> beta_nu_mapping;
ArrayList<short int> gamma_eta_mapping;
alpha_mu_mapping.Init(dim);
beta_nu_mapping.Init(dim);
gamma_eta_mapping.Init(dim);
mu_nu_mapping.Init(dim);
alpha_mu_eta_mapping.Init(dim);
beta_gamma_nu_eta_mapping.Init(dim);
std::vector<short int> mu_nu_mapping;
std::vector<short int> alpha_mu_eta_mapping;
std::vector<short int> beta_gamma_nu_eta_mapping;
std::vector<short int> alpha_mu_mapping;
std::vector<short int> beta_nu_mapping;
std::vector<short int> gamma_eta_mapping;
alpha_mu_mapping.reserve(dim);
beta_nu_mapping.reserve(dim);
gamma_eta_mapping.reserve(dim);
mu_nu_mapping.reserve(dim);
alpha_mu_eta_mapping.reserve(dim);
beta_gamma_nu_eta_mapping.reserve(dim);
// partial derivatives table
Matrix derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order1, &derivative_map_alpha);
Matrix derivative_map_beta;
ka_->AllocateDerivativeMap(dim, order2, &derivative_map_beta);
Matrix derivative_map_gamma;
ka_->AllocateDerivativeMap(dim, order3, &derivative_map_gamma);
arma::mat derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order1, derivative_map_alpha);
arma::mat derivative_map_beta;
ka_->AllocateDerivativeMap(dim, order2, derivative_map_beta);
arma::mat derivative_map_gamma;
ka_->AllocateDerivativeMap(dim, order3, derivative_map_gamma);
// compute center differences and complete the table of partial derivatives
Vector xI_xJ, xI_xK, xJ_xK;
xI_xJ.Init(dim);
xI_xK.Init(dim);
xJ_xK.Init(dim);
Vector xJ_center, xK_center;
xJ_center.Alias(*(fe2.get_center()));
xK_center.Alias(*(fe3.get_center()));
arma::vec xI_xJ(dim), xI_xK(dim), xJ_xK(dim);
arma::vec& xJ_center = fe2.get_center();
arma::vec& xK_center = fe3.get_center();
for(index_t d = 0; d < dim; d++) {
xI_xJ[d] = (center_[d] - xJ_center[d]) / bandwidth_factor;
xI_xK[d] = (center_[d] - xK_center[d]) / bandwidth_factor;
xJ_xK[d] = (xJ_center[d] - xK_center[d]) / bandwidth_factor;
}
ka_->ComputeDirectionalDerivatives(xI_xJ, &derivative_map_alpha, order1);
ka_->ComputeDirectionalDerivatives(xI_xK, &derivative_map_beta, order2);
ka_->ComputeDirectionalDerivatives(xJ_xK, &derivative_map_gamma, order3);
ka_->ComputeDirectionalDerivatives(xI_xJ, derivative_map_alpha, order1);
ka_->ComputeDirectionalDerivatives(xI_xK, derivative_map_beta, order2);
ka_->ComputeDirectionalDerivatives(xJ_xK, derivative_map_gamma, order3);
// inverse factorials
Vector inv_multiindex_factorials;
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
arma::vec& inv_multiindex_factorials = sea_->get_inv_multiindex_factorials();
// main loop
for(index_t alpha = 0; alpha < total_num_coeffs1; alpha++) {
const ArrayList <short int> &alpha_mapping = multiindex_mapping[alpha];
const ArrayList <short int> &lower_mappings_for_alpha =
const std::vector<short int>& alpha_mapping = multiindex_mapping[alpha];
const std::vector<short int>& lower_mappings_for_alpha =
lower_mapping_index[alpha];
double alpha_derivative = ka_->ComputePartialDerivative
(derivative_map_alpha, alpha_mapping);
for(index_t mu = 0; mu < lower_mappings_for_alpha.size(); mu++) {
const ArrayList <short int> &mu_mapping =
const std::vector<short int>& mu_mapping =
multiindex_mapping[lower_mappings_for_alpha[mu]];
// alpha - mu
@@ -670,15 +638,15 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
for(index_t beta = 0; beta < total_num_coeffs2; beta++) {
const ArrayList <short int> &beta_mapping = multiindex_mapping[beta];
const ArrayList <short int> &lower_mappings_for_beta =
const std::vector<short int>& beta_mapping = multiindex_mapping[beta];
const std::vector<short int>& lower_mappings_for_beta =
lower_mapping_index[beta];
double beta_derivative = ka_->ComputePartialDerivative
(derivative_map_beta, beta_mapping);
for(index_t nu = 0; nu < lower_mappings_for_beta.size(); nu++) {
const ArrayList<short int> &nu_mapping =
const std::vector<short int> &nu_mapping =
multiindex_mapping[lower_mappings_for_beta[nu]];
// mu + nu and beta - nu
@@ -689,20 +657,20 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
for(index_t gamma = 0; gamma < total_num_coeffs3; gamma++) {
const ArrayList <short int> &gamma_mapping =
const std::vector<short int> &gamma_mapping =
multiindex_mapping[gamma];
const ArrayList <short int> &lower_mappings_for_gamma =
const std::vector<short int> &lower_mappings_for_gamma =
lower_mapping_index[gamma];
double gamma_derivative = ka_->ComputePartialDerivative
(derivative_map_gamma, gamma_mapping);
for(index_t eta = 0; eta < lower_mappings_for_gamma.size();
eta++){
eta++) {
// add up alpha, mu, eta and beta, gamma, nu, eta
int sign = 0;
const ArrayList<short int> &eta_mapping =
const std::vector<short int>& eta_mapping =
multiindex_mapping[lower_mappings_for_gamma[eta]];
for(index_t d = 0; d < dim; d++) {
@@ -766,19 +734,18 @@ double FarFieldExpansion<TKernelAux>::ConvolveField
}
template<typename TKernelAux>
void FarFieldExpansion<TKernelAux>::Init(const Vector& center,
void FarFieldExpansion<TKernelAux>::Init(const arma::vec& center,
const TKernelAux &ka) {
// copy kernel type, center, and bandwidth squared
kernel_ = &(ka.kernel_);
center_.Copy(center);
center_ = center;
order_ = -1;
sea_ = &(ka.sea_);
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
@@ -788,20 +755,18 @@ void FarFieldExpansion<TKernelAux>::Init(const TKernelAux &ka) {
kernel_ = &(ka.kernel_);
order_ = -1;
sea_ = &(ka.sea_);
center_.Init(sea_->get_dimension());
center_.SetZero();
center_.zeros(sea_->get_dimension());
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
template<typename TBound>
int FarFieldExpansion<TKernelAux>::OrderForConvolving
(const TBound &far_field_region, const Vector &far_field_region_centroid,
const TBound &local_field_region, const Vector &local_field_region_centroid,
(const TBound &far_field_region, const arma::vec& far_field_region_centroid,
const TBound &local_field_region, const arma::vec& local_field_region_centroid,
double min_dist_sqd_regions, double max_dist_sqd_regions, double max_error,
double *actual_error) const {
@@ -853,7 +818,7 @@ void FarFieldExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, "Far field expansion\n");
fprintf(stream, "Center: ");
for (index_t i = 0; i < center_.length(); i++) {
for (index_t i = 0; i < center_.n_elem; i++) {
fprintf(stream, "%g ", center_[i]);
}
fprintf(stream, "\n");
@@ -867,7 +832,7 @@ void FarFieldExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, ") = \\sum\\limits_{x_r \\in R} K(||x_q - x_r||) = ");
for (index_t i = 0; i < total_num_coeffs; i++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(i);
const std::vector<short int> &mapping = sea_->get_multiindex(i);
fprintf(stream, "%g ", coeffs_[i]);
fprintf(stream, "(-1)^(");
@@ -899,24 +864,20 @@ void FarFieldExpansion<TKernelAux>::TranslateFromFarField
int dim = sea_->get_dimension();
int order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(order);
Vector prev_coeffs;
Vector prev_center;
const ArrayList <short int> *multiindex_mapping =
const arma::vec& prev_coeffs = se.get_coeffs();
const arma::vec& prev_center = se.get_center();
const std::vector<std::vector<short int> >& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList <short int> *lower_mapping_index =
const std::vector<std::vector<short int> >& lower_mapping_index =
sea_->get_lower_mapping_index();
ArrayList <short int> tmp_storage;
Vector center_diff;
Vector inv_multiindex_factorials;
center_diff.Init(dim);
std::vector<short int> tmp_storage;
arma::vec center_diff(dim);
const arma::vec& inv_multiindex_factorials =
sea_->get_inv_multiindex_factorials();
// retrieve coefficients to be translated and helper mappings
prev_coeffs.Alias(se.get_coeffs());
prev_center.Alias(*(se.get_center()));
tmp_storage.Init(sea_->get_dimension());
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
tmp_storage.reserve(sea_->get_dimension());
// no coefficients can be translated
if(order == -1)
@@ -931,15 +892,15 @@ void FarFieldExpansion<TKernelAux>::TranslateFromFarField
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList <short int> &gamma_mapping = multiindex_mapping[j];
const ArrayList <short int> &lower_mappings_for_gamma =
const std::vector<short int>& gamma_mapping = multiindex_mapping[j];
const std::vector<short int>& lower_mappings_for_gamma =
lower_mapping_index[j];
double pos_coeff = 0;
double neg_coeff = 0;
for(index_t k = 0; k < lower_mappings_for_gamma.size(); k++) {
const ArrayList <short int> &inner_mapping =
const std::vector<short int>& inner_mapping =
multiindex_mapping[lower_mappings_for_gamma[k]];
int flag = 0;
@@ -987,22 +948,20 @@ template<typename TKernelAux>
void FarFieldExpansion<TKernelAux>::TranslateToLocal
(LocalExpansion<TKernelAux> &se, int truncation_order) {
Vector pos_arrtmp, neg_arrtmp;
Matrix derivative_map;
arma::vec pos_arrtmp, neg_arrtmp;
arma::mat derivative_map;
ka_->AllocateDerivativeMap(sea_->get_dimension(), 2 * truncation_order,
&derivative_map);
Vector local_center;
Vector cent_diff;
Vector local_coeffs;
derivative_map);
const arma::vec& local_center = se.get_center();
arma::vec cent_diff;
arma::vec& local_coeffs = se.get_coeffs();
int local_order = se.get_order();
int dimension = sea_->get_dimension();
int total_num_coeffs = sea_->get_total_num_coeffs(truncation_order);
double bandwidth_factor = ka_->BandwidthFactor(se.bandwidth_sq());
// get center and coefficients for local expansion
local_center.Alias(*(se.get_center()));
local_coeffs.Alias(se.get_coeffs());
cent_diff.Init(dimension);
cent_diff.set_size(dimension);
// if the order of the far field expansion is greater than the
// local one we are adding onto, then increase the order.
@@ -1011,8 +970,8 @@ void FarFieldExpansion<TKernelAux>::TranslateToLocal
}
// Compute derivatives.
pos_arrtmp.Init(total_num_coeffs);
neg_arrtmp.Init(total_num_coeffs);
pos_arrtmp.set_size(total_num_coeffs);
neg_arrtmp.set_size(total_num_coeffs);
// Compute center difference divided by the bandwidth factor.
for(index_t j = 0; j < dimension; j++) {
@@ -1020,19 +979,19 @@ void FarFieldExpansion<TKernelAux>::TranslateToLocal
}
// Compute required partial derivatives.
ka_->ComputeDirectionalDerivatives(cent_diff, &derivative_map,
ka_->ComputeDirectionalDerivatives(cent_diff, derivative_map,
2 * truncation_order);
ArrayList<short int> beta_plus_alpha;
beta_plus_alpha.Init(dimension);
std::vector<short int> beta_plus_alpha;
beta_plus_alpha.reserve(dimension);
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList<short int> &beta_mapping = sea_->get_multiindex(j);
const std::vector<short int>& beta_mapping = sea_->get_multiindex(j);
pos_arrtmp[j] = neg_arrtmp[j] = 0;
for(index_t k = 0; k < total_num_coeffs; k++) {
const ArrayList<short int> &alpha_mapping = sea_->get_multiindex(k);
const std::vector<short int>& alpha_mapping = sea_->get_multiindex(k);
for(index_t d = 0; d < dimension; d++) {
beta_plus_alpha[d] = beta_mapping[d] + alpha_mapping[d];
}
@@ -1050,7 +1009,7 @@ void FarFieldExpansion<TKernelAux>::TranslateToLocal
} // end of k-loop
} // end of j-loop
Vector C_k_neg = sea_->get_neg_inv_multiindex_factorials();
arma::vec C_k_neg = sea_->get_neg_inv_multiindex_factorials();
for(index_t j = 0; j < total_num_coeffs; j++) {
local_coeffs[j] += (pos_arrtmp[j] + neg_arrtmp[j]) * C_k_neg[j];
}
@@ -11,8 +11,8 @@ class InversePowDistGradientKernelAux {
private:
void SubFrom_(index_t dimension, int decrement,
const ArrayList<short int> &subtract_from,
ArrayList<short int> &result) const {
const std::vector<short int> &subtract_from,
std::vector<short int> &result) const {
for(index_t d = 0; d < subtract_from.size(); d++) {
if(d == dimension) {
@@ -30,8 +30,7 @@ class InversePowDistGradientKernelAux {
typedef SeriesExpansionAux TSeriesExpansionAux;
typedef FarFieldExpansion<InversePowDistGradientKernelAux> \
TFarFieldExpansion;
typedef FarFieldExpansion<InversePowDistGradientKernelAux> TFarFieldExpansion;
typedef LocalExpansion<InversePowDistGradientKernelAux> TLocalExpansion;
@@ -43,11 +42,6 @@ class InversePowDistGradientKernelAux {
*/
TSeriesExpansionAux sea_;
OT_DEF_BASIC(InversePowDistGradientKernelAux) {
OT_MY_OBJECT(kernel_);
OT_MY_OBJECT(sea_);
}
public:
void Init(double bandwidth, int max_order, int dim) {
@@ -56,40 +50,40 @@ class InversePowDistGradientKernelAux {
}
void AllocateDerivativeMap(int dim, int order,
Matrix *derivative_map) const {
derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
arma::mat& derivative_map) const {
derivative_map.set_size(sea_.get_total_num_coeffs(order), 1);
}
void ComputeDirectionalDerivatives(const Vector &x,
Matrix *derivative_map, int order) const {
void ComputeDirectionalDerivatives(const arma::vec &x,
arma::mat& derivative_map, int order) const {
derivative_map->SetZero();
derivative_map.zeros();
// Squared L2 norm of the vector.
double squared_l2_norm = la::Dot(x, x);
double squared_l2_norm = dot(x, x);
// Temporary variable to look for arithmetic operations on
// multiindex.
ArrayList<short int> tmp_multiindex;
tmp_multiindex.Init(sea_.get_dimension());
std::vector<short int> tmp_multiindex;
tmp_multiindex.reserve(sea_.get_dimension());
for(index_t i = 0; i < derivative_map->n_rows(); i++) {
for(index_t i = 0; i < derivative_map.n_rows; i++) {
// Contribution to the current multiindex position.
double contribution = 0;
// Retrieve the multiindex mapping.
const ArrayList<short int> &multiindex = sea_.get_multiindex(i);
const std::vector<short int>& multiindex = sea_.get_multiindex(i);
// $D_{x}^{0} \phi_{\nu, d}(x)$ should be computed normally.
if(i == 0) {
derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
derivative_map(0, 0) = kernel_.EvalUnnorm(x.memptr());
continue;
}
// Compute the contribution of $D_{x}^{n - e_d} \phi_{\nu,
// d}(x)$ component for each $d$.
for(index_t d = 0; d < x.length(); d++) {
for(index_t d = 0; d < x.n_elem; d++) {
// Subtract 1 from the given dimension.
SubFrom_(d, 1, multiindex, tmp_multiindex);
@@ -102,7 +96,7 @@ class InversePowDistGradientKernelAux {
factor += (kernel_.lambda_ - 2);
}
contribution += factor *
derivative_map->get(n_minus_e_d_position, 0);
derivative_map(n_minus_e_d_position, 0);
}
// Subtract 2 from the given dimension.
@@ -118,39 +112,39 @@ class InversePowDistGradientKernelAux {
}
contribution += factor *
derivative_map->get(n_minus_two_e_d_position, 0);
derivative_map(n_minus_two_e_d_position, 0);
}
} // end of iterating over each dimension.
// Set the final contribution for this multiindex.
derivative_map->set(i, 0, -contribution / squared_l2_norm);
derivative_map(i, 0) = -contribution / squared_l2_norm;
} // end of iterating over all required multiindex positions...
// Iterate again, and invert the sum if the sum of the indices of
// the current mapping is odd.
for(index_t i = 1; i < derivative_map->n_rows(); i++) {
for(index_t i = 1; i < derivative_map.n_rows; i++) {
// Retrieve the multiindex mapping.
const ArrayList<short int> &multiindex = sea_.get_multiindex(i);
const std::vector<short int>& multiindex = sea_.get_multiindex(i);
// The sum of the indices.
index_t sum_of_indices = 0;
for(index_t d = 0; d < x.length(); d++) {
for(index_t d = 0; d < x.n_elem; d++) {
sum_of_indices += multiindex[d];
}
if(sum_of_indices % 2 == 1) {
derivative_map->set(i, 0, -derivative_map->get(i, 0));
derivative_map(i, 0) *= -1;
}
}
}
double ComputePartialDerivative(const Matrix &derivative_map,
const ArrayList<short int> &mapping) const {
double ComputePartialDerivative(const arma::mat& derivative_map,
const std::vector<short int>& mapping) const {
return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
return derivative_map(sea_.ComputeMultiindexPosition(mapping), 0);
}
};
@@ -162,8 +156,8 @@ class InversePowDistKernelAux {
private:
void SubFrom_(index_t dimension, int decrement,
const ArrayList<short int> &subtract_from,
ArrayList<short int> &result) const {
const std::vector<short int>& subtract_from,
std::vector<short int>& result) const {
for(index_t d = 0; d < subtract_from.size(); d++) {
if(d == dimension) {
@@ -201,44 +195,44 @@ class InversePowDistKernelAux {
}
void AllocateDerivativeMap(int dim, int order,
Matrix *derivative_map) const {
derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
arma::mat& derivative_map) const {
derivative_map.set_size(sea_.get_total_num_coeffs(order), 1);
}
void ComputeDirectionalDerivatives(const Vector &x,
Matrix *derivative_map, int order) const {
void ComputeDirectionalDerivatives(const arma::vec& x,
arma::mat& derivative_map, int order) const {
derivative_map->SetZero();
derivative_map.zeros();
// Squared L2 norm of the vector.
double squared_l2_norm = la::Dot(x, x);
double squared_l2_norm = dot(x, x);
// Temporary variable to look for arithmetic operations on
// multiindex.
ArrayList<short int> tmp_multiindex;
tmp_multiindex.Init(sea_.get_dimension());
std::vector<short int> tmp_multiindex;
tmp_multiindex.reserve(sea_.get_dimension());
// Get the inverse multiindex factorial factors.
const Vector &inv_multiindex_factorials =
const arma::vec& inv_multiindex_factorials =
sea_.get_inv_multiindex_factorials();
for(index_t i = 0; i < derivative_map->n_rows(); i++) {
for(index_t i = 0; i < derivative_map.n_rows; i++) {
// Contribution to the current multiindex position.
double contribution = 0;
// Retrieve the multiindex mapping.
const ArrayList<short int> &multiindex = sea_.get_multiindex(i);
const std::vector<short int>& multiindex = sea_.get_multiindex(i);
// $D_{x}^{0} \phi_{\nu, d}(x)$ should be computed normally.
if(i == 0) {
derivative_map->set(0, 0, kernel_.EvalUnnorm(x.ptr()));
derivative_map(0, 0) = kernel_.EvalUnnorm(x.memptr());
continue;
}
// The sum of the indices.
index_t sum_of_indices = 0;
for(index_t d = 0; d < x.length(); d++) {
for(index_t d = 0; d < x.n_elem; d++) {
sum_of_indices += multiindex[d];
}
@@ -250,7 +244,7 @@ class InversePowDistKernelAux {
// Compute the contribution of $D_{x}^{n - e_d} \phi_{\nu,
// d}(x)$ component for each $d$.
for(index_t d = 0; d < x.length(); d++) {
for(index_t d = 0; d < x.n_elem; d++) {
// Subtract 1 from the given dimension.
SubFrom_(d, 1, multiindex, tmp_multiindex);
@@ -258,7 +252,7 @@ class InversePowDistKernelAux {
sea_.ComputeMultiindexPosition(tmp_multiindex);
if(n_minus_e_d_position >= 0) {
contribution += first_factor * x[d] *
derivative_map->get(n_minus_e_d_position, 0) *
derivative_map(n_minus_e_d_position, 0) *
inv_multiindex_factorials[n_minus_e_d_position];
}
@@ -268,7 +262,7 @@ class InversePowDistKernelAux {
sea_.ComputeMultiindexPosition(tmp_multiindex);
if(n_minus_two_e_d_position >= 0) {
contribution += second_factor *
derivative_map->get(n_minus_two_e_d_position, 0) *
derivative_map(n_minus_two_e_d_position, 0) *
inv_multiindex_factorials[n_minus_two_e_d_position];
}
@@ -276,38 +270,38 @@ class InversePowDistKernelAux {
// Set the final contribution for this multiindex.
if(squared_l2_norm == 0) {
derivative_map->set(i, 0, 0);
derivative_map(i, 0) = 0;
}
else {
derivative_map->set(i, 0, -contribution / squared_l2_norm /
sum_of_indices / inv_multiindex_factorials[i]);
derivative_map(i, 0) = -contribution / squared_l2_norm /
sum_of_indices / inv_multiindex_factorials[i];
}
} // end of iterating over all required multiindex positions...
// Iterate again, and invert the sum if the sum of the indices of
// the current mapping is odd.
for(index_t i = 1; i < derivative_map->n_rows(); i++) {
for(index_t i = 1; i < derivative_map.n_rows; i++) {
// Retrieve the multiindex mapping.
const ArrayList<short int> &multiindex = sea_.get_multiindex(i);
const std::vector<short int>& multiindex = sea_.get_multiindex(i);
// The sum of the indices.
index_t sum_of_indices = 0;
for(index_t d = 0; d < x.length(); d++) {
for(index_t d = 0; d < x.n_elem; d++) {
sum_of_indices += multiindex[d];
}
if(sum_of_indices % 2 == 1) {
derivative_map->set(i, 0, -derivative_map->get(i, 0));
derivative_map(i, 0) *= -1;
}
}
}
double ComputePartialDerivative(const Matrix &derivative_map,
const ArrayList<short int> &mapping) const {
double ComputePartialDerivative(const arma::mat& derivative_map,
const std::vector<short int>& mapping) const {
return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
return derivative_map(sea_.ComputeMultiindexPosition(mapping), 0);
}
};
@@ -43,11 +43,6 @@ class GaussianKernelMultAux {
/** pointer to the series expansion auxiliary object */
TSeriesExpansionAux sea_;
OT_DEF_BASIC(GaussianKernelMultAux) {
OT_MY_OBJECT(kernel_);
OT_MY_OBJECT(sea_);
}
public:
void Init(double bandwidth, int max_order, int dim) {
@@ -60,14 +55,14 @@ class GaussianKernelMultAux {
}
void AllocateDerivativeMap(int dim, int order,
Matrix *derivative_map) const {
derivative_map->Init(dim, order + 1);
arma::mat& derivative_map) const {
derivative_map.set_size(dim, order + 1);
}
void ComputeDirectionalDerivatives(const Vector &x,
Matrix *derivative_map, int order) const {
void ComputeDirectionalDerivatives(const arma::vec &x,
arma::mat& derivative_map, int order) const {
int dim = x.length();
int dim = x.n_elem;
// precompute necessary Hermite polynomials based on coordinate difference
for(index_t d = 0; d < dim; d++) {
@@ -76,30 +71,30 @@ class GaussianKernelMultAux {
double d2 = 2 * coord_div_band;
double facj = exp(-coord_div_band * coord_div_band);
derivative_map->set(d, 0, facj);
derivative_map(d, 0) = facj;
if(order > 0) {
derivative_map->set(d, 1, d2 * facj);
derivative_map(d, 1) = d2 * facj;
if(order > 1) {
for(index_t k = 1; k < order; k++) {
int k2 = k * 2;
derivative_map->set(d, k + 1, d2 * derivative_map->get(d, k) -
k2 * derivative_map->get(d, k - 1));
derivative_map(d, k + 1) = d2 * derivative_map(d, k) -
k2 * derivative_map(d, k - 1);
}
}
}
} // end of looping over each dimension
}
double ComputePartialDerivative(const Matrix &derivative_map,
const ArrayList<short int> &mapping) const {
double ComputePartialDerivative(const arma::mat& derivative_map,
const std::vector<short int>& mapping) const {
double partial_derivative = 1.0;
for(index_t d = 0; d < mapping.size(); d++) {
partial_derivative *= derivative_map.get(d, mapping[d]);
partial_derivative *= derivative_map(d, mapping[d]);
}
return partial_derivative;
}
@@ -299,11 +294,6 @@ class GaussianKernelAux {
/** pointer to the series expansion auxiliary object */
TSeriesExpansionAux sea_;
OT_DEF_BASIC(GaussianKernelAux) {
OT_MY_OBJECT(kernel_);
OT_MY_OBJECT(sea_);
}
public:
void Init(double bandwidth, int max_order, int dim) {
@@ -316,14 +306,14 @@ class GaussianKernelAux {
}
void AllocateDerivativeMap(int dim, int order,
Matrix *derivative_map) const {
derivative_map->Init(dim, order + 1);
arma::mat& derivative_map) const {
derivative_map.set_size(dim, order + 1);
}
void ComputeDirectionalDerivatives(const Vector &x,
Matrix *derivative_map, int order) const {
void ComputeDirectionalDerivatives(const arma::vec& x,
arma::mat& derivative_map, int order) const {
int dim = x.length();
int dim = x.n_elem;
// precompute necessary Hermite polynomials based on coordinate difference
for(index_t d = 0; d < dim; d++) {
@@ -332,48 +322,47 @@ class GaussianKernelAux {
double d2 = 2 * coord_div_band;
double facj = exp(-coord_div_band * coord_div_band);
derivative_map->set(d, 0, facj);
derivative_map(d, 0) = facj;
if(order > 0) {
derivative_map->set(d, 1, d2 * facj);
derivative_map(d, 1) = d2 * facj;
if(order > 1) {
for(index_t k = 1; k < order; k++) {
int k2 = k * 2;
derivative_map->set(d, k + 1, d2 * derivative_map->get(d, k) -
k2 * derivative_map->get(d, k - 1));
derivative_map(d, k + 1) = d2 * derivative_map(d, k) -
k2 * derivative_map(d, k - 1);
}
}
}
} // end of looping over each dimension
}
double ComputePartialDerivative(const Matrix &derivative_map,
const ArrayList<short int> &mapping) const {
double ComputePartialDerivative(const arma::mat& derivative_map,
const std::vector<short int>& mapping) const {
double partial_derivative = 1.0;
for(index_t d = 0; d < mapping.size(); d++) {
partial_derivative *= derivative_map.get(d, mapping[d]);
partial_derivative *= derivative_map(d, mapping[d]);
}
return partial_derivative;
}
template<typename TBound>
int OrderForConvolvingFarField(const TBound &far_field_region,
const Vector &far_field_region_centroid,
const arma::vec &far_field_region_centroid,
const TBound &local_field_region,
const Vector &local_field_region_centroid,
const arma::vec &local_field_region_centroid,
double min_dist_sqd_regions,
double max_dist_sqd_regions,
double max_error,
double *actual_error) const {
double squared_distance_between_two_centroids =
la::DistanceSqEuclidean(far_field_region_centroid.length(),
far_field_region_centroid.ptr(),
local_field_region_centroid.ptr());
la::DistanceSqEuclidean(far_field_region_centroid,
local_field_region_centroid);
double frontfactor =
exp(-squared_distance_between_two_centroids /
(4 * kernel_.bandwidth_sq()));
@@ -586,12 +575,6 @@ class EpanKernelAux {
InversePowDistKernelAux squared_component_;
OT_DEF_BASIC(EpanKernelAux) {
OT_MY_OBJECT(kernel_);
OT_MY_OBJECT(sea_);
OT_MY_OBJECT(squared_component_);
}
public:
void Init(double bandwidth, int max_order, int dim) {
@@ -607,26 +590,25 @@ class EpanKernelAux {
}
void AllocateDerivativeMap(int dim, int order,
Matrix *derivative_map) const {
derivative_map->Init(sea_.get_total_num_coeffs(order), 1);
arma::mat& derivative_map) const {
derivative_map.set_size(sea_.get_total_num_coeffs(order), 1);
}
void ComputeDirectionalDerivatives(const Vector &x,
Matrix *derivative_map, int order) const {
void ComputeDirectionalDerivatives(const arma::vec& x,
arma::mat& derivative_map, int order) const {
// Compute the derivatives for $||x||^2$ and negate it. Then, add
// $(1, 0, 0, ... 0)$ to it.
squared_component_.ComputeDirectionalDerivatives(x, derivative_map, order);
la::Scale(derivative_map->n_rows(), -1, derivative_map->GetColumnPtr(0));
(derivative_map->GetColumnPtr(0))[0] += 1.0;
derivative_map.unsafe_col(0) *= -1;
derivative_map(0, 0) += 1.0;
}
double ComputePartialDerivative(const Matrix &derivative_map,
const ArrayList<short int> &mapping) const {
double ComputePartialDerivative(const arma::mat& derivative_map,
const std::vector<short int>& mapping) const {
return derivative_map.get(sea_.ComputeMultiindexPosition(mapping), 0);
return derivative_map(sea_.ComputeMultiindexPosition(mapping), 0);
}
template<typename TBound>
@@ -12,7 +12,7 @@
#ifndef LOCAL_EXPANSION
#define LOCAL_EXPANSION
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include "kernel_aux.h"
#include "series_expansion_aux.h"
@@ -28,10 +28,10 @@ class LocalExpansion {
private:
/** The center of the expansion */
Vector center_;
arma::vec center_;
/** The coefficients */
Vector coeffs_;
arma::vec coeffs_;
/** order */
int order_;
@@ -45,12 +45,6 @@ class LocalExpansion {
/** pointer to the precomputed constants inside kernel auxiliary object */
const typename TKernelAux::TSeriesExpansionAux *sea_;
OT_DEF(LocalExpansion) {
OT_MY_OBJECT(center_);
OT_MY_OBJECT(coeffs_);
OT_MY_OBJECT(order_);
}
public:
// getters and setters
@@ -59,12 +53,12 @@ class LocalExpansion {
double bandwidth_sq() const { return kernel_->bandwidth_sq(); }
/** Get the center of expansion */
Vector* get_center() { return &center_; }
const Vector* get_center() const { return &center_; }
arma::vec& get_center() { return center_; }
const arma::vec& get_center() const { return center_; }
/** Get the coefficients */
const Vector& get_coeffs() const { return coeffs_; }
arma::vec& get_coeffs() { return coeffs_; }
const arma::vec& get_coeffs() const { return coeffs_; }
/** Get the approximation order */
int get_order() const { return order_; }
@@ -81,26 +75,26 @@ class LocalExpansion {
* Accumulates the local moment represented by the given reference
* data into the coefficients
*/
void AccumulateCoeffs(const Matrix& data, const Vector& weights,
void AccumulateCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/**
* This does not apply for local coefficients.
*/
void RefineCoeffs(const Matrix& data, const Vector& weights,
void RefineCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order) { }
/**
* Evaluates the local coefficients at the given point
*/
double EvaluateField(const Matrix& data, int row_num) const;
double EvaluateField(const arma::mat& data, int row_num) const;
double EvaluateField(const double *x_q) const;
/**
* Initializes the current local expansion object with the given
* center.
*/
void Init(const Vector& center, const TKernelAux &ka);
void Init(const arma::vec& center, const TKernelAux &ka);
void Init(const TKernelAux &ka);
/**
@@ -7,32 +7,27 @@
template<typename TKernelAux>
void LocalExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
const Vector& weights,
void LocalExpansion<TKernelAux>::AccumulateCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
if(order > order_) {
if(order > order_)
order_ = order;
}
int dim = sea_->get_dimension();
int total_num_coeffs = sea_->get_total_num_coeffs(order);
// get inverse factorials (precomputed)
Vector neg_inv_multiindex_factorials;
neg_inv_multiindex_factorials.Alias
(sea_->get_neg_inv_multiindex_factorials());
// TODO: this is supposed to be an alias (just get it compiling for now)
arma::vec neg_inv_multiindex_factorials = sea_->get_neg_inv_multiindex_factorials();
// declare deritave mapping
Matrix derivative_map;
ka_->AllocateDerivativeMap(dim, order, &derivative_map);
arma::mat derivative_map;
ka_->AllocateDerivativeMap(dim, order, derivative_map);
// some temporary variables
Vector arrtmp;
arrtmp.Init(total_num_coeffs);
Vector x_r_minus_x_Q;
x_r_minus_x_Q.Init(dim);
arma::vec arrtmp(total_num_coeffs), x_r_minus_x_Q(dim);
// The bandwidth factor to be divided along each dimension.
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
@@ -42,22 +37,22 @@ void LocalExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
// calculate x_r - x_Q
for(index_t d = 0; d < dim; d++) {
x_r_minus_x_Q[d] = (center_[d] - data.get(d, r)) /
x_r_minus_x_Q[d] = (center_[d] - data(d, r)) /
bandwidth_factor;
}
// precompute necessary partial derivatives based on coordinate difference
ka_->ComputeDirectionalDerivatives(x_r_minus_x_Q, &derivative_map, order);
ka_->ComputeDirectionalDerivatives(x_r_minus_x_Q, derivative_map, order);
// compute h_{beta}((x_r - x_Q) / sqrt(2h^2))
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(j);
const std::vector<short int>& mapping = sea_->get_multiindex(j);
arrtmp[j] = ka_->ComputePartialDerivative(derivative_map, mapping);
}
for(index_t j = 0; j < total_num_coeffs; j++) {
coeffs_[j] += neg_inv_multiindex_factorials[j] * weights[r] *
arrtmp[j];
arrtmp[j];
}
} // End of looping through each reference point.
}
@@ -73,7 +68,7 @@ void LocalExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, "Local expansion\n");
fprintf(stream, "Center: ");
for (index_t i = 0; i < center_.length(); i++) {
for (index_t i = 0; i < center_.n_elem; i++) {
fprintf(stream, "%g ", center_[i]);
}
fprintf(stream, "\n");
@@ -87,7 +82,7 @@ void LocalExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, ") = \\sum\\limits_{x_r \\in R} K(||x_q - x_r||) = ");
for (index_t i = 0; i < total_num_coeffs; i++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(i);
const std::vector<short int>& mapping = sea_->get_multiindex(i);
fprintf(stream, "%g", coeffs_[i]);
for(index_t d = 0; d < dim; d++) {
@@ -102,18 +97,17 @@ void LocalExpansion<TKernelAux>::PrintDebug(const char *name,
}
template<typename TKernelAux>
double LocalExpansion<TKernelAux>::EvaluateField(const Matrix& data,
double LocalExpansion<TKernelAux>::EvaluateField(const arma::mat& data,
int row_num) const {
return EvaluateField(data.GetColumnPtr(row_num));
return EvaluateField(data.colptr(row_num));
}
template<typename TKernelAux>
double LocalExpansion<TKernelAux>::EvaluateField(const double *x_q) const {
// if there are no local expansion here, then return 0
if(order_ < 0) {
if(order_ < 0)
return 0;
}
index_t k, t, tail;
@@ -130,12 +124,9 @@ double LocalExpansion<TKernelAux>::EvaluateField(const double *x_q) const {
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// temporary variable
Vector x_Q_to_x_q;
x_Q_to_x_q.Init(dim);
Vector tmp;
tmp.Init(total_num_coeffs);
ArrayList<short int> heads;
heads.Init(dim + 1);
arma::vec x_Q_to_x_q(dim), tmp(total_num_coeffs);
std::vector<short int> heads;
heads.reserve(dim + 1);
// compute (x_q - x_Q) / (sqrt(2h^2))
for(index_t i = 0; i < dim; i++) {
@@ -169,19 +160,18 @@ double LocalExpansion<TKernelAux>::EvaluateField(const double *x_q) const {
}
template<typename TKernelAux>
void LocalExpansion<TKernelAux>::Init(const Vector& center,
void LocalExpansion<TKernelAux>::Init(const arma::vec& center,
const TKernelAux &ka) {
// copy kernel type, center, and bandwidth squared
kernel_ = &(ka.kernel_);
center_.Copy(center);
center_ = center;
order_ = -1;
sea_ = &(ka.sea_);
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
@@ -191,12 +181,11 @@ void LocalExpansion<TKernelAux>::Init(const TKernelAux &ka) {
kernel_ = &(ka.kernel_);
order_ = -1;
sea_ = &(ka.sea_);
center_.Init(sea_->get_dimension());
center_.set_size(sea_->get_dimension());
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
@@ -216,13 +205,12 @@ template<typename TKernelAux>
void LocalExpansion<TKernelAux>::TranslateFromFarField
(const FarFieldExpansion<TKernelAux> &se) {
Vector pos_arrtmp, neg_arrtmp;
Matrix derivative_map;
Vector far_center;
Vector cent_diff;
Vector far_coeffs;
arma::vec pos_arrtmp, neg_arrtmp;
arma::mat derivative_map;
arma::vec cent_diff;
int dimension = sea_->get_dimension();
ka_->AllocateDerivativeMap(dimension, 2 * order_, &derivative_map);
ka_->AllocateDerivativeMap(dimension, 2 * order_, derivative_map);
int far_order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(far_order);
@@ -230,9 +218,9 @@ void LocalExpansion<TKernelAux>::TranslateFromFarField
double bandwidth_factor = ka_->BandwidthFactor(se.bandwidth_sq());
// get center and coefficients for far field expansion
far_center.Alias(*(se.get_center()));
far_coeffs.Alias(se.get_coeffs());
cent_diff.Init(dimension);
arma::vec& far_center = se.get_center();
arma::vec& far_coeffs = se.get_coeffs();
cent_diff.set_size(dimension);
// if the order of the far field expansion is greater than the
// local one we are adding onto, then increase the order.
@@ -241,8 +229,8 @@ void LocalExpansion<TKernelAux>::TranslateFromFarField
}
// compute Gaussian derivative
pos_arrtmp.Init(total_num_coeffs);
neg_arrtmp.Init(total_num_coeffs);
pos_arrtmp.set_size(total_num_coeffs);
neg_arrtmp.set_size(total_num_coeffs);
// compute center difference divided by bw_times_sqrt_two;
for(index_t j = 0; j < dimension; j++) {
@@ -250,18 +238,18 @@ void LocalExpansion<TKernelAux>::TranslateFromFarField
}
// compute required partial derivatives
ka_->ComputeDirectionalDerivatives(cent_diff, &derivative_map, 2 * order_);
ArrayList<short int> beta_plus_alpha;
beta_plus_alpha.Init(dimension);
ka_->ComputeDirectionalDerivatives(cent_diff, derivative_map, 2 * order_);
std::vector<short int> beta_plus_alpha;
beta_plus_alpha.reserve(dimension);
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList<short int> &beta_mapping = sea_->get_multiindex(j);
const std::vector<short int>& beta_mapping = sea_->get_multiindex(j);
pos_arrtmp[j] = neg_arrtmp[j] = 0;
for(index_t k = 0; k < total_num_coeffs; k++) {
const ArrayList<short int> &alpha_mapping = sea_->get_multiindex(k);
const std::vector<short int>& alpha_mapping = sea_->get_multiindex(k);
for(index_t d = 0; d < dimension; d++) {
beta_plus_alpha[d] = beta_mapping[d] + alpha_mapping[d];
}
@@ -270,16 +258,14 @@ void LocalExpansion<TKernelAux>::TranslateFromFarField
double prod = far_coeffs[k] * derivative_factor;
if(prod > 0) {
if(prod > 0)
pos_arrtmp[j] += prod;
}
else {
else
neg_arrtmp[j] += prod;
}
} // end of k-loop
} // end of j-loop
Vector C_k_neg = sea_->get_neg_inv_multiindex_factorials();
arma::vec& C_k_neg = sea_->get_neg_inv_multiindex_factorials();
for(index_t j = 0; j < total_num_coeffs; j++) {
coeffs_[j] += (pos_arrtmp[j] + neg_arrtmp[j]) * C_k_neg[j];
}
@@ -296,28 +282,25 @@ void LocalExpansion<TKernelAux>::TranslateToLocal(LocalExpansion &se) {
// get the center and the order and the total number of coefficients of
// the expansion we are translating from. Also get coefficients we
// are translating
Vector new_center;
new_center.Alias(*(se.get_center()));
const arma::vec& new_center = se.get_center();
int prev_order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(order_);
const ArrayList<short int> *upper_mapping_index =
const std::vector<std::vector<short int> >& upper_mapping_index =
sea_->get_upper_mapping_index();
Vector new_coeffs;
new_coeffs.Alias(se.get_coeffs());
arma::vec& new_coeffs = se.get_coeffs();
// dimension
int dim = sea_->get_dimension();
// temporary variable
ArrayList<short int> tmp_storage;
tmp_storage.Init(dim);
std::vector<short int> tmp_storage;
tmp_storage.reserve(dim);
// sqrt two times bandwidth
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// center difference between the old center and the new one
Vector center_diff;
center_diff.Init(dim);
arma::vec center_diff(dim);
for(index_t d = 0; d < dim; d++) {
center_diff[d] = (new_center[d] - center_[d]) / bandwidth_factor;
}
@@ -329,25 +312,24 @@ void LocalExpansion<TKernelAux>::TranslateToLocal(LocalExpansion &se) {
}
// inverse multiindex factorials
Vector C_k;
C_k.Alias(sea_->get_inv_multiindex_factorials());
const arma::vec& C_k = sea_->get_inv_multiindex_factorials();
// do the actual translation
for(index_t j = 0; j < total_num_coeffs; j++) {
const ArrayList<short int> &alpha_mapping = sea_->get_multiindex(j);
const ArrayList<short int> &upper_mappings_for_alpha =
upper_mapping_index[j];
const std::vector<short int>& alpha_mapping = sea_->get_multiindex(j);
const std::vector<short int>& upper_mappings_for_alpha =
upper_mapping_index[j];
double pos_coeffs = 0;
double neg_coeffs = 0;
for(index_t k = 0; k < upper_mappings_for_alpha.size(); k++) {
if(upper_mappings_for_alpha[k] >= total_num_coeffs) {
break;
}
const ArrayList<short int> &beta_mapping =
const std::vector<short int>& beta_mapping =
sea_->get_multiindex(upper_mappings_for_alpha[k]);
int flag = 0;
double diff1 = 1.0;
@@ -385,4 +367,3 @@ void LocalExpansion<TKernelAux>::TranslateToLocal(LocalExpansion &se) {
}
#endif
@@ -12,8 +12,7 @@
#ifndef MULT_FARFIELD_EXPANSION
#define MULT_FARFIELD_EXPANSION
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include "kernel_aux.h"
#include "mult_series_expansion_aux.h"
@@ -29,10 +28,10 @@ class MultFarFieldExpansion {
private:
/** @brief The center of the expansion. */
Vector center_;
arma::vec center_;
/** @brief The coefficients. */
Vector coeffs_;
arma::vec coeffs_;
/** @brief The order of approximation. */
int order_;
@@ -46,12 +45,6 @@ class MultFarFieldExpansion {
/** pointer to the precomputed constants inside kernel auxiliary object */
const typename TKernelAux::TSeriesExpansionAux *sea_;
OT_DEF(MultFarFieldExpansion) {
OT_MY_OBJECT(center_);
OT_MY_OBJECT(coeffs_);
OT_MY_OBJECT(order_);
}
public:
// getters and setters
@@ -60,12 +53,13 @@ class MultFarFieldExpansion {
double bandwidth_sq() const { return kernel_->bandwidth_sq(); }
/** Get the center of expansion */
Vector *get_center() { return &center_; }
arma::vec& get_center() { return center_; }
const Vector *get_center() const { return &center_; }
const arma::vec& get_center() const { return center_; }
/** Get the coefficients */
const Vector& get_coeffs() const { return coeffs_; }
arma::vec& get_coeffs() { return coeffs_; }
const arma::vec& get_coeffs() const { return coeffs_; }
/** Get the approximation order */
int get_order() const { return order_; }
@@ -84,9 +78,9 @@ class MultFarFieldExpansion {
* Set the center of the expansion - assumes that the center has been
* initialized before...
*/
void set_center(const Vector &center) {
void set_center(const arma::vec& center) {
for(index_t i = 0; i < center.length(); i++) {
for(index_t i = 0; i < center.n_elem; i++) {
center_[i] = center[i];
}
}
@@ -97,56 +91,56 @@ class MultFarFieldExpansion {
* Accumulates the far field moment represented by the given reference
* data into the coefficients
*/
void AccumulateCoeffs(const Matrix& data, const Vector& weights,
void AccumulateCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/**
* Refine the far field moment that has been computed before up to
* a new order.
*/
void RefineCoeffs(const Matrix& data, const Vector& weights,
void RefineCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/**
* Evaluates the far-field coefficients at the given point
*/
double EvaluateField(const Matrix& data, int row_num, int order) const;
double EvaluateField(const arma::mat& data, int row_num, int order) const;
double EvaluateField(const double *x_q, int order) const;
/**
* Evaluates the two-way convolution mixed with exhaustive computations
* with two other far field expansions
*/
double MixField(const Matrix &data, int node1_begin, int node1_end,
double MixField(const arma::mat& data, int node1_begin, int node1_end,
int node2_begin, int node2_end,
const MultFarFieldExpansion &fe2,
const MultFarFieldExpansion &fe3,
const MultFarFieldExpansion& fe2,
const MultFarFieldExpansion& fe3,
int order2, int order3) const;
double ConvolveField(const MultFarFieldExpansion &fe, int order) const;
double ConvolveField(const MultFarFieldExpansion& fe, int order) const;
/**
* Evaluates the three-way convolution with two other far field
* expansions
*/
double ConvolveField(const MultFarFieldExpansion &fe2,
const MultFarFieldExpansion &fe3,
double ConvolveField(const MultFarFieldExpansion& fe2,
const MultFarFieldExpansion& fe3,
int order1, int order2, int order3) const;
/**
* Initializes the current far field expansion object with the given
* center.
*/
void Init(const Vector& center, const TKernelAux &ka);
void Init(const TKernelAux &ka);
void Init(const arma::vec& center, const TKernelAux& ka);
void Init(const TKernelAux& ka);
/** @brief Computes the required order for evaluating the far field
* expansion for any query point within the specified region
* for a given bound.
*/
template<typename TBound>
int OrderForEvaluating(const TBound &far_field_region,
const TBound &local_field_region,
int OrderForEvaluating(const TBound& far_field_region,
const TBound& local_field_region,
double min_dist_sqd_regions,
double max_dist_sqd_regions,
double max_error, double *actual_error) const;
@@ -161,8 +155,8 @@ class MultFarFieldExpansion {
* -1 if approximation up to the maximum order is not possible
*/
template<typename TBound>
int OrderForConvertingToLocal(const TBound &far_field_region,
const TBound &local_field_region,
int OrderForConvertingToLocal(const TBound& far_field_region,
const TBound& local_field_region,
double min_dist_sqd_regions,
double max_dist_sqd_regions,
double required_bound,
@@ -177,13 +171,13 @@ class MultFarFieldExpansion {
* here. The translated coefficients are added up to the
* ones here.
*/
void TranslateFromFarField(const MultFarFieldExpansion &se);
void TranslateFromFarField(const MultFarFieldExpansion& se);
/**
* Translate to the given local expansion. The translated coefficients
* are added up to the passed-in local expansion coefficients.
*/
void TranslateToLocal(MultLocalExpansion<TKernelAux> &se,
void TranslateToLocal(MultLocalExpansion<TKernelAux>& se,
int truncation_order);
};
@@ -6,26 +6,24 @@
#define MULT_FARFIELD_EXPANSION_IMPL_H
template<typename TKernelAux>
void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
const Vector& weights,
void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
int dim = data.n_rows();
int dim = data.n_rows;
int total_num_coeffs = sea_->get_total_num_coeffs(order);
int max_total_num_coeffs = sea_->get_max_total_num_coeffs();
Vector x_r, tmp;
arma::vec x_r, tmp;
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// initialize temporary variables
x_r.Init(dim);
tmp.Init(max_total_num_coeffs);
Vector pos_coeffs;
Vector neg_coeffs;
pos_coeffs.Init(max_total_num_coeffs);
pos_coeffs.SetZero();
neg_coeffs.Init(max_total_num_coeffs);
neg_coeffs.SetZero();
x_r.set_size(dim);
tmp.set_size(max_total_num_coeffs);
arma::vec pos_coeffs;
arma::vec neg_coeffs;
pos_coeffs.zeros(max_total_num_coeffs);
neg_coeffs.zeros(max_total_num_coeffs);
// set to new order if greater
if(order_ < order) {
@@ -33,7 +31,7 @@ void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
}
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int>& traversal_order =
sea_->traversal_mapping_[order_];
// Repeat for each reference point in this reference node.
@@ -42,16 +40,16 @@ void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
// Calculate the coordinate difference between the ref point and the
// centroid.
for(index_t i = 0; i < dim; i++) {
x_r[i] = (data.get(i, r) - center_[i]) / bandwidth_factor;
x_r[i] = (data(i, r) - center_[i]) / bandwidth_factor;
}
tmp.SetZero();
tmp.zeros();
tmp[0] = 1.0;
for(index_t i = 1; i < total_num_coeffs; i++) {
int index = traversal_order[i];
const ArrayList<short int> &lower_mappings =
const std::vector<short int>& lower_mappings =
sea_->lower_mapping_index_[index];
// from the direct descendant, recursively compute the multipole moments
@@ -59,8 +57,8 @@ void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
lower_mappings[lower_mappings.size() - 2];
int position = 0;
const ArrayList<short int> &mapping = sea_->multiindex_mapping_[index];
const ArrayList<short int> &direct_ancestor_mapping =
const std::vector<short int>& mapping = sea_->multiindex_mapping_[index];
const std::vector<short int>& direct_ancestor_mapping =
sea_->multiindex_mapping_[direct_ancestor_mapping_pos];
for(index_t i = 0; i < dim; i++) {
if(mapping[i] != direct_ancestor_mapping[i]) {
@@ -97,20 +95,19 @@ void MultFarFieldExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
template<typename TKernelAux>
double MultFarFieldExpansion<TKernelAux>::ConvolveField
(const MultFarFieldExpansion &fe, int order) const {
(const MultFarFieldExpansion& fe, int order) const {
// The bandwidth factor and the multiindex mapping stuffs.
double bandwidth_factor = ka_->BandwidthFactor(bandwidth_sq());
const ArrayList<short int> *multiindex_mapping =
const std::vector<short int>& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList<short int> *lower_mapping_index =
const std::vector<short int>& lower_mapping_index =
sea_->get_lower_mapping_index();
// Get the total number of coefficients and the coefficient themselves.
int total_num_coeffs = sea_->get_total_num_coeffs(order);
int dim = sea_->get_dimension();
Vector coeffs2;
coeffs2.Alias(fe.get_coeffs());
arma::vec& coeffs2 = fe.get_coeffs();
// Actual accumulated sum.
double neg_sum = 0;
@@ -118,41 +115,38 @@ double MultFarFieldExpansion<TKernelAux>::ConvolveField
double sum = 0;
// The partial derivatives table.
Matrix derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order, &derivative_map_alpha);
arma::mat derivative_map_alpha;
ka_->AllocateDerivativeMap(dim, order, derivative_map_alpha);
// Compute the center difference and its table of partial
// derivatives.
Vector xI_xJ;
xI_xJ.Init(dim);
Vector xJ_center;
xJ_center.Alias(*(fe.get_center()));
arma::vec xI_xJ(dim);
arma::vec& xJ_center = fe.get_center();
for(index_t d = 0; d < dim; d++) {
xI_xJ[d] = (center_[d] - xJ_center[d]) / bandwidth_factor;
}
ka_->ComputeDirectionalDerivatives(xI_xJ, &derivative_map_alpha, order);
ka_->ComputeDirectionalDerivatives(xI_xJ, derivative_map_alpha, order);
// The inverse factorials.
Vector inv_multiindex_factorials;
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
arma::vec& inv_multiindex_factorials = sea_->get_inv_multiindex_factorials();
// The temporary space for computing the difference of two mappings.
ArrayList<short int> alpha_minus_beta_mapping;
alpha_minus_beta_mapping.Init(dim);
std::vector<short int> alpha_minus_beta_mapping;
alpha_minus_beta_mapping.reserve(dim);
// The main loop.
for(index_t alpha = 0; alpha < total_num_coeffs; alpha++) {
const ArrayList<short int> &alpha_mapping = multiindex_mapping[alpha];
const ArrayList<short int> &lower_mappings_for_alpha =
const std::vector<short int>& alpha_mapping = multiindex_mapping[alpha];
const std::vector<short int>& lower_mappings_for_alpha =
lower_mapping_index[alpha];
double alpha_derivative = ka_->ComputePartialDerivative
(derivative_map_alpha, alpha_mapping);
for(index_t beta = 0; beta < lower_mappings_for_alpha.size(); beta++) {
const ArrayList<short int> &beta_mapping =
const std::vector<short int>& beta_mapping =
multiindex_mapping[lower_mappings_for_alpha[beta]];
double n_choose_k_factor = sea_->get_n_multichoose_k_by_pos
@@ -192,8 +186,8 @@ double MultFarFieldExpansion<TKernelAux>::ConvolveField
}
template<typename TKernelAux>
void MultFarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
const Vector& weights,
void MultFarFieldExpansion<TKernelAux>::RefineCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
@@ -208,16 +202,17 @@ void MultFarFieldExpansion<TKernelAux>::RefineCoeffs(const Matrix& data,
else {
order_ = order;
coeffs_.SetZero();
coeffs_.zeros();
AccumulateCoeffs(data, weights, begin, end, order);
}
}
template<typename TKernelAux>
double MultFarFieldExpansion<TKernelAux>::EvaluateField(const Matrix& data,
double MultFarFieldExpansion<TKernelAux>::EvaluateField(const arma::mat& data,
int row_num,
int order) const {
return EvaluateField(data.GetColumnPtr(row_num), order);
// TODO: use of "row" is misleading and wrong
return EvaluateField(data.unsafe_col(row_num).memptr(), order);
}
template<typename TKernelAux>
@@ -239,16 +234,14 @@ double MultFarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
double multipole_sum = 0;
// computed derivative map
Matrix derivative_map;
ka_->AllocateDerivativeMap(dim, order_, &derivative_map);
arma::mat derivative_map;
ka_->AllocateDerivativeMap(dim, order_, derivative_map);
// temporary variable
Vector arrtmp;
arrtmp.Init(total_num_coeffs);
arma::vec arrtmp(total_num_coeffs);
// (x_q - x_R) scaled by bandwidth
Vector x_q_minus_x_R;
x_q_minus_x_R.Init(dim);
arma::vec x_q_minus_x_R(dim);
// compute (x_q - x_R) / (sqrt(2h^2))
for(index_t d = 0; d < dim; d++) {
@@ -256,17 +249,17 @@ double MultFarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
}
// compute deriative maps based on coordinate difference.
ka_->ComputeDirectionalDerivatives(x_q_minus_x_R, &derivative_map, order_);
ka_->ComputeDirectionalDerivatives(x_q_minus_x_R, derivative_map, order_);
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int>& traversal_order =
sea_->traversal_mapping_[order_];
// compute h_{\alpha}((x_q - x_R)/sqrt(2h^2)) ((x_r - x_R)/h)^{\alpha}
for(index_t j = 0; j < total_num_coeffs; j++) {
int index = traversal_order[j];
const ArrayList<short int> &mapping = sea_->get_multiindex(index);
const std::vector<short int>& mapping = sea_->get_multiindex(index);
double arrtmp = ka_->ComputePartialDerivative(derivative_map, mapping);
double prod = coeffs_[index] * arrtmp;
@@ -283,19 +276,18 @@ double MultFarFieldExpansion<TKernelAux>::EvaluateField(const double *x_q,
}
template<typename TKernelAux>
void MultFarFieldExpansion<TKernelAux>::Init(const Vector& center,
void MultFarFieldExpansion<TKernelAux>::Init(const arma::vec& center,
const TKernelAux &ka) {
// copy kernel type, center, and bandwidth squared
kernel_ = &(ka.kernel_);
center_.Copy(center);
center_ = center;
order_ = -1;
sea_ = &(ka.sea_);
ka_ = &ka;
// Initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
@@ -305,13 +297,11 @@ template<typename TKernelAux>
kernel_ = &(ka.kernel_);
order_ = -1;
sea_ = &(ka.sea_);
center_.Init(sea_->get_dimension());
center_.SetZero();
center_.zeros(sea_->get_dimension());
ka_ = &ka;
// Initialize coefficient array.
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
@@ -355,7 +345,7 @@ void MultFarFieldExpansion<TKernelAux>::PrintDebug
fprintf(stream, "Far field expansion\n");
fprintf(stream, "Center: ");
for (index_t i = 0; i < center_.length(); i++) {
for (index_t i = 0; i < center_.n_elem; i++) {
fprintf(stream, "%g ", center_[i]);
}
fprintf(stream, "\n");
@@ -369,7 +359,7 @@ void MultFarFieldExpansion<TKernelAux>::PrintDebug
fprintf(stream, ") = \\sum\\limits_{x_r \\in R} K(||x_q - x_r||) = ");
for (index_t i = 0; i < total_num_coeffs; i++) {
const ArrayList<short int> &mapping = sea_->get_multiindex(i);
const std::vector<short int>& mapping = sea_->get_multiindex(i);
fprintf(stream, "%g ", coeffs_[i]);
fprintf(stream, "(-1)^(");
@@ -401,24 +391,19 @@ void MultFarFieldExpansion<TKernelAux>::TranslateFromFarField
int dim = sea_->get_dimension();
int order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(order);
Vector prev_coeffs;
Vector prev_center;
const ArrayList<short int> *multiindex_mapping =
const std::vector<std::vector<short int> >& multiindex_mapping =
sea_->get_multiindex_mapping();
const ArrayList<short int> *lower_mapping_index =
const std::vector<std::vector<short int> >& lower_mapping_index =
sea_->get_lower_mapping_index();
ArrayList<short int> tmp_storage;
Vector center_diff;
Vector inv_multiindex_factorials;
center_diff.Init(dim);
std::vector<short int> tmp_storage;
arma::vec center_diff(dim);
// retrieve coefficients to be translated and helper mappings
prev_coeffs.Alias(se.get_coeffs());
prev_center.Alias(*(se.get_center()));
tmp_storage.Init(sea_->get_dimension());
inv_multiindex_factorials.Alias(sea_->get_inv_multiindex_factorials());
const arma::vec& prev_coeffs = se.get_coeffs();
const arma::vec& prev_center = se.get_center();
tmp_storage.reserve(sea_->get_dimension());
const arma::vec& inv_multiindex_factorials = sea_->get_inv_multiindex_factorials();
// no coefficients can be translated
if(order == -1) {
@@ -434,22 +419,21 @@ void MultFarFieldExpansion<TKernelAux>::TranslateFromFarField
}
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int>& traversal_order =
sea_->traversal_mapping_[order];
for(index_t j = 0; j < total_num_coeffs; j++) {
int index = traversal_order[j];
const ArrayList<short int> &gamma_mapping = multiindex_mapping[index];
const ArrayList<short int> &lower_mappings_for_gamma =
const std::vector<short int>& gamma_mapping = multiindex_mapping[index];
const std::vector<short int>& lower_mappings_for_gamma =
lower_mapping_index[index];
double pos_coeff = 0;
double neg_coeff = 0;
for(index_t k = 0; k < lower_mappings_for_gamma.size(); k++) {
const ArrayList<short int> &inner_mapping =
multiindex_mapping[lower_mappings_for_gamma[k]];
const std::vector<short int>& inner_mapping = multiindex_mapping[lower_mappings_for_gamma[k]];
int flag = 0;
double diff1;
@@ -496,22 +480,18 @@ template<typename TKernelAux>
void MultFarFieldExpansion<TKernelAux>::TranslateToLocal
(MultLocalExpansion<TKernelAux> &se, int truncation_order) {
Vector pos_arrtmp, neg_arrtmp;
Matrix derivative_map;
Vector local_center;
Vector cent_diff;
Vector local_coeffs;
int local_order = se.get_order();
arma::vec pos_arrtmp, neg_arrtmp;
arma::mat derivative_map;
// get center and coefficients for local expansion
const arma::vec& local_center = se.get_center();
int dimension = sea_->get_dimension();
arma::vec cent_diff(dimension);
arma::vec& local_coeffs = se.get_coeffs();
int local_order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(truncation_order);
double bandwidth_factor = ka_->BandwidthFactor(se.bandwidth_sq());
ka_->AllocateDerivativeMap(dimension, 2 * truncation_order, &derivative_map);
// get center and coefficients for local expansion
local_center.Alias(*(se.get_center()));
local_coeffs.Alias(se.get_coeffs());
cent_diff.Init(dimension);
ka_->AllocateDerivativeMap(dimension, 2 * truncation_order, derivative_map);
// if the order of the far field expansion is greater than the
// local one we are adding onto, then increase the order.
@@ -520,8 +500,8 @@ void MultFarFieldExpansion<TKernelAux>::TranslateToLocal
}
// compute Gaussian derivative
pos_arrtmp.Init(sea_->get_max_total_num_coeffs());
neg_arrtmp.Init(sea_->get_max_total_num_coeffs());
pos_arrtmp.set_size(sea_->get_max_total_num_coeffs());
neg_arrtmp.set_size(sea_->get_max_total_num_coeffs());
// compute center difference divided by bw_times_sqrt_two;
for(index_t j = 0; j < dimension; j++) {
@@ -529,26 +509,26 @@ void MultFarFieldExpansion<TKernelAux>::TranslateToLocal
}
// compute required partial derivatives
ka_->ComputeDirectionalDerivatives(cent_diff, &derivative_map,
ka_->ComputeDirectionalDerivatives(cent_diff, derivative_map,
2 * truncation_order);
ArrayList<short int> beta_plus_alpha;
beta_plus_alpha.Init(dimension);
std::vector<short int> beta_plus_alpha;
beta_plus_alpha.reserve(dimension);
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int> &traversal_order =
sea_->traversal_mapping_[truncation_order];
for(index_t j = 0; j < total_num_coeffs; j++) {
int index = traversal_order[j];
const ArrayList<short int> &beta_mapping = sea_->get_multiindex(index);
const std::vector<short int> &beta_mapping = sea_->get_multiindex(index);
pos_arrtmp[index] = neg_arrtmp[index] = 0;
for(index_t k = 0; k < total_num_coeffs; k++) {
int index_k = traversal_order[k];
const ArrayList<short int> &alpha_mapping =
const std::vector<short int> &alpha_mapping =
sea_->get_multiindex(index_k);
for(index_t d = 0; d < dimension; d++) {
beta_plus_alpha[d] = beta_mapping[d] + alpha_mapping[d];
@@ -567,7 +547,7 @@ void MultFarFieldExpansion<TKernelAux>::TranslateToLocal
} // end of k-loop
} // end of j-loop
Vector C_k_neg = sea_->get_neg_inv_multiindex_factorials();
arma::vec C_k_neg = sea_->get_neg_inv_multiindex_factorials();
for(index_t j = 0; j < total_num_coeffs; j++) {
int index = traversal_order[j];
local_coeffs[index] += (pos_arrtmp[index] + neg_arrtmp[index]) *
@@ -12,7 +12,8 @@
#ifndef MULT_LOCAL_EXPANSION
#define MULT_LOCAL_EXPANSION
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include "kernel_aux.h"
#include "mult_series_expansion_aux.h"
@@ -28,10 +29,10 @@ class MultLocalExpansion {
private:
/** The center of the expansion */
Vector center_;
arma::vec center_;
/** The coefficients */
Vector coeffs_;
arma::vec coeffs_;
/** order */
int order_;
@@ -45,12 +46,6 @@ class MultLocalExpansion {
/** pointer to the precomputed constants inside kernel auxiliary object */
const typename TKernelAux::TSeriesExpansionAux *sea_;
OT_DEF(MultLocalExpansion) {
OT_MY_OBJECT(center_);
OT_MY_OBJECT(coeffs_);
OT_MY_OBJECT(order_);
}
public:
// getters and setters
@@ -59,12 +54,12 @@ class MultLocalExpansion {
double bandwidth_sq() const { return kernel_->bandwidth_sq(); }
/** Get the center of expansion */
Vector* get_center() { return &center_; }
const Vector* get_center() const { return &center_; }
arma::vec& get_center() { return center_; }
const arma::vec& get_center() const { return center_; }
/** Get the coefficients */
const Vector& get_coeffs() const { return coeffs_; }
arma::vec& get_coeffs() { return coeffs_; }
const arma::vec& get_coeffs() const { return coeffs_; }
/** Get the approximation order */
int get_order() const { return order_; }
@@ -81,26 +76,26 @@ class MultLocalExpansion {
* Accumulates the local moment represented by the given reference
* data into the coefficients
*/
void AccumulateCoeffs(const Matrix& data, const Vector& weights,
void AccumulateCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order);
/**
* This does not apply for local coefficients.
*/
void RefineCoeffs(const Matrix& data, const Vector& weights,
void RefineCoeffs(const arma::mat& data, const arma::vec& weights,
int begin, int end, int order) { }
/**
* Evaluates the local coefficients at the given point
*/
double EvaluateField(const Matrix& data, int row_num) const;
double EvaluateField(const Vector& x_q) const;
double EvaluateField(const arma::mat& data, int row_num) const;
double EvaluateField(const arma::vec& x_q) const;
/**
* Initializes the current local expansion object with the given
* center.
*/
void Init(const Vector& center, const TKernelAux &sea);
void Init(const arma::vec& center, const TKernelAux &sea);
void Init(const TKernelAux &sea);
/**
@@ -6,8 +6,8 @@
#define MULT_LOCAL_EXPANSION_IMPL_H
template<typename TKernelAux>
void MultLocalExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
const Vector& weights,
void MultLocalExpansion<TKernelAux>::AccumulateCoeffs(const arma::mat& data,
const arma::vec& weights,
int begin, int end,
int order) {
@@ -19,23 +19,20 @@ void MultLocalExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
int total_num_coeffs = sea_->get_total_num_coeffs(order);
// get inverse factorials (precomputed)
Vector neg_inv_multiindex_factorials;
neg_inv_multiindex_factorials.Alias
(sea_->get_neg_inv_multiindex_factorials());
const arma::vec& neg_inv_multiindex_factorials = sea_->get_neg_inv_multiindex_factorials();
// declare deritave mapping
Matrix derivative_map;
ka_->AllocateDerivativeMap(dim, order, &derivative_map);
arma::mat derivative_map;
ka_->AllocateDerivativeMap(dim, order, derivative_map);
// some temporary variables
Vector x_r_minus_x_Q;
x_r_minus_x_Q.Init(dim);
arma::vec x_r_minus_x_Q(dim);
// sqrt two times bandwidth
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int> &traversal_order =
sea_->traversal_mapping_[order];
// for each data point,
@@ -43,17 +40,17 @@ void MultLocalExpansion<TKernelAux>::AccumulateCoeffs(const Matrix& data,
// calculate x_r - x_Q
for(index_t d = 0; d < dim; d++) {
x_r_minus_x_Q[d] = (center_[d] - data.get(d, r)) /
x_r_minus_x_Q[d] = (center_[d] - data(d, r)) /
bandwidth_factor;
}
// precompute necessary partial derivatives based on coordinate difference
ka_->ComputeDirectionalDerivatives(x_r_minus_x_Q, &derivative_map, order);
ka_->ComputeDirectionalDerivatives(x_r_minus_x_Q, derivative_map, order);
// compute h_{beta}((x_r - x_Q) / sqrt(2h^2))
for(index_t j = 0; j < total_num_coeffs; j++) {
int index = traversal_order[j];
const ArrayList<short int> &mapping = sea_->get_multiindex(index);
const std::vector<short int>& mapping = sea_->get_multiindex(index);
double partial_derivative =
ka_->ComputePartialDerivative(derivative_map, mapping);
coeffs_[index] += neg_inv_multiindex_factorials[index] * weights[r] *
@@ -74,7 +71,7 @@ void MultLocalExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, "Local expansion\n");
fprintf(stream, "Center: ");
for (index_t i = 0; i < center_.length(); i++) {
for (index_t i = 0; i < center_.n_elem; i++) {
fprintf(stream, "%g ", center_[i]);
}
fprintf(stream, "\n");
@@ -88,7 +85,7 @@ void MultLocalExpansion<TKernelAux>::PrintDebug(const char *name,
fprintf(stream, ") = \\sum\\limits_{x_r \\in R} K(||x_q - x_r||) = ");
for (index_t i = 0; i < total_num_coeffs; i++) {
ArrayList<short int> mapping = sea_->get_multiindex(i);
std::vector<short int> mapping = sea_->get_multiindex(i);
fprintf(stream, "%g", coeffs_[i]);
for(index_t d = 0; d < dim; d++) {
@@ -103,7 +100,7 @@ void MultLocalExpansion<TKernelAux>::PrintDebug(const char *name,
}
template<typename TKernelAux>
double MultLocalExpansion<TKernelAux>::EvaluateField(const Matrix& data,
double MultLocalExpansion<TKernelAux>::EvaluateField(const arma::mat& data,
int row_num) const {
// if there are no local coefficients, then return 0
@@ -124,16 +121,13 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Matrix& data,
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// temporary variable
Vector x_Q_to_x_q;
x_Q_to_x_q.Init(dim);
Vector tmp;
tmp.Init(sea_->get_max_total_num_coeffs());
ArrayList<short int> heads;
heads.Init(dim + 1);
arma::vec x_Q_to_x_q(dim);
arma::vec tmp(sea_->get_max_total_num_coeffs());
std::vector<short int> heads(dim + 1);
// compute (x_q - x_Q) / (sqrt(2h^2))
for(index_t i = 0; i < dim; i++) {
x_Q_to_x_q[i] = (data.get(i, row_num) - center_[i]) / bandwidth_factor;
x_Q_to_x_q[i] = (data(i, row_num) - center_[i]) / bandwidth_factor;
}
for(index_t i = 0; i < dim; i++)
@@ -143,21 +137,21 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Matrix& data,
tmp[0] = 1.0;
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int>& traversal_order =
sea_->traversal_mapping_[order_];
for(index_t i = 1; i < total_num_coeffs; i++) {
int index = traversal_order[i];
const ArrayList<short int> &lower_mappings =
const std::vector<short int> &lower_mappings =
sea_->lower_mapping_index_[index];
// from the direct descendant, recursively compute the multipole moments
int direct_ancestor_mapping_pos =
lower_mappings[lower_mappings.size() - 2];
int position = 0;
const ArrayList<short int> &mapping = sea_->multiindex_mapping_[index];
const ArrayList<short int> &direct_ancestor_mapping =
const std::vector<short int>& mapping = sea_->multiindex_mapping_[index];
const std::vector<short int>& direct_ancestor_mapping =
sea_->multiindex_mapping_[direct_ancestor_mapping_pos];
for(index_t i = 0; i < dim; i++) {
if(mapping[i] != direct_ancestor_mapping[i]) {
@@ -177,7 +171,7 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Matrix& data,
}
template<typename TKernelAux>
double MultLocalExpansion<TKernelAux>::EvaluateField(const Vector& x_q) const {
double MultLocalExpansion<TKernelAux>::EvaluateField(const arma::vec& x_q) const {
// if there are no local coefficients, then return 0
if(order_ < 0) {
@@ -197,12 +191,9 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Vector& x_q) const {
double bandwidth_factor = ka_->BandwidthFactor(kernel_.bandwidth_sq());
// temporary variable
Vector x_Q_to_x_q;
x_Q_to_x_q.Init(dim);
Vector tmp;
tmp.Init(sea_->get_max_total_num_coeffs());
ArrayList<short int> heads;
heads.Init(dim + 1);
arma::vec x_Q_to_x_q(dim);
arma::vec tmp(sea_->get_max_total_num_coeffs());
std::vector<short int> heads(dim + 1);
// compute (x_q - x_Q) / (sqrt(2h^2))
for(index_t i = 0; i < dim; i++) {
@@ -216,19 +207,19 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Vector& x_q) const {
tmp[0] = 1.0;
// get the order of traversal for the given order of approximation
ArrayList<short int> &traversal_order = sea_->traversal_mapping_[order_];
std::vector<short int>& traversal_order = sea_->traversal_mapping_[order_];
for(index_t i = 1; i < total_num_coeffs; i++) {
int index = traversal_order[i];
ArrayList<short int> &lower_mappings = sea_->lower_mapping_index_[index];
std::vector<short int> &lower_mappings = sea_->lower_mapping_index_[index];
// from the direct descendant, recursively compute the multipole moments
int direct_ancestor_mapping_pos =
lower_mappings[lower_mappings.size() - 2];
int position = 0;
const ArrayList<short int> &mapping = sea_->multiindex_mapping_[index];
const ArrayList<short int> &direct_ancestor_mapping =
const std::vector<short int> &mapping = sea_->multiindex_mapping_[index];
const std::vector<short int> &direct_ancestor_mapping =
sea_->multiindex_mapping_[direct_ancestor_mapping_pos];
for(index_t i = 0; i < dim; i++) {
if(mapping[i] != direct_ancestor_mapping[i]) {
@@ -248,19 +239,18 @@ double MultLocalExpansion<TKernelAux>::EvaluateField(const Vector& x_q) const {
}
template<typename TKernelAux>
void MultLocalExpansion<TKernelAux>::Init(const Vector& center,
void MultLocalExpansion<TKernelAux>::Init(const arma::vec& center,
const TKernelAux &ka) {
// copy kernel type, center, and bandwidth squared
kernel_ = &(ka.kernel_);
center_.Copy(center);
center_ = center;
order_ = -1;
sea_ = &(ka.sea_);
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
coeffs_.zeros(sea_->get_max_total_num_coeffs());
}
template<typename TKernelAux>
@@ -269,13 +259,10 @@ void MultLocalExpansion<TKernelAux>::Init(const TKernelAux &ka) {
// copy kernel type, center, and bandwidth squared
kernel_ = &(ka.kernel_);
sea_ = &(ka.sea_);
center_.Init(sea_->get_dimension());
// initialize coefficient array
center_.zeros(sea_->get_dimension());
order_ = -1;
ka_ = &ka;
// initialize coefficient array
coeffs_.Init(sea_->get_max_total_num_coeffs());
coeffs_.SetZero();
}
template<typename TKernelAux>
@@ -295,11 +282,11 @@ template<typename TKernelAux>
void MultLocalExpansion<TKernelAux>::TranslateFromFarField
(const MultFarFieldExpansion<TKernelAux> &se) {
Vector pos_arrtmp, neg_arrtmp;
Matrix derivative_map;
Vector far_center;
Vector cent_diff;
Vector far_coeffs;
arma::vec pos_arrtmp, neg_arrtmp;
arma::mat derivative_map;
arma::vec& far_center;
arma::vec cent_diff;
arma::vec& far_coeffs;
int dimension = sea_->get_dimension();
int far_order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(far_order);
@@ -309,9 +296,9 @@ void MultLocalExpansion<TKernelAux>::TranslateFromFarField
ka_->AllocateDerivativeMap(dimension, 2 * order_, &derivative_map);
// get center and coefficients for far field expansion
far_center.Alias(*(se.get_center()));
far_coeffs.Alias(se.get_coeffs());
cent_diff.Init(dimension);
far_center = se.get_center();
far_coeffs = se.get_coeffs();
cent_diff.set_size(dimension);
// if the order of the far field expansion is greater than the
// local one we are adding onto, then increase the order.
@@ -320,8 +307,8 @@ void MultLocalExpansion<TKernelAux>::TranslateFromFarField
}
// compute Gaussian derivative
pos_arrtmp.Init(total_num_coeffs);
neg_arrtmp.Init(total_num_coeffs);
pos_arrtmp.set_size(total_num_coeffs);
neg_arrtmp.set_size(total_num_coeffs);
// compute center difference divided by bw_times_sqrt_two;
for(index_t j = 0; j < dimension; j++) {
@@ -330,22 +317,22 @@ void MultLocalExpansion<TKernelAux>::TranslateFromFarField
// compute required partial derivatives
ka_->ComputeDirectionalDerivatives(cent_diff, &derivative_map, 2 * order_);
ArrayList<short int> beta_plus_alpha;
beta_plus_alpha.Init(dimension);
std::vector<short int> beta_plus_alpha;
beta_plus_alpha.reserve(dimension);
// get the order of traversal for the given order of approximation
ArrayList<short int> &traversal_order = sea_->traversal_mapping_[far_order];
std::vector<short int> &traversal_order = sea_->traversal_mapping_[far_order];
for(index_t j = 0; j < total_num_coeffs; j++) {
int index_j = traversal_order[j];
ArrayList<short int> beta_mapping = sea_->get_multiindex(index_j);
std::vector<short int> beta_mapping = sea_->get_multiindex(index_j);
pos_arrtmp[index_j] = neg_arrtmp[index_j] = 0;
for(index_t k = 0; k < total_num_coeffs; k++) {
int index_k = traversal_order[k];
ArrayList<short int> alpha_mapping = sea_->get_multiindex(index_k);
std::vector<short int> alpha_mapping = sea_->get_multiindex(index_k);
for(index_t d = 0; d < dimension; d++) {
beta_plus_alpha[d] = beta_mapping[d] + alpha_mapping[d];
}
@@ -363,7 +350,7 @@ void MultLocalExpansion<TKernelAux>::TranslateFromFarField
} // end of k-loop
} // end of j-loop
Vector C_k_neg = sea_->get_neg_inv_multiindex_factorials();
arma::vec C_k_neg = sea_->get_neg_inv_multiindex_factorials();
for(index_t j = 0; j < total_num_coeffs; j++) {
int index_j = traversal_order[j];
coeffs_[index_j] += (pos_arrtmp[index_j] + neg_arrtmp[index_j]) *
@@ -382,28 +369,25 @@ void MultLocalExpansion<TKernelAux>::TranslateToLocal(MultLocalExpansion &se) {
// get the center and the order and the total number of coefficients of
// the expansion we are translating from. Also get coefficients we
// are translating
Vector new_center;
new_center.Alias(*(se.get_center()));
arma::vec& new_center = se.get_center();
int prev_order = se.get_order();
int total_num_coeffs = sea_->get_total_num_coeffs(order_);
const ArrayList<short int> *upper_mapping_index =
const std::vector<std::vector<short int> >& upper_mapping_index =
sea_->get_upper_mapping_index();
Vector new_coeffs;
new_coeffs.Alias(se.get_coeffs());
arma::vec& new_coeffs = se.get_coeffs();
// dimension
int dim = sea_->get_dimension();
// temporary variable
ArrayList<short int> tmp_storage;
tmp_storage.Init(dim);
std::vector<short int> tmp_storage;
tmp_storage.reserve(dim);
// sqrt two times bandwidth
double bandwidth_factor = ka_->BandwidthFactor(kernel_->bandwidth_sq());
// center difference between the old center and the new one
Vector center_diff;
center_diff.Init(dim);
arma::vec center_diff(dim);
for(index_t d = 0; d < dim; d++) {
center_diff[d] = (new_center[d] - center_[d]) / bandwidth_factor;
}
@@ -415,19 +399,18 @@ void MultLocalExpansion<TKernelAux>::TranslateToLocal(MultLocalExpansion &se) {
}
// inverse multiindex factorials
Vector C_k;
C_k.Alias(sea_->get_inv_multiindex_factorials());
const arma::vec& C_k = sea_->get_inv_multiindex_factorials();
// get the order of traversal for the given order of approximation
const ArrayList<short int> &traversal_order =
const std::vector<short int> &traversal_order =
sea_->traversal_mapping_[order_];
// do the actual translation
for(index_t j = 0; j < total_num_coeffs; j++) {
int index_j = traversal_order[j];
const ArrayList<short int> &alpha_mapping = sea_->get_multiindex(index_j);
const ArrayList<short int> &upper_mappings_for_alpha =
const std::vector<short int> &alpha_mapping = sea_->get_multiindex(index_j);
const std::vector<short int> &upper_mappings_for_alpha =
upper_mapping_index[index_j];
double pos_coeffs = 0;
double neg_coeffs = 0;
@@ -438,7 +421,7 @@ void MultLocalExpansion<TKernelAux>::TranslateToLocal(MultLocalExpansion &se) {
break;
}
const ArrayList<short int> &beta_mapping =
const std::vector<short int> &beta_mapping =
sea_->get_multiindex(upper_mappings_for_alpha[k]);
int flag = 0;
double diff1 = 1.0;
@@ -4,7 +4,8 @@
#ifndef MULT_SERIES_EXPANSION_AUX_H
#define MULT_SERIES_EXPANSION_AUX_H
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include <armadillo>
/**
* Series expansion class for multiplicative kernel functions
@@ -18,63 +19,48 @@ class MultSeriesExpansionAux {
int max_order_;
Vector factorials_;
arma::vec factorials_;
ArrayList<int> list_total_num_coeffs_;
std::vector<int> list_total_num_coeffs_;
Vector inv_multiindex_factorials_;
arma::vec inv_multiindex_factorials_;
Vector neg_inv_multiindex_factorials_;
arma::vec neg_inv_multiindex_factorials_;
Matrix multiindex_combination_;
arma::mat multiindex_combination_;
ArrayList< ArrayList<short int> > multiindex_mapping_;
std::vector< std::vector<short int> > multiindex_mapping_;
/**
* for each i-th multiindex m_i, store the positions of the j-th
* multiindex mapping such that m_i - m_j >= 0 (the difference in
* all coordinates is nonnegative).
*/
ArrayList< ArrayList<short int> > lower_mapping_index_;
std::vector< std::vector<short int> > lower_mapping_index_;
/**
* for each i-th multiindex m_i, store the positions of the j-th
* multiindex mapping such that m_i - m_j <= 0 (the difference in
* all coordinates is nonpositive).
*/
ArrayList< ArrayList<short int> > upper_mapping_index_;
std::vector< std::vector<short int> > upper_mapping_index_;
/** row index is for n, column index is for k */
Matrix n_choose_k_;
arma::mat n_choose_k_;
/**
* For each i-th order, store the positions of the coefficient
* array to traverse.
*/
ArrayList< ArrayList<short int> > traversal_mapping_;
OT_DEF_BASIC(MultSeriesExpansionAux) {
OT_MY_OBJECT(dim_);
OT_MY_OBJECT(max_order_);
OT_MY_OBJECT(factorials_);
OT_MY_OBJECT(list_total_num_coeffs_);
OT_MY_OBJECT(inv_multiindex_factorials_);
OT_MY_OBJECT(neg_inv_multiindex_factorials_);
OT_MY_OBJECT(multiindex_combination_);
OT_MY_OBJECT(multiindex_mapping_);
OT_MY_OBJECT(lower_mapping_index_);
OT_MY_OBJECT(upper_mapping_index_);
OT_MY_OBJECT(n_choose_k_);
OT_MY_OBJECT(traversal_mapping_);
}
std::vector< std::vector<short int> > traversal_mapping_;
public:
void ComputeFactorials() {
factorials_.Init(2 * max_order_ + 1);
factorials_.set_size(2 * max_order_ + 1);
factorials_[0] = 1;
for(index_t t = 1; t < factorials_.length(); t++) {
for(index_t t = 1; t < factorials_.n_elem; t++) {
factorials_[t] = t * factorials_[t - 1];
}
}
@@ -83,15 +69,15 @@ class MultSeriesExpansionAux {
// initialize the index
int limit = 2 * max_order_;
traversal_mapping_.Init(limit + 1);
traversal_mapping_.reserve(limit + 1);
for(index_t i = 0; i <= max_order_; i++) {
traversal_mapping_[i].Init();
traversal_mapping_[i].clear();
for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
const ArrayList<short int> &mapping = multiindex_mapping_[j];
const std::vector<short int>& mapping = multiindex_mapping_[j];
int flag = 0;
for(index_t d = 0; d < dim_; d++) {
@@ -102,7 +88,7 @@ class MultSeriesExpansionAux {
}
if(flag == 0) {
(traversal_mapping_[i]).PushBackCopy(j);
(traversal_mapping_[i]).push_back(j);
}
} // end of j-loop
} // end of i-loop
@@ -110,19 +96,19 @@ class MultSeriesExpansionAux {
void ComputeLowerMappingIndex() {
ArrayList<short int> diff;
diff.Init(dim_);
std::vector<short int> diff;
diff.reserve(dim_);
// initialize the index
int limit = 2 * max_order_;
lower_mapping_index_.Init(list_total_num_coeffs_[limit]);
lower_mapping_index_.reserve(list_total_num_coeffs_[limit]);
for(index_t i = 0; i < list_total_num_coeffs_[limit]; i++) {
const ArrayList<short int> &outer_mapping = multiindex_mapping_[i];
lower_mapping_index_[i].Init();
const std::vector<short int>& outer_mapping = multiindex_mapping_[i];
lower_mapping_index_[i].clear();
for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
const ArrayList<short int> &inner_mapping = multiindex_mapping_[j];
const std::vector<short int>& inner_mapping = multiindex_mapping_[j];
int flag = 0;
for(index_t d = 0; d < dim_; d++) {
@@ -135,7 +121,7 @@ class MultSeriesExpansionAux {
}
if(flag == 0) {
(lower_mapping_index_[i]).PushBackCopy(j);
(lower_mapping_index_[i]).push_back(j);
}
} // end of j-loop
} // end of i-loop
@@ -144,28 +130,27 @@ class MultSeriesExpansionAux {
void ComputeMultiindexCombination() {
int limit = 2 * max_order_;
multiindex_combination_.Init(list_total_num_coeffs_[limit],
list_total_num_coeffs_[limit]);
multiindex_combination_.set_size(list_total_num_coeffs_[limit],
list_total_num_coeffs_[limit]);
for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
// beta mapping
const ArrayList<short int> &beta_mapping = multiindex_mapping_[j];
const std::vector<short int>& beta_mapping = multiindex_mapping_[j];
for(index_t k = 0; k < list_total_num_coeffs_[limit]; k++) {
// alpha mapping
const ArrayList<short int> &alpha_mapping = multiindex_mapping_[k];
const std::vector<short int>& alpha_mapping = multiindex_mapping_[k];
// initialize the factor to 1
multiindex_combination_.set(j, k, 1);
multiindex_combination_(j, k) = 1;
for(index_t i = 0; i < dim_; i++) {
multiindex_combination_.set
(j, k, multiindex_combination_.get(j, k) *
n_choose_k_.get(beta_mapping[i], alpha_mapping[i]));
multiindex_combination_(j, k) *=
n_choose_k_(beta_mapping[i], alpha_mapping[i]);
if(multiindex_combination_.get(j, k) == 0)
if(multiindex_combination_(j, k) == 0)
break;
}
}
@@ -174,19 +159,19 @@ class MultSeriesExpansionAux {
void ComputeUpperMappingIndex() {
ArrayList<short int> diff;
diff.Init(dim_);
std::vector<short int> diff;
diff.reserve(dim_);
// initialize the index
int limit = 2 * max_order_;
upper_mapping_index_.Init(list_total_num_coeffs_[limit]);
upper_mapping_index_.reserve(list_total_num_coeffs_[limit]);
for(index_t i = 0; i < list_total_num_coeffs_[limit]; i++) {
const ArrayList<short int> &outer_mapping = multiindex_mapping_[i];
upper_mapping_index_[i].Init();
const std::vector<short int>& outer_mapping = multiindex_mapping_[i];
upper_mapping_index_[i].clear();
for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
const ArrayList<short int> &inner_mapping = multiindex_mapping_[j];
const std::vector<short int>& inner_mapping = multiindex_mapping_[j];
int flag = 0;
for(index_t d = 0; d < dim_; d++) {
@@ -199,7 +184,7 @@ class MultSeriesExpansionAux {
}
if(flag == 0) {
(upper_mapping_index_[i]).PushBackCopy(j);
(upper_mapping_index_[i]).push_back(j);
}
} // end of j-loop
} // end of i-loop
@@ -218,40 +203,40 @@ class MultSeriesExpansionAux {
return list_total_num_coeffs_[max_order_];
}
const Vector& get_inv_multiindex_factorials() const {
const arma::vec& get_inv_multiindex_factorials() const {
return inv_multiindex_factorials_;
}
const ArrayList<short int> * get_lower_mapping_index() const {
return lower_mapping_index_.begin();
const std::vector<std::vector<short int> >& get_lower_mapping_index() const {
return lower_mapping_index_;
}
int get_max_order() const {
return max_order_;
}
const ArrayList<short int> & get_multiindex(int pos) const {
const std::vector<short int>& get_multiindex(int pos) const {
return multiindex_mapping_[pos];
}
const ArrayList<short int> * get_multiindex_mapping() const {
return multiindex_mapping_.begin();
const std::vector<std::vector<short int> >& get_multiindex_mapping() const {
return multiindex_mapping_;
}
const Vector& get_neg_inv_multiindex_factorials() const {
const arma::vec& get_neg_inv_multiindex_factorials() const {
return neg_inv_multiindex_factorials_;
}
double get_n_choose_k(int n, int k) const {
return n_choose_k_.get(n, (int) math::ClampNonNegative(k));
return n_choose_k_(n, (int) math::ClampNonNegative(k));
}
double get_n_multichoose_k_by_pos(int n, int k) const {
return multiindex_combination_.get(n, k);
return multiindex_combination_(n, k);
}
const ArrayList<short int> * get_upper_mapping_index() const {
return upper_mapping_index_.begin();
const std::vector<std::vector<short int> >& get_upper_mapping_index() const {
return upper_mapping_index_;
}
// interesting functions
@@ -259,7 +244,7 @@ class MultSeriesExpansionAux {
/**
* Computes the position of the given multiindex
*/
int ComputeMultiindexPosition(const ArrayList<short int> &multiindex) const {
int ComputeMultiindexPosition(const std::vector<short int>& multiindex) const {
int index = 0;
// using Horner's rule
@@ -304,7 +289,7 @@ class MultSeriesExpansionAux {
// compute the list of total number of coefficients for p-th order
// expansion
int limit = 2 * max_order_;
list_total_num_coeffs_.Init(limit + 1);
list_total_num_coeffs_.reserve(limit + 1);
list_total_num_coeffs_[0] = 1;
for(index_t p = 1; p <= limit; p++) {
list_total_num_coeffs_[p] = (int) pow(p + 1, dim);
@@ -316,15 +301,14 @@ class MultSeriesExpansionAux {
// allocate space for inverse factorial and
// negative inverse factorials and multiindex mapping and n_choose_k
// and multiindex_combination precomputed factors
inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit]);
neg_inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit]);
multiindex_mapping_.Init(list_total_num_coeffs_[limit]);
(multiindex_mapping_[0]).Init(dim_);
inv_multiindex_factorials_.set_size(list_total_num_coeffs_[limit]);
neg_inv_multiindex_factorials_.set_size(list_total_num_coeffs_[limit]);
multiindex_mapping_.reserve(list_total_num_coeffs_[limit]);
(multiindex_mapping_[0]).reserve(dim_);
for(index_t j = 0; j < dim; j++) {
(multiindex_mapping_[0])[j] = 0;
}
n_choose_k_.Init(dim * (limit + 1), dim * (limit + 1));
n_choose_k_.SetZero();
n_choose_k_.zeros(dim * (limit + 1), dim * (limit + 1));
// compute inverse factorial and negative inverse factorials and
// multiindex mappings...
@@ -353,7 +337,7 @@ class MultSeriesExpansionAux {
div++;
// copy multiindex from old to the new position
multiindex_mapping_[i].InitCopy(multiindex_mapping_[i - step]);
multiindex_mapping_[i] = multiindex_mapping_[i - step];
(multiindex_mapping_[i])[k] = (multiindex_mapping_[i])[k] + 1;
}
}
@@ -361,9 +345,9 @@ class MultSeriesExpansionAux {
}
// compute n choose k's
for(index_t j = 0; j < n_choose_k_.n_rows(); j++) {
for(index_t k = 0; k < n_choose_k_.n_cols(); k++) {
n_choose_k_.set(j, k, math::BinomialCoefficient(j, k));
for(index_t j = 0; j < n_choose_k_.n_rows; j++) {
for(index_t k = 0; k < n_choose_k_.n_cols; k++) {
n_choose_k_(j, k) = math::BinomialCoefficient(j, k);
}
}
@@ -1,6 +1,6 @@
#include "series_expansion_aux.h"
const Vector& SeriesExpansionAux::get_inv_multiindex_factorials() const {
const arma::vec& SeriesExpansionAux::get_inv_multiindex_factorials() const {
return inv_multiindex_factorials_;
}
@@ -8,9 +8,9 @@ int SeriesExpansionAux::get_max_total_num_coeffs() const {
return list_total_num_coeffs_[max_order_];
}
const std::vector < short int > &SeriesExpansionAux::get_lower_mapping_index()
const std::vector < std::vector<short int> >& SeriesExpansionAux::get_lower_mapping_index()
const {
return lower_mapping_index_.front();
return lower_mapping_index_;
}
int SeriesExpansionAux::get_max_order() const {
@@ -22,21 +22,21 @@ const std::vector < short int > &SeriesExpansionAux::get_multiindex(int pos)
return multiindex_mapping_[pos];
}
const std::vector < short int > &SeriesExpansionAux::get_multiindex_mapping()
const std::vector < std::vector<short int> >& SeriesExpansionAux::get_multiindex_mapping()
const {
return multiindex_mapping_.front();
return multiindex_mapping_;
}
const Vector& SeriesExpansionAux::get_neg_inv_multiindex_factorials() const {
const arma::vec& SeriesExpansionAux::get_neg_inv_multiindex_factorials() const {
return neg_inv_multiindex_factorials_;
}
double SeriesExpansionAux::get_n_choose_k(int n, int k) const {
return n_choose_k_.get(n, (int) math::ClampNonNegative(k));
return n_choose_k_(n, (int) math::ClampNonNegative(k));
}
double SeriesExpansionAux::get_n_multichoose_k_by_pos(int n, int k) const {
return multiindex_combination_.get(n, k);
return multiindex_combination_(n, k);
}
int SeriesExpansionAux::get_total_num_coeffs(int order) const {
@@ -44,10 +44,10 @@ int SeriesExpansionAux::get_total_num_coeffs(int order) const {
return list_total_num_coeffs_[order];
}
const std::vector < short int > &SeriesExpansionAux::get_upper_mapping_index()
const std::vector < std::vector< short int > >& SeriesExpansionAux::get_upper_mapping_index()
const {
return upper_mapping_index_.front();
return upper_mapping_index_;
}
int SeriesExpansionAux::ComputeMultiindexPosition
@@ -112,15 +112,14 @@ void SeriesExpansionAux::Init(int max_order, int dim) {
// allocate space for inverse factorial and
// negative inverse factorials and multiindex mapping and n_choose_k
// and multiindex_combination precomputed factors
inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit - 1]);
neg_inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit - 1]);
inv_multiindex_factorials_.set_size(list_total_num_coeffs_[limit - 1]);
neg_inv_multiindex_factorials_.set_size(list_total_num_coeffs_[limit - 1]);
multiindex_mapping_.reserve(list_total_num_coeffs_[limit - 1]);
(multiindex_mapping_[0]).reserve(dim_);
for(j = 0; j < dim; j++) {
(multiindex_mapping_[0])[j] = 0;
}
n_choose_k_.Init((limit - 1) + dim + 1, (limit - 1) + dim + 1);
n_choose_k_.SetZero();
n_choose_k_.zeros((limit - 1) + dim + 1, (limit - 1) + dim + 1);
// initialization of temporary variables for computation...
heads.reserve(dim + 1);
@@ -156,7 +155,7 @@ void SeriesExpansionAux::Init(int max_order, int dim) {
// compute n choose k's
for(j = 0; j <= 2 * max_order + dim; j++) {
for(k = 0; k <= 2 * max_order + dim; k++) {
n_choose_k_.set(j, k, math::BinomialCoefficient(j, k));
n_choose_k_(j, k) = math::BinomialCoefficient(j, k);
}
}
@@ -4,7 +4,8 @@
#ifndef SERIES_EXPANSION_AUX
#define SERIES_EXPANSION_AUX
#include "fastlib/fastlib.h"
#include <fastlib/fastlib.h>
#include <armadillo>
/**
* Series expansion class.
@@ -17,15 +18,15 @@ class SeriesExpansionAux {
int max_order_;
Vector factorials_;
arma::vec factorials_;
std::vector<int> list_total_num_coeffs_;
Vector inv_multiindex_factorials_;
arma::vec inv_multiindex_factorials_;
Vector neg_inv_multiindex_factorials_;
arma::vec neg_inv_multiindex_factorials_;
Matrix multiindex_combination_;
arma::mat multiindex_combination_;
std::vector< std::vector<short int> > multiindex_mapping_;
@@ -44,29 +45,15 @@ class SeriesExpansionAux {
std::vector< std::vector<short int> > upper_mapping_index_;
/** row index is for n, column index is for k */
Matrix n_choose_k_;
OT_DEF_BASIC(SeriesExpansionAux) {
OT_MY_OBJECT(dim_);
OT_MY_OBJECT(max_order_);
OT_MY_OBJECT(factorials_);
OT_MY_OBJECT(list_total_num_coeffs_);
OT_MY_OBJECT(inv_multiindex_factorials_);
OT_MY_OBJECT(neg_inv_multiindex_factorials_);
OT_MY_OBJECT(multiindex_combination_);
OT_MY_OBJECT(multiindex_mapping_);
OT_MY_OBJECT(lower_mapping_index_);
OT_MY_OBJECT(upper_mapping_index_);
OT_MY_OBJECT(n_choose_k_);
}
arma::mat n_choose_k_;
public:
void ComputeFactorials() {
factorials_.Init(2 * max_order_ + 1);
factorials_.set_size(2 * max_order_ + 1);
factorials_[0] = 1;
for(index_t t = 1; t < factorials_.length(); t++) {
for(index_t t = 1; t < factorials_.n_elem; t++) {
factorials_[t] = t * factorials_[t - 1];
}
}
@@ -107,8 +94,8 @@ class SeriesExpansionAux {
void ComputeMultiindexCombination() {
int limit = 2 * max_order_;
multiindex_combination_.Init(list_total_num_coeffs_[limit],
list_total_num_coeffs_[limit]);
multiindex_combination_.set_size(list_total_num_coeffs_[limit],
list_total_num_coeffs_[limit]);
for(index_t j = 0; j < list_total_num_coeffs_[limit]; j++) {
@@ -121,14 +108,13 @@ class SeriesExpansionAux {
const std::vector<short int> &alpha_mapping = multiindex_mapping_[k];
// initialize the factor to 1
multiindex_combination_.set(j, k, 1);
multiindex_combination_(j, k) = 1;
for(index_t i = 0; i < dim_; i++) {
multiindex_combination_.set
(j, k, multiindex_combination_.get(j, k) *
n_choose_k_.get(beta_mapping[i], alpha_mapping[i]));
multiindex_combination_(j, k) *=
n_choose_k_(beta_mapping[i], alpha_mapping[i]);
if(multiindex_combination_.get(j, k) == 0)
if(multiindex_combination_(j, k) == 0)
break;
}
}
@@ -176,23 +162,23 @@ class SeriesExpansionAux {
int get_max_total_num_coeffs() const;
const Vector& get_inv_multiindex_factorials() const;
const arma::vec& get_inv_multiindex_factorials() const;
const std::vector< short int > & get_lower_mapping_index() const;
const std::vector< std::vector<short int> > & get_lower_mapping_index() const;
int get_max_order() const;
const std::vector< short int > & get_multiindex(int pos) const;
const std::vector< short int > & get_multiindex_mapping() const;
const std::vector< std::vector<short int> > & get_multiindex_mapping() const;
const Vector& get_neg_inv_multiindex_factorials() const;
const arma::vec& get_neg_inv_multiindex_factorials() const;
double get_n_choose_k(int n, int k) const;
double get_n_multichoose_k_by_pos(int n, int k) const;
const std::vector< short int > & get_upper_mapping_index() const;
const std::vector< std::vector<short int> >& get_upper_mapping_index() const;
// interesting functions