TMatrix fgt(const TMatrix& x, const TMatrix& y, const TMatrix& q, T h, T epsilon = 1e-3, int evalMethod = FIGTREE_EVAL_AUTO, int ifgtParamMethod = FIGTREE_PARAM_NON_UNIFORM, int ifgtTruncMethod = FIGTREE_TRUNC_CLUSTER, int verbose = 0) { // very strange usage... typename MatrixType<double, D>::MatrixD x_r = x.template cast<double>(); typename MatrixType<double, D>::MatrixD y_r = y.template cast<double>(); typename MatrixType<double, D>::Matrix q_r = q.template cast<double>().transpose(); int d = D; int N = x_r.rows(); int M = y_r.rows(); int W = q_r.rows(); double *X, *Y, *Q; X = x_r.data(); Y = y_r.data(); Q = q_r.data(); typename MatrixType<double, D>::Matrix G(W, M); figtree(d, N, M, W, X, h, Q, Y, epsilon, G.data(), evalMethod, ifgtParamMethod, ifgtTruncMethod, verbose); TMatrix g = G.template cast<T>().transpose(); return g; }
int main() { // The dimensionality of each sample vector. int d = 7; // The number of targets (vectors at which gauss transform is evaluated). int M = 10; // The number of sources which will be used for the gauss transform. int N = 20; // The bandwidth. NOTE: this is not the same as standard deviation since // the Gauss Transform sums terms exp( -||x_i - y_j||^2 / h^2 ) as opposed // to exp( -||x_i - y_j||^2 / (2*sigma^2) ). Thus, if sigma is known, // bandwidth can be set to h = sqrt(2)*sigma. double h = .8; // Desired maximum absolute error after normalizing output by sum of weights. // If the weights, q_i (see below), add up to 1, then this is will be the // maximum absolute error. // The smaller epsilon is, the more accurate the results will be, at the // expense of increased computational complexity. double epsilon = 1e-2; // The source array. It is a contiguous array, where // ( x[i*d], x[i*d+1], ..., x[i*d+d-1] ) is the ith d-dimensional sample. // For example, below N = 20 and d = 7, so there are 20 rows, each // a 7-dimensional sample. double x[] = {0.7165, 0.5113, 0.7764, 0.4893, 0.1859, 0.7006, 0.9827, 0.8066, 0.7036, 0.4850, 0.1146, 0.6649, 0.3654, 0.1400, 0.5668, 0.8230, 0.6739, 0.9994, 0.9616, 0.0589, 0.3603, 0.5485, 0.2618, 0.5973, 0.0493, 0.5711, 0.7009, 0.9623, 0.7505, 0.7400, 0.4319, 0.6343, 0.8030, 0.0839, 0.9455, 0.9159, 0.6020, 0.2536, 0.8735, 0.5134, 0.7327, 0.4222, 0.1959, 0.1059, 0.3923, 0.1003, 0.6930, 0.2069, 0.6094, 0.1059, 0.0396, 0.2093, 0.9693, 0.1059, 0.3029, 0.3069, 0.9692, 0.6029, 0.2222, 0.2059, 0.3059, 0.6092, 0.2133, 0.9614, 0.0721, 0.5534, 0.2920, 0.8580, 0.3358, 0.6802, 0.2473, 0.3527, 0.1879, 0.4906, 0.4093, 0.4635, 0.6109, 0.1865, 0.0395, 0.5921, 0.1853, 0.9963, 0.1953, 0.7659, 0.0534, 0.3567, 0.4983, 0.4344, 0.5625, 0.6166, 0.1133, 0.8983, 0.7546, 0.7911, 0.8150, 0.6700, 0.2009, 0.2731, 0.6262, 0.5369, 0.0595, 0.0890, 0.2713, 0.4091, 0.4740, 0.1332, 0.6926, 0.0009, 0.1532, 0.9632, 0.3521, 0.9692, 0.9623, 0.3532, 0.7432, 0.0693, 0.2336, 0.6022, 0.2936, 0.3921, 0.6023, 0.6323, 0.9353, 0.3963, 0.2835, 0.9868, 0.2362, 0.6682, 0.2026, 0.0263, 0.1632, 0.9164, 0.1153, 0.9090, 0.5962, 0.3290, 0.4782, 0.5972, 0.1614, 0.8295 }; // The target array. It is a contiguous array, where // ( y[j*d], y[j*d+1], ..., y[j*d+d-1] ) is the jth d-dimensional sample. // For example, below M = 10 and d = 7, so there are 10 rows, each // a 7-dimensional sample. double y[] = {0.9561, 0.5955, 0.0287, 0.8121, 0.6101, 0.7015, 0.0922, 0.4249, 0.3756, 0.1662, 0.8332, 0.8386, 0.4516, 0.9566, 0.1472, 0.8699, 0.7694, 0.4442, 0.6206, 0.9517, 0.6400, 0.0712, 0.3143, 0.6084, 0.1750, 0.6210, 0.2460, 0.5874, 0.5061, 0.4648, 0.5414, 0.9423, 0.3418, 0.4018, 0.3077, 0.4116, 0.2859, 0.3941, 0.5030, 0.7220, 0.3062, 0.1122, 0.4433, 0.4668, 0.0147, 0.6641, 0.7241, 0.2816, 0.2618, 0.7085, 0.7839, 0.9862, 0.4733, 0.9028, 0.4511, 0.8045, 0.8289, 0.1663, 0.3939, 0.5208, 0.7181, 0.5692, 0.4608, 0.4453, 0.0877, 0.4435, 0.3663, 0.3025, 0.8518, 0.7595 }; // The weight array. The ith weight is associated with the ith source sample. // To evaluate the Gauss Transform with the same sources and targets, but // different sets of weights, add another row of weights and set W = 2. double q[] = {0.2280, 0.4496, 0.1722, 0.9688, 0.3557, 0.0490, 0.7553, 0.8948, 0.2861, 0.2512, 0.9327, 0.3353, 0.2530, 0.2532, 0.3352, 0.7235, 0.2506, 0.0235, 0.1062, 0.1061, 0.7234, 0.1532}; // Number of weights. For each set of weights a different Gauss Transform is computed, // but by giving multiple sets of weights at once some overhead can be shared. int W = 1; // in this case W = 1. // allocate array into which the result of the Gauss Transform will be stored for each // target sample. The first M elements will correspond to the Gauss Transform computed // with the first set of weights, second M elements will correspond to the G.T. computed // with the second set of weights, etc. double * g_auto = new double[W*M]; double * g_sf = new double[W*M]; double * g_sf_tree = new double[W*M]; double * g_ifgt_u = new double[W*M]; double * g_ifgt_tree_u = new double[W*M]; double * g_ifgt_nu = new double[W*M]; double * g_ifgt_tree_nu = new double[W*M]; // initialize all output arrays to zero memset( g_auto , 0, sizeof(double)*W*M ); memset( g_sf , 0, sizeof(double)*W*M ); memset( g_sf_tree , 0, sizeof(double)*W*M ); memset( g_ifgt_u , 0, sizeof(double)*W*M ); memset( g_ifgt_tree_u , 0, sizeof(double)*W*M ); memset( g_ifgt_nu , 0, sizeof(double)*W*M ); memset( g_ifgt_tree_nu, 0, sizeof(double)*W*M ); // // RECOMMENDED way to call figtree(). // // Evaluates the Gauss transform using automatic method selection (the automatic // method selection function analyzes the inputs -- including source/target // points, weights, bandwidth, and error tolerance -- to automatically choose // between FIGTREE_EVAL_DIRECT, FIGTREE_EVAL_DIRECT_TREE, FIGTREE_EVAL_IFGT, // FIGTREE_EVAL_IFGT_TREE. // This function call makes use of the default parameters for the eval method // and param method, and is equivalent to // figtree( d, N, M, W, x, h, q, y, epsilon, g_auto, FIGTREE_EVAL_AUTO, FIGTREE_PARAM_NON_UNIFORM ). figtree( d, N, M, W, x, h, q, y, epsilon, g_auto ); // // MANUAL EVALUATION METHOD and PARAMETER METHOD selection. If chosen // incorrectly, this could cause run times to be several orders of // magnitudes longer or to require several orders of magnitude more // memory (resulting in crashes). The recommended way to call figtree // is using the automatic method selection, as shown above. // // evaluate gauss transform using direct (slow) method figtree( d, N, M, W, x, h, q, y, epsilon, g_sf, FIGTREE_EVAL_DIRECT ); // evaluate gauss transform using direct method with approximate nearest neighbors figtree( d, N, M, W, x, h, q, y, epsilon, g_sf_tree, FIGTREE_EVAL_DIRECT_TREE ); // evaluate gauss transform using FIGTREE (truncated series), estimating parameters with and without // the assumption that sources are uniformly distributed figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_u, FIGTREE_EVAL_IFGT, FIGTREE_PARAM_UNIFORM, 1 ); figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_nu, FIGTREE_EVAL_IFGT, FIGTREE_PARAM_NON_UNIFORM, 1 ); // evaluate gauss transform using FIGTREE (truncated series), estimating parameters with and without // the assumption that sources are uniformly distributed figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_u, FIGTREE_EVAL_IFGT_TREE, FIGTREE_PARAM_UNIFORM, 1 ); figtree( d, N, M, W, x, h, q, y, epsilon, g_ifgt_tree_nu, FIGTREE_EVAL_IFGT_TREE, FIGTREE_PARAM_NON_UNIFORM, 1 ); // compute absolute error of the Gauss Transform at each target and for all sets of weights. for( int i = 0; i < W*M; i++) { g_auto[i] = fabs(g_auto[i] -g_sf[i]); g_sf_tree[i] = fabs(g_sf_tree[i] -g_sf[i]); g_ifgt_u[i] = fabs(g_ifgt_u[i] -g_sf[i]); g_ifgt_nu[i] = fabs(g_ifgt_nu[i] -g_sf[i]); g_ifgt_tree_u[i] = fabs(g_ifgt_tree_u[i] -g_sf[i]); g_ifgt_tree_nu[i] = fabs(g_ifgt_tree_nu[i]-g_sf[i]); } // print out results for all six ways to evaluate printf("Results:\n"); printf("Direct result auto error sf-tree error ifgt-u error ifgt-nu error ifgt-tree-u e ifgt-tree-nu error\n"); for( int i = 0; i < W*M; i++ ) printf("%13.4f %13.4e %13.4e %13.4e %13.4e %13.4e %13.4e\n", g_sf[i], g_auto[i], g_sf_tree[i], g_ifgt_u[i], g_ifgt_nu[i], g_ifgt_tree_u[i], g_ifgt_tree_nu[i] ); printf("\n"); // deallocate memory delete [] g_auto; delete [] g_sf; delete [] g_sf_tree; delete [] g_ifgt_u; delete [] g_ifgt_nu; delete [] g_ifgt_tree_u; delete [] g_ifgt_tree_nu; return 0; }