I was trying to rewrite the Python code in MATLAB.
The result is consistent.
But, the MATLAB code is so slow. Any help would be appreciated.
The MATLAB code written by me is as follows: so slow, whereas definitely correct.
I guess the critical time-costing step is compMultiFoxHIntegrand
function. How can I rewrite it to make it faster?
function result = compMultiFoxH(params, nsubdivisions, boundaryTol) if nargin < 3 boundaryTol = 0.0001; end boundaries = detBoundaries(params, boundaryTol); dim = numel(boundaries); signs = dec2bin(0:2^dim-1) - '0'; signs(signs == 0) = -1; signs=signs.*(-1); inputs = repmat({(0:floor(nsubdivisions/2)-1)}, 1, dim); code = cartesian(inputs{:}); quad = 0; % res = []; for i = 1:size(signs, 1) fprintf("i=%d\n",i); points = signs(i, :) .* (bsxfun(@plus, code, 0.5)) .* (boundaries * 2 / nsubdivisions); integrandVals = (compMultiFoxHIntegrand(points, params)); % res = [res; integrandVals]; quad = quad + sum(integrandVals); end volume = prod(2 * boundaries / nsubdivisions); result = quad * volume; end function boundaries = detBoundaries(params, tol) boundary_range = 0:0.05:50; dims = numel(params{1}); boundaries = zeros(1, dims); for dim_l = 1:dims points = zeros(length(boundary_range), dims); points(:, dim_l) = boundary_range; abs_integrand = abs(compMultiFoxHIntegrand(points, params)); index = find(abs_integrand > tol * abs_integrand(1), 1, 'last'); boundaries(dim_l) = boundary_range(index); end end function result = compMultiFoxHIntegrand(y, params) z = params{1}; mn = params{2}; pq = params{3}; c = params{4}; d = params{5}; a = params{6}; b = params{7}; m = cellfun(@(x) x(1), mn); n = cellfun(@(x) x(2), mn); p = cellfun(@(x) x(1), pq); q = cellfun(@(x) x(2), pq); npoints = size(y, 1); dims = size(y, 2); s = 1j * y; lower = zeros(1, dims); upper = zeros(1, dims); for dim_l = 1:dims if ~isempty(b{dim_l}) bj = cellfun(@(x) x(1), b{dim_l}(1:m(dim_l+1))); Bj = cellfun(@(x) x(2), b{dim_l}(1:m(dim_l+1))); lower(dim_l) = -min(bj ./ Bj); else lower(dim_l) = -100; end if ~isempty(a{dim_l}) aj = cellfun(@(x) x(1), a{dim_l}(1:n(dim_l+1))); Aj = cellfun(@(x) x(2), a{dim_l}(1:n(dim_l+1))); upper(dim_l) = min((1 - aj) ./ Aj); else upper(dim_l) = 1; end end mindist = norm(upper - lower); sigs = 0.5 * (upper + lower); for j = 1:n(1) num = 1 - c{j}(1) - sum(c{j}(2:end) .* lower); cnorm = norm(c{j}(2:end)); newdist = abs(num) / (cnorm + eps); if newdist < mindist mindist = newdist; sigs = lower + 0.5 * num * c{j}(2:end) / (cnorm * cnorm); end end s = bsxfun(@plus, s, sigs); s1 = [ones(npoints, 1), s]; prod_gam_num = 1 + 0j; prod_gam_denom = 1 + 0j; for j = 1:n(1) prod_gam_num = prod_gam_num .* gamma(sym(1 - s1 * c{j}')); end for j = 1:q(1) prod_gam_denom = prod_gam_denom .* gamma(sym(1 - s1 * d{j}')); end for j = n(1)+1:p(1) prod_gam_denom = prod_gam_denom .* gamma(sym(s1 * c{j}')); end for dim_l = 1:dims for j = 1:n(dim_l+1) prod_gam_num = prod_gam_num .* gamma(sym(1 - a{dim_l}{j}(1) - a{dim_l}{j}(2) * s(:, dim_l))); end for j = 1:m(dim_l+1) prod_gam_num = prod_gam_num .* gamma(sym(b{dim_l}{j}(1) + b{dim_l}{j}(2) * s(:, dim_l))); end for j = n(dim_l+1)+1:p(dim_l+1) prod_gam_denom = prod_gam_denom .* gamma(sym(a{dim_l}{j}(1) + a{dim_l}{j}(2) * s(:, dim_l))); end for j = m(dim_l+1)+1:q(dim_l+1) prod_gam_denom = prod_gam_denom .* gamma(sym(1 - b{dim_l}{j}(1) - b{dim_l}{j}(2) * s(:, dim_l))); end end zs = z .^ -s; result = double((prod_gam_num ./ prod_gam_denom) .* prod(zs, 2) ./ (2 * pi)^dims); end function C = cartesian(varargin) args = varargin; n = nargin; [F{1:n}] = ndgrid(args{:}); for i=n:-1:1 G(:,i) = F{i}(:); end C = unique(G , 'rows'); end
clear;clc; % Example usage params1 = {... [16.2982237081499, 16.2982237081499, 16.2982237081499, 16.2982237081499], ... {[0, 0], [2, 1], [2, 1], [2, 1], [2, 1]}, ... {[0, 1], [1, 2], [1, 2], [1, 2], [1, 2]}, ... {}, ... {[0, 1, 1, 1, 1]}, ... {{[1, 2]}, {[1, 2]}, {[1, 2]}, {[1, 2]}}, ... {{[1, 0.6666666666666666], [3.5, 0.5]}, {[1, 0.6666666666666666], [3.5, 0.5]}, {[1, 0.6666666666666666], [3.5, 0.5]}, {[1, 0.6666666666666666], [3.5, 0.5]}} ... }; result = compMultiFoxH(params1, 20); format longG disp(result);