From f7de7ced92463c8e49a94bd78640972096ee05a0 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Tue, 11 Feb 2025 08:38:25 -0500 Subject: [PATCH 01/11] test mexcuda --- makefile | 3 +- matlab/cufinufft.mw | 264 +++++++++++++++++++++++++++++++++ matlab/guru1d1_gpu.m | 49 ++++++ matlab/guru2d1_gpu.m | 50 +++++++ src/cuda/1d/spreadinterp1d.cuh | 12 +- 5 files changed, 373 insertions(+), 5 deletions(-) create mode 100644 matlab/cufinufft.mw create mode 100644 matlab/guru1d1_gpu.m create mode 100644 matlab/guru2d1_gpu.m diff --git a/makefile b/makefile index 23a5bab61..9321e0c95 100644 --- a/makefile +++ b/makefile @@ -417,7 +417,8 @@ octave: matlab/finufft.cpp $(STATICLIB) mex: matlab/finufft.mw ifneq ($(MINGW),ON) (cd matlab ;\ - $(MWRAP) -mex finufft -c finufft.cpp -mb -cppcomplex finufft.mw) + $(MWRAP) -mex finufft -c finufft.cpp -mb -cppcomplex finufft.mw ;\ + $(MWRAP) -mex cufinufft -c cufinufft.cu -mb -cppcomplex -gpu cufinufft.mw) else (cd matlab & $(MWRAP) -mex finufft -c finufft.cpp -mb -cppcomplex finufft.mw) endif diff --git a/matlab/cufinufft.mw b/matlab/cufinufft.mw new file mode 100644 index 000000000..e639f2ed1 --- /dev/null +++ b/matlab/cufinufft.mw @@ -0,0 +1,264 @@ +% cufinufft.mw +% MWrap MEX interface descriptor file for cuFINUFFT, using the guru interface. +% This provides an object-oriented style interface to the guru interface, by +% mirroring the cufinufft_plan C++ object with a matlab object "cufinufft_plan". +% The OO use makes it compatible only with MATLAB R2008a or later, and octave +% version 4.4 or later. mexcuda in Matlab introduced in R2015b +% +% To match the object name, generated matlab interface is (and must be) called +% cufinufft_plan.m; see Path Folders here: +% https://www.mathworks.com/help/matlab/matlab_oop/organizing-classes-in-folders.html +% +% +% Hints for linux/GNU build (see ../makefile for definitive build): +% first build libcufinufft.so +% cmake -S . -B build -D FINUFFT_USE_CUDA=ON -D FINUFFT_STATIC_LINKING=OFF -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON -D FINUFFT_CUDA_ARCHITECTURES="60;70;80" +% cmake --build build --verbose +% To generate the MEX C++ file, run: +% +% mwrap -mex cufinufft -c cufinufft.cu -mb -cppcomplex cufinufft.mw +% +% Then to compile for matlab: +% mexcuda -v matlab/cufinufft.cu build/src/cuda/libcufinufft.so -Iinclude -DR2008OO -largeArrayDims -output matlab/cufinufft + +% export LD_LIBRARY_PATH to include where libcufinufft.so is if dylink cufinufft + +% both precisions... +$ #include + +$ #include +$ #include +$ #include +$ #include + + +% ......................................................................... +% This C++ code overwrites any properties of cufinufft_opts *oc with any valid +% fields in the matlab struct *om. Note: fftw_{un}lock stuff not included. +% +$ void copy_cufinufft_opts(const mxArray* om, cufinufft_opts *oc) { +$ if(!mxIsStruct(om)) +$ mexErrMsgIdAndTxt("FINUFFT:inputNotStruct","opts input must be a structure."); +$ mwIndex idx = 0; +$ int ifield, nfields; +$ const char **fname; +$ nfields = mxGetNumberOfFields(om); +$ fname = (const char**)mxCalloc(nfields, sizeof(*fname)); +$ for(ifield=0; ifielddebug = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_sort") == 0) { +$ oc->gpu_sort = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_kerevalmeth") == 0) { +$ oc->gpu_kerevalmeth = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_spreadinterponly") == 0) { +$ oc->gpu_spreadinterponly = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"modeord") == 0) { +$ oc->modeord = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"upsampfac") == 0) { +$ oc->upsampfac = (double)*mxGetPr(mxGetFieldByNumber(om,idx,ifield)); +$ } +$ else if (strcmp(fname[ifield],"gpu_maxbatchsize") == 0) { +$ oc->gpu_maxbatchsize = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_maxsubprobsize") == 0) { +$ oc->gpu_maxsubprobsize = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_method") == 0) { +$ oc->gpu_method = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_binsizex") == 0) { +$ oc->gpu_binsizex = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_binsizey") == 0) { +$ oc->gpu_binsizey = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_binsizez") == 0) { +$ oc->gpu_binsizez = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else if (strcmp(fname[ifield],"gpu_device_id") == 0) { +$ oc->gpu_device_id = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); +$ } +$ else +$ continue; +$ } +$ mxFree(fname); +$ } + +@ cufinufft_plan.m -------------------------------------------- + +classdef cufinufft_plan < handle + + properties + % this is a special property that MWrap uses as an opaque pointer to C++ + % object (mwptr = MWrap-pointer, not MathWorks! see MWrap manual)... + mwptr + % track what prec C++ library is being called ('single' or 'double')... + floatprec + % track other properties we'd rather not have to query the C++ plan for... + type + dim + n_modes % 3-element array, 1's in the unused dims + n_trans + nj % number of NU pts (type 1,2), or input NU pts (type 3) + nk % number of output NU pts (type 3) + xj + yj + zj + end + + methods + + function plan = cufinufft_plan(type, n_modes_or_dim, iflag, n_trans, tol, opts) + % FINUFFT_PLAN create guru plan object for one/many general nonuniform FFTs. + + plan.floatprec='double'; % set precision: default + if nargin<6, opts = []; end + if isfield(opts,'floatprec') % a matlab-only option + if ~strcmp(opts.floatprec,'single') && ~strcmp(opts.floatprec,'double') + error('FINUFFT:badFloatPrec','FINUFFT plan opts.floatprec must be single or double'); + else + plan.floatprec = opts.floatprec; + end + end + + n_modes = ones(3,1); % is dummy for type 3 + if type==3 + if length(n_modes_or_dim)~=1 + error('FINUFFT:badT3dim', 'FINUFFT type 3 plan n_modes_or_dim must be one number, the dimension'); + end + dim = n_modes_or_dim; % interpret as dim + else + dim = length(n_modes_or_dim); % allows any ms,mt,mu to be 1 (weird..) + n_modes(1:dim) = n_modes_or_dim; % unused dims left as 1 + end + % (checks of type, dim will occur in the C++ library, so omit them above) + + # cufinufft_opts* o = new cufinufft_opts(); + if strcmp(plan.floatprec,'double') + # cufinufft_plan* p = new cufinufft_plan(); + # cufinufft_default_opts(cufinufft_opts* o); + else + # cufinufftf_plan* p = new cufinufftf_plan(); + # cufinufft_default_opts(cufinufft_opts* o); + end + plan.mwptr = p; % crucial: save the opaque ptr (p.12 of MWrap manual) + plan.dim = dim; % save other stuff to avoid having to access via C++... + plan.type = type; + plan.n_modes = n_modes; + plan.n_trans = n_trans; + % Note the peculiarity that mwrap only accepts a double for n_trans, even + % though it's declared int. It complains, also with int64 for nj, etc :( + + % replace in cufinufft_opts struct whichever fields are in incoming opts... + # copy_cufinufft_opts(mxArray opts, cufinufft_opts* o); + if strcmp(plan.floatprec,'double') + tol = double(tol); % scalar type must match for mwrap>=0.33.11 + # int ier = cufinufft_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, double tol, cufinufft_plan* plan, cufinufft_opts* o); + else + tol = single(tol); % ditto + # int ier = cufinufftf_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, float tol, cufinufftf_plan* plan, cufinufft_opts* o); + end + # delete(cufinufft_opts* o); + errhandler(ier); % convert C++ codes to matlab-style errors + end + + function setpts(plan, xj, yj, zj, s, t, u) + % SETPTS process nonuniform points for general FINUFFT transform(s). + + % fill missing inputs with empties of correct type + if strcmp(plan.floatprec,'double') + emp = gpuArray(double([])); + else + emp = gpuArray(single([])); + end + if nargin<3, yj=emp; end + if nargin<4, zj=emp; end + if nargin<5, s=emp; end + if nargin<6, t=emp; end + if nargin<7, u=emp; end + % get number(s) of NU pts (also validates the NU pt array sizes)... + [nj, nk] = valid_setpts(plan.type, plan.dim, xj, yj, zj, s, t, u); + plan.nj = nj; % save to avoid having to query the C++ plan + plan.nk = nk; % " + % Force MATLAB to preserve the memory of xj/yj/zj by storing them as class + % properties (see issue #185). Ideally, we would pass plan.xj/yj/zj to the + % MWrap call below, but MWrap fails to parse the "." syntax. However, + % simply storing xj/yj/zj ensures that the memory will be preserved. + plan.xj = xj; + plan.yj = yj; + plan.zj = zj; + if strcmp(plan.floatprec,'double') + # int ier = cufinufft_setpts(cufinufft_plan plan, int nj, gpu double[] xj, gpu double[] yj, gpu double[] zj, int nk, gpu double[] s, gpu double[] t, gpu double[] u); + else + # int ier = cufinufftf_setpts(cufinufftf_plan plan, int nj, gpu float[] xj, gpu float[] yj, gpu float[] zj, int nk, gpu float[] s, gpu float[] t, gpu float[] u); + end + errhandler(ier); + end + + function result = execute(plan, data_in) + % EXECUTE execute single or many-vector FINUFFT transforms in a plan. + + % get shape info from the matlab-side plan (since can't pass "dot" + % variables like a.b as mwrap sizes, too)... + ms = plan.n_modes(1); mt = plan.n_modes(2); mu = plan.n_modes(3); + nj = plan.nj; nk = plan.nk; n_trans = plan.n_trans; + + % check data input length... + if plan.type==1 || plan.type==2 + ncoeffs = ms*mt*mu*n_trans; % total # Fourier coeffs + end + if plan.type==2 + ninputs = ncoeffs; + else + ninputs = n_trans*nj; + end + if numel(data_in)~=ninputs + error('FINUFFT:badDataInSize','FINUFFT numel(data_in) must be n_trans times number of NU pts (type 1, 3) or Fourier modes (type 2)'); + end + if plan.type == 1 + if strcmp(plan.floatprec,'double') + # int ier = cufinufft_execute(cufinufft_plan plan, gpu dcomplex[] data_in, gpu output dcomplex[ncoeffs] result); + else + # int ier = cufinufftf_execute(cufinufftf_plan plan, gpu fcomplex[] data_in, gpu output fcomplex[ncoeffs] result); + end + % make modes output correct shape; when d<3 squeeze removes unused dims... + result = squeeze(reshape(result, [ms mt mu n_trans])); + elseif plan.type == 2 + if strcmp(plan.floatprec,'double') + # int ier = cufinufft_execute(cufinufft_plan plan, gpu output dcomplex[nj, n_trans] result, gpu dcomplex[] data_in); + else + # int ier = cufinufftf_execute(cufinufftf_plan plan, gpu output fcomplex[nj, n_trans] result, gpu fcomplex[] data_in); + end + elseif plan.type == 3 + if strcmp(plan.floatprec,'double') + # int ier = cufinufft_execute(cufinufft_plan plan, gpu dcomplex[] data_in, gpu output dcomplex[nk, n_trans] result); + else + # int ier = cufinufftf_execute(cufinufftf_plan plan, gpu fcomplex[] data_in, gpu output fcomplex[nk, n_trans] result); + end + end + errhandler(ier); + end + + function delete(plan) + % This does clean-up (deallocation) of the C++ struct before the matlab + % object deletes. It is automatically called by MATLAB and octave if the + % plan goes out of scope. + if ~isempty(plan.mwptr) % catch octave's allowance of >1 deletings! + if strcmp(plan.floatprec,'double') + # cufinufft_destroy(cufinufft_plan plan); + else + # cufinufftf_destroy(cufinufftf_plan plan); + end + plan.mwptr = ''; % we use to mean "destroyed on the C++ side" + end + end + + end +end diff --git a/matlab/guru1d1_gpu.m b/matlab/guru1d1_gpu.m new file mode 100644 index 000000000..054158485 --- /dev/null +++ b/matlab/guru1d1_gpu.m @@ -0,0 +1,49 @@ +clear + +% set required parameters... +isign = +1; % sign of imaginary unit in exponential +tol = 1e-8; % requested accuracy +M = 1e6; +N = 1e6; % # of modes (approx total, used in all dims) +type = 1; +n_modes = [N]; % n_dims inferred from length of this +ntrans = 1; + +%x = pi*(2*rand(1,M,'single')-1); % choose NU points +%c = randn(1,M*ntrans,'single')+1i*randn(1,M*ntrans,'single'); % strengths +x = pi*(2*rand(1,M)-1); % choose NU points +c = randn(1,M*ntrans)+1i*randn(1,M*ntrans); % choose stack of strengths + +xg = gpuArray(x); cg = gpuArray(c); % move to GPU + +opts.debug=1; % set options then plan the transform... +opts.floatprec = 'double'; % tells it to make a single-precision plan +%opts.floatprec = 'single'; % tells it to make a single-precision plan + +disp('starting...'), tic % just time FINUFFT not the data creation + +plan = finufft_plan(type,n_modes,isign,ntrans,tol,opts); + +opts.gpu_method=2; +plang = cufinufft_plan(type,n_modes,isign,ntrans,tol,opts); + +plan.setpts(x); % send in NU pts + +plang.setpts(xg); % send in NU pts + +f = plan.execute(c); % do the transform + +fg = plang.execute(cg); % do the transform + +disp('done.'); toc + +% relative diff CPU vs GPU +norm(c-cg)/norm(c) +norm(x-xg)/norm(x) +norm(f-fg)/norm(f) +%f(1:10) +%fg(1:10) + +% if you do not want to do more transforms of this size, clean up... +delete(plan); +delete(plang); diff --git a/matlab/guru2d1_gpu.m b/matlab/guru2d1_gpu.m new file mode 100644 index 000000000..5a7edcf0f --- /dev/null +++ b/matlab/guru2d1_gpu.m @@ -0,0 +1,50 @@ +clear + +% set required parameters... +isign = +1; % sign of imaginary unit in exponential +tol = 1e-8; % requested accuracy +M = 1e6; +N = 1e3; % # of modes (approx total, used in all dims) +type = 1; +n_modes = [N;N]; % n_dims inferred from length of this +ntrans = 1; + +%x = pi*(2*rand(1,M,'single')-1); % choose NU points +%c = randn(1,M*ntrans,'single')+1i*randn(1,M*ntrans,'single'); % strengths +x = pi*(2*rand(1,M)-1); % choose NU points +y = pi*(2*rand(1,M)-1); % choose NU points +c = randn(1,M*ntrans)+1i*randn(1,M*ntrans); % choose stack of strengths + +xg = gpuArray(x); yg = gpuArray(y); cg = gpuArray(c); % move to GPU + +opts.debug=1; % set options then plan the transform... +opts.floatprec = 'double'; % tells it to make a single-precision plan +%opts.floatprec = 'single'; % tells it to make a single-precision plan + +disp('starting...'), tic % just time FINUFFT not the data creation + +plan = finufft_plan(type,n_modes,isign,ntrans,tol,opts); + +opts.gpu_method=2; +plang = cufinufft_plan(type,n_modes,isign,ntrans,tol,opts); + +plan.setpts(x,y); % send in NU pts + +plang.setpts(xg,yg); % send in NU pts + +f = plan.execute(c); % do the transform + +fg = plang.execute(cg); % do the transform + +disp('done.'); toc +% relative diff CPU vs GPU +norm(c-cg)/norm(c) +norm(x-xg)/norm(x) +norm(y-yg)/norm(y) +norm(f-fg)/norm(f) +%f(1:10) +%fg(1:10) + +% if you do not want to do more transforms of this size, clean up... +delete(plan); +delete(plang); diff --git a/src/cuda/1d/spreadinterp1d.cuh b/src/cuda/1d/spreadinterp1d.cuh index 72c776c06..d1fdd2b97 100644 --- a/src/cuda/1d/spreadinterp1d.cuh +++ b/src/cuda/1d/spreadinterp1d.cuh @@ -105,7 +105,8 @@ __global__ void spread_1d_subprob( const int nupts = min(maxsubprobsize, bin_size[bidx] - binsubp_idx * maxsubprobsize); const int xoffset = (bidx % nbinx) * bin_size_x; const auto ns_2 = (ns + 1) / 2; - const int N = bin_size_x + 2 * ns_2; + const auto rounded_ns = ns_2 * 2; + const int N = bin_size_x + rounded_ns; // dynamic stack allocation #if ALLOCA_SUPPORTED @@ -127,15 +128,18 @@ __global__ void spread_1d_subprob( const auto idx = ptstart + i; const auto x_rescaled = fold_rescale(x[idxnupts[idx]], nf1); const auto cnow = c[idxnupts[idx]]; - const auto [xstart, xend] = interval(ns, x_rescaled); - const T x1 = T(xstart + xoffset) - x_rescaled; + auto [xstart, xend] = interval(ns, x_rescaled); + const T x1 = T(xstart) - x_rescaled; + xstart -= xoffset; + xend -= xoffset; + if constexpr (KEREVALMETH == 1) eval_kernel_vec_horner(ker1, x1, ns, sigma); else eval_kernel_vec(ker1, x1, ns, es_c, es_beta); for (int xx = xstart; xx <= xend; xx++) { const auto ix = xx + ns_2; - if (ix >= (bin_size_x + ns_2) || ix < 0) break; + if (ix >= (bin_size_x + rounded_ns) || ix < 0) break; const cuda_complex result{cnow.x * ker1[xx - xstart], cnow.y * ker1[xx - xstart]}; atomicAddComplexShared(fwshared + ix, result); From d9d72b3360f945149ee17fee832b151de1faa8fd Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 17:40:04 -0500 Subject: [PATCH 02/11] adding gpuArray check layer, to do more testing and docs --- matlab/cufinufft.mw | 17 +++++++++++------ matlab/finufft.mw | 7 ++++++- matlab/finufft1d1.m | 13 +++++++++---- matlab/finufft1d2.m | 13 +++++++++---- matlab/finufft1d3.m | 11 ++++++++--- matlab/finufft2d1.m | 13 +++++++++---- matlab/finufft2d2.m | 13 +++++++++---- matlab/finufft2d3.m | 11 ++++++++--- matlab/finufft3d1.m | 11 ++++++++--- matlab/finufft3d2.m | 11 ++++++++--- matlab/finufft3d3.m | 12 ++++++++---- matlab/valid_ntr.m | 5 +++++ matlab/valid_setpts.m | 22 +++++++++++++++------- 13 files changed, 113 insertions(+), 46 deletions(-) diff --git a/matlab/cufinufft.mw b/matlab/cufinufft.mw index e639f2ed1..bd6326017 100644 --- a/matlab/cufinufft.mw +++ b/matlab/cufinufft.mw @@ -178,13 +178,13 @@ classdef cufinufft_plan < handle else emp = gpuArray(single([])); end - if nargin<3, yj=emp; end - if nargin<4, zj=emp; end - if nargin<5, s=emp; end - if nargin<6, t=emp; end - if nargin<7, u=emp; end + if nargin<3 || numel(yj)==0, yj=emp; end + if nargin<4 || numel(zj)==0, zj=emp; end + if nargin<5 || numel(s)==0, s=emp; end + if nargin<6 || numel(t)==0, t=emp; end + if nargin<7 || numel(u)==0, u=emp; end % get number(s) of NU pts (also validates the NU pt array sizes)... - [nj, nk] = valid_setpts(plan.type, plan.dim, xj, yj, zj, s, t, u); + [nj, nk] = valid_setpts(1,plan.type, plan.dim, xj, yj, zj, s, t, u); plan.nj = nj; % save to avoid having to query the C++ plan plan.nk = nk; % " % Force MATLAB to preserve the memory of xj/yj/zj by storing them as class @@ -205,6 +205,11 @@ classdef cufinufft_plan < handle function result = execute(plan, data_in) % EXECUTE execute single or many-vector FINUFFT transforms in a plan. + % check if data_in is gpuArray + if ~isgpuarray(data_in) + error('FINUFFT:badDataDevice','input data must be a gpuArray'); + end + % get shape info from the matlab-side plan (since can't pass "dot" % variables like a.b as mwrap sizes, too)... ms = plan.n_modes(1); mt = plan.n_modes(2); mu = plan.n_modes(3); diff --git a/matlab/finufft.mw b/matlab/finufft.mw index 41f3709ae..fd9536eaa 100644 --- a/matlab/finufft.mw +++ b/matlab/finufft.mw @@ -211,7 +211,7 @@ classdef finufft_plan < handle if nargin<6, t=emp; end if nargin<7, u=emp; end % get number(s) of NU pts (also validates the NU pt array sizes)... - [nj, nk] = valid_setpts(plan.type, plan.dim, xj, yj, zj, s, t, u); + [nj, nk] = valid_setpts(0, plan.type, plan.dim, xj, yj, zj, s, t, u); plan.nj = nj; % save to avoid having to query the C++ plan plan.nk = nk; % " % Force MATLAB to preserve the memory of xj/yj/zj by storing them as class @@ -232,6 +232,11 @@ classdef finufft_plan < handle function result = execute(plan, data_in) % EXECUTE execute single or many-vector FINUFFT transforms in a plan. + % check if data_in is gpuArray + if isgpuarray(data_in) + error('FINUFFT:badDataDevice','input data must be a cpuArray'); + end + % get shape info from the matlab-side plan (since can't pass "dot" % variables like a.b as mwrap sizes, too)... ms = plan.n_modes(1); mt = plan.n_modes(2); mu = plan.n_modes(3); diff --git a/matlab/finufft1d1.m b/matlab/finufft1d1.m index c24e85642..fffaa07c7 100644 --- a/matlab/finufft1d1.m +++ b/matlab/finufft1d1.m @@ -47,9 +47,14 @@ function f = finufft1d1(x,c,isign,eps,ms,o) if nargin<6, o.dummy=1; end % make a dummy options struct -valid_setpts(1,1,x,[],[]); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,1,1,x); +o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(1,ms,isign,n_transf,eps,o); -p.setpts(x,[],[]); +if is_gpuarray + p = cufinufft_plan(1,ms,isign,n_transf,eps,o); +else + p = finufft_plan(1,ms,isign,n_transf,eps,o); +end +p.setpts(x); f = p.execute(c); diff --git a/matlab/finufft1d2.m b/matlab/finufft1d2.m index 37f8f47cb..58b38d44b 100644 --- a/matlab/finufft1d2.m +++ b/matlab/finufft1d2.m @@ -46,10 +46,15 @@ function c = finufft1d2(x,isign,eps,f,o) if nargin<5, o.dummy=1; end -valid_setpts(2,1,x,[],[]); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,2,1,x); +o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,n_transf]=size(f); % if f a col vec, n_transf=1, but... if ms==1, ms=n_transf; n_transf=1; end % allow a single row vec as valid f -p = finufft_plan(2,ms,isign,n_transf,eps,o); -p.setpts(x,[],[]); +if is_gpuarray + p = cufinufft_plan(2,ms,isign,n_transf,eps,o); +else + p = finufft_plan(2,ms,isign,n_transf,eps,o); +end +p.setpts(x); c = p.execute(f); diff --git a/matlab/finufft1d3.m b/matlab/finufft1d3.m index c1586e5ca..f12413abd 100644 --- a/matlab/finufft1d3.m +++ b/matlab/finufft1d3.m @@ -44,9 +44,14 @@ function f = finufft1d3(x,c,isign,eps,s,o) if nargin<6, o.dummy=1; end -valid_setpts(3,1,x,[],[],s,[],[]); -o.floatprec=class(x); % should be 'double' or 'single' +if_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,3,1,x,[],[],s,[],[]); +o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(3,1,isign,n_transf,eps,o); +if is_gpuarray + p = cufinufft_plan(3,1,isign,n_transf,eps,o); +else + p = finufft_plan(3,1,isign,n_transf,eps,o); +end p.setpts(x,[],[],s,[],[]); f = p.execute(c); diff --git a/matlab/finufft2d1.m b/matlab/finufft2d1.m index 76feb4d2d..6f2d36803 100644 --- a/matlab/finufft2d1.m +++ b/matlab/finufft2d1.m @@ -52,9 +52,14 @@ function f = finufft2d1(x,y,c,isign,eps,ms,mt,o) if nargin<8, o.dummy=1; end -valid_setpts(1,2,x,y,[]); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,1,2,x,y); +o.floatprec = underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(1,[ms;mt],isign,n_transf,eps,o); -p.setpts(x,y,[]); +if is_gpuarray + p = cufinufft_plan(1,[ms;mt],isign,n_transf,eps,o); +else + p = finufft_plan(1,[ms;mt],isign,n_transf,eps,o); +end +p.setpts(x,y); f = p.execute(c); diff --git a/matlab/finufft2d2.m b/matlab/finufft2d2.m index 3a3d2d768..026e3046f 100644 --- a/matlab/finufft2d2.m +++ b/matlab/finufft2d2.m @@ -48,9 +48,14 @@ function c = finufft2d2(x,y,isign,eps,f,o) if nargin<6, o.dummy=1; end -valid_setpts(2,2,x,y,[]); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,2,2,x,y); +o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,mt,n_transf] = size(f); % if f 2D array, n_transf=1 -p = finufft_plan(2,[ms;mt],isign,n_transf,eps,o); -p.setpts(x,y,[]); +if is_gpuarray + p = cufinufft_plan(2,[ms;mt],isign,n_transf,eps,o); +else + p = finufft_plan(2,[ms;mt],isign,n_transf,eps,o); +end +p.setpts(x,y); c = p.execute(f); diff --git a/matlab/finufft2d3.m b/matlab/finufft2d3.m index daba6620e..0f7c4dae1 100644 --- a/matlab/finufft2d3.m +++ b/matlab/finufft2d3.m @@ -45,9 +45,14 @@ function f = finufft2d3(x,y,c,isign,eps,s,t,o) if nargin<8, o.dummy=1; end -valid_setpts(3,2,x,y,[],s,t,[]); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,3,2,x,y,[],s,t,[]); +o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(3,2,isign,n_transf,eps,o); +if is_gpuarray + p = cufinufft_plan(3,2,isign,n_transf,eps,o); +else + p = finufft_plan(3,2,isign,n_transf,eps,o); +end p.setpts(x,y,[],s,t,[]); f = p.execute(c); diff --git a/matlab/finufft3d1.m b/matlab/finufft3d1.m index 71cf358cb..73be3a6ff 100644 --- a/matlab/finufft3d1.m +++ b/matlab/finufft3d1.m @@ -54,9 +54,14 @@ function f = finufft3d1(x,y,z,c,isign,eps,ms,mt,mu,o) if nargin<10, o.dummy=1; end -valid_setpts(1,3,x,y,z); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,1,3,x,y,z); +o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(1,[ms;mt;mu],isign,n_transf,eps,o); +if is_gpuarray + p = cufinufft_plan(1,[ms;mt;mu],isign,n_transf,eps,o); +else + p = finufft_plan(1,[ms;mt;mu],isign,n_transf,eps,o); +end p.setpts(x,y,z); f = p.execute(c); diff --git a/matlab/finufft3d2.m b/matlab/finufft3d2.m index ba1ab61f5..a0282b96c 100644 --- a/matlab/finufft3d2.m +++ b/matlab/finufft3d2.m @@ -50,9 +50,14 @@ function c = finufft3d2(x,y,z,isign,eps,f,o) if nargin<7, o.dummy=1; end -valid_setpts(2,3,x,y,z); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,2,3,x,y,z); +o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,mt,mu,n_transf] = size(f); % if f 3D array, n_transf=1 -p = finufft_plan(2,[ms;mt;mu],isign,n_transf,eps,o); +if is_gpuarray + p = cufinufft_plan(2,[ms;mt;mu],isign,n_transf,eps,o); +else + p = finufft_plan(2,[ms;mt;mu],isign,n_transf,eps,o); +end p.setpts(x,y,z); c = p.execute(f); diff --git a/matlab/finufft3d3.m b/matlab/finufft3d3.m index a18129b7f..8219f3c5f 100644 --- a/matlab/finufft3d3.m +++ b/matlab/finufft3d3.m @@ -46,10 +46,14 @@ function f = finufft3d3(x,y,z,c,isign,eps,s,t,u,o) if nargin<10, o.dummy=1; end -valid_setpts(3,3,x,y,z,s,t,u); -o.floatprec=class(x); % should be 'double' or 'single' +is_gpuarray = isgpuarray(x); +valid_setpts(is_gpuarray,3,3,x,y,z,s,t,u); +o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); -p = finufft_plan(3,3,isign,n_transf,eps,o); +if is_gpuarray + p = cufinufft_plan(3,3,isign,n_transf,eps,o); +else + p = finufft_plan(3,3,isign,n_transf,eps,o); +end p.setpts(x,y,z,s,t,u); f = p.execute(c); - diff --git a/matlab/valid_ntr.m b/matlab/valid_ntr.m index c6eaaf2cf..e4fe36ecf 100644 --- a/matlab/valid_ntr.m +++ b/matlab/valid_ntr.m @@ -1,5 +1,10 @@ function n_transf = valid_ntr(x,c); % VALID_NTR deduce n_transforms and validate the size of c, for types 1 and 3. +% also check for array device consistency. + +if isgpuarray(x) ~= isgpuarray(c) + error('FINUFFT:mixedDevice','FINUFFT: x and c must be both on GPU or CPU'); +end n_transf = round(numel(c)/numel(x)); % this allows general row/col vec, matrix, input shapes if n_transf*numel(x)~=numel(c) diff --git a/matlab/valid_setpts.m b/matlab/valid_setpts.m index 0b0eef28a..5cdeafa53 100644 --- a/matlab/valid_setpts.m +++ b/matlab/valid_setpts.m @@ -1,37 +1,45 @@ -function [nj, nk] = valid_setpts(type,dim,x,y,z,s,t,u) +function [nj, nk] = valid_setpts(is_gpuarray,type,dim,x,y,z,s,t,u) % VALID_SETPTS validate guru finufft_setpts input sizes for a type and dim +% is_gpuarray should be 1 if data is expected on gpu, or 0 if on cpu % -% [nj nk] = valid_setpts(type,dim,x,y,z,s,t,u) raises errors if there are +% [nj nk] = valid_setpts(is_gpuarray,type,dim,x,y,z,s,t,u) raises errors if there are % incompatible input sizes for transform type (1, 2 or 3) and dimension dim, -% and returns nj (aka M), and, for type 3, also nk (aka N). The returned +% and returns nj (aka M), and, for type 3, also nk (aka N). It also checks if the arrays +% are on the expected device, is_gpuarray 0 for cpu, 1 for gpu. The returned % values are int64 (not the usual double class of numel). % -% nj = valid_setpts(type,dim,x,y,z) is also allowed for types 1, 2. +% nj = valid_setpts(is_gpuarray,type,dim,x,y,z) is also allowed for types 1, 2. % Barnett 6/19/20, split out from guru so simple ints can check before plan. % s,t,u are only checked for type 3. -% note that isvector([]) is false. +% note that isvector([]) is false, isgpuarray([]) is false, isgpuarray(gpuArray([])) if true. if ~isvector(x), error('FINUFFT:badXshape','FINUFFT x must be a vector'); end +if isgpuarray(x) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end nj = numel(x); if type==3 nk = numel(s); if ~isvector(s), error('FINUFFT:badSshape','FINUFFT s must be a vector'); end + if isgpuarray(s) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end else nk = 0; % dummy output end if dim>1 if ~isvector(y), error('FINUFFT:badYshape','FINUFFT y must be a vector'); end + if isgpuarray(y) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(y)~=nj, error('FINUFFT:badYlen','FINUFFT y must have same length as x'); end if type==3 if ~isvector(t), error('FINUFFT:badTshape','FINUFFT t must be a vector'); end + if isgpuarray(t) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(t)~=nk, error('FINUFFT:badTlen','FINUFFT t must have same length as s'); end end -end +end if dim>2 if ~isvector(z), error('FINUFFT:badZshape','FINUFFT z must be a vector'); end + if isgpuarray(z) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(z)~=nj, error('FINUFFT:badZlen','FINUFFT z must have same length as x'); end if type==3 if ~isvector(u), error('FINUFFT:badUshape','FINUFFT u must be a vector'); end + if isgpuarray(u) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(u)~=nk, error('FINUFFT:badUlen','FINUFFT u must have same length as s'); end end -end +end From 799d0d021d0ca18b956ff846d1c83d302fe64215 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 17:46:20 -0500 Subject: [PATCH 03/11] add math check matlab guru1d1, move to examples --- matlab/{ => examples}/guru1d1_gpu.m | 7 +++++++ matlab/{ => examples}/guru2d1_gpu.m | 0 2 files changed, 7 insertions(+) rename matlab/{ => examples}/guru1d1_gpu.m (80%) rename matlab/{ => examples}/guru2d1_gpu.m (100%) diff --git a/matlab/guru1d1_gpu.m b/matlab/examples/guru1d1_gpu.m similarity index 80% rename from matlab/guru1d1_gpu.m rename to matlab/examples/guru1d1_gpu.m index 054158485..12c7be987 100644 --- a/matlab/guru1d1_gpu.m +++ b/matlab/examples/guru1d1_gpu.m @@ -44,6 +44,13 @@ %f(1:10) %fg(1:10) +% check the error of one output... +nt = ceil(0.37*N); % pick a mode index +t = ceil(0.7*ntrans); % pick a transform in stack +fe = sum(c(M*(t-1)+(1:M)).*exp(1i*isign*nt*x)); % exact +of1 = floor(N/2) + 1 + N*(t-1); % mode index offset +fprintf('rel err in F[%d] is %.3g\n',nt,abs(fe-fg(nt+of1))/norm(fg,Inf)) + % if you do not want to do more transforms of this size, clean up... delete(plan); delete(plang); diff --git a/matlab/guru2d1_gpu.m b/matlab/examples/guru2d1_gpu.m similarity index 100% rename from matlab/guru2d1_gpu.m rename to matlab/examples/guru2d1_gpu.m From 6642bc6d11bbaff49ec9815dff892bfe818238e8 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 17:52:00 -0500 Subject: [PATCH 04/11] add mwrap generated files --- matlab/cufinufft.cu | 2407 ++++++++++++++++++++++++ matlab/cufinufft_plan.m | 194 ++ matlab/finufft.cpp | 3826 ++++++++++++++++++++++----------------- matlab/finufft_plan.m | 197 +- 4 files changed, 4746 insertions(+), 1878 deletions(-) create mode 100644 matlab/cufinufft.cu create mode 100644 matlab/cufinufft_plan.m diff --git a/matlab/cufinufft.cu b/matlab/cufinufft.cu new file mode 100644 index 000000000..b785e94ce --- /dev/null +++ b/matlab/cufinufft.cu @@ -0,0 +1,2407 @@ +/* --------------------------------------------------- */ +/* Automatically generated by mwrap */ +/* --------------------------------------------------- */ + +/* Code generated by mwrap 1.1 */ +/* + Copyright statement for mwrap: + + mwrap -- MEX file generation for MATLAB and Octave + Copyright (c) 2007-2008 David Bindel + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + You may distribute a work that contains part or all of the source code + generated by mwrap under the terms of your choice. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#include +#include + +#include + +#if MX_HAS_INTERLEAVED_COMPLEX +#include +#endif + + +/* + * Records for call profile. + */ +int* mexprofrecord_= NULL; + +double mxWrapGetChar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxCHAR_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid char argument"; + return 0; + } + return (char) (*mxGetChars(a)); +} + +/* + * Support routines for copying data into and out of the MEX stubs, R2018a + */ + +#if MX_HAS_INTERLEAVED_COMPLEX + +void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) +{ + void* p = NULL; +#ifdef R2008OO + mxArray* ap; +#endif + if (mxGetClassID(a) == mxDOUBLE_CLASS && mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexDoubles(a)).real == 0 ) + return NULL; + } + if (mxGetClassID(a) == mxDOUBLE_CLASS && !mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && *mxGetDoubles(a) == 0) + return NULL; + } + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } +#ifdef R2008OO + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } +#endif + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetDoubles(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetDoubles(z) = 0; + return z; + } +} + +char* mxWrapGetString(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +double mxWrapGetScalar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + if( mxIsComplex(a) ) + return (double) (*mxGetComplexDoubles(a)).real; + else + return (double) (*mxGetDoubles(a)); +} + +#define mxWrapGetArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + mxComplexDouble* z; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*z++).real; \ + } \ + else \ + { \ + q = mxGetDoubles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + } \ + return array; \ +} + + +#define mxWrapCopyDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + mxComplexDouble* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < n; ++i) \ + (*z++).real = (double) *q++; \ + (*z++).imag = 0; \ + } \ + else \ + { \ + p = mxGetDoubles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = (double) *q++; \ + } \ +} + + +#define mxWrapReturnDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetDoubles(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = (double) *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + if( mxIsComplex(a) ) \ + { \ + setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) (*mxGetComplexDoubles(a)).imag); \ + } \ + else \ + { \ + setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) 0); \ + } \ +} + + +#define mxWrapGetArrayZDef(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + mxComplexDouble* z; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ + ++p; ++z; } \ + } \ + else \ + { \ + q = mxGetDoubles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*q), (ZT) 0 ); \ + ++p; ++q; } \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef(func, T, freal, fimag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + mxComplexDouble* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < n; ++i) { \ + (*z).real = freal(*q); \ + (*z).imag = fimag(*q); \ + ++z; ++q; } \ + } \ + else \ + { \ + p = mxGetDoubles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = freal(*q++); \ + } \ +} + + +#define mxWrapReturnZDef(func, T, freal, fimag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + mxComplexDouble* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ + p = mxGetComplexDoubles(a); \ + for (i = 0; i < m*n; ++i) { \ + (*p).real = freal(*q); \ + (*p).imag = fimag(*q); \ + ++p; ++q; } \ + return a; \ + } \ +} + + + + + + +void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) +{ + void* p = NULL; +#ifdef R2008OO + mxArray* ap; +#endif + if (mxGetClassID(a) == mxSINGLE_CLASS && mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexSingles(a)).real == 0 ) + return NULL; + } + if (mxGetClassID(a) == mxSINGLE_CLASS && !mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && *mxGetSingles(a) == 0) + return NULL; + } + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } +#ifdef R2008OO + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } +#endif + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP_single(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *mxGetSingles(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy_single(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *mxGetSingles(z) = 0; + return z; + } +} + +float mxWrapGetScalar_single(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + if( mxIsComplex(a) ) + return (float) (*mxGetComplexSingles(a)).real; + else + return (float) (*mxGetSingles(a)); +} + + +char* mxWrapGetString_single(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + +#define mxWrapGetArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + mxComplexSingle* z; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*z++).real; \ + } \ + else \ + { \ + q = mxGetSingles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + } \ + return array; \ +} + + +#define mxWrapCopyDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + mxComplexSingle* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < n; ++i) \ + (*z++).real = (float) *q++; \ + (*z++).imag = 0; \ + } \ + else \ + { \ + p = mxGetSingles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = (float) *q++; \ + } \ +} + + +#define mxWrapReturnDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL); \ + p = mxGetSingles(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = (float) *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + if( mxIsComplex(a) ) \ + { \ + setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) (*mxGetComplexSingles(a)).imag); \ + } \ + else \ + { \ + setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) 0); \ + } \ +} + + +#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + mxComplexSingle* z; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ + ++p; ++z; } \ + } \ + else \ + { \ + q = mxGetSingles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*q), (ZT) 0 ); \ + ++p; ++q; } \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef_single(func, T, freal, fimag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + mxComplexSingle* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < n; ++i) { \ + (*z).real = freal(*q); \ + (*z).imag = fimag(*q); \ + ++z; ++q; } \ + } \ + else \ + { \ + p = mxGetSingles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = freal(*q++); \ + } \ +} + + +#define mxWrapReturnZDef_single(func, T, freal, fimag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + mxComplexSingle* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX); \ + p = mxGetComplexSingles(a); \ + for (i = 0; i < m*n; ++i) { \ + (*p).real = freal(*q); \ + (*p).imag = fimag(*q); \ + ++p; ++q; } \ + return a; \ + } \ +} + + + +#else + +/* + * Support routines for copying data into and out of the MEX stubs, -R2017b + */ + +void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) +{ + void* p = 0; +#ifdef R2008OO + mxArray* ap; +#endif + if (mxGetClassID(a) == mxDOUBLE_CLASS && + mxGetM(a)*mxGetN(a) == 1 && *mxGetPr(a) == 0) + return p; + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } +#ifdef R2008OO + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } +#endif + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetPr(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetPr(z) = 0; + return z; + } +} + +double mxWrapGetScalar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + return *mxGetPr(a); +} + +char* mxWrapGetString(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +#define mxWrapGetArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + double* pr = mxGetPr(a); \ + double* pi = mxGetPi(a); \ + setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ +} + + +#define mxWrapGetArrayZDef(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* qr; \ + double* qi; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + qr = mxGetPr(a); \ + qi = mxGetPi(a); \ + for (i = 0; i < arraylen; ++i) { \ + ZT val_qr = *qr++; \ + ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ + setz(p, val_qr, val_qi); \ + ++p; \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef(func, T, real, imag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* pr = mxGetPr(a); \ + double* pi = mxGetPi(a); \ + for (i = 0; i < n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ +} + + +#define mxWrapReturnZDef(func, T, real, imag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* pr; \ + double* pi; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ + pr = mxGetPr(a); \ + pi = mxGetPi(a); \ + for (i = 0; i < m*n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ + return a; \ + } \ +} + + + + + + +void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) +{ + void* p = 0; +#ifdef R2008OO + mxArray* ap; +#endif + if (mxGetClassID(a) == mxSINGLE_CLASS && + mxGetM(a)*mxGetN(a) == 1 && *((float*)mxGetData(a)) == 0) + return p; + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } +#ifdef R2008OO + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } +#endif + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP_single(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *((float*)mxGetData(z)) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} +mxArray* mxWrapStrncpy_single(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *((float*)mxGetData(z)) = 0; + return z; + } +} + +float mxWrapGetScalar_single(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + return *((float*)mxGetData(a)); +} + +char* mxWrapGetString_single(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument, mxSINGLE_CLASS expected"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +#define mxWrapGetArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = (float*) mxGetData(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p = (float*) mxGetData(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL);\ + p = (float*) mxGetData(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + float* pr = (float*) mxGetData(a); \ + float* pi = (float*) mxGetImagData(a); \ + setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ +} + + +#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* qr; \ + float* qi; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + qr = (float*) mxGetData(a); \ + qi = (float*) mxGetImagData(a); \ + for (i = 0; i < arraylen; ++i) { \ + ZT val_qr = *qr++; \ + ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ + setz(p, val_qr, val_qi); \ + ++p; \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef_single(func, T, real, imag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* pr = (float*) mxGetData(a); \ + float* pi = (float*) mxGetImagData(a); \ + for (i = 0; i < n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ +} + + +#define mxWrapReturnZDef_single(func, T, real, imag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* pr; \ + float* pi; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX);\ + pr = (float*) mxGetData(a); \ + pi = (float*) mxGetImagData(a); \ + for (i = 0; i < m*n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ + return a; \ + } \ +} + + + + + +#endif + +#define mxWrapGetGPUArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyGPUArrayDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnGPUArrayDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapReturnGPUArrayPDef(func, T) \ +T* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapGetGPUArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyGPUArrayDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnGPUArrayDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapReturnGPUArrayPDef_single(func, T) \ +T* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#include + +#include + +#include + +typedef std::complex dcomplex; +#define real_dcomplex(z) std::real(z) +#define imag_dcomplex(z) std::imag(z) +#define setz_dcomplex(z,r,i) *z = dcomplex(r,i) + +typedef std::complex fcomplex; +#define real_fcomplex(z) std::real(z) +#define imag_fcomplex(z) std::imag(z) +#define setz_fcomplex(z,r,i) *z = fcomplex(r,i) + + #include + #include + #include + #include + #include + void copy_cufinufft_opts(const mxArray* om, cufinufft_opts *oc) { + if(!mxIsStruct(om)) + mexErrMsgIdAndTxt("FINUFFT:inputNotStruct","opts input must be a structure."); + mwIndex idx = 0; + int ifield, nfields; + const char **fname; + nfields = mxGetNumberOfFields(om); + fname = (const char**)mxCalloc(nfields, sizeof(*fname)); + for(ifield=0; ifielddebug = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_sort") == 0) { + oc->gpu_sort = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_kerevalmeth") == 0) { + oc->gpu_kerevalmeth = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_spreadinterponly") == 0) { + oc->gpu_spreadinterponly = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"modeord") == 0) { + oc->modeord = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"upsampfac") == 0) { + oc->upsampfac = (double)*mxGetPr(mxGetFieldByNumber(om,idx,ifield)); + } + else if (strcmp(fname[ifield],"gpu_maxbatchsize") == 0) { + oc->gpu_maxbatchsize = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_maxsubprobsize") == 0) { + oc->gpu_maxsubprobsize = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_method") == 0) { + oc->gpu_method = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_binsizex") == 0) { + oc->gpu_binsizex = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_binsizey") == 0) { + oc->gpu_binsizey = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_binsizez") == 0) { + oc->gpu_binsizez = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"gpu_device_id") == 0) { + oc->gpu_device_id = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else + continue; + } + mxFree(fname); + } + + + +/* Array copier definitions */ +mxWrapGetArrayDef(mxWrapGetArray_bool, bool) +mxWrapCopyDef (mxWrapCopy_bool, bool) +mxWrapReturnDef (mxWrapReturn_bool, bool) +mxWrapGetArrayDef_single(mxWrapGetArray_single_bool, bool) +mxWrapCopyDef_single (mxWrapCopy_single_bool, bool) +mxWrapReturnDef_single (mxWrapReturn_single_bool, bool) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_bool, bool) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_bool, bool) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_bool, bool) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_bool, bool) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_bool, bool) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_bool, bool) +mxWrapGetArrayDef(mxWrapGetArray_char, char) +mxWrapCopyDef (mxWrapCopy_char, char) +mxWrapReturnDef (mxWrapReturn_char, char) +mxWrapGetArrayDef_single(mxWrapGetArray_single_char, char) +mxWrapCopyDef_single (mxWrapCopy_single_char, char) +mxWrapReturnDef_single (mxWrapReturn_single_char, char) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_char, char) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_char, char) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_char, char) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_char, char) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_char, char) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_char, char) +mxWrapGetArrayDef(mxWrapGetArray_double, double) +mxWrapCopyDef (mxWrapCopy_double, double) +mxWrapReturnDef (mxWrapReturn_double, double) +mxWrapGetArrayDef_single(mxWrapGetArray_single_double, double) +mxWrapCopyDef_single (mxWrapCopy_single_double, double) +mxWrapReturnDef_single (mxWrapReturn_single_double, double) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_double, double) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_double, double) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_double, double) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_double, double) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_double, double) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_double, double) +mxWrapGetArrayDef(mxWrapGetArray_float, float) +mxWrapCopyDef (mxWrapCopy_float, float) +mxWrapReturnDef (mxWrapReturn_float, float) +mxWrapGetArrayDef_single(mxWrapGetArray_single_float, float) +mxWrapCopyDef_single (mxWrapCopy_single_float, float) +mxWrapReturnDef_single (mxWrapReturn_single_float, float) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_float, float) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_float, float) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_float, float) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_float, float) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_float, float) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_float, float) +mxWrapGetArrayDef(mxWrapGetArray_int, int) +mxWrapCopyDef (mxWrapCopy_int, int) +mxWrapReturnDef (mxWrapReturn_int, int) +mxWrapGetArrayDef_single(mxWrapGetArray_single_int, int) +mxWrapCopyDef_single (mxWrapCopy_single_int, int) +mxWrapReturnDef_single (mxWrapReturn_single_int, int) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_int, int) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_int, int) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_int, int) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_int, int) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_int, int) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_int, int) +mxWrapGetArrayDef(mxWrapGetArray_int64_t, int64_t) +mxWrapCopyDef (mxWrapCopy_int64_t, int64_t) +mxWrapReturnDef (mxWrapReturn_int64_t, int64_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_int64_t, int64_t) +mxWrapCopyDef_single (mxWrapCopy_single_int64_t, int64_t) +mxWrapReturnDef_single (mxWrapReturn_single_int64_t, int64_t) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_int64_t, int64_t) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_int64_t, int64_t) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_int64_t, int64_t) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_int64_t, int64_t) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_int64_t, int64_t) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_int64_t, int64_t) +mxWrapGetArrayDef(mxWrapGetArray_long, long) +mxWrapCopyDef (mxWrapCopy_long, long) +mxWrapReturnDef (mxWrapReturn_long, long) +mxWrapGetArrayDef_single(mxWrapGetArray_single_long, long) +mxWrapCopyDef_single (mxWrapCopy_single_long, long) +mxWrapReturnDef_single (mxWrapReturn_single_long, long) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_long, long) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_long, long) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_long, long) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_long, long) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_long, long) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_long, long) +mxWrapGetArrayDef(mxWrapGetArray_ptrdiff_t, ptrdiff_t) +mxWrapCopyDef (mxWrapCopy_ptrdiff_t, ptrdiff_t) +mxWrapReturnDef (mxWrapReturn_ptrdiff_t, ptrdiff_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_ptrdiff_t, ptrdiff_t) +mxWrapCopyDef_single (mxWrapCopy_single_ptrdiff_t, ptrdiff_t) +mxWrapReturnDef_single (mxWrapReturn_single_ptrdiff_t, ptrdiff_t) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_ptrdiff_t, ptrdiff_t) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_ptrdiff_t, ptrdiff_t) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_ptrdiff_t, ptrdiff_t) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_ptrdiff_t, ptrdiff_t) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_ptrdiff_t, ptrdiff_t) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_ptrdiff_t, ptrdiff_t) +mxWrapGetArrayDef(mxWrapGetArray_short, short) +mxWrapCopyDef (mxWrapCopy_short, short) +mxWrapReturnDef (mxWrapReturn_short, short) +mxWrapGetArrayDef_single(mxWrapGetArray_single_short, short) +mxWrapCopyDef_single (mxWrapCopy_single_short, short) +mxWrapReturnDef_single (mxWrapReturn_single_short, short) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_short, short) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_short, short) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_short, short) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_short, short) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_short, short) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_short, short) +mxWrapGetArrayDef(mxWrapGetArray_size_t, size_t) +mxWrapCopyDef (mxWrapCopy_size_t, size_t) +mxWrapReturnDef (mxWrapReturn_size_t, size_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_size_t, size_t) +mxWrapCopyDef_single (mxWrapCopy_single_size_t, size_t) +mxWrapReturnDef_single (mxWrapReturn_single_size_t, size_t) +mxWrapGetGPUArrayDef(mxWrapGetGPUArray_size_t, size_t) +mxWrapCopyGPUArrayDef (mxWrapCopyGPUArray_size_t, size_t) +mxWrapReturnGPUArrayDef (mxWrapReturnGPUArray_size_t, size_t) +mxWrapGetGPUArrayDef_single(mxWrapGetGPUArray_single_size_t, size_t) +mxWrapCopyGPUArrayDef_single (mxWrapGPUArrayCopy_single_size_t, size_t) +mxWrapReturnGPUArrayDef_single (mxWrapReturnGPUArray_single_size_t, size_t) +mxWrapGetScalarZDef(mxWrapGetScalar_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapGetArrayZDef (mxWrapGetArray_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapCopyZDef (mxWrapCopy_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapReturnZDef (mxWrapReturn_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapGetScalarZDef_single(mxWrapGetScalar_single_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapGetArrayZDef_single (mxWrapGetArray_single_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapCopyZDef_single (mxWrapCopy_single_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapReturnZDef_single (mxWrapReturn_single_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapGetScalarZDef(mxWrapGetScalar_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapGetArrayZDef (mxWrapGetArray_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapCopyZDef (mxWrapCopy_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapReturnZDef (mxWrapReturn_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapGetScalarZDef_single(mxWrapGetScalar_single_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapGetArrayZDef_single (mxWrapGetArray_single_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapCopyZDef_single (mxWrapCopy_single_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapReturnZDef_single (mxWrapReturn_single_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) + +/* ---- cufinufft.mw: 143 ---- + * cufinufft_opts* o = new(); + */ +static const char* stubids1_ = "c o cufinufft_opts* = new()"; + +void mexStub1(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_opts* out0_=0; /* o */ + + if (mexprofrecord_) + mexprofrecord_[1]++; + out0_ = new cufinufft_opts(); + plhs[0] = mxWrapCreateP(out0_, "cufinufft_opts:%p"); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 145 ---- + * cufinufft_plan* p = new(); + */ +static const char* stubids2_ = "c o cufinufft_plan* = new()"; + +void mexStub2(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* out0_=0; /* p */ + + if (mexprofrecord_) + mexprofrecord_[2]++; + out0_ = new cufinufft_plan(); + plhs[0] = mxWrapCreateP(out0_, "cufinufft_plan:%p"); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 146 ---- + * cufinufft_default_opts(cufinufft_opts* o); + * Also at cufinufft.mw: 149 + */ +static const char* stubids3_ = "cufinufft_default_opts(c i cufinufft_opts*)"; + +void mexStub3(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_opts* in0_ =0; /* o */ + + in0_ = (cufinufft_opts*) mxWrapGetP(prhs[0], "cufinufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[3]++; + cufinufft_default_opts(in0_); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 148 ---- + * cufinufftf_plan* p = new(); + */ +static const char* stubids4_ = "c o cufinufftf_plan* = new()"; + +void mexStub4(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* out0_=0; /* p */ + + if (mexprofrecord_) + mexprofrecord_[4]++; + out0_ = new cufinufftf_plan(); + plhs[0] = mxWrapCreateP(out0_, "cufinufftf_plan:%p"); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 160 ---- + * copy_cufinufft_opts(mxArray opts, cufinufft_opts* o); + */ +static const char* stubids6_ = "copy_cufinufft_opts(c i mxArray, c i cufinufft_opts*)"; + +void mexStub6(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + const mxArray* in0_; /* opts */ + cufinufft_opts* in1_ =0; /* o */ + + in0_ = prhs[0]; + + in1_ = (cufinufft_opts*) mxWrapGetP(prhs[1], "cufinufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[6]++; + copy_cufinufft_opts(in0_, in1_); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 163 ---- + * int ier = cufinufft_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, double tol, cufinufft_plan* plan, cufinufft_opts* o); + */ +static const char* stubids7_ = "c o int = cufinufft_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i double, c i cufinufft_plan*, c i cufinufft_opts*)"; + +void mexStub7(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + int in0_; /* type */ + int in1_; /* dim */ + int64_t* in2_ =0; /* n_modes */ + int in3_; /* iflag */ + int in4_; /* n_trans */ + double in5_; /* tol */ + cufinufft_plan* in6_ =0; /* plan */ + cufinufft_opts* in7_ =0; /* o */ + int out0_; /* ier */ + mwSize dim8_; /* 3 */ + + dim8_ = (mwSize) mxWrapGetScalar(prhs[8], &mw_err_txt_); + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != dim8_) { + mw_err_txt_ = "Bad argument size: n_modes"; goto mw_err_label; + } + + if( mxGetClassID(prhs[0]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in0_ = (int) mxWrapGetScalar(prhs[0], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in2_ = NULL; + + if( mxGetClassID(prhs[3]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in3_ = (int) mxWrapGetScalar(prhs[3], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[4]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in4_ = (int) mxWrapGetScalar(prhs[4], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in5_ = (double) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in6_ = (cufinufft_plan*) mxWrapGetP(prhs[6], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in7_ = (cufinufft_opts*) mxWrapGetP(prhs[7], "cufinufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[7]++; + out0_ = cufinufft_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + +mw_err_label: + if (in2_) mxFree(in2_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 166 ---- + * int ier = cufinufftf_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, float tol, cufinufftf_plan* plan, cufinufft_opts* o); + */ +static const char* stubids8_ = "c o int = cufinufftf_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i float, c i cufinufftf_plan*, c i cufinufft_opts*)"; + +void mexStub8(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + int in0_; /* type */ + int in1_; /* dim */ + int64_t* in2_ =0; /* n_modes */ + int in3_; /* iflag */ + int in4_; /* n_trans */ + float in5_; /* tol */ + cufinufftf_plan* in6_ =0; /* plan */ + cufinufft_opts* in7_ =0; /* o */ + int out0_; /* ier */ + mwSize dim8_; /* 3 */ + + dim8_ = (mwSize) mxWrapGetScalar(prhs[8], &mw_err_txt_); + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != dim8_) { + mw_err_txt_ = "Bad argument size: n_modes"; goto mw_err_label; + } + + if( mxGetClassID(prhs[0]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in0_ = (int) mxWrapGetScalar(prhs[0], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in2_ = NULL; + + if( mxGetClassID(prhs[3]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in3_ = (int) mxWrapGetScalar(prhs[3], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[4]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in4_ = (int) mxWrapGetScalar(prhs[4], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[5]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in5_ = (float) mxWrapGetScalar_single(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in6_ = (cufinufftf_plan*) mxWrapGetP(prhs[6], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in7_ = (cufinufft_opts*) mxWrapGetP(prhs[7], "cufinufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[8]++; + out0_ = cufinufftf_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + +mw_err_label: + if (in2_) mxFree(in2_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 168 ---- + * delete(cufinufft_opts* o); + */ +static const char* stubids9_ = "delete(c i cufinufft_opts*)"; + +void mexStub9(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_opts* in0_ =0; /* o */ + + in0_ = (cufinufft_opts*) mxWrapGetP(prhs[0], "cufinufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[9]++; + delete(in0_); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 198 ---- + * int ier = cufinufft_setpts(cufinufft_plan plan, int nj, gpu double[] xj, gpu double[] yj, gpu double[] zj, int nk, gpu double[] s, gpu double[] t, gpu double[] u); + */ +static const char* stubids10_ = "c o int = cufinufft_setpts(c i cufinufft_plan, c i int, g i double[], g i double[], g i double[], c i int, g i double[], g i double[], g i double[])"; + +void mexStub10(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* in0_ =0; /* plan */ + int in1_; /* nj */ + double* in2_ =0; /* xj */ + mxGPUArray const *mxGPUArray_in2_ =0; /* xj */ + double* in3_ =0; /* yj */ + mxGPUArray const *mxGPUArray_in3_ =0; /* yj */ + double* in4_ =0; /* zj */ + mxGPUArray const *mxGPUArray_in4_ =0; /* zj */ + int in5_; /* nk */ + double* in6_ =0; /* s */ + mxGPUArray const *mxGPUArray_in6_ =0; /* s */ + double* in7_ =0; /* t */ + mxGPUArray const *mxGPUArray_in7_ =0; /* t */ + double* in8_ =0; /* u */ + mxGPUArray const *mxGPUArray_in8_ =0; /* u */ + int out0_; /* ier */ + + in0_ = (cufinufft_plan*) mxWrapGetP(prhs[0], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[2]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in2_ = mxGPUCreateFromMxArray(prhs[2]); + in2_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in2_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[3]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in3_ = mxGPUCreateFromMxArray(prhs[3]); + in3_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in3_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[4]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in4_ = mxGPUCreateFromMxArray(prhs[4]); + in4_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in4_); + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in5_ = (int) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[6]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in6_ = mxGPUCreateFromMxArray(prhs[6]); + in6_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in6_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[7]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in7_ = mxGPUCreateFromMxArray(prhs[7]); + in7_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in7_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[8]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in8_ = mxGPUCreateFromMxArray(prhs[8]); + in8_ = (double *)mxGPUGetDataReadOnly(mxGPUArray_in8_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[10]++; + out0_ = cufinufft_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + +mw_err_label: + if (mxGPUArray_in2_) mxGPUDestroyGPUArray(mxGPUArray_in2_); + if (mxGPUArray_in3_) mxGPUDestroyGPUArray(mxGPUArray_in3_); + if (mxGPUArray_in4_) mxGPUDestroyGPUArray(mxGPUArray_in4_); + if (mxGPUArray_in6_) mxGPUDestroyGPUArray(mxGPUArray_in6_); + if (mxGPUArray_in7_) mxGPUDestroyGPUArray(mxGPUArray_in7_); + if (mxGPUArray_in8_) mxGPUDestroyGPUArray(mxGPUArray_in8_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 200 ---- + * int ier = cufinufftf_setpts(cufinufftf_plan plan, int nj, gpu float[] xj, gpu float[] yj, gpu float[] zj, int nk, gpu float[] s, gpu float[] t, gpu float[] u); + */ +static const char* stubids11_ = "c o int = cufinufftf_setpts(c i cufinufftf_plan, c i int, g i float[], g i float[], g i float[], c i int, g i float[], g i float[], g i float[])"; + +void mexStub11(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* in0_ =0; /* plan */ + int in1_; /* nj */ + float* in2_ =0; /* xj */ + mxGPUArray const *mxGPUArray_in2_ =0; /* xj */ + float* in3_ =0; /* yj */ + mxGPUArray const *mxGPUArray_in3_ =0; /* yj */ + float* in4_ =0; /* zj */ + mxGPUArray const *mxGPUArray_in4_ =0; /* zj */ + int in5_; /* nk */ + float* in6_ =0; /* s */ + mxGPUArray const *mxGPUArray_in6_ =0; /* s */ + float* in7_ =0; /* t */ + mxGPUArray const *mxGPUArray_in7_ =0; /* t */ + float* in8_ =0; /* u */ + mxGPUArray const *mxGPUArray_in8_ =0; /* u */ + int out0_; /* ier */ + + in0_ = (cufinufftf_plan*) mxWrapGetP(prhs[0], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[2]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in2_ = mxGPUCreateFromMxArray(prhs[2]); + in2_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in2_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[3]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in3_ = mxGPUCreateFromMxArray(prhs[3]); + in3_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in3_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[4]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in4_ = mxGPUCreateFromMxArray(prhs[4]); + in4_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in4_); + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in5_ = (int) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[6]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in6_ = mxGPUCreateFromMxArray(prhs[6]); + in6_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in6_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[7]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in7_ = mxGPUCreateFromMxArray(prhs[7]); + in7_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in7_); + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[8]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in8_ = mxGPUCreateFromMxArray(prhs[8]); + in8_ = (float *)mxGPUGetDataReadOnly(mxGPUArray_in8_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[11]++; + out0_ = cufinufftf_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + +mw_err_label: + if (mxGPUArray_in2_) mxGPUDestroyGPUArray(mxGPUArray_in2_); + if (mxGPUArray_in3_) mxGPUDestroyGPUArray(mxGPUArray_in3_); + if (mxGPUArray_in4_) mxGPUDestroyGPUArray(mxGPUArray_in4_); + if (mxGPUArray_in6_) mxGPUDestroyGPUArray(mxGPUArray_in6_); + if (mxGPUArray_in7_) mxGPUDestroyGPUArray(mxGPUArray_in7_); + if (mxGPUArray_in8_) mxGPUDestroyGPUArray(mxGPUArray_in8_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 232 ---- + * int ier = cufinufft_execute(cufinufft_plan plan, gpu dcomplex[] data_in, gpu output dcomplex[ncoeffs] result); + */ +static const char* stubids12_ = "c o int = cufinufft_execute(c i cufinufft_plan, g i dcomplex[], g o dcomplex[x])"; + +void mexStub12(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* in0_ =0; /* plan */ + cuDoubleComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuDoubleComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* ncoeffs */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + + in0_ = (cufinufft_plan*) mxWrapGetP(prhs[0], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuDoubleComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(1, gpu_outdims1_, mxDOUBLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuDoubleComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[12]++; + out0_ = cufinufft_execute(*in0_, in1_, out1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 234 ---- + * int ier = cufinufftf_execute(cufinufftf_plan plan, gpu fcomplex[] data_in, gpu output fcomplex[ncoeffs] result); + */ +static const char* stubids13_ = "c o int = cufinufftf_execute(c i cufinufftf_plan, g i fcomplex[], g o fcomplex[x])"; + +void mexStub13(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* in0_ =0; /* plan */ + cuFloatComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuFloatComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* ncoeffs */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + + in0_ = (cufinufftf_plan*) mxWrapGetP(prhs[0], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuFloatComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(1, gpu_outdims1_, mxSINGLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuFloatComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[13]++; + out0_ = cufinufftf_execute(*in0_, in1_, out1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 240 ---- + * int ier = cufinufft_execute(cufinufft_plan plan, gpu output dcomplex[nj, n_trans] result, gpu dcomplex[] data_in); + */ +static const char* stubids14_ = "c o int = cufinufft_execute(c i cufinufft_plan, g o dcomplex[xx], g i dcomplex[])"; + +void mexStub14(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* in0_ =0; /* plan */ + cuDoubleComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuDoubleComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* nj */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (cufinufft_plan*) mxWrapGetP(prhs[0], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuDoubleComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; gpu_outdims1_[1] = dim3_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(2, gpu_outdims1_, mxDOUBLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuDoubleComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[14]++; + out0_ = cufinufft_execute(*in0_, out1_, in1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 242 ---- + * int ier = cufinufftf_execute(cufinufftf_plan plan, gpu output fcomplex[nj, n_trans] result, gpu fcomplex[] data_in); + */ +static const char* stubids15_ = "c o int = cufinufftf_execute(c i cufinufftf_plan, g o fcomplex[xx], g i fcomplex[])"; + +void mexStub15(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* in0_ =0; /* plan */ + cuFloatComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuFloatComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* nj */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (cufinufftf_plan*) mxWrapGetP(prhs[0], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuFloatComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; gpu_outdims1_[1] = dim3_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(2, gpu_outdims1_, mxSINGLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuFloatComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[15]++; + out0_ = cufinufftf_execute(*in0_, out1_, in1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 246 ---- + * int ier = cufinufft_execute(cufinufft_plan plan, gpu dcomplex[] data_in, gpu output dcomplex[nk, n_trans] result); + */ +static const char* stubids16_ = "c o int = cufinufft_execute(c i cufinufft_plan, g i dcomplex[], g o dcomplex[xx])"; + +void mexStub16(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* in0_ =0; /* plan */ + cuDoubleComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuDoubleComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* nk */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (cufinufft_plan*) mxWrapGetP(prhs[0], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuDoubleComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; gpu_outdims1_[1] = dim3_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(2, gpu_outdims1_, mxDOUBLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuDoubleComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[16]++; + out0_ = cufinufft_execute(*in0_, in1_, out1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 248 ---- + * int ier = cufinufftf_execute(cufinufftf_plan plan, gpu fcomplex[] data_in, gpu output fcomplex[nk, n_trans] result); + */ +static const char* stubids17_ = "c o int = cufinufftf_execute(c i cufinufftf_plan, g i fcomplex[], g o fcomplex[xx])"; + +void mexStub17(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* in0_ =0; /* plan */ + cuFloatComplex* in1_ =0; /* data_in */ + mxGPUArray const *mxGPUArray_in1_ =0; /* data_in */ + int out0_; /* ier */ + cuFloatComplex* out1_=0; /* result */ + mxGPUArray *mxGPUArray_out1_ =0; /* result */ + mwSize gpu_outdims1_[2] = {0,0}; /* result dims*/ + mwSize dim2_; /* nk */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (cufinufftf_plan*) mxWrapGetP(prhs[0], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + // extract input GPU array pointer + if(!(mxIsGPUArray(prhs[1]))) + mw_err_txt_ = "Invalid array argument, gpuArray expected"; + if (mw_err_txt_) goto mw_err_label; + mxGPUArray_in1_ = mxGPUCreateFromMxArray(prhs[1]); + in1_ = (cuFloatComplex *)mxGPUGetDataReadOnly(mxGPUArray_in1_); + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + gpu_outdims1_[0] = dim2_; gpu_outdims1_[1] = dim3_; + mxGPUArray_out1_ = mxGPUCreateGPUArray(2, gpu_outdims1_, mxSINGLE_CLASS, mxCOMPLEX, MX_GPU_DO_NOT_INITIALIZE); + out1_ = (cuFloatComplex *)mxGPUGetData(mxGPUArray_out1_); + + if (mexprofrecord_) + mexprofrecord_[17]++; + out0_ = cufinufftf_execute(*in0_, in1_, out1_); +#if MX_HAS_INTERLEAVED_COMPLEX + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; +#else + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; +#endif + plhs[1] = mxGPUCreateMxArrayOnGPU(mxGPUArray_out1_); + +mw_err_label: + if (mxGPUArray_in1_) mxGPUDestroyGPUArray(mxGPUArray_in1_); + if (mxGPUArray_out1_) mxGPUDestroyGPUArray(mxGPUArray_out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 260 ---- + * cufinufft_destroy(cufinufft_plan plan); + */ +static const char* stubids18_ = "cufinufft_destroy(c i cufinufft_plan)"; + +void mexStub18(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufft_plan* in0_ =0; /* plan */ + + in0_ = (cufinufft_plan*) mxWrapGetP(prhs[0], "cufinufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[18]++; + cufinufft_destroy(*in0_); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- cufinufft.mw: 262 ---- + * cufinufftf_destroy(cufinufftf_plan plan); + */ +static const char* stubids19_ = "cufinufftf_destroy(c i cufinufftf_plan)"; + +void mexStub19(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + cufinufftf_plan* in0_ =0; /* plan */ + + in0_ = (cufinufftf_plan*) mxWrapGetP(prhs[0], "cufinufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[19]++; + cufinufftf_destroy(*in0_); + +mw_err_label: + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); +} + +/* ---- + */ +void mexFunction(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + char id[1024]; + if (nrhs == 0) { + mexPrintf("Mex function installed\n"); + return; + } + + + mxInitGPU(); + + if (mxGetString(prhs[0], id, sizeof(id)) != 0) + mexErrMsgTxt("Identifier should be a string"); + else if (strcmp(id, stubids1_) == 0) + mexStub1(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids2_) == 0) + mexStub2(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids3_) == 0) + mexStub3(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids4_) == 0) + mexStub4(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids6_) == 0) + mexStub6(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids7_) == 0) + mexStub7(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids8_) == 0) + mexStub8(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids9_) == 0) + mexStub9(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids10_) == 0) + mexStub10(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids11_) == 0) + mexStub11(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids12_) == 0) + mexStub12(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids13_) == 0) + mexStub13(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids14_) == 0) + mexStub14(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids15_) == 0) + mexStub15(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids16_) == 0) + mexStub16(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids17_) == 0) + mexStub17(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids18_) == 0) + mexStub18(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids19_) == 0) + mexStub19(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, "*profile on*") == 0) { + if (!mexprofrecord_) { + mexprofrecord_ = (int*) malloc(20 * sizeof(int)); + mexLock(); + } + memset(mexprofrecord_, 0, 20 * sizeof(int)); + } else if (strcmp(id, "*profile off*") == 0) { + if (mexprofrecord_) { + free(mexprofrecord_); + mexUnlock(); + } + mexprofrecord_ = NULL; + } else if (strcmp(id, "*profile report*") == 0) { + if (!mexprofrecord_) + mexPrintf("Profiler inactive\n"); + mexPrintf("%d calls to cufinufft.mw:143\n", mexprofrecord_[1]); + mexPrintf("%d calls to cufinufft.mw:145\n", mexprofrecord_[2]); + mexPrintf("%d calls to cufinufft.mw:146 (cufinufft.mw:149)\n", mexprofrecord_[3]); + mexPrintf("%d calls to cufinufft.mw:148\n", mexprofrecord_[4]); + mexPrintf("%d calls to cufinufft.mw:160\n", mexprofrecord_[6]); + mexPrintf("%d calls to cufinufft.mw:163\n", mexprofrecord_[7]); + mexPrintf("%d calls to cufinufft.mw:166\n", mexprofrecord_[8]); + mexPrintf("%d calls to cufinufft.mw:168\n", mexprofrecord_[9]); + mexPrintf("%d calls to cufinufft.mw:198\n", mexprofrecord_[10]); + mexPrintf("%d calls to cufinufft.mw:200\n", mexprofrecord_[11]); + mexPrintf("%d calls to cufinufft.mw:232\n", mexprofrecord_[12]); + mexPrintf("%d calls to cufinufft.mw:234\n", mexprofrecord_[13]); + mexPrintf("%d calls to cufinufft.mw:240\n", mexprofrecord_[14]); + mexPrintf("%d calls to cufinufft.mw:242\n", mexprofrecord_[15]); + mexPrintf("%d calls to cufinufft.mw:246\n", mexprofrecord_[16]); + mexPrintf("%d calls to cufinufft.mw:248\n", mexprofrecord_[17]); + mexPrintf("%d calls to cufinufft.mw:260\n", mexprofrecord_[18]); + mexPrintf("%d calls to cufinufft.mw:262\n", mexprofrecord_[19]); + } else if (strcmp(id, "*profile log*") == 0) { + FILE* logfp; + if (nrhs != 2 || mxGetString(prhs[1], id, sizeof(id)) != 0) + mexErrMsgTxt("Must have two string arguments"); + logfp = fopen(id, "w+"); + if (!logfp) + mexErrMsgTxt("Cannot open log for output"); + if (!mexprofrecord_) + fprintf(logfp, "Profiler inactive\n"); + fprintf(logfp, "%d calls to cufinufft.mw:143\n", mexprofrecord_[1]); + fprintf(logfp, "%d calls to cufinufft.mw:145\n", mexprofrecord_[2]); + fprintf(logfp, "%d calls to cufinufft.mw:146 (cufinufft.mw:149)\n", mexprofrecord_[3]); + fprintf(logfp, "%d calls to cufinufft.mw:148\n", mexprofrecord_[4]); + fprintf(logfp, "%d calls to cufinufft.mw:160\n", mexprofrecord_[6]); + fprintf(logfp, "%d calls to cufinufft.mw:163\n", mexprofrecord_[7]); + fprintf(logfp, "%d calls to cufinufft.mw:166\n", mexprofrecord_[8]); + fprintf(logfp, "%d calls to cufinufft.mw:168\n", mexprofrecord_[9]); + fprintf(logfp, "%d calls to cufinufft.mw:198\n", mexprofrecord_[10]); + fprintf(logfp, "%d calls to cufinufft.mw:200\n", mexprofrecord_[11]); + fprintf(logfp, "%d calls to cufinufft.mw:232\n", mexprofrecord_[12]); + fprintf(logfp, "%d calls to cufinufft.mw:234\n", mexprofrecord_[13]); + fprintf(logfp, "%d calls to cufinufft.mw:240\n", mexprofrecord_[14]); + fprintf(logfp, "%d calls to cufinufft.mw:242\n", mexprofrecord_[15]); + fprintf(logfp, "%d calls to cufinufft.mw:246\n", mexprofrecord_[16]); + fprintf(logfp, "%d calls to cufinufft.mw:248\n", mexprofrecord_[17]); + fprintf(logfp, "%d calls to cufinufft.mw:260\n", mexprofrecord_[18]); + fprintf(logfp, "%d calls to cufinufft.mw:262\n", mexprofrecord_[19]); + fclose(logfp); + } else + mexErrMsgTxt("Unknown identifier"); +} + diff --git a/matlab/cufinufft_plan.m b/matlab/cufinufft_plan.m new file mode 100644 index 000000000..6f7456b11 --- /dev/null +++ b/matlab/cufinufft_plan.m @@ -0,0 +1,194 @@ + +classdef cufinufft_plan < handle + + properties + % this is a special property that MWrap uses as an opaque pointer to C++ + % object (mwptr = MWrap-pointer, not MathWorks! see MWrap manual)... + mwptr + % track what prec C++ library is being called ('single' or 'double')... + floatprec + % track other properties we'd rather not have to query the C++ plan for... + type + dim + n_modes % 3-element array, 1's in the unused dims + n_trans + nj % number of NU pts (type 1,2), or input NU pts (type 3) + nk % number of output NU pts (type 3) + xj + yj + zj + end + + methods + + function plan = cufinufft_plan(type, n_modes_or_dim, iflag, n_trans, tol, opts) + % FINUFFT_PLAN create guru plan object for one/many general nonuniform FFTs. + + plan.floatprec='double'; % set precision: default + if nargin<6, opts = []; end + if isfield(opts,'floatprec') % a matlab-only option + if ~strcmp(opts.floatprec,'single') && ~strcmp(opts.floatprec,'double') + error('FINUFFT:badFloatPrec','FINUFFT plan opts.floatprec must be single or double'); + else + plan.floatprec = opts.floatprec; + end + end + + n_modes = ones(3,1); % is dummy for type 3 + if type==3 + if length(n_modes_or_dim)~=1 + error('FINUFFT:badT3dim', 'FINUFFT type 3 plan n_modes_or_dim must be one number, the dimension'); + end + dim = n_modes_or_dim; % interpret as dim + else + dim = length(n_modes_or_dim); % allows any ms,mt,mu to be 1 (weird..) + n_modes(1:dim) = n_modes_or_dim; % unused dims left as 1 + end + % (checks of type, dim will occur in the C++ library, so omit them above) + + mex_id_ = 'c o cufinufft_opts* = new()'; +[o] = cufinufft(mex_id_); + if strcmp(plan.floatprec,'double') + mex_id_ = 'c o cufinufft_plan* = new()'; +[p] = cufinufft(mex_id_); + mex_id_ = 'cufinufft_default_opts(c i cufinufft_opts*)'; +cufinufft(mex_id_, o); + else + mex_id_ = 'c o cufinufftf_plan* = new()'; +[p] = cufinufft(mex_id_); + mex_id_ = 'cufinufft_default_opts(c i cufinufft_opts*)'; +cufinufft(mex_id_, o); + end + plan.mwptr = p; % crucial: save the opaque ptr (p.12 of MWrap manual) + plan.dim = dim; % save other stuff to avoid having to access via C++... + plan.type = type; + plan.n_modes = n_modes; + plan.n_trans = n_trans; + % Note the peculiarity that mwrap only accepts a double for n_trans, even + % though it's declared int. It complains, also with int64 for nj, etc :( + + % replace in cufinufft_opts struct whichever fields are in incoming opts... + mex_id_ = 'copy_cufinufft_opts(c i mxArray, c i cufinufft_opts*)'; +cufinufft(mex_id_, opts, o); + if strcmp(plan.floatprec,'double') + tol = double(tol); % scalar type must match for mwrap>=0.33.11 + mex_id_ = 'c o int = cufinufft_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i double, c i cufinufft_plan*, c i cufinufft_opts*)'; +[ier] = cufinufft(mex_id_, type, dim, n_modes, iflag, n_trans, tol, plan, o, 3); + else + tol = single(tol); % ditto + mex_id_ = 'c o int = cufinufftf_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i float, c i cufinufftf_plan*, c i cufinufft_opts*)'; +[ier] = cufinufft(mex_id_, type, dim, n_modes, iflag, n_trans, tol, plan, o, 3); + end + mex_id_ = 'delete(c i cufinufft_opts*)'; +cufinufft(mex_id_, o); + errhandler(ier); % convert C++ codes to matlab-style errors + end + + function setpts(plan, xj, yj, zj, s, t, u) + % SETPTS process nonuniform points for general FINUFFT transform(s). + + % fill missing inputs with empties of correct type + if strcmp(plan.floatprec,'double') + emp = gpuArray(double([])); + else + emp = gpuArray(single([])); + end + if nargin<3 || numel(yj)==0, yj=emp; end + if nargin<4 || numel(zj)==0, zj=emp; end + if nargin<5 || numel(s)==0, s=emp; end + if nargin<6 || numel(t)==0, t=emp; end + if nargin<7 || numel(u)==0, u=emp; end + % get number(s) of NU pts (also validates the NU pt array sizes)... + [nj, nk] = valid_setpts(1,plan.type, plan.dim, xj, yj, zj, s, t, u); + plan.nj = nj; % save to avoid having to query the C++ plan + plan.nk = nk; % " + % Force MATLAB to preserve the memory of xj/yj/zj by storing them as class + % properties (see issue #185). Ideally, we would pass plan.xj/yj/zj to the + % MWrap call below, but MWrap fails to parse the "." syntax. However, + % simply storing xj/yj/zj ensures that the memory will be preserved. + plan.xj = xj; + plan.yj = yj; + plan.zj = zj; + if strcmp(plan.floatprec,'double') + mex_id_ = 'c o int = cufinufft_setpts(c i cufinufft_plan, c i int, g i double[], g i double[], g i double[], c i int, g i double[], g i double[], g i double[])'; +[ier] = cufinufft(mex_id_, plan, nj, xj, yj, zj, nk, s, t, u); + else + mex_id_ = 'c o int = cufinufftf_setpts(c i cufinufftf_plan, c i int, g i float[], g i float[], g i float[], c i int, g i float[], g i float[], g i float[])'; +[ier] = cufinufft(mex_id_, plan, nj, xj, yj, zj, nk, s, t, u); + end + errhandler(ier); + end + + function result = execute(plan, data_in) + % EXECUTE execute single or many-vector FINUFFT transforms in a plan. + + % check if data_in is gpuArray + if ~isgpuarray(data_in) + error('FINUFFT:badDataDevice','input data must be a gpuArray'); + end + + % get shape info from the matlab-side plan (since can't pass "dot" + % variables like a.b as mwrap sizes, too)... + ms = plan.n_modes(1); mt = plan.n_modes(2); mu = plan.n_modes(3); + nj = plan.nj; nk = plan.nk; n_trans = plan.n_trans; + + % check data input length... + if plan.type==1 || plan.type==2 + ncoeffs = ms*mt*mu*n_trans; % total # Fourier coeffs + end + if plan.type==2 + ninputs = ncoeffs; + else + ninputs = n_trans*nj; + end + if numel(data_in)~=ninputs + error('FINUFFT:badDataInSize','FINUFFT numel(data_in) must be n_trans times number of NU pts (type 1, 3) or Fourier modes (type 2)'); + end + if plan.type == 1 + if strcmp(plan.floatprec,'double') + mex_id_ = 'c o int = cufinufft_execute(c i cufinufft_plan, g i dcomplex[], g o dcomplex[x])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, ncoeffs); + else + mex_id_ = 'c o int = cufinufftf_execute(c i cufinufftf_plan, g i fcomplex[], g o fcomplex[x])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, ncoeffs); + end + % make modes output correct shape; when d<3 squeeze removes unused dims... + result = squeeze(reshape(result, [ms mt mu n_trans])); + elseif plan.type == 2 + if strcmp(plan.floatprec,'double') + mex_id_ = 'c o int = cufinufft_execute(c i cufinufft_plan, g o dcomplex[xx], g i dcomplex[])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, nj, n_trans); + else + mex_id_ = 'c o int = cufinufftf_execute(c i cufinufftf_plan, g o fcomplex[xx], g i fcomplex[])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, nj, n_trans); + end + elseif plan.type == 3 + if strcmp(plan.floatprec,'double') + mex_id_ = 'c o int = cufinufft_execute(c i cufinufft_plan, g i dcomplex[], g o dcomplex[xx])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, nk, n_trans); + else + mex_id_ = 'c o int = cufinufftf_execute(c i cufinufftf_plan, g i fcomplex[], g o fcomplex[xx])'; +[ier, result] = cufinufft(mex_id_, plan, data_in, nk, n_trans); + end + end + errhandler(ier); + end + + function delete(plan) + % This does clean-up (deallocation) of the C++ struct before the matlab + % object deletes. It is automatically called by MATLAB and octave if the + % plan goes out of scope. + if ~isempty(plan.mwptr) % catch octave's allowance of >1 deletings! + if strcmp(plan.floatprec,'double') + mex_id_ = 'cufinufft_destroy(c i cufinufft_plan)'; +cufinufft(mex_id_, plan); + else + mex_id_ = 'cufinufftf_destroy(c i cufinufftf_plan)'; +cufinufft(mex_id_, plan); + end + plan.mwptr = ''; % we use to mean "destroyed on the C++ side" + end + end + + end +end diff --git a/matlab/finufft.cpp b/matlab/finufft.cpp index 98ca0a806..26601ef69 100644 --- a/matlab/finufft.cpp +++ b/matlab/finufft.cpp @@ -31,9 +31,9 @@ THE SOFTWARE. */ -#include #include #include +#include #include @@ -41,10 +41,20 @@ #include #endif + /* * Records for call profile. */ -int *mexprofrecord_ = NULL; +int* mexprofrecord_= NULL; + +double mxWrapGetChar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxCHAR_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid char argument"; + return 0; + } + return (char) (*mxGetChars(a)); +} /* * Support routines for copying data into and out of the MEX stubs, R2018a @@ -52,421 +62,502 @@ int *mexprofrecord_ = NULL; #if MX_HAS_INTERLEAVED_COMPLEX -void *mxWrapGetP(const mxArray *a, const char *fmt, const char **e) { - void *p = NULL; +void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) +{ + void* p = NULL; #ifdef R2008OO - mxArray *ap; + mxArray* ap; #endif - if (mxGetClassID(a) == mxDOUBLE_CLASS && mxIsComplex(a)) { - if (mxGetM(a) * mxGetN(a) == 1 && (*mxGetComplexDoubles(a)).real == 0) return NULL; - } - if (mxGetClassID(a) == mxDOUBLE_CLASS && !mxIsComplex(a)) { - if (mxGetM(a) * mxGetN(a) == 1 && *mxGetDoubles(a) == 0) return NULL; - } - if (mxIsChar(a)) { - char pbuf[128]; - mxGetString(a, pbuf, sizeof(pbuf)); - sscanf(pbuf, fmt, &p); - } + if (mxGetClassID(a) == mxDOUBLE_CLASS && mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexDoubles(a)).real == 0 ) + return NULL; + } + if (mxGetClassID(a) == mxDOUBLE_CLASS && !mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && *mxGetDoubles(a) == 0) + return NULL; + } + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } #ifdef R2008OO - else if (ap = mxGetProperty(a, 0, "mwptr")) { - return mxWrapGetP(ap, fmt, e); - } + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } #endif - if (p == 0) *e = "Invalid pointer"; - return p; -} - -mxArray *mxWrapCreateP(void *p, const char *fmt) { - if (p == 0) { - mxArray *z = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(z) = 0; - return z; - } else { - char pbuf[128]; - sprintf(pbuf, fmt, p); - return mxCreateString(pbuf); - } -} - -mxArray *mxWrapStrncpy(const char *s) { - if (s) { - return mxCreateString(s); - } else { - mxArray *z = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(z) = 0; - return z; - } -} - -char *mxWrapGetString(const mxArray *a, const char **e) { - char *s; - mwSize slen; - if (!a || (!mxIsChar(a) && mxGetM(a) * mxGetN(a) > 0)) { - *e = "Invalid string argument"; - return NULL; - } - slen = mxGetM(a) * mxGetN(a) + 1; - s = (char *)mxMalloc(slen); - if (mxGetM(a) * mxGetN(a) == 0) - *s = 0; - else - mxGetString(a, s, slen); - return s; -} - -double mxWrapGetScalar(const mxArray *a, const char **e) { - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a) * mxGetN(a) != 1) { - *e = "Invalid scalar argument"; - return 0; - } - if (mxIsComplex(a)) - return (double)(*mxGetComplexDoubles(a)).real; - else - return (double)(*mxGetDoubles(a)); -} - -#define mxWrapGetArrayDef(func, T) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - double *q; \ - mxComplexDouble *z; \ - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ - *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexDoubles(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*z++).real; \ - } else { \ - q = mxGetDoubles(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*q++); \ - } \ - return array; \ - } - -#define mxWrapCopyDef(func, T) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - double *p; \ - mxComplexDouble *z; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexDoubles(a); \ - for (i = 0; i < n; ++i) (*z++).real = (double)*q++; \ - (*z++).imag = 0; \ - } else { \ - p = mxGetDoubles(a); \ - for (i = 0; i < n; ++i) *p++ = (double)*q++; \ - } \ - } - -#define mxWrapReturnDef(func, T) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - double *p; \ - if (!q) { \ - return mxCreateDoubleMatrix(0, 0, mxREAL); \ - } else { \ - mxArray *a = mxCreateDoubleMatrix(m, n, mxREAL); \ - p = mxGetDoubles(a); \ - for (i = 0; i < m * n; ++i) *p++ = (double)*q++; \ - return a; \ - } \ - } - -#define mxWrapGetScalarZDef(func, T, ZT, setz) \ - void func(T *z, const mxArray *a) { \ - if (mxIsComplex(a)) { \ - setz(z, (ZT)(*mxGetComplexDoubles(a)).real, (ZT)(*mxGetComplexDoubles(a)).imag); \ - } else { \ - setz(z, (ZT)(*mxGetComplexDoubles(a)).real, (ZT)0); \ - } \ - } - -#define mxWrapGetArrayZDef(func, T, ZT, setz) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - double *q; \ - mxComplexDouble *z; \ - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ - *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexDoubles(a); \ - for (i = 0; i < arraylen; ++i) { \ - setz(p, (ZT)(*z).real, (ZT)(*z).imag); \ - ++p; \ - ++z; \ - } \ - } else { \ - q = mxGetDoubles(a); \ - for (i = 0; i < arraylen; ++i) { \ - setz(p, (ZT)(*q), (ZT)0); \ - ++p; \ - ++q; \ - } \ - } \ - return array; \ - } - -#define mxWrapCopyZDef(func, T, freal, fimag) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - double *p; \ - mxComplexDouble *z; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexDoubles(a); \ - for (i = 0; i < n; ++i) { \ - (*z).real = freal(*q); \ - (*z).imag = fimag(*q); \ - ++z; \ - ++q; \ - } \ - } else { \ - p = mxGetDoubles(a); \ - for (i = 0; i < n; ++i) *p++ = freal(*q++); \ - } \ - } - -#define mxWrapReturnZDef(func, T, freal, fimag) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - mxComplexDouble *p; \ - if (!q) { \ - return mxCreateDoubleMatrix(0, 0, mxCOMPLEX); \ - } else { \ - mxArray *a = mxCreateDoubleMatrix(m, n, mxCOMPLEX); \ - p = mxGetComplexDoubles(a); \ - for (i = 0; i < m * n; ++i) { \ - (*p).real = freal(*q); \ - (*p).imag = fimag(*q); \ - ++p; \ - ++q; \ - } \ - return a; \ - } \ - } - -void *mxWrapGetP_single(const mxArray *a, const char *fmt, const char **e) { - void *p = NULL; + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetDoubles(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetDoubles(z) = 0; + return z; + } +} + +char* mxWrapGetString(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +double mxWrapGetScalar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + if( mxIsComplex(a) ) + return (double) (*mxGetComplexDoubles(a)).real; + else + return (double) (*mxGetDoubles(a)); +} + +#define mxWrapGetArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + mxComplexDouble* z; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*z++).real; \ + } \ + else \ + { \ + q = mxGetDoubles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + } \ + return array; \ +} + + +#define mxWrapCopyDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + mxComplexDouble* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < n; ++i) \ + (*z++).real = (double) *q++; \ + (*z++).imag = 0; \ + } \ + else \ + { \ + p = mxGetDoubles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = (double) *q++; \ + } \ +} + + +#define mxWrapReturnDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetDoubles(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = (double) *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + if( mxIsComplex(a) ) \ + { \ + setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) (*mxGetComplexDoubles(a)).imag); \ + } \ + else \ + { \ + setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) 0); \ + } \ +} + + +#define mxWrapGetArrayZDef(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + mxComplexDouble* z; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ + ++p; ++z; } \ + } \ + else \ + { \ + q = mxGetDoubles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*q), (ZT) 0 ); \ + ++p; ++q; } \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef(func, T, freal, fimag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + mxComplexDouble* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexDoubles(a); \ + for (i = 0; i < n; ++i) { \ + (*z).real = freal(*q); \ + (*z).imag = fimag(*q); \ + ++z; ++q; } \ + } \ + else \ + { \ + p = mxGetDoubles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = freal(*q++); \ + } \ +} + + +#define mxWrapReturnZDef(func, T, freal, fimag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + mxComplexDouble* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ + p = mxGetComplexDoubles(a); \ + for (i = 0; i < m*n; ++i) { \ + (*p).real = freal(*q); \ + (*p).imag = fimag(*q); \ + ++p; ++q; } \ + return a; \ + } \ +} + + + + + + +void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) +{ + void* p = NULL; #ifdef R2008OO - mxArray *ap; + mxArray* ap; #endif - if (mxGetClassID(a) == mxSINGLE_CLASS && mxIsComplex(a)) { - if (mxGetM(a) * mxGetN(a) == 1 && (*mxGetComplexSingles(a)).real == 0) return NULL; - } - if (mxGetClassID(a) == mxSINGLE_CLASS && !mxIsComplex(a)) { - if (mxGetM(a) * mxGetN(a) == 1 && *mxGetSingles(a) == 0) return NULL; - } - if (mxIsChar(a)) { - char pbuf[128]; - mxGetString(a, pbuf, sizeof(pbuf)); - sscanf(pbuf, fmt, &p); - } + if (mxGetClassID(a) == mxSINGLE_CLASS && mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexSingles(a)).real == 0 ) + return NULL; + } + if (mxGetClassID(a) == mxSINGLE_CLASS && !mxIsComplex(a) ) + { + if( mxGetM(a)*mxGetN(a) == 1 && *mxGetSingles(a) == 0) + return NULL; + } + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } #ifdef R2008OO - else if (ap = mxGetProperty(a, 0, "mwptr")) { - return mxWrapGetP(ap, fmt, e); - } + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } #endif - if (p == 0) *e = "Invalid pointer"; - return p; -} - -mxArray *mxWrapCreateP_single(void *p, const char *fmt) { - if (p == 0) { - mxArray *z = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); - *mxGetSingles(z) = 0; - return z; - } else { - char pbuf[128]; - sprintf(pbuf, fmt, p); - return mxCreateString(pbuf); - } -} - -mxArray *mxWrapStrncpy_single(const char *s) { - if (s) { - return mxCreateString(s); - } else { - mxArray *z = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); - *mxGetSingles(z) = 0; - return z; - } -} - -char *mxWrapGetString_single(const mxArray *a, const char **e) { - char *s; - mwSize slen; - if (!a || (!mxIsChar(a) && mxGetM(a) * mxGetN(a) > 0)) { - *e = "Invalid string argument"; - return NULL; - } - slen = mxGetM(a) * mxGetN(a) + 1; - s = (char *)mxMalloc(slen); - if (mxGetM(a) * mxGetN(a) == 0) - *s = 0; - else - mxGetString(a, s, slen); - return s; -} - -float mxWrapGetScalar_single(const mxArray *a, const char **e) { - if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a) * mxGetN(a) != 1) { - *e = "Invalid scalar argument"; - return 0; - } - if (mxIsComplex(a)) - return (float)(*mxGetComplexSingles(a)).real; - else - return (float)(*mxGetSingles(a)); -} - -#define mxWrapGetArrayDef_single(func, T) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - float *q; \ - mxComplexSingle *z; \ - if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ - *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexSingles(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*z++).real; \ - } else { \ - q = mxGetSingles(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*q++); \ - } \ - return array; \ - } - -#define mxWrapCopyDef_single(func, T) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - float *p; \ - mxComplexSingle *z; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexSingles(a); \ - for (i = 0; i < n; ++i) (*z++).real = (float)*q++; \ - (*z++).imag = 0; \ - } else { \ - p = mxGetSingles(a); \ - for (i = 0; i < n; ++i) *p++ = (float)*q++; \ - } \ - } - -#define mxWrapReturnDef_single(func, T) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - float *p; \ - if (!q) { \ - return mxCreateNumericMatrix(0, 0, mxSINGLE_CLASS, mxREAL); \ - } else { \ - mxArray *a = mxCreateNumericMatrix(m, n, mxSINGLE_CLASS, mxREAL); \ - p = mxGetSingles(a); \ - for (i = 0; i < m * n; ++i) *p++ = (float)*q++; \ - return a; \ - } \ - } - -#define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ - void func(T *z, const mxArray *a) { \ - if (mxIsComplex(a)) { \ - setz(z, (ZT)(*mxGetComplexSingles(a)).real, (ZT)(*mxGetComplexSingles(a)).imag); \ - } else { \ - setz(z, (ZT)(*mxGetComplexSingles(a)).real, (ZT)0); \ - } \ - } - -#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - float *q; \ - mxComplexSingle *z; \ - if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ - *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexSingles(a); \ - for (i = 0; i < arraylen; ++i) { \ - setz(p, (ZT)(*z).real, (ZT)(*z).imag); \ - ++p; \ - ++z; \ - } \ - } else { \ - q = mxGetSingles(a); \ - for (i = 0; i < arraylen; ++i) { \ - setz(p, (ZT)(*q), (ZT)0); \ - ++p; \ - ++q; \ - } \ - } \ - return array; \ - } - -#define mxWrapCopyZDef_single(func, T, freal, fimag) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - float *p; \ - mxComplexSingle *z; \ - if (mxIsComplex(a)) { \ - z = mxGetComplexSingles(a); \ - for (i = 0; i < n; ++i) { \ - (*z).real = freal(*q); \ - (*z).imag = fimag(*q); \ - ++z; \ - ++q; \ - } \ - } else { \ - p = mxGetSingles(a); \ - for (i = 0; i < n; ++i) *p++ = freal(*q++); \ - } \ - } - -#define mxWrapReturnZDef_single(func, T, freal, fimag) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - mxComplexSingle *p; \ - if (!q) { \ - return mxCreateNumericMatrix(0, 0, mxSINGLE_CLASS, mxCOMPLEX); \ - } else { \ - mxArray *a = mxCreateNumericMatrix(m, n, mxSINGLE_CLASS, mxCOMPLEX); \ - p = mxGetComplexSingles(a); \ - for (i = 0; i < m * n; ++i) { \ - (*p).real = freal(*q); \ - (*p).imag = fimag(*q); \ - ++p; \ - ++q; \ - } \ - return a; \ - } \ - } + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP_single(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *mxGetSingles(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy_single(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *mxGetSingles(z) = 0; + return z; + } +} + +float mxWrapGetScalar_single(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + if( mxIsComplex(a) ) + return (float) (*mxGetComplexSingles(a)).real; + else + return (float) (*mxGetSingles(a)); +} + + +char* mxWrapGetString_single(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + +#define mxWrapGetArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + mxComplexSingle* z; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*z++).real; \ + } \ + else \ + { \ + q = mxGetSingles(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + } \ + return array; \ +} + + +#define mxWrapCopyDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + mxComplexSingle* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < n; ++i) \ + (*z++).real = (float) *q++; \ + (*z++).imag = 0; \ + } \ + else \ + { \ + p = mxGetSingles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = (float) *q++; \ + } \ +} + + +#define mxWrapReturnDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL); \ + p = mxGetSingles(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = (float) *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + if( mxIsComplex(a) ) \ + { \ + setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) (*mxGetComplexSingles(a)).imag); \ + } \ + else \ + { \ + setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) 0); \ + } \ +} + + +#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + mxComplexSingle* z; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ + ++p; ++z; } \ + } \ + else \ + { \ + q = mxGetSingles(a); \ + for (i = 0; i < arraylen; ++i) { \ + setz(p, (ZT) (*q), (ZT) 0 ); \ + ++p; ++q; } \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef_single(func, T, freal, fimag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + mxComplexSingle* z; \ + if( mxIsComplex(a) ) \ + { \ + z = mxGetComplexSingles(a); \ + for (i = 0; i < n; ++i) { \ + (*z).real = freal(*q); \ + (*z).imag = fimag(*q); \ + ++z; ++q; } \ + } \ + else \ + { \ + p = mxGetSingles(a); \ + for (i = 0; i < n; ++i) \ + *p++ = freal(*q++); \ + } \ +} + + +#define mxWrapReturnZDef_single(func, T, freal, fimag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + mxComplexSingle* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX); \ + p = mxGetComplexSingles(a); \ + for (i = 0; i < m*n; ++i) { \ + (*p).real = freal(*q); \ + (*p).imag = fimag(*q); \ + ++p; ++q; } \ + return a; \ + } \ +} + + #else @@ -474,1535 +565,1858 @@ float mxWrapGetScalar_single(const mxArray *a, const char **e) { * Support routines for copying data into and out of the MEX stubs, -R2017b */ -void *mxWrapGetP(const mxArray *a, const char *fmt, const char **e) { - void *p = 0; +void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) +{ + void* p = 0; #ifdef R2008OO - mxArray *ap; + mxArray* ap; #endif - if (mxGetClassID(a) == mxDOUBLE_CLASS && mxGetM(a) * mxGetN(a) == 1 && *mxGetPr(a) == 0) - return p; - if (mxIsChar(a)) { - char pbuf[128]; - mxGetString(a, pbuf, sizeof(pbuf)); - sscanf(pbuf, fmt, &p); - } + if (mxGetClassID(a) == mxDOUBLE_CLASS && + mxGetM(a)*mxGetN(a) == 1 && *mxGetPr(a) == 0) + return p; + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } #ifdef R2008OO - else if (ap = mxGetProperty(a, 0, "mwptr")) { - return mxWrapGetP(ap, fmt, e); - } + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } #endif - if (p == 0) *e = "Invalid pointer"; - return p; -} - -mxArray *mxWrapCreateP(void *p, const char *fmt) { - if (p == 0) { - mxArray *z = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(z) = 0; - return z; - } else { - char pbuf[128]; - sprintf(pbuf, fmt, p); - return mxCreateString(pbuf); - } -} - -mxArray *mxWrapStrncpy(const char *s) { - if (s) { - return mxCreateString(s); - } else { - mxArray *z = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(z) = 0; - return z; - } -} - -double mxWrapGetScalar(const mxArray *a, const char **e) { - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a) * mxGetN(a) != 1) { - *e = "Invalid scalar argument"; - return 0; - } - return *mxGetPr(a); -} - -char *mxWrapGetString(const mxArray *a, const char **e) { - char *s; - mwSize slen; - if (!a || (!mxIsChar(a) && mxGetM(a) * mxGetN(a) > 0)) { - *e = "Invalid string argument"; - return NULL; - } - slen = mxGetM(a) * mxGetN(a) + 1; - s = (char *)mxMalloc(slen); - if (mxGetM(a) * mxGetN(a) == 0) - *s = 0; - else - mxGetString(a, s, slen); - return s; -} - -#define mxWrapGetArrayDef(func, T) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - double *q; \ - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ - *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - q = mxGetPr(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*q++); \ - return array; \ - } - -#define mxWrapCopyDef(func, T) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - double *p = mxGetPr(a); \ - for (i = 0; i < n; ++i) *p++ = *q++; \ - } - -#define mxWrapReturnDef(func, T) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - double *p; \ - if (!q) { \ - return mxCreateDoubleMatrix(0, 0, mxREAL); \ - } else { \ - mxArray *a = mxCreateDoubleMatrix(m, n, mxREAL); \ - p = mxGetPr(a); \ - for (i = 0; i < m * n; ++i) *p++ = *q++; \ - return a; \ - } \ - } - -#define mxWrapGetScalarZDef(func, T, ZT, setz) \ - void func(T *z, const mxArray *a) { \ - double *pr = mxGetPr(a); \ - double *pi = mxGetPi(a); \ - setz(z, (ZT) * pr, (pi ? (ZT) * pi : (ZT)0)); \ - } - -#define mxWrapGetArrayZDef(func, T, ZT, setz) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - double *qr; \ - double *qi; \ - if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ - *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - qr = mxGetPr(a); \ - qi = mxGetPi(a); \ - for (i = 0; i < arraylen; ++i) { \ - ZT val_qr = *qr++; \ - ZT val_qi = (qi ? (ZT) * qi++ : (ZT)0); \ - setz(p, val_qr, val_qi); \ - ++p; \ - } \ - return array; \ - } - -#define mxWrapCopyZDef(func, T, real, imag) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - double *pr = mxGetPr(a); \ - double *pi = mxGetPi(a); \ - for (i = 0; i < n; ++i) { \ - *pr++ = real(*q); \ - *pi++ = imag(*q); \ - ++q; \ - } \ - } - -#define mxWrapReturnZDef(func, T, real, imag) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - double *pr; \ - double *pi; \ - if (!q) { \ - return mxCreateDoubleMatrix(0, 0, mxCOMPLEX); \ - } else { \ - mxArray *a = mxCreateDoubleMatrix(m, n, mxCOMPLEX); \ - pr = mxGetPr(a); \ - pi = mxGetPi(a); \ - for (i = 0; i < m * n; ++i) { \ - *pr++ = real(*q); \ - *pi++ = imag(*q); \ - ++q; \ - } \ - return a; \ - } \ - } - -void *mxWrapGetP_single(const mxArray *a, const char *fmt, const char **e) { - void *p = 0; + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetPr(z) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} + +mxArray* mxWrapStrncpy(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); + *mxGetPr(z) = 0; + return z; + } +} + +double mxWrapGetScalar(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + return *mxGetPr(a); +} + +char* mxWrapGetString(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +#define mxWrapGetArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + + +#define mxWrapGetScalarZDef(func, T, ZT, setz) \ +void func(T* z, const mxArray* a) \ +{ \ + double* pr = mxGetPr(a); \ + double* pi = mxGetPi(a); \ + setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ +} + + +#define mxWrapGetArrayZDef(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* qr; \ + double* qi; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + qr = mxGetPr(a); \ + qi = mxGetPi(a); \ + for (i = 0; i < arraylen; ++i) { \ + ZT val_qr = *qr++; \ + ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ + setz(p, val_qr, val_qi); \ + ++p; \ + } \ + return array; \ +} + + +#define mxWrapCopyZDef(func, T, real, imag) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* pr = mxGetPr(a); \ + double* pi = mxGetPi(a); \ + for (i = 0; i < n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ +} + + +#define mxWrapReturnZDef(func, T, real, imag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* pr; \ + double* pi; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ + pr = mxGetPr(a); \ + pi = mxGetPi(a); \ + for (i = 0; i < m*n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ + return a; \ + } \ +} + + + + + + +void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) +{ + void* p = 0; #ifdef R2008OO - mxArray *ap; + mxArray* ap; #endif - if (mxGetClassID(a) == mxSINGLE_CLASS && mxGetM(a) * mxGetN(a) == 1 && - *((float *)mxGetData(a)) == 0) - return p; - if (mxIsChar(a)) { - char pbuf[128]; - mxGetString(a, pbuf, sizeof(pbuf)); - sscanf(pbuf, fmt, &p); - } + if (mxGetClassID(a) == mxSINGLE_CLASS && + mxGetM(a)*mxGetN(a) == 1 && *((float*)mxGetData(a)) == 0) + return p; + if (mxIsChar(a)) { + char pbuf[128]; + mxGetString(a, pbuf, sizeof(pbuf)); + sscanf(pbuf, fmt, &p); + } #ifdef R2008OO - else if (ap = mxGetProperty(a, 0, "mwptr")) { - return mxWrapGetP(ap, fmt, e); - } + else if (ap = mxGetProperty(a, 0, "mwptr")) { + return mxWrapGetP(ap, fmt, e); + } #endif - if (p == 0) *e = "Invalid pointer"; - return p; -} - -mxArray *mxWrapCreateP_single(void *p, const char *fmt) { - if (p == 0) { - mxArray *z = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); - *((float *)mxGetData(z)) = 0; - return z; - } else { - char pbuf[128]; - sprintf(pbuf, fmt, p); - return mxCreateString(pbuf); - } -} -mxArray *mxWrapStrncpy_single(const char *s) { - if (s) { - return mxCreateString(s); - } else { - mxArray *z = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); - *((float *)mxGetData(z)) = 0; - return z; - } -} - -float mxWrapGetScalar_single(const mxArray *a, const char **e) { - if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a) * mxGetN(a) != 1) { - *e = "Invalid scalar argument"; - return 0; - } - return *((float *)mxGetData(a)); -} - -char *mxWrapGetString_single(const mxArray *a, const char **e) { - char *s; - mwSize slen; - if (!a || (!mxIsChar(a) && mxGetM(a) * mxGetN(a) > 0)) { - *e = "Invalid string argument, mxSINGLE_CLASS expected"; - return NULL; - } - slen = mxGetM(a) * mxGetN(a) + 1; - s = (char *)mxMalloc(slen); - if (mxGetM(a) * mxGetN(a) == 0) - *s = 0; - else - mxGetString(a, s, slen); - return s; -} - -#define mxWrapGetArrayDef_single(func, T) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - float *q; \ - if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ - *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - q = (float *)mxGetData(a); \ - for (i = 0; i < arraylen; ++i) *p++ = (T)(*q++); \ - return array; \ - } - -#define mxWrapCopyDef_single(func, T) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - float *p = (float *)mxGetData(a); \ - for (i = 0; i < n; ++i) *p++ = *q++; \ - } - -#define mxWrapReturnDef_single(func, T) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - float *p; \ - if (!q) { \ - return mxCreateNumericMatrix(0, 0, mxSINGLE_CLASS, mxREAL); \ - } else { \ - mxArray *a = mxCreateNumericMatrix(m, n, mxSINGLE_CLASS, mxREAL); \ - p = (float *)mxGetData(a); \ - for (i = 0; i < m * n; ++i) *p++ = *q++; \ - return a; \ - } \ - } + if (p == 0) + *e = "Invalid pointer"; + return p; +} + +mxArray* mxWrapCreateP_single(void* p, const char* fmt) +{ + if (p == 0) { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *((float*)mxGetData(z)) = 0; + return z; + } else { + char pbuf[128]; + sprintf(pbuf, fmt, p); + return mxCreateString(pbuf); + } +} +mxArray* mxWrapStrncpy_single(const char* s) +{ + if (s) { + return mxCreateString(s); + } else { + mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); + *((float*)mxGetData(z)) = 0; + return z; + } +} + +float mxWrapGetScalar_single(const mxArray* a, const char** e) +{ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { + *e = "Invalid scalar argument"; + return 0; + } + return *((float*)mxGetData(a)); +} + +char* mxWrapGetString_single(const mxArray* a, const char** e) +{ + char* s; + mwSize slen; + if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { + *e = "Invalid string argument, mxSINGLE_CLASS expected"; + return NULL; + } + slen = mxGetM(a)*mxGetN(a) + 1; + s = (char*) mxMalloc(slen); + if (mxGetM(a)*mxGetN(a) == 0) + *s = 0; + else + mxGetString(a, s, slen); + return s; +} + + +#define mxWrapGetArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* q; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = (float*) mxGetData(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* p = (float*) mxGetData(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* p; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL);\ + p = (float*) mxGetData(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + #define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ - void func(T *z, const mxArray *a) { \ - float *pr = (float *)mxGetData(a); \ - float *pi = (float *)mxGetImagData(a); \ - setz(z, (ZT) * pr, (pi ? (ZT) * pi : (ZT)0)); \ - } - -#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ - T *func(const mxArray *a, const char **e) { \ - T *array; \ - mwSize arraylen; \ - mwIndex i; \ - T *p; \ - float *qr; \ - float *qi; \ - if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ - *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ - return 0; \ - } \ - arraylen = mxGetM(a) * mxGetN(a); \ - array = (T *)mxMalloc(mxGetM(a) * mxGetN(a) * sizeof(T)); \ - p = array; \ - qr = (float *)mxGetData(a); \ - qi = (float *)mxGetImagData(a); \ - for (i = 0; i < arraylen; ++i) { \ - ZT val_qr = *qr++; \ - ZT val_qi = (qi ? (ZT) * qi++ : (ZT)0); \ - setz(p, val_qr, val_qi); \ - ++p; \ - } \ - return array; \ - } +void func(T* z, const mxArray* a) \ +{ \ + float* pr = (float*) mxGetData(a); \ + float* pi = (float*) mxGetImagData(a); \ + setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ +} + + +#define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + float* qr; \ + float* qi; \ + if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ + *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + qr = (float*) mxGetData(a); \ + qi = (float*) mxGetImagData(a); \ + for (i = 0; i < arraylen; ++i) { \ + ZT val_qr = *qr++; \ + ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ + setz(p, val_qr, val_qi); \ + ++p; \ + } \ + return array; \ +} + #define mxWrapCopyZDef_single(func, T, real, imag) \ - void func(mxArray *a, const T *q, mwSize n) { \ - mwIndex i; \ - float *pr = (float *)mxGetData(a); \ - float *pi = (float *)mxGetImagData(a); \ - for (i = 0; i < n; ++i) { \ - *pr++ = real(*q); \ - *pi++ = imag(*q); \ - ++q; \ - } \ - } - -#define mxWrapReturnZDef_single(func, T, real, imag) \ - mxArray *func(const T *q, mwSize m, mwSize n) { \ - mwIndex i; \ - float *pr; \ - float *pi; \ - if (!q) { \ - return mxCreateNumericMatrix(0, 0, mxSINGLE_CLASS, mxCOMPLEX); \ - } else { \ - mxArray *a = mxCreateNumericMatrix(m, n, mxSINGLE_CLASS, mxCOMPLEX); \ - pr = (float *)mxGetData(a); \ - pi = (float *)mxGetImagData(a); \ - for (i = 0; i < m * n; ++i) { \ - *pr++ = real(*q); \ - *pi++ = imag(*q); \ - ++q; \ - } \ - return a; \ - } \ - } +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + float* pr = (float*) mxGetData(a); \ + float* pi = (float*) mxGetImagData(a); \ + for (i = 0; i < n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ +} + + +#define mxWrapReturnZDef_single(func, T, real, imag) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + float* pr; \ + float* pi; \ + if (!q) { \ + return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ + } else { \ + mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX);\ + pr = (float*) mxGetData(a); \ + pi = (float*) mxGetImagData(a); \ + for (i = 0; i < m*n; ++i) { \ + *pr++ = real(*q); \ + *pi++ = imag(*q); \ + ++q; \ + } \ + return a; \ + } \ +} + + + + #endif +#define mxWrapGetGPUArrayDef(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyGPUArrayDef(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnGPUArrayDef(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapReturnGPUArrayPDef(func, T) \ +T* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapGetGPUArrayDef_single(func, T) \ +T* func(const mxArray* a, const char** e) \ +{ \ + T* array; \ + mwSize arraylen; \ + mwIndex i; \ + T* p; \ + double* q; \ + if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ + *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ + return 0; \ + } \ + arraylen = mxGetM(a)*mxGetN(a); \ + array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ + p = array; \ + q = mxGetPr(a); \ + for (i = 0; i < arraylen; ++i) \ + *p++ = (T) (*q++); \ + return array; \ +} + + +#define mxWrapCopyGPUArrayDef_single(func, T) \ +void func(mxArray* a, const T* q, mwSize n) \ +{ \ + mwIndex i; \ + double* p = mxGetPr(a); \ + for (i = 0; i < n; ++i) \ + *p++ = *q++; \ +} + + +#define mxWrapReturnGPUArrayDef_single(func, T) \ +mxArray* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + +#define mxWrapReturnGPUArrayPDef_single(func, T) \ +T* func(const T* q, mwSize m, mwSize n) \ +{ \ + mwIndex i; \ + double* p; \ + if (!q) { \ + return mxCreateDoubleMatrix(0,0, mxREAL); \ + } else { \ + mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ + p = mxGetPr(a); \ + for (i = 0; i < m*n; ++i) \ + *p++ = *q++; \ + return a; \ + } \ +} + #include typedef std::complex dcomplex; -#define real_dcomplex(z) std::real(z) -#define imag_dcomplex(z) std::imag(z) -#define setz_dcomplex(z, r, i) *z = dcomplex(r, i) +#define real_dcomplex(z) std::real(z) +#define imag_dcomplex(z) std::imag(z) +#define setz_dcomplex(z,r,i) *z = dcomplex(r,i) typedef std::complex fcomplex; -#define real_fcomplex(z) std::real(z) -#define imag_fcomplex(z) std::imag(z) -#define setz_fcomplex(z, r, i) *z = fcomplex(r, i) - -#include -#include -#include -#include -#include -void copy_finufft_opts(const mxArray *om, finufft_opts *oc) { - if (!mxIsStruct(om)) - mexErrMsgIdAndTxt("FINUFFT:inputNotStruct", "opts input must be a structure."); - mwIndex idx = 0; - int ifield, nfields; - const char **fname; - nfields = mxGetNumberOfFields(om); - fname = (const char **)mxCalloc(nfields, sizeof(*fname)); - for (ifield = 0; ifield < nfields; ifield++) { - fname[ifield] = mxGetFieldNameByNumber(om, ifield); - if (strcmp(fname[ifield], "debug") == 0) { - oc->debug = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_debug") == 0) { - oc->spread_debug = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_sort") == 0) { - oc->spread_sort = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_kerevalmeth") == 0) { - oc->spread_kerevalmeth = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_kerpad") == 0) { - oc->spread_kerpad = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "fftw") == 0) { - oc->fftw = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "modeord") == 0) { - oc->modeord = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "upsampfac") == 0) { - oc->upsampfac = (double)*mxGetPr(mxGetFieldByNumber(om, idx, ifield)); - } else if (strcmp(fname[ifield], "spread_thread") == 0) { - oc->spread_thread = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "maxbatchsize") == 0) { - oc->maxbatchsize = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "nthreads") == 0) { - oc->nthreads = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_nthr_atomic") == 0) { - oc->spread_nthr_atomic = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spread_max_sp_size") == 0) { - oc->spread_max_sp_size = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else if (strcmp(fname[ifield], "spreadinterponly") == 0) { - oc->spreadinterponly = (int)round(*mxGetPr(mxGetFieldByNumber(om, idx, ifield))); - } else - continue; - } - mxFree(fname); -} -void finufft_mex_setup() { - /* Forces MATLAB to properly initialize their FFTW library. */ - mexEvalString("fft(1:8);"); -} +#define real_fcomplex(z) std::real(z) +#define imag_fcomplex(z) std::imag(z) +#define setz_fcomplex(z,r,i) *z = fcomplex(r,i) + + #include + #include + #include + #include + #include + void copy_finufft_opts(const mxArray* om, finufft_opts *oc) { + if(!mxIsStruct(om)) + mexErrMsgIdAndTxt("FINUFFT:inputNotStruct","opts input must be a structure."); + mwIndex idx = 0; + int ifield, nfields; + const char **fname; + nfields = mxGetNumberOfFields(om); + fname = (const char**)mxCalloc(nfields, sizeof(*fname)); + for(ifield=0; ifielddebug = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_debug") == 0) { + oc->spread_debug = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_sort") == 0) { + oc->spread_sort = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_kerevalmeth") == 0) { + oc->spread_kerevalmeth = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_kerpad") == 0) { + oc->spread_kerpad = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"fftw") == 0) { + oc->fftw = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"modeord") == 0) { + oc->modeord = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"upsampfac") == 0) { + oc->upsampfac = (double)*mxGetPr(mxGetFieldByNumber(om,idx,ifield)); + } + else if (strcmp(fname[ifield],"spread_thread") == 0) { + oc->spread_thread = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"maxbatchsize") == 0) { + oc->maxbatchsize = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"nthreads") == 0) { + oc->nthreads = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_nthr_atomic") == 0) { + oc->spread_nthr_atomic = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spread_max_sp_size") == 0) { + oc->spread_max_sp_size = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else if (strcmp(fname[ifield],"spreadinterponly") == 0) { + oc->spreadinterponly = (int)round(*mxGetPr(mxGetFieldByNumber(om,idx,ifield))); + } + else + continue; + } + mxFree(fname); + } + void finufft_mex_setup() { + /* Forces MATLAB to properly initialize their FFTW library. */ + mexEvalString("fft(1:8);"); + } + + /* Array copier definitions */ -mxWrapGetArrayDef(mxWrapGetArray_bool, bool) mxWrapCopyDef(mxWrapCopy_bool, bool) mxWrapReturnDef( - mxWrapReturn_bool, - bool) mxWrapGetArrayDef_single(mxWrapGetArray_single_bool, - bool) mxWrapCopyDef_single(mxWrapCopy_single_bool, - bool) mxWrapReturnDef_single(mxWrapReturn_single_bool, - bool) - mxWrapGetArrayDef(mxWrapGetArray_char, char) mxWrapCopyDef(mxWrapCopy_char, char) mxWrapReturnDef( - mxWrapReturn_char, - char) mxWrapGetArrayDef_single(mxWrapGetArray_single_char, - char) mxWrapCopyDef_single(mxWrapCopy_single_char, - char) - mxWrapReturnDef_single(mxWrapReturn_single_char, char) mxWrapGetArrayDef( - mxWrapGetArray_double, - double) mxWrapCopyDef(mxWrapCopy_double, - double) mxWrapReturnDef(mxWrapReturn_double, - double) mxWrapGetArrayDef_single(mxWrapGetArray_single_double, - double) - mxWrapCopyDef_single(mxWrapCopy_single_double, double) mxWrapReturnDef_single( - mxWrapReturn_single_double, - double) mxWrapGetArrayDef(mxWrapGetArray_float, - float) mxWrapCopyDef(mxWrapCopy_float, - float) mxWrapReturnDef(mxWrapReturn_float, - float) - mxWrapGetArrayDef_single(mxWrapGetArray_single_float, float) mxWrapCopyDef_single( - mxWrapCopy_single_float, - float) mxWrapReturnDef_single(mxWrapReturn_single_float, - float) mxWrapGetArrayDef(mxWrapGetArray_int, - int) - mxWrapCopyDef(mxWrapCopy_int, int) mxWrapReturnDef(mxWrapReturn_int, int) mxWrapGetArrayDef_single( - mxWrapGetArray_single_int, - int) mxWrapCopyDef_single(mxWrapCopy_single_int, - int) mxWrapReturnDef_single(mxWrapReturn_single_int, - int) mxWrapGetArrayDef(mxWrapGetArray_int64_t, - int64_t) - mxWrapCopyDef(mxWrapCopy_int64_t, int64_t) mxWrapReturnDef(mxWrapReturn_int64_t, int64_t) mxWrapGetArrayDef_single( - mxWrapGetArray_single_int64_t, - int64_t) mxWrapCopyDef_single(mxWrapCopy_single_int64_t, - int64_t) mxWrapReturnDef_single(mxWrapReturn_single_int64_t, - int64_t) - mxWrapGetArrayDef(mxWrapGetArray_long, long) mxWrapCopyDef(mxWrapCopy_long, long) mxWrapReturnDef( - mxWrapReturn_long, - long) mxWrapGetArrayDef_single(mxWrapGetArray_single_long, - long) mxWrapCopyDef_single(mxWrapCopy_single_long, - long) - mxWrapReturnDef_single(mxWrapReturn_single_long, long) mxWrapGetArrayDef( - mxWrapGetArray_ptrdiff_t, - ptrdiff_t) mxWrapCopyDef(mxWrapCopy_ptrdiff_t, - ptrdiff_t) mxWrapReturnDef(mxWrapReturn_ptrdiff_t, ptrdiff_t) - mxWrapGetArrayDef_single(mxWrapGetArray_single_ptrdiff_t, ptrdiff_t) mxWrapCopyDef_single( - mxWrapCopy_single_ptrdiff_t, - ptrdiff_t) mxWrapReturnDef_single(mxWrapReturn_single_ptrdiff_t, - ptrdiff_t) - mxWrapGetArrayDef(mxWrapGetArray_short, short) mxWrapCopyDef( - mxWrapCopy_short, - short) mxWrapReturnDef(mxWrapReturn_short, - short) mxWrapGetArrayDef_single(mxWrapGetArray_single_short, - short) - mxWrapCopyDef_single(mxWrapCopy_single_short, short) mxWrapReturnDef_single( - mxWrapReturn_single_short, - short) mxWrapGetArrayDef(mxWrapGetArray_size_t, - size_t) mxWrapCopyDef(mxWrapCopy_size_t, size_t) - mxWrapReturnDef(mxWrapReturn_size_t, size_t) mxWrapGetArrayDef_single( - mxWrapGetArray_single_size_t, - size_t) mxWrapCopyDef_single(mxWrapCopy_single_size_t, size_t) - mxWrapReturnDef_single(mxWrapReturn_single_size_t, size_t) mxWrapGetScalarZDef( - mxWrapGetScalar_fcomplex, - fcomplex, float, - setz_fcomplex) mxWrapGetArrayZDef(mxWrapGetArray_fcomplex, fcomplex, float, setz_fcomplex) - mxWrapCopyZDef(mxWrapCopy_fcomplex, fcomplex, real_fcomplex, imag_fcomplex) mxWrapReturnZDef( - mxWrapReturn_fcomplex, - fcomplex, real_fcomplex, - imag_fcomplex) - mxWrapGetScalarZDef_single( - mxWrapGetScalar_single_fcomplex, - fcomplex, float, - setz_fcomplex) mxWrapGetArrayZDef_single(mxWrapGetArray_single_fcomplex, - fcomplex, - float, setz_fcomplex) - mxWrapCopyZDef_single( - mxWrapCopy_single_fcomplex, - fcomplex, - real_fcomplex, - imag_fcomplex) - mxWrapReturnZDef_single( - mxWrapReturn_single_fcomplex, - fcomplex, - real_fcomplex, - imag_fcomplex) mxWrapGetScalarZDef(mxWrapGetScalar_dcomplex, - dcomplex, - double, - setz_dcomplex) - mxWrapGetArrayZDef( - mxWrapGetArray_dcomplex, - dcomplex, - double, - setz_dcomplex) - mxWrapCopyZDef( - mxWrapCopy_dcomplex, - dcomplex, - real_dcomplex, - imag_dcomplex) - mxWrapReturnZDef( - mxWrapReturn_dcomplex, - dcomplex, - real_dcomplex, - imag_dcomplex) - mxWrapGetScalarZDef_single( - mxWrapGetScalar_single_dcomplex, - dcomplex, - double, - setz_dcomplex) - mxWrapGetArrayZDef_single( - mxWrapGetArray_single_dcomplex, - dcomplex, - double, - setz_dcomplex) - mxWrapCopyZDef_single( - mxWrapCopy_single_dcomplex, - dcomplex, - real_dcomplex, - imag_dcomplex) - mxWrapReturnZDef_single( - mxWrapReturn_single_dcomplex, - dcomplex, - real_dcomplex, - imag_dcomplex) - - /* ---- finufft.mw: 169 ---- - * finufft_mex_setup(); - */ - static const char *stubids1_ = "finufft_mex_setup()"; - -void mexStub1(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - if (mexprofrecord_) mexprofrecord_[1]++; - finufft_mex_setup(); +mxWrapGetArrayDef(mxWrapGetArray_bool, bool) +mxWrapCopyDef (mxWrapCopy_bool, bool) +mxWrapReturnDef (mxWrapReturn_bool, bool) +mxWrapGetArrayDef_single(mxWrapGetArray_single_bool, bool) +mxWrapCopyDef_single (mxWrapCopy_single_bool, bool) +mxWrapReturnDef_single (mxWrapReturn_single_bool, bool) +mxWrapGetArrayDef(mxWrapGetArray_char, char) +mxWrapCopyDef (mxWrapCopy_char, char) +mxWrapReturnDef (mxWrapReturn_char, char) +mxWrapGetArrayDef_single(mxWrapGetArray_single_char, char) +mxWrapCopyDef_single (mxWrapCopy_single_char, char) +mxWrapReturnDef_single (mxWrapReturn_single_char, char) +mxWrapGetArrayDef(mxWrapGetArray_double, double) +mxWrapCopyDef (mxWrapCopy_double, double) +mxWrapReturnDef (mxWrapReturn_double, double) +mxWrapGetArrayDef_single(mxWrapGetArray_single_double, double) +mxWrapCopyDef_single (mxWrapCopy_single_double, double) +mxWrapReturnDef_single (mxWrapReturn_single_double, double) +mxWrapGetArrayDef(mxWrapGetArray_float, float) +mxWrapCopyDef (mxWrapCopy_float, float) +mxWrapReturnDef (mxWrapReturn_float, float) +mxWrapGetArrayDef_single(mxWrapGetArray_single_float, float) +mxWrapCopyDef_single (mxWrapCopy_single_float, float) +mxWrapReturnDef_single (mxWrapReturn_single_float, float) +mxWrapGetArrayDef(mxWrapGetArray_int, int) +mxWrapCopyDef (mxWrapCopy_int, int) +mxWrapReturnDef (mxWrapReturn_int, int) +mxWrapGetArrayDef_single(mxWrapGetArray_single_int, int) +mxWrapCopyDef_single (mxWrapCopy_single_int, int) +mxWrapReturnDef_single (mxWrapReturn_single_int, int) +mxWrapGetArrayDef(mxWrapGetArray_int64_t, int64_t) +mxWrapCopyDef (mxWrapCopy_int64_t, int64_t) +mxWrapReturnDef (mxWrapReturn_int64_t, int64_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_int64_t, int64_t) +mxWrapCopyDef_single (mxWrapCopy_single_int64_t, int64_t) +mxWrapReturnDef_single (mxWrapReturn_single_int64_t, int64_t) +mxWrapGetArrayDef(mxWrapGetArray_long, long) +mxWrapCopyDef (mxWrapCopy_long, long) +mxWrapReturnDef (mxWrapReturn_long, long) +mxWrapGetArrayDef_single(mxWrapGetArray_single_long, long) +mxWrapCopyDef_single (mxWrapCopy_single_long, long) +mxWrapReturnDef_single (mxWrapReturn_single_long, long) +mxWrapGetArrayDef(mxWrapGetArray_ptrdiff_t, ptrdiff_t) +mxWrapCopyDef (mxWrapCopy_ptrdiff_t, ptrdiff_t) +mxWrapReturnDef (mxWrapReturn_ptrdiff_t, ptrdiff_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_ptrdiff_t, ptrdiff_t) +mxWrapCopyDef_single (mxWrapCopy_single_ptrdiff_t, ptrdiff_t) +mxWrapReturnDef_single (mxWrapReturn_single_ptrdiff_t, ptrdiff_t) +mxWrapGetArrayDef(mxWrapGetArray_short, short) +mxWrapCopyDef (mxWrapCopy_short, short) +mxWrapReturnDef (mxWrapReturn_short, short) +mxWrapGetArrayDef_single(mxWrapGetArray_single_short, short) +mxWrapCopyDef_single (mxWrapCopy_single_short, short) +mxWrapReturnDef_single (mxWrapReturn_single_short, short) +mxWrapGetArrayDef(mxWrapGetArray_size_t, size_t) +mxWrapCopyDef (mxWrapCopy_size_t, size_t) +mxWrapReturnDef (mxWrapReturn_size_t, size_t) +mxWrapGetArrayDef_single(mxWrapGetArray_single_size_t, size_t) +mxWrapCopyDef_single (mxWrapCopy_single_size_t, size_t) +mxWrapReturnDef_single (mxWrapReturn_single_size_t, size_t) +mxWrapGetScalarZDef(mxWrapGetScalar_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapGetArrayZDef (mxWrapGetArray_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapCopyZDef (mxWrapCopy_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapReturnZDef (mxWrapReturn_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapGetScalarZDef_single(mxWrapGetScalar_single_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapGetArrayZDef_single (mxWrapGetArray_single_fcomplex, fcomplex, + float, setz_fcomplex) +mxWrapCopyZDef_single (mxWrapCopy_single_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapReturnZDef_single (mxWrapReturn_single_fcomplex, fcomplex, + real_fcomplex, imag_fcomplex) +mxWrapGetScalarZDef(mxWrapGetScalar_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapGetArrayZDef (mxWrapGetArray_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapCopyZDef (mxWrapCopy_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapReturnZDef (mxWrapReturn_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapGetScalarZDef_single(mxWrapGetScalar_single_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapGetArrayZDef_single (mxWrapGetArray_single_dcomplex, dcomplex, + double, setz_dcomplex) +mxWrapCopyZDef_single (mxWrapCopy_single_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) +mxWrapReturnZDef_single (mxWrapReturn_single_dcomplex, dcomplex, + real_dcomplex, imag_dcomplex) + +/* ---- finufft.mw: 169 ---- + * finufft_mex_setup(); + */ +static const char* stubids1_ = "finufft_mex_setup()"; + +void mexStub1(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + if (mexprofrecord_) + mexprofrecord_[1]++; + finufft_mex_setup(); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 170 ---- * finufft_opts* o = new(); */ -static const char *stubids2_ = "o finufft_opts* = new()"; +static const char* stubids2_ = "c o finufft_opts* = new()"; -void mexStub2(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_opts *out0_ = 0; /* o */ +void mexStub2(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_opts* out0_=0; /* o */ - if (mexprofrecord_) mexprofrecord_[2]++; - out0_ = new finufft_opts(); - plhs[0] = mxWrapCreateP(out0_, "finufft_opts:%p"); + if (mexprofrecord_) + mexprofrecord_[2]++; + out0_ = new finufft_opts(); + plhs[0] = mxWrapCreateP(out0_, "finufft_opts:%p"); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 172 ---- * finufft_plan* p = new(); */ -static const char *stubids3_ = "o finufft_plan* = new()"; +static const char* stubids3_ = "c o finufft_plan* = new()"; -void mexStub3(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *out0_ = 0; /* p */ +void mexStub3(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* out0_=0; /* p */ - if (mexprofrecord_) mexprofrecord_[3]++; - out0_ = new finufft_plan(); - plhs[0] = mxWrapCreateP(out0_, "finufft_plan:%p"); + if (mexprofrecord_) + mexprofrecord_[3]++; + out0_ = new finufft_plan(); + plhs[0] = mxWrapCreateP(out0_, "finufft_plan:%p"); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 173 ---- * finufft_default_opts(finufft_opts* o); */ -static const char *stubids4_ = "finufft_default_opts(i finufft_opts*)"; +static const char* stubids4_ = "finufft_default_opts(c i finufft_opts*)"; + +void mexStub4(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_opts* in0_ =0; /* o */ -void mexStub4(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_opts *in0_ = 0; /* o */ + in0_ = (finufft_opts*) mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; - in0_ = (finufft_opts *)mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[4]++; - finufft_default_opts(in0_); + if (mexprofrecord_) + mexprofrecord_[4]++; + finufft_default_opts(in0_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 175 ---- * finufftf_plan* p = new(); */ -static const char *stubids5_ = "o finufftf_plan* = new()"; +static const char* stubids5_ = "c o finufftf_plan* = new()"; -void mexStub5(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *out0_ = 0; /* p */ +void mexStub5(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* out0_=0; /* p */ - if (mexprofrecord_) mexprofrecord_[5]++; - out0_ = new finufftf_plan(); - plhs[0] = mxWrapCreateP(out0_, "finufftf_plan:%p"); + if (mexprofrecord_) + mexprofrecord_[5]++; + out0_ = new finufftf_plan(); + plhs[0] = mxWrapCreateP(out0_, "finufftf_plan:%p"); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 176 ---- * finufftf_default_opts(finufft_opts* o); */ -static const char *stubids6_ = "finufftf_default_opts(i finufft_opts*)"; +static const char* stubids6_ = "finufftf_default_opts(c i finufft_opts*)"; -void mexStub6(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_opts *in0_ = 0; /* o */ +void mexStub6(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_opts* in0_ =0; /* o */ - in0_ = (finufft_opts *)mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[6]++; - finufftf_default_opts(in0_); + in0_ = (finufft_opts*) mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[6]++; + finufftf_default_opts(in0_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 187 ---- * copy_finufft_opts(mxArray opts, finufft_opts* o); */ -static const char *stubids7_ = "copy_finufft_opts(i mxArray, i finufft_opts*)"; +static const char* stubids7_ = "copy_finufft_opts(c i mxArray, c i finufft_opts*)"; + +void mexStub7(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + const mxArray* in0_; /* opts */ + finufft_opts* in1_ =0; /* o */ -void mexStub7(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - const mxArray *in0_; /* opts */ - finufft_opts *in1_ = 0; /* o */ + in0_ = prhs[0]; - in0_ = prhs[0]; - in1_ = (finufft_opts *)mxWrapGetP(prhs[1], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[7]++; - copy_finufft_opts(in0_, in1_); + in1_ = (finufft_opts*) mxWrapGetP(prhs[1], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[7]++; + copy_finufft_opts(in0_, in1_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 190 ---- - * int ier = finufft_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int - * n_trans, double tol, finufft_plan* plan, finufft_opts* o); + * int ier = finufft_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, double tol, finufft_plan* plan, finufft_opts* o); */ -static const char *stubids8_ = "o int = finufft_makeplan(i int, i int, i int64_t[x], i " - "int, i int, i double, i finufft_plan*, i finufft_opts*)"; - -void mexStub8(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - int in0_; /* type */ - int in1_; /* dim */ - int64_t *in2_ = 0; /* n_modes */ - int in3_; /* iflag */ - int in4_; /* n_trans */ - double in5_; /* tol */ - finufft_plan *in6_ = 0; /* plan */ - finufft_opts *in7_ = 0; /* o */ - int out0_; /* ier */ - mwSize dim8_; /* 3 */ - - dim8_ = (mwSize)mxWrapGetScalar(prhs[8], &mw_err_txt_); - - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != dim8_) { - mw_err_txt_ = "Bad argument size: n_modes"; - goto mw_err_label; - } - - if (mxGetClassID(prhs[0]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in0_ = (int)mxWrapGetScalar(prhs[0], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = (int)mxWrapGetScalar(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != 0) { - in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); +static const char* stubids8_ = "c o int = finufft_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i double, c i finufft_plan*, c i finufft_opts*)"; + +void mexStub8(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + int in0_; /* type */ + int in1_; /* dim */ + int64_t* in2_ =0; /* n_modes */ + int in3_; /* iflag */ + int in4_; /* n_trans */ + double in5_; /* tol */ + finufft_plan* in6_ =0; /* plan */ + finufft_opts* in7_ =0; /* o */ + int out0_; /* ier */ + mwSize dim8_; /* 3 */ + + dim8_ = (mwSize) mxWrapGetScalar(prhs[8], &mw_err_txt_); + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != dim8_) { + mw_err_txt_ = "Bad argument size: n_modes"; goto mw_err_label; + } + + if( mxGetClassID(prhs[0]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in0_ = (int) mxWrapGetScalar(prhs[0], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in2_ = NULL; + + if( mxGetClassID(prhs[3]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in3_ = (int) mxWrapGetScalar(prhs[3], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[4]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in4_ = (int) mxWrapGetScalar(prhs[4], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; - } else - in2_ = NULL; - if (mxGetClassID(prhs[3]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in3_ = (int)mxWrapGetScalar(prhs[3], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[4]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in4_ = (int)mxWrapGetScalar(prhs[4], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[5]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in5_ = (double)mxWrapGetScalar(prhs[5], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - in6_ = (finufft_plan *)mxWrapGetP(prhs[6], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - in7_ = (finufft_opts *)mxWrapGetP(prhs[7], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[8]++; - out0_ = finufft_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); + in5_ = (double) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in6_ = (finufft_plan*) mxWrapGetP(prhs[6], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in7_ = (finufft_opts*) mxWrapGetP(prhs[7], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[8]++; + out0_ = finufft_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif mw_err_label: - if (in2_) mxFree(in2_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in2_) mxFree(in2_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 193 ---- - * int ier = finufftf_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int - * n_trans, float tol, finufftf_plan* plan, finufft_opts* o); + * int ier = finufftf_makeplan(int type, int dim, int64_t[3] n_modes, int iflag, int n_trans, float tol, finufftf_plan* plan, finufft_opts* o); */ -static const char *stubids9_ = "o int = finufftf_makeplan(i int, i int, i int64_t[x], i " - "int, i int, i float, i finufftf_plan*, i finufft_opts*)"; - -void mexStub9(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - int in0_; /* type */ - int in1_; /* dim */ - int64_t *in2_ = 0; /* n_modes */ - int in3_; /* iflag */ - int in4_; /* n_trans */ - float in5_; /* tol */ - finufftf_plan *in6_ = 0; /* plan */ - finufft_opts *in7_ = 0; /* o */ - int out0_; /* ier */ - mwSize dim8_; /* 3 */ - - dim8_ = (mwSize)mxWrapGetScalar(prhs[8], &mw_err_txt_); - - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != dim8_) { - mw_err_txt_ = "Bad argument size: n_modes"; - goto mw_err_label; - } - - if (mxGetClassID(prhs[0]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in0_ = (int)mxWrapGetScalar(prhs[0], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = (int)mxWrapGetScalar(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != 0) { - in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); +static const char* stubids9_ = "c o int = finufftf_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i float, c i finufftf_plan*, c i finufft_opts*)"; + +void mexStub9(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + int in0_; /* type */ + int in1_; /* dim */ + int64_t* in2_ =0; /* n_modes */ + int in3_; /* iflag */ + int in4_; /* n_trans */ + float in5_; /* tol */ + finufftf_plan* in6_ =0; /* plan */ + finufft_opts* in7_ =0; /* o */ + int out0_; /* ier */ + mwSize dim8_; /* 3 */ + + dim8_ = (mwSize) mxWrapGetScalar(prhs[8], &mw_err_txt_); + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != dim8_) { + mw_err_txt_ = "Bad argument size: n_modes"; goto mw_err_label; + } + + if( mxGetClassID(prhs[0]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in0_ = (int) mxWrapGetScalar(prhs[0], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; - } else - in2_ = NULL; - if (mxGetClassID(prhs[3]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in3_ = (int)mxWrapGetScalar(prhs[3], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[4]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in4_ = (int)mxWrapGetScalar(prhs[4], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[5]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in5_ = (float)mxWrapGetScalar_single(prhs[5], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - in6_ = (finufftf_plan *)mxWrapGetP(prhs[6], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - in7_ = (finufft_opts *)mxWrapGetP(prhs[7], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[9]++; - out0_ = finufftf_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); + in1_ = (int) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + in2_ = mxWrapGetArray_int64_t(prhs[2], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in2_ = NULL; + + if( mxGetClassID(prhs[3]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in3_ = (int) mxWrapGetScalar(prhs[3], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[4]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in4_ = (int) mxWrapGetScalar(prhs[4], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[5]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in5_ = (float) mxWrapGetScalar_single(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in6_ = (finufftf_plan*) mxWrapGetP(prhs[6], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + in7_ = (finufft_opts*) mxWrapGetP(prhs[7], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mexprofrecord_) + mexprofrecord_[9]++; + out0_ = finufftf_makeplan(in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif mw_err_label: - if (in2_) mxFree(in2_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in2_) mxFree(in2_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 195 ---- * delete(finufft_opts* o); */ -static const char *stubids10_ = "delete(i finufft_opts*)"; +static const char* stubids10_ = "delete(c i finufft_opts*)"; + +void mexStub10(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_opts* in0_ =0; /* o */ -void mexStub10(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_opts *in0_ = 0; /* o */ + in0_ = (finufft_opts*) mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; - in0_ = (finufft_opts *)mxWrapGetP(prhs[0], "finufft_opts:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mexprofrecord_) mexprofrecord_[10]++; - delete (in0_); + if (mexprofrecord_) + mexprofrecord_[10]++; + delete(in0_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 225 ---- - * int ier = finufft_setpts(finufft_plan plan, int64_t nj, double[] xj, double[] yj, - * double[] zj, int64_t nk, double[] s, double[] t, double[] u); + * int ier = finufft_setpts(finufft_plan plan, int64_t nj, double[] xj, double[] yj, double[] zj, int64_t nk, double[] s, double[] t, double[] u); */ -static const char *stubids11_ = - "o int = finufft_setpts(i finufft_plan, i int64_t, i double[], i double[], i " - "double[], i int64_t, i double[], i double[], i double[])"; - -void mexStub11(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *in0_ = 0; /* plan */ - int64_t in1_; /* nj */ - double *in2_ = 0; /* xj */ - double *in3_ = 0; /* yj */ - double *in4_ = 0; /* zj */ - int64_t in5_; /* nk */ - double *in6_ = 0; /* s */ - double *in7_ = 0; /* t */ - double *in8_ = 0; /* u */ - int out0_; /* ier */ - - in0_ = (finufft_plan *)mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = (int64_t)mxWrapGetScalar(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != 0) { - if (mxGetClassID(prhs[2]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; +static const char* stubids11_ = "c o int = finufft_setpts(c i finufft_plan, c i int64_t, c i double[], c i double[], c i double[], c i int64_t, c i double[], c i double[], c i double[])"; + +void mexStub11(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* in0_ =0; /* plan */ + int64_t in1_; /* nj */ + double* in2_ =0; /* xj */ + double* in3_ =0; /* yj */ + double* in4_ =0; /* zj */ + int64_t in5_; /* nk */ + double* in6_ =0; /* s */ + double* in7_ =0; /* t */ + double* in8_ =0; /* u */ + int out0_; /* ier */ + + in0_ = (finufft_plan*) mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; + in1_ = (int64_t) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + if( mxGetClassID(prhs[2]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in2_ = mxGetDoubles(prhs[2]); + in2_ = mxGetDoubles(prhs[2]); #else - in2_ = mxGetPr(prhs[2]); + in2_ = mxGetPr(prhs[2]); #endif - } else - in2_ = NULL; - if (mxGetM(prhs[3]) * mxGetN(prhs[3]) != 0) { - if (mxGetClassID(prhs[3]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in2_ = NULL; + + if (mxGetM(prhs[3])*mxGetN(prhs[3]) != 0) { + if( mxGetClassID(prhs[3]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in3_ = mxGetDoubles(prhs[3]); + in3_ = mxGetDoubles(prhs[3]); #else - in3_ = mxGetPr(prhs[3]); + in3_ = mxGetPr(prhs[3]); #endif - } else - in3_ = NULL; - if (mxGetM(prhs[4]) * mxGetN(prhs[4]) != 0) { - if (mxGetClassID(prhs[4]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in3_ = NULL; + + if (mxGetM(prhs[4])*mxGetN(prhs[4]) != 0) { + if( mxGetClassID(prhs[4]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in4_ = mxGetDoubles(prhs[4]); + in4_ = mxGetDoubles(prhs[4]); #else - in4_ = mxGetPr(prhs[4]); + in4_ = mxGetPr(prhs[4]); #endif - } else - in4_ = NULL; - if (mxGetClassID(prhs[5]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in5_ = (int64_t)mxWrapGetScalar(prhs[5], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[6]) * mxGetN(prhs[6]) != 0) { - if (mxGetClassID(prhs[6]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + } else + in4_ = NULL; + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; + in5_ = (int64_t) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[6])*mxGetN(prhs[6]) != 0) { + if( mxGetClassID(prhs[6]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in6_ = mxGetDoubles(prhs[6]); + in6_ = mxGetDoubles(prhs[6]); #else - in6_ = mxGetPr(prhs[6]); + in6_ = mxGetPr(prhs[6]); #endif - } else - in6_ = NULL; - if (mxGetM(prhs[7]) * mxGetN(prhs[7]) != 0) { - if (mxGetClassID(prhs[7]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in6_ = NULL; + + if (mxGetM(prhs[7])*mxGetN(prhs[7]) != 0) { + if( mxGetClassID(prhs[7]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in7_ = mxGetDoubles(prhs[7]); + in7_ = mxGetDoubles(prhs[7]); #else - in7_ = mxGetPr(prhs[7]); + in7_ = mxGetPr(prhs[7]); #endif - } else - in7_ = NULL; - if (mxGetM(prhs[8]) * mxGetN(prhs[8]) != 0) { - if (mxGetClassID(prhs[8]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in7_ = NULL; + + if (mxGetM(prhs[8])*mxGetN(prhs[8]) != 0) { + if( mxGetClassID(prhs[8]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in8_ = mxGetDoubles(prhs[8]); + in8_ = mxGetDoubles(prhs[8]); #else - in8_ = mxGetPr(prhs[8]); + in8_ = mxGetPr(prhs[8]); #endif - } else - in8_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - if (mexprofrecord_) mexprofrecord_[11]++; - out0_ = finufft_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); + } else + in8_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[11]++; + out0_ = finufft_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- finufft.mw: 227 ---- - * int ier = finufftf_setpts(finufftf_plan plan, int64_t nj, float[] xj, float[] yj, - * float[] zj, int64_t nk, float[] s, float[] t, float[] u); + * int ier = finufftf_setpts(finufftf_plan plan, int64_t nj, float[] xj, float[] yj, float[] zj, int64_t nk, float[] s, float[] t, float[] u); */ -static const char *stubids12_ = - "o int = finufftf_setpts(i finufftf_plan, i int64_t, i float[], i float[], i " - "float[], i int64_t, i float[], i float[], i float[])"; - -void mexStub12(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *in0_ = 0; /* plan */ - int64_t in1_; /* nj */ - float *in2_ = 0; /* xj */ - float *in3_ = 0; /* yj */ - float *in4_ = 0; /* zj */ - int64_t in5_; /* nk */ - float *in6_ = 0; /* s */ - float *in7_ = 0; /* t */ - float *in8_ = 0; /* u */ - int out0_; /* ier */ - - in0_ = (finufftf_plan *)mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = (int64_t)mxWrapGetScalar(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[2]) * mxGetN(prhs[2]) != 0) { - if (mxGetClassID(prhs[2]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; +static const char* stubids12_ = "c o int = finufftf_setpts(c i finufftf_plan, c i int64_t, c i float[], c i float[], c i float[], c i int64_t, c i float[], c i float[], c i float[])"; + +void mexStub12(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* in0_ =0; /* plan */ + int64_t in1_; /* nj */ + float* in2_ =0; /* xj */ + float* in3_ =0; /* yj */ + float* in4_ =0; /* zj */ + int64_t in5_; /* nk */ + float* in6_ =0; /* s */ + float* in7_ =0; /* t */ + float* in8_ =0; /* u */ + int out0_; /* ier */ + + in0_ = (finufftf_plan*) mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; + in1_ = (int64_t) mxWrapGetScalar(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[2])*mxGetN(prhs[2]) != 0) { + if( mxGetClassID(prhs[2]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in2_ = mxGetSingles(prhs[2]); + in2_ = mxGetSingles(prhs[2]); #else - in2_ = (float *)mxGetData(prhs[2]); + in2_ = (float*) mxGetData(prhs[2]); #endif - } else - in2_ = NULL; - if (mxGetM(prhs[3]) * mxGetN(prhs[3]) != 0) { - if (mxGetClassID(prhs[3]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in2_ = NULL; + + if (mxGetM(prhs[3])*mxGetN(prhs[3]) != 0) { + if( mxGetClassID(prhs[3]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in3_ = mxGetSingles(prhs[3]); + in3_ = mxGetSingles(prhs[3]); #else - in3_ = (float *)mxGetData(prhs[3]); + in3_ = (float*) mxGetData(prhs[3]); #endif - } else - in3_ = NULL; - if (mxGetM(prhs[4]) * mxGetN(prhs[4]) != 0) { - if (mxGetClassID(prhs[4]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in3_ = NULL; + + if (mxGetM(prhs[4])*mxGetN(prhs[4]) != 0) { + if( mxGetClassID(prhs[4]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in4_ = mxGetSingles(prhs[4]); + in4_ = mxGetSingles(prhs[4]); #else - in4_ = (float *)mxGetData(prhs[4]); + in4_ = (float*) mxGetData(prhs[4]); #endif - } else - in4_ = NULL; - if (mxGetClassID(prhs[5]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in5_ = (int64_t)mxWrapGetScalar(prhs[5], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[6]) * mxGetN(prhs[6]) != 0) { - if (mxGetClassID(prhs[6]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + } else + in4_ = NULL; + + if( mxGetClassID(prhs[5]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid scalar argument, mxDOUBLE_CLASS expected"; if (mw_err_txt_) goto mw_err_label; + in5_ = (int64_t) mxWrapGetScalar(prhs[5], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[6])*mxGetN(prhs[6]) != 0) { + if( mxGetClassID(prhs[6]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in6_ = mxGetSingles(prhs[6]); + in6_ = mxGetSingles(prhs[6]); #else - in6_ = (float *)mxGetData(prhs[6]); + in6_ = (float*) mxGetData(prhs[6]); #endif - } else - in6_ = NULL; - if (mxGetM(prhs[7]) * mxGetN(prhs[7]) != 0) { - if (mxGetClassID(prhs[7]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in6_ = NULL; + + if (mxGetM(prhs[7])*mxGetN(prhs[7]) != 0) { + if( mxGetClassID(prhs[7]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in7_ = mxGetSingles(prhs[7]); + in7_ = mxGetSingles(prhs[7]); #else - in7_ = (float *)mxGetData(prhs[7]); + in7_ = (float*) mxGetData(prhs[7]); #endif - } else - in7_ = NULL; - if (mxGetM(prhs[8]) * mxGetN(prhs[8]) != 0) { - if (mxGetClassID(prhs[8]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; + } else + in7_ = NULL; + + if (mxGetM(prhs[8])*mxGetN(prhs[8]) != 0) { + if( mxGetClassID(prhs[8]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; #if MX_HAS_INTERLEAVED_COMPLEX - in8_ = mxGetSingles(prhs[8]); + in8_ = mxGetSingles(prhs[8]); #else - in8_ = (float *)mxGetData(prhs[8]); + in8_ = (float*) mxGetData(prhs[8]); #endif - } else - in8_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - if (mexprofrecord_) mexprofrecord_[12]++; - out0_ = finufftf_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); + } else + in8_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[12]++; + out0_ = finufftf_setpts(*in0_, in1_, in2_, in3_, in4_, in5_, in6_, in7_, in8_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 254 ---- - * int ier = finufft_execute(finufft_plan plan, dcomplex[] data_in, output - * dcomplex[ncoeffs] result); +/* ---- finufft.mw: 259 ---- + * int ier = finufft_execute(finufft_plan plan, dcomplex[] data_in, output dcomplex[ncoeffs] result); */ -static const char *stubids13_ = - "o int = finufft_execute(i finufft_plan, i dcomplex[], o dcomplex[x])"; - -void mexStub13(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *in0_ = 0; /* plan */ - dcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - dcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* ncoeffs */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - - in0_ = (finufft_plan *)mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (dcomplex *)mxMalloc(dim2_ * sizeof(dcomplex)); - if (mexprofrecord_) mexprofrecord_[13]++; - out0_ = finufft_execute(*in0_, in1_, out1_); +static const char* stubids13_ = "c o int = finufft_execute(c i finufft_plan, c i dcomplex[], c o dcomplex[x])"; + +void mexStub13(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* in0_ =0; /* plan */ + dcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + dcomplex* out1_=0; /* result */ + mwSize dim2_; /* ncoeffs */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + + in0_ = (finufft_plan*) mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (dcomplex*) mxMalloc(dim2_*sizeof(dcomplex)); + if (mexprofrecord_) + mexprofrecord_[13]++; + out0_ = finufft_execute(*in0_, in1_, out1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateDoubleMatrix(dim2_, 1, mxCOMPLEX); - mxWrapCopy_dcomplex(plhs[1], out1_, dim2_); + plhs[1] = mxCreateDoubleMatrix(dim2_, 1, mxCOMPLEX); + mxWrapCopy_dcomplex(plhs[1], out1_, dim2_); mw_err_label: - if (in1_) mxFree(in1_); - if (out1_) mxFree(out1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in1_) mxFree(in1_); + if (out1_) mxFree(out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 256 ---- - * int ier = finufftf_execute(finufftf_plan plan, fcomplex[] data_in, output - * fcomplex[ncoeffs] result); +/* ---- finufft.mw: 261 ---- + * int ier = finufftf_execute(finufftf_plan plan, fcomplex[] data_in, output fcomplex[ncoeffs] result); */ -static const char *stubids14_ = - "o int = finufftf_execute(i finufftf_plan, i fcomplex[], o fcomplex[x])"; - -void mexStub14(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *in0_ = 0; /* plan */ - fcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - fcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* ncoeffs */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - - in0_ = (finufftf_plan *)mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (fcomplex *)mxMalloc(dim2_ * sizeof(fcomplex)); - if (mexprofrecord_) mexprofrecord_[14]++; - out0_ = finufftf_execute(*in0_, in1_, out1_); +static const char* stubids14_ = "c o int = finufftf_execute(c i finufftf_plan, c i fcomplex[], c o fcomplex[x])"; + +void mexStub14(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* in0_ =0; /* plan */ + fcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + fcomplex* out1_=0; /* result */ + mwSize dim2_; /* ncoeffs */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + + in0_ = (finufftf_plan*) mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (fcomplex*) mxMalloc(dim2_*sizeof(fcomplex)); + if (mexprofrecord_) + mexprofrecord_[14]++; + out0_ = finufftf_execute(*in0_, in1_, out1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateNumericMatrix(dim2_, 1, mxSINGLE_CLASS, mxCOMPLEX); - mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_); + plhs[1] = mxCreateNumericMatrix(dim2_, 1, mxSINGLE_CLASS, mxCOMPLEX); + mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_); mw_err_label: - if (in1_) mxFree(in1_); - if (out1_) mxFree(out1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in1_) mxFree(in1_); + if (out1_) mxFree(out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 262 ---- - * int ier = finufft_execute(finufft_plan plan, output dcomplex[nj, n_trans] result, - * dcomplex[] data_in); +/* ---- finufft.mw: 267 ---- + * int ier = finufft_execute(finufft_plan plan, output dcomplex[nj, n_trans] result, dcomplex[] data_in); */ -static const char *stubids15_ = - "o int = finufft_execute(i finufft_plan, o dcomplex[xx], i dcomplex[])"; - -void mexStub15(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *in0_ = 0; /* plan */ - dcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - dcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* nj */ - mwSize dim3_; /* n_trans */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - dim3_ = (mwSize)mxWrapGetScalar(prhs[3], &mw_err_txt_); - - in0_ = (finufft_plan *)mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (dcomplex *)mxMalloc(dim2_ * dim3_ * sizeof(dcomplex)); - if (mexprofrecord_) mexprofrecord_[15]++; - out0_ = finufft_execute(*in0_, out1_, in1_); +static const char* stubids15_ = "c o int = finufft_execute(c i finufft_plan, c o dcomplex[xx], c i dcomplex[])"; + +void mexStub15(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* in0_ =0; /* plan */ + dcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + dcomplex* out1_=0; /* result */ + mwSize dim2_; /* nj */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (finufft_plan*) mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (dcomplex*) mxMalloc(dim2_*dim3_*sizeof(dcomplex)); + if (mexprofrecord_) + mexprofrecord_[15]++; + out0_ = finufft_execute(*in0_, out1_, in1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateDoubleMatrix(dim2_, dim3_, mxCOMPLEX); - mxWrapCopy_dcomplex(plhs[1], out1_, dim2_ * dim3_); + plhs[1] = mxCreateDoubleMatrix(dim2_, dim3_, mxCOMPLEX); + mxWrapCopy_dcomplex(plhs[1], out1_, dim2_*dim3_); mw_err_label: - if (out1_) mxFree(out1_); - if (in1_) mxFree(in1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (out1_) mxFree(out1_); + if (in1_) mxFree(in1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 264 ---- - * int ier = finufftf_execute(finufftf_plan plan, output fcomplex[nj, n_trans] result, - * fcomplex[] data_in); +/* ---- finufft.mw: 269 ---- + * int ier = finufftf_execute(finufftf_plan plan, output fcomplex[nj, n_trans] result, fcomplex[] data_in); */ -static const char *stubids16_ = - "o int = finufftf_execute(i finufftf_plan, o fcomplex[xx], i fcomplex[])"; - -void mexStub16(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *in0_ = 0; /* plan */ - fcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - fcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* nj */ - mwSize dim3_; /* n_trans */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - dim3_ = (mwSize)mxWrapGetScalar(prhs[3], &mw_err_txt_); - - in0_ = (finufftf_plan *)mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (fcomplex *)mxMalloc(dim2_ * dim3_ * sizeof(fcomplex)); - if (mexprofrecord_) mexprofrecord_[16]++; - out0_ = finufftf_execute(*in0_, out1_, in1_); +static const char* stubids16_ = "c o int = finufftf_execute(c i finufftf_plan, c o fcomplex[xx], c i fcomplex[])"; + +void mexStub16(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* in0_ =0; /* plan */ + fcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + fcomplex* out1_=0; /* result */ + mwSize dim2_; /* nj */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (finufftf_plan*) mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (fcomplex*) mxMalloc(dim2_*dim3_*sizeof(fcomplex)); + if (mexprofrecord_) + mexprofrecord_[16]++; + out0_ = finufftf_execute(*in0_, out1_, in1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateNumericMatrix(dim2_, dim3_, mxSINGLE_CLASS, mxCOMPLEX); - mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_ * dim3_); + plhs[1] = mxCreateNumericMatrix(dim2_, dim3_, mxSINGLE_CLASS, mxCOMPLEX); + mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_*dim3_); mw_err_label: - if (out1_) mxFree(out1_); - if (in1_) mxFree(in1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (out1_) mxFree(out1_); + if (in1_) mxFree(in1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 268 ---- - * int ier = finufft_execute(finufft_plan plan, dcomplex[] data_in, output dcomplex[nk, - * n_trans] result); +/* ---- finufft.mw: 273 ---- + * int ier = finufft_execute(finufft_plan plan, dcomplex[] data_in, output dcomplex[nk, n_trans] result); */ -static const char *stubids17_ = - "o int = finufft_execute(i finufft_plan, i dcomplex[], o dcomplex[xx])"; - -void mexStub17(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *in0_ = 0; /* plan */ - dcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - dcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* nk */ - mwSize dim3_; /* n_trans */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - dim3_ = (mwSize)mxWrapGetScalar(prhs[3], &mw_err_txt_); - - in0_ = (finufft_plan *)mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxDOUBLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (dcomplex *)mxMalloc(dim2_ * dim3_ * sizeof(dcomplex)); - if (mexprofrecord_) mexprofrecord_[17]++; - out0_ = finufft_execute(*in0_, in1_, out1_); +static const char* stubids17_ = "c o int = finufft_execute(c i finufft_plan, c i dcomplex[], c o dcomplex[xx])"; + +void mexStub17(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* in0_ =0; /* plan */ + dcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + dcomplex* out1_=0; /* result */ + mwSize dim2_; /* nk */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (finufft_plan*) mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxDOUBLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxDOUBLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_dcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (dcomplex*) mxMalloc(dim2_*dim3_*sizeof(dcomplex)); + if (mexprofrecord_) + mexprofrecord_[17]++; + out0_ = finufft_execute(*in0_, in1_, out1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateDoubleMatrix(dim2_, dim3_, mxCOMPLEX); - mxWrapCopy_dcomplex(plhs[1], out1_, dim2_ * dim3_); + plhs[1] = mxCreateDoubleMatrix(dim2_, dim3_, mxCOMPLEX); + mxWrapCopy_dcomplex(plhs[1], out1_, dim2_*dim3_); mw_err_label: - if (in1_) mxFree(in1_); - if (out1_) mxFree(out1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in1_) mxFree(in1_); + if (out1_) mxFree(out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 270 ---- - * int ier = finufftf_execute(finufftf_plan plan, fcomplex[] data_in, output fcomplex[nk, - * n_trans] result); +/* ---- finufft.mw: 275 ---- + * int ier = finufftf_execute(finufftf_plan plan, fcomplex[] data_in, output fcomplex[nk, n_trans] result); */ -static const char *stubids18_ = - "o int = finufftf_execute(i finufftf_plan, i fcomplex[], o fcomplex[xx])"; - -void mexStub18(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *in0_ = 0; /* plan */ - fcomplex *in1_ = 0; /* data_in */ - int out0_; /* ier */ - fcomplex *out1_ = 0; /* result */ - mwSize dim2_; /* nk */ - mwSize dim3_; /* n_trans */ - - dim2_ = (mwSize)mxWrapGetScalar(prhs[2], &mw_err_txt_); - dim3_ = (mwSize)mxWrapGetScalar(prhs[3], &mw_err_txt_); - - in0_ = (finufftf_plan *)mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (mxGetM(prhs[1]) * mxGetN(prhs[1]) != 0) { - if (mxGetClassID(prhs[1]) != mxSINGLE_CLASS) - mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; - if (mw_err_txt_) goto mw_err_label; - in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - } else - in1_ = NULL; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - out1_ = (fcomplex *)mxMalloc(dim2_ * dim3_ * sizeof(fcomplex)); - if (mexprofrecord_) mexprofrecord_[18]++; - out0_ = finufftf_execute(*in0_, in1_, out1_); +static const char* stubids18_ = "c o int = finufftf_execute(c i finufftf_plan, c i fcomplex[], c o fcomplex[xx])"; + +void mexStub18(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* in0_ =0; /* plan */ + fcomplex* in1_ =0; /* data_in */ + int out0_; /* ier */ + fcomplex* out1_=0; /* result */ + mwSize dim2_; /* nk */ + mwSize dim3_; /* n_trans */ + + dim2_ = (mwSize) mxWrapGetScalar(prhs[2], &mw_err_txt_); + dim3_ = (mwSize) mxWrapGetScalar(prhs[3], &mw_err_txt_); + + in0_ = (finufftf_plan*) mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 0) { + if( mxGetClassID(prhs[1]) != mxSINGLE_CLASS ) + mw_err_txt_ = "Invalid array argument, mxSINGLE_CLASS expected"; + if (mw_err_txt_) goto mw_err_label; + in1_ = mxWrapGetArray_single_fcomplex(prhs[1], &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + } else + in1_ = NULL; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + out1_ = (fcomplex*) mxMalloc(dim2_*dim3_*sizeof(fcomplex)); + if (mexprofrecord_) + mexprofrecord_[18]++; + out0_ = finufftf_execute(*in0_, in1_, out1_); #if MX_HAS_INTERLEAVED_COMPLEX - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetDoubles(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetDoubles(plhs[0]) = out0_; #else - plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); - *mxGetPr(plhs[0]) = out0_; + plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(plhs[0]) = out0_; #endif - plhs[1] = mxCreateNumericMatrix(dim2_, dim3_, mxSINGLE_CLASS, mxCOMPLEX); - mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_ * dim3_); + plhs[1] = mxCreateNumericMatrix(dim2_, dim3_, mxSINGLE_CLASS, mxCOMPLEX); + mxWrapCopy_single_fcomplex(plhs[1], out1_, dim2_*dim3_); mw_err_label: - if (in1_) mxFree(in1_); - if (out1_) mxFree(out1_); - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (in1_) mxFree(in1_); + if (out1_) mxFree(out1_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 282 ---- +/* ---- finufft.mw: 287 ---- * finufft_destroy(finufft_plan plan); */ -static const char *stubids19_ = "finufft_destroy(i finufft_plan)"; +static const char* stubids19_ = "finufft_destroy(c i finufft_plan)"; -void mexStub19(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufft_plan *in0_ = 0; /* plan */ +void mexStub19(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufft_plan* in0_ =0; /* plan */ - in0_ = (finufft_plan *)mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - if (mexprofrecord_) mexprofrecord_[19]++; - finufft_destroy(*in0_); + in0_ = (finufft_plan*) mxWrapGetP(prhs[0], "finufft_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; + + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[19]++; + finufft_destroy(*in0_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } -/* ---- finufft.mw: 284 ---- +/* ---- finufft.mw: 289 ---- * finufftf_destroy(finufftf_plan plan); */ -static const char *stubids20_ = "finufftf_destroy(i finufftf_plan)"; +static const char* stubids20_ = "finufftf_destroy(c i finufftf_plan)"; + +void mexStub20(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + const char* mw_err_txt_ = 0; + finufftf_plan* in0_ =0; /* plan */ -void mexStub20(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - const char *mw_err_txt_ = 0; - finufftf_plan *in0_ = 0; /* plan */ + in0_ = (finufftf_plan*) mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); + if (mw_err_txt_) + goto mw_err_label; - in0_ = (finufftf_plan *)mxWrapGetP(prhs[0], "finufftf_plan:%p", &mw_err_txt_); - if (mw_err_txt_) goto mw_err_label; - if (!in0_) { - mw_err_txt_ = "Argument plan cannot be null"; - goto mw_err_label; - } - if (mexprofrecord_) mexprofrecord_[20]++; - finufftf_destroy(*in0_); + if (!in0_) { + mw_err_txt_ = "Argument plan cannot be null"; + goto mw_err_label; + } + if (mexprofrecord_) + mexprofrecord_[20]++; + finufftf_destroy(*in0_); mw_err_label: - if (mw_err_txt_) mexErrMsgTxt(mw_err_txt_); + if (mw_err_txt_) + mexErrMsgTxt(mw_err_txt_); } /* ---- */ -void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - char id[512]; - if (nrhs == 0) { - mexPrintf("Mex function installed\n"); - return; - } - - if (mxGetString(prhs[0], id, sizeof(id)) != 0) - mexErrMsgTxt("Identifier should be a string"); - else if (strcmp(id, stubids1_) == 0) - mexStub1(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids2_) == 0) - mexStub2(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids3_) == 0) - mexStub3(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids4_) == 0) - mexStub4(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids5_) == 0) - mexStub5(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids6_) == 0) - mexStub6(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids7_) == 0) - mexStub7(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids8_) == 0) - mexStub8(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids9_) == 0) - mexStub9(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids10_) == 0) - mexStub10(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids11_) == 0) - mexStub11(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids12_) == 0) - mexStub12(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids13_) == 0) - mexStub13(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids14_) == 0) - mexStub14(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids15_) == 0) - mexStub15(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids16_) == 0) - mexStub16(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids17_) == 0) - mexStub17(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids18_) == 0) - mexStub18(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids19_) == 0) - mexStub19(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, stubids20_) == 0) - mexStub20(nlhs, plhs, nrhs - 1, prhs + 1); - else if (strcmp(id, "*profile on*") == 0) { - if (!mexprofrecord_) { - mexprofrecord_ = (int *)malloc(21 * sizeof(int)); - mexLock(); +void mexFunction(int nlhs, mxArray* plhs[], + int nrhs, const mxArray* prhs[]) +{ + char id[1024]; + if (nrhs == 0) { + mexPrintf("Mex function installed\n"); + return; } - memset(mexprofrecord_, 0, 21 * sizeof(int)); - } else if (strcmp(id, "*profile off*") == 0) { - if (mexprofrecord_) { - free(mexprofrecord_); - mexUnlock(); - } - mexprofrecord_ = NULL; - } else if (strcmp(id, "*profile report*") == 0) { - if (!mexprofrecord_) mexPrintf("Profiler inactive\n"); - mexPrintf("%d calls to finufft.mw:169\n", mexprofrecord_[1]); - mexPrintf("%d calls to finufft.mw:170\n", mexprofrecord_[2]); - mexPrintf("%d calls to finufft.mw:172\n", mexprofrecord_[3]); - mexPrintf("%d calls to finufft.mw:173\n", mexprofrecord_[4]); - mexPrintf("%d calls to finufft.mw:175\n", mexprofrecord_[5]); - mexPrintf("%d calls to finufft.mw:176\n", mexprofrecord_[6]); - mexPrintf("%d calls to finufft.mw:187\n", mexprofrecord_[7]); - mexPrintf("%d calls to finufft.mw:190\n", mexprofrecord_[8]); - mexPrintf("%d calls to finufft.mw:193\n", mexprofrecord_[9]); - mexPrintf("%d calls to finufft.mw:195\n", mexprofrecord_[10]); - mexPrintf("%d calls to finufft.mw:225\n", mexprofrecord_[11]); - mexPrintf("%d calls to finufft.mw:227\n", mexprofrecord_[12]); - mexPrintf("%d calls to finufft.mw:254\n", mexprofrecord_[13]); - mexPrintf("%d calls to finufft.mw:256\n", mexprofrecord_[14]); - mexPrintf("%d calls to finufft.mw:262\n", mexprofrecord_[15]); - mexPrintf("%d calls to finufft.mw:264\n", mexprofrecord_[16]); - mexPrintf("%d calls to finufft.mw:268\n", mexprofrecord_[17]); - mexPrintf("%d calls to finufft.mw:270\n", mexprofrecord_[18]); - mexPrintf("%d calls to finufft.mw:282\n", mexprofrecord_[19]); - mexPrintf("%d calls to finufft.mw:284\n", mexprofrecord_[20]); - } else if (strcmp(id, "*profile log*") == 0) { - FILE *logfp; - if (nrhs != 2 || mxGetString(prhs[1], id, sizeof(id)) != 0) - mexErrMsgTxt("Must have two string arguments"); - logfp = fopen(id, "w+"); - if (!logfp) mexErrMsgTxt("Cannot open log for output"); - if (!mexprofrecord_) fprintf(logfp, "Profiler inactive\n"); - fprintf(logfp, "%d calls to finufft.mw:169\n", mexprofrecord_[1]); - fprintf(logfp, "%d calls to finufft.mw:170\n", mexprofrecord_[2]); - fprintf(logfp, "%d calls to finufft.mw:172\n", mexprofrecord_[3]); - fprintf(logfp, "%d calls to finufft.mw:173\n", mexprofrecord_[4]); - fprintf(logfp, "%d calls to finufft.mw:175\n", mexprofrecord_[5]); - fprintf(logfp, "%d calls to finufft.mw:176\n", mexprofrecord_[6]); - fprintf(logfp, "%d calls to finufft.mw:187\n", mexprofrecord_[7]); - fprintf(logfp, "%d calls to finufft.mw:190\n", mexprofrecord_[8]); - fprintf(logfp, "%d calls to finufft.mw:193\n", mexprofrecord_[9]); - fprintf(logfp, "%d calls to finufft.mw:195\n", mexprofrecord_[10]); - fprintf(logfp, "%d calls to finufft.mw:225\n", mexprofrecord_[11]); - fprintf(logfp, "%d calls to finufft.mw:227\n", mexprofrecord_[12]); - fprintf(logfp, "%d calls to finufft.mw:254\n", mexprofrecord_[13]); - fprintf(logfp, "%d calls to finufft.mw:256\n", mexprofrecord_[14]); - fprintf(logfp, "%d calls to finufft.mw:262\n", mexprofrecord_[15]); - fprintf(logfp, "%d calls to finufft.mw:264\n", mexprofrecord_[16]); - fprintf(logfp, "%d calls to finufft.mw:268\n", mexprofrecord_[17]); - fprintf(logfp, "%d calls to finufft.mw:270\n", mexprofrecord_[18]); - fprintf(logfp, "%d calls to finufft.mw:282\n", mexprofrecord_[19]); - fprintf(logfp, "%d calls to finufft.mw:284\n", mexprofrecord_[20]); - fclose(logfp); - } else - mexErrMsgTxt("Unknown identifier"); + + + + if (mxGetString(prhs[0], id, sizeof(id)) != 0) + mexErrMsgTxt("Identifier should be a string"); + else if (strcmp(id, stubids1_) == 0) + mexStub1(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids2_) == 0) + mexStub2(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids3_) == 0) + mexStub3(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids4_) == 0) + mexStub4(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids5_) == 0) + mexStub5(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids6_) == 0) + mexStub6(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids7_) == 0) + mexStub7(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids8_) == 0) + mexStub8(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids9_) == 0) + mexStub9(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids10_) == 0) + mexStub10(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids11_) == 0) + mexStub11(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids12_) == 0) + mexStub12(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids13_) == 0) + mexStub13(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids14_) == 0) + mexStub14(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids15_) == 0) + mexStub15(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids16_) == 0) + mexStub16(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids17_) == 0) + mexStub17(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids18_) == 0) + mexStub18(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids19_) == 0) + mexStub19(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, stubids20_) == 0) + mexStub20(nlhs,plhs, nrhs-1,prhs+1); + else if (strcmp(id, "*profile on*") == 0) { + if (!mexprofrecord_) { + mexprofrecord_ = (int*) malloc(21 * sizeof(int)); + mexLock(); + } + memset(mexprofrecord_, 0, 21 * sizeof(int)); + } else if (strcmp(id, "*profile off*") == 0) { + if (mexprofrecord_) { + free(mexprofrecord_); + mexUnlock(); + } + mexprofrecord_ = NULL; + } else if (strcmp(id, "*profile report*") == 0) { + if (!mexprofrecord_) + mexPrintf("Profiler inactive\n"); + mexPrintf("%d calls to finufft.mw:169\n", mexprofrecord_[1]); + mexPrintf("%d calls to finufft.mw:170\n", mexprofrecord_[2]); + mexPrintf("%d calls to finufft.mw:172\n", mexprofrecord_[3]); + mexPrintf("%d calls to finufft.mw:173\n", mexprofrecord_[4]); + mexPrintf("%d calls to finufft.mw:175\n", mexprofrecord_[5]); + mexPrintf("%d calls to finufft.mw:176\n", mexprofrecord_[6]); + mexPrintf("%d calls to finufft.mw:187\n", mexprofrecord_[7]); + mexPrintf("%d calls to finufft.mw:190\n", mexprofrecord_[8]); + mexPrintf("%d calls to finufft.mw:193\n", mexprofrecord_[9]); + mexPrintf("%d calls to finufft.mw:195\n", mexprofrecord_[10]); + mexPrintf("%d calls to finufft.mw:225\n", mexprofrecord_[11]); + mexPrintf("%d calls to finufft.mw:227\n", mexprofrecord_[12]); + mexPrintf("%d calls to finufft.mw:259\n", mexprofrecord_[13]); + mexPrintf("%d calls to finufft.mw:261\n", mexprofrecord_[14]); + mexPrintf("%d calls to finufft.mw:267\n", mexprofrecord_[15]); + mexPrintf("%d calls to finufft.mw:269\n", mexprofrecord_[16]); + mexPrintf("%d calls to finufft.mw:273\n", mexprofrecord_[17]); + mexPrintf("%d calls to finufft.mw:275\n", mexprofrecord_[18]); + mexPrintf("%d calls to finufft.mw:287\n", mexprofrecord_[19]); + mexPrintf("%d calls to finufft.mw:289\n", mexprofrecord_[20]); + } else if (strcmp(id, "*profile log*") == 0) { + FILE* logfp; + if (nrhs != 2 || mxGetString(prhs[1], id, sizeof(id)) != 0) + mexErrMsgTxt("Must have two string arguments"); + logfp = fopen(id, "w+"); + if (!logfp) + mexErrMsgTxt("Cannot open log for output"); + if (!mexprofrecord_) + fprintf(logfp, "Profiler inactive\n"); + fprintf(logfp, "%d calls to finufft.mw:169\n", mexprofrecord_[1]); + fprintf(logfp, "%d calls to finufft.mw:170\n", mexprofrecord_[2]); + fprintf(logfp, "%d calls to finufft.mw:172\n", mexprofrecord_[3]); + fprintf(logfp, "%d calls to finufft.mw:173\n", mexprofrecord_[4]); + fprintf(logfp, "%d calls to finufft.mw:175\n", mexprofrecord_[5]); + fprintf(logfp, "%d calls to finufft.mw:176\n", mexprofrecord_[6]); + fprintf(logfp, "%d calls to finufft.mw:187\n", mexprofrecord_[7]); + fprintf(logfp, "%d calls to finufft.mw:190\n", mexprofrecord_[8]); + fprintf(logfp, "%d calls to finufft.mw:193\n", mexprofrecord_[9]); + fprintf(logfp, "%d calls to finufft.mw:195\n", mexprofrecord_[10]); + fprintf(logfp, "%d calls to finufft.mw:225\n", mexprofrecord_[11]); + fprintf(logfp, "%d calls to finufft.mw:227\n", mexprofrecord_[12]); + fprintf(logfp, "%d calls to finufft.mw:259\n", mexprofrecord_[13]); + fprintf(logfp, "%d calls to finufft.mw:261\n", mexprofrecord_[14]); + fprintf(logfp, "%d calls to finufft.mw:267\n", mexprofrecord_[15]); + fprintf(logfp, "%d calls to finufft.mw:269\n", mexprofrecord_[16]); + fprintf(logfp, "%d calls to finufft.mw:273\n", mexprofrecord_[17]); + fprintf(logfp, "%d calls to finufft.mw:275\n", mexprofrecord_[18]); + fprintf(logfp, "%d calls to finufft.mw:287\n", mexprofrecord_[19]); + fprintf(logfp, "%d calls to finufft.mw:289\n", mexprofrecord_[20]); + fclose(logfp); + } else + mexErrMsgTxt("Unknown identifier"); } + diff --git a/matlab/finufft_plan.m b/matlab/finufft_plan.m index 6a841481c..c21083cda 100644 --- a/matlab/finufft_plan.m +++ b/matlab/finufft_plan.m @@ -1,155 +1,3 @@ -% FINUFFT_PLAN is a class which wraps the guru interface to FINUFFT. -% -% Full documentation is given in ../finufft-manual.pdf and online at -% http://finufft.readthedocs.io -% Also see examples in the matlab/examples and matlab/test directories. -% -% PROPERTIES -% mwptr - opaque pointer to a C++ finufft_plan object (see MWrap manual), -% whose properties cannot be accessed directly -% floatprec - either 'double' or 'single', tracks what precision of C++ -% library is being called -% type, dim, n_modes, n_trans, nj, nk - other plan parameters -% Note: the user should never alter these plan properties directly! Rather, -% the below methods should be used to create, use, and destroy plans. -% -% METHODS -% finufft_plan - create guru plan object for one/many general nonuniform FFTs. -% setpts - process nonuniform points for general FINUFFT transform(s). -% execute - execute single or many-vector FINUFFT transforms in a plan. -% -% General notes: -% * use delete(plan) to remove a plan after use. -% * See ERRHANDLER, VALID_*, and this code for warning/error IDs. -% -% -% -% =========== Detailed description of guru methods ========================== -% -% 1) FINUFFT_PLAN create guru plan object for one/many general nonuniform FFTs. -% -% plan = finufft_plan(type, n_modes_or_dim, isign, ntrans, eps) -% plan = finufft_plan(type, n_modes_or_dim, isign, ntrans, eps, opts) -% -% Creates a finufft_plan MATLAB object in the guru interface to FINUFFT, of -% type 1, 2 or 3, and with given numbers of Fourier modes (unless type 3). -% -% Inputs: -% type transform type: 1, 2, or 3 -% n_modes_or_dim if type is 1 or 2, the number of Fourier modes in each -% dimension: [ms] in 1D, [ms mt] in 2D, or [ms mt mu] in 3D. -% Its length sets the dimension, which must be 1, 2 or 3. -% If type is 3, in contrast, its *value* fixes the dimension -% isign if >=0, uses + sign in exponential, otherwise - sign. -% eps relative precision requested (generally between 1e-15 and 1e-1) -% opts optional struct with optional fields controlling the following: -% opts.debug: 0 (silent, default), 1 (timing breakdown), 2 (debug info). -% opts.spread_debug: spreader: 0 (no text, default), 1 (some), or 2 (lots) -% opts.spread_sort: 0 (don't sort NU pts), 1 (do), 2 (auto, default) -% opts.spread_kerevalmeth: 0: exp(sqrt()), 1: Horner ppval (faster) -% opts.spread_kerpad: (iff kerevalmeth=0) 0: don't pad to mult of 4, 1: do -% opts.fftw: FFTW plan mode, 64=FFTW_ESTIMATE (default), 0=FFTW_MEASURE, etc -% opts.upsampfac: sigma. 2.0 (default), or 1.25 (low RAM, smaller FFT) -% opts.spread_thread: for ntrans>1 only. 0:auto, 1:seq multi, 2:par, etc -% opts.maxbatchsize: for ntrans>1 only. max blocking size, or 0 for auto. -% opts.nthreads: number of threads, or 0: use all available (default) -% opts.floatprec: library precision to use, 'double' (default) or 'single'. -% for type 1 and 2 only, the following opts fields are also relevant: -% opts.modeord: 0 (CMCL increasing mode ordering, default), 1 (FFT ordering) -% opts.spreadinterponly: 0 (perform NUFFT, default), 1 (only spread/interp) -% Outputs: -% plan finufft_plan object (opaque pointer) -% -% Notes: -% * For type 1 and 2, this does the FFTW planning and kernel-FT precomputation. -% * For type 3, this does very little, since the FFT sizes are not yet known. -% * Be default all threads are planned; control how many with opts.nthreads. -% * The vectorized (many vector) plan, ie ntrans>1, can be much faster -% than repeated calls with the same nonuniform points. Note that here the I/O -% data ordering is stacked rather than interleaved. See ../docs/matlab.rst -% * For more details about the opts fields, see ../docs/opts.rst -% -% -% 2) SETPTS process nonuniform points for general FINUFFT transform(s). -% -% plan.setpts(xj) -% plan.setpts(xj, yj) -% plan.setpts(xj, yj, zj) -% plan.setpts(xj, [], [], s) -% plan.setpts(xj, yj, [], s, t) -% plan.setpts(xj, yj, zj, s, t, u) -% -% When plan is a finufft_plan MATLAB object, brings in nonuniform point -% coordinates (xj,yj,zj), and additionally in the type 3 case, nonuniform -% frequency target points (s,t,u). Empty arrays may be passed in the case of -% unused dimensions. For all types, sorting is done to internally store a -% reindexing of points, and for type 3 the spreading and FFTs are planned. -% The nonuniform points may be used for multiple transforms. -% -% Inputs: -% xj vector of x-coords of all nonuniform points -% yj empty (if dim<2), or vector of y-coords of all nonuniform points -% zj empty (if dim<3), or vector of z-coords of all nonuniform points -% s vector of x-coords of all nonuniform frequency targets -% t empty (if dim<2), or vector of y-coords of all frequency targets -% u empty (if dim<3), or vector of z-coords of all frequency targets -% Input/Outputs: -% plan finufft_plan object -% -% Notes: -% * The values in xj (and if nonempty, yj and zj) are real-valued, and -% invariant under translations by multiples of 2pi. For type 1 -% they are "sources", whereas for type 2 they are "targets". -% For type 3 there is no periodicity, and no restrictions other -% than the resulting size of the internal fine grids. -% * s (and t and u) are only relevant for type 3, and may be omitted otherwise -% * The matlab vectors xj,... and s,... should not be changed before calling -% future execute calls, because the plan stores only pointers to the -% arrays (they are not duplicated internally). -% * The precision (double/single) of all inputs must match that chosen at the -% plan stage using opts.floatprec, otherwise an error is raised. -% -% -% 3) EXECUTE execute single or many-vector FINUFFT transforms in a plan. -% -% result = plan.execute(data_in); -% -% For plan a previously created finufft_plan object also containing all -% needed nonuniform point coordinates, do a single (or if ntrans>1 in the -% plan stage, multiple) NUFFT transform(s), with the strengths or Fourier -% coefficient inputs vector(s) from data_in. The result of the transform(s) -% is returned as a (possibly multidimensional) array. -% -% Inputs: -% plan finufft_plan object -% data_in strengths (types 1 or 3) or Fourier coefficients (type 2) -% vector, matrix, or array of appropriate size. For type 1 and 3, -% this is either a length-M vector (where M is the length of xj), -% or an (M,ntrans) matrix when ntrans>1. For type 2, in 1D this is -% length-ms, in 2D size (ms,mt), or in 3D size (ms,mt,mu), or -% each of these with an extra last dimension ntrans if ntrans>1. -% Outputs: -% result vector of output strengths at targets (types 2 or 3), or array -% of Fourier coefficients (type 1), or, if ntrans>1, a stack of -% such vectors or arrays, of appropriate size. -% Specifically, if ntrans=1, for type 1, in 1D -% this is a length-ms column vector, in 2D a matrix of size -% (ms,mt), or in 3D an array of size (ms,mt,mu); for types 2 and 3 -% it is a column vector of length M (the length of xj in type 2), -% or nk (the length of s in type 3). If ntrans>1 its is a stack -% of such objects, ie, it has an extra last dimension ntrans. -% -% Notes: -% * The precision (double/single) of all inputs must match that chosen at the -% plan stage using opts.floatprec, otherwise an error is raised. -% -% -% 4) To deallocate (delete) a nonuniform FFT plan, use delete(plan) -% -% This deallocates all stored FFTW plans, nonuniform point sorting arrays, -% kernel Fourier transforms arrays, etc. -% -% classdef finufft_plan < handle @@ -200,17 +48,17 @@ mex_id_ = 'finufft_mex_setup()'; finufft(mex_id_); - mex_id_ = 'o finufft_opts* = new()'; + mex_id_ = 'c o finufft_opts* = new()'; [o] = finufft(mex_id_); if strcmp(plan.floatprec,'double') - mex_id_ = 'o finufft_plan* = new()'; + mex_id_ = 'c o finufft_plan* = new()'; [p] = finufft(mex_id_); - mex_id_ = 'finufft_default_opts(i finufft_opts*)'; + mex_id_ = 'finufft_default_opts(c i finufft_opts*)'; finufft(mex_id_, o); else - mex_id_ = 'o finufftf_plan* = new()'; + mex_id_ = 'c o finufftf_plan* = new()'; [p] = finufft(mex_id_); - mex_id_ = 'finufftf_default_opts(i finufft_opts*)'; + mex_id_ = 'finufftf_default_opts(c i finufft_opts*)'; finufft(mex_id_, o); end plan.mwptr = p; % crucial: save the opaque ptr (p.12 of MWrap manual) @@ -222,18 +70,18 @@ % though it's declared int. It complains, also with int64 for nj, etc :( % replace in finufft_opts struct whichever fields are in incoming opts... - mex_id_ = 'copy_finufft_opts(i mxArray, i finufft_opts*)'; + mex_id_ = 'copy_finufft_opts(c i mxArray, c i finufft_opts*)'; finufft(mex_id_, opts, o); if strcmp(plan.floatprec,'double') tol = double(tol); % scalar type must match for mwrap>=0.33.11 - mex_id_ = 'o int = finufft_makeplan(i int, i int, i int64_t[x], i int, i int, i double, i finufft_plan*, i finufft_opts*)'; + mex_id_ = 'c o int = finufft_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i double, c i finufft_plan*, c i finufft_opts*)'; [ier] = finufft(mex_id_, type, dim, n_modes, iflag, n_trans, tol, plan, o, 3); else tol = single(tol); % ditto - mex_id_ = 'o int = finufftf_makeplan(i int, i int, i int64_t[x], i int, i int, i float, i finufftf_plan*, i finufft_opts*)'; + mex_id_ = 'c o int = finufftf_makeplan(c i int, c i int, c i int64_t[x], c i int, c i int, c i float, c i finufftf_plan*, c i finufft_opts*)'; [ier] = finufft(mex_id_, type, dim, n_modes, iflag, n_trans, tol, plan, o, 3); end - mex_id_ = 'delete(i finufft_opts*)'; + mex_id_ = 'delete(c i finufft_opts*)'; finufft(mex_id_, o); errhandler(ier); % convert C++ codes to matlab-style errors end @@ -253,7 +101,7 @@ function setpts(plan, xj, yj, zj, s, t, u) if nargin<6, t=emp; end if nargin<7, u=emp; end % get number(s) of NU pts (also validates the NU pt array sizes)... - [nj, nk] = valid_setpts(plan.type, plan.dim, xj, yj, zj, s, t, u); + [nj, nk] = valid_setpts(0, plan.type, plan.dim, xj, yj, zj, s, t, u); plan.nj = nj; % save to avoid having to query the C++ plan plan.nk = nk; % " % Force MATLAB to preserve the memory of xj/yj/zj by storing them as class @@ -264,10 +112,10 @@ function setpts(plan, xj, yj, zj, s, t, u) plan.yj = yj; plan.zj = zj; if strcmp(plan.floatprec,'double') - mex_id_ = 'o int = finufft_setpts(i finufft_plan, i int64_t, i double[], i double[], i double[], i int64_t, i double[], i double[], i double[])'; + mex_id_ = 'c o int = finufft_setpts(c i finufft_plan, c i int64_t, c i double[], c i double[], c i double[], c i int64_t, c i double[], c i double[], c i double[])'; [ier] = finufft(mex_id_, plan, nj, xj, yj, zj, nk, s, t, u); else - mex_id_ = 'o int = finufftf_setpts(i finufftf_plan, i int64_t, i float[], i float[], i float[], i int64_t, i float[], i float[], i float[])'; + mex_id_ = 'c o int = finufftf_setpts(c i finufftf_plan, c i int64_t, c i float[], c i float[], c i float[], c i int64_t, c i float[], c i float[], c i float[])'; [ier] = finufft(mex_id_, plan, nj, xj, yj, zj, nk, s, t, u); end errhandler(ier); @@ -276,6 +124,11 @@ function setpts(plan, xj, yj, zj, s, t, u) function result = execute(plan, data_in) % EXECUTE execute single or many-vector FINUFFT transforms in a plan. + % check if data_in is gpuArray + if isgpuarray(data_in) + error('FINUFFT:badDataDevice','input data must be a cpuArray'); + end + % get shape info from the matlab-side plan (since can't pass "dot" % variables like a.b as mwrap sizes, too)... ms = plan.n_modes(1); mt = plan.n_modes(2); mu = plan.n_modes(3); @@ -295,28 +148,28 @@ function setpts(plan, xj, yj, zj, s, t, u) end if plan.type == 1 if strcmp(plan.floatprec,'double') - mex_id_ = 'o int = finufft_execute(i finufft_plan, i dcomplex[], o dcomplex[x])'; + mex_id_ = 'c o int = finufft_execute(c i finufft_plan, c i dcomplex[], c o dcomplex[x])'; [ier, result] = finufft(mex_id_, plan, data_in, ncoeffs); else - mex_id_ = 'o int = finufftf_execute(i finufftf_plan, i fcomplex[], o fcomplex[x])'; + mex_id_ = 'c o int = finufftf_execute(c i finufftf_plan, c i fcomplex[], c o fcomplex[x])'; [ier, result] = finufft(mex_id_, plan, data_in, ncoeffs); end % make modes output correct shape; when d<3 squeeze removes unused dims... result = squeeze(reshape(result, [ms mt mu n_trans])); elseif plan.type == 2 if strcmp(plan.floatprec,'double') - mex_id_ = 'o int = finufft_execute(i finufft_plan, o dcomplex[xx], i dcomplex[])'; + mex_id_ = 'c o int = finufft_execute(c i finufft_plan, c o dcomplex[xx], c i dcomplex[])'; [ier, result] = finufft(mex_id_, plan, data_in, nj, n_trans); else - mex_id_ = 'o int = finufftf_execute(i finufftf_plan, o fcomplex[xx], i fcomplex[])'; + mex_id_ = 'c o int = finufftf_execute(c i finufftf_plan, c o fcomplex[xx], c i fcomplex[])'; [ier, result] = finufft(mex_id_, plan, data_in, nj, n_trans); end elseif plan.type == 3 if strcmp(plan.floatprec,'double') - mex_id_ = 'o int = finufft_execute(i finufft_plan, i dcomplex[], o dcomplex[xx])'; + mex_id_ = 'c o int = finufft_execute(c i finufft_plan, c i dcomplex[], c o dcomplex[xx])'; [ier, result] = finufft(mex_id_, plan, data_in, nk, n_trans); else - mex_id_ = 'o int = finufftf_execute(i finufftf_plan, i fcomplex[], o fcomplex[xx])'; + mex_id_ = 'c o int = finufftf_execute(c i finufftf_plan, c i fcomplex[], c o fcomplex[xx])'; [ier, result] = finufft(mex_id_, plan, data_in, nk, n_trans); end end @@ -329,10 +182,10 @@ function delete(plan) % plan goes out of scope. if ~isempty(plan.mwptr) % catch octave's allowance of >1 deletings! if strcmp(plan.floatprec,'double') - mex_id_ = 'finufft_destroy(i finufft_plan)'; + mex_id_ = 'finufft_destroy(c i finufft_plan)'; finufft(mex_id_, plan); else - mex_id_ = 'finufftf_destroy(i finufftf_plan)'; + mex_id_ = 'finufftf_destroy(c i finufftf_plan)'; finufft(mex_id_, plan); end plan.mwptr = ''; % we use to mean "destroyed on the C++ side" From 7902e3897f6b5b67eba9ef76fc633eebede83e2e Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 18:02:17 -0500 Subject: [PATCH 05/11] update mex ci --- .github/workflows/mex.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/mex.yml b/.github/workflows/mex.yml index 60177e64d..56d6d1209 100644 --- a/.github/workflows/mex.yml +++ b/.github/workflows/mex.yml @@ -15,6 +15,7 @@ jobs: with: release: R2023b cache: true + products: Parallel_Computing_Toolbox - name: Generate Windows mex file if: runner.os == 'Windows' run: | From fc25125b5c1e632ae5d75baa9fdfa97b272ff8a0 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 18:58:11 -0500 Subject: [PATCH 06/11] fix typo --- matlab/finufft1d3.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/finufft1d3.m b/matlab/finufft1d3.m index f12413abd..106a64443 100644 --- a/matlab/finufft1d3.m +++ b/matlab/finufft1d3.m @@ -44,7 +44,7 @@ function f = finufft1d3(x,c,isign,eps,s,o) if nargin<6, o.dummy=1; end -if_gpuarray = isgpuarray(x); +is_gpuarray = isgpuarray(x); valid_setpts(is_gpuarray,3,1,x,[],[],s,[],[]); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); From 04791db66c0fddb019c5e4cdd4891484f705627a Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 22:27:13 -0500 Subject: [PATCH 07/11] remove isgpuarray requirement --- .github/workflows/mex.yml | 1 - matlab/cufinufft.mw | 2 +- matlab/cufinufft_plan.m | 2 +- matlab/finufft.mw | 2 +- matlab/finufft1d1.m | 2 +- matlab/finufft1d2.m | 2 +- matlab/finufft1d3.m | 2 +- matlab/finufft2d1.m | 2 +- matlab/finufft2d2.m | 2 +- matlab/finufft2d3.m | 2 +- matlab/finufft3d1.m | 2 +- matlab/finufft3d2.m | 2 +- matlab/finufft3d3.m | 2 +- matlab/finufft_plan.m | 2 +- matlab/valid_ntr.m | 2 +- matlab/valid_setpts.m | 14 +++++++------- 16 files changed, 21 insertions(+), 22 deletions(-) diff --git a/.github/workflows/mex.yml b/.github/workflows/mex.yml index 56d6d1209..60177e64d 100644 --- a/.github/workflows/mex.yml +++ b/.github/workflows/mex.yml @@ -15,7 +15,6 @@ jobs: with: release: R2023b cache: true - products: Parallel_Computing_Toolbox - name: Generate Windows mex file if: runner.os == 'Windows' run: | diff --git a/matlab/cufinufft.mw b/matlab/cufinufft.mw index bd6326017..e2b1457f2 100644 --- a/matlab/cufinufft.mw +++ b/matlab/cufinufft.mw @@ -206,7 +206,7 @@ classdef cufinufft_plan < handle % EXECUTE execute single or many-vector FINUFFT transforms in a plan. % check if data_in is gpuArray - if ~isgpuarray(data_in) + if ~finufft_isgpuarray(data_in) error('FINUFFT:badDataDevice','input data must be a gpuArray'); end diff --git a/matlab/cufinufft_plan.m b/matlab/cufinufft_plan.m index 6f7456b11..4f892fade 100644 --- a/matlab/cufinufft_plan.m +++ b/matlab/cufinufft_plan.m @@ -123,7 +123,7 @@ function setpts(plan, xj, yj, zj, s, t, u) % EXECUTE execute single or many-vector FINUFFT transforms in a plan. % check if data_in is gpuArray - if ~isgpuarray(data_in) + if ~finufft_isgpuarray(data_in) error('FINUFFT:badDataDevice','input data must be a gpuArray'); end diff --git a/matlab/finufft.mw b/matlab/finufft.mw index fd9536eaa..fbf35b653 100644 --- a/matlab/finufft.mw +++ b/matlab/finufft.mw @@ -233,7 +233,7 @@ classdef finufft_plan < handle % EXECUTE execute single or many-vector FINUFFT transforms in a plan. % check if data_in is gpuArray - if isgpuarray(data_in) + if finufft_isgpuarray(data_in) error('FINUFFT:badDataDevice','input data must be a cpuArray'); end diff --git a/matlab/finufft1d1.m b/matlab/finufft1d1.m index fffaa07c7..0b07063d7 100644 --- a/matlab/finufft1d1.m +++ b/matlab/finufft1d1.m @@ -47,7 +47,7 @@ function f = finufft1d1(x,c,isign,eps,ms,o) if nargin<6, o.dummy=1; end % make a dummy options struct -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,1,1,x); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft1d2.m b/matlab/finufft1d2.m index 58b38d44b..c6fe20287 100644 --- a/matlab/finufft1d2.m +++ b/matlab/finufft1d2.m @@ -46,7 +46,7 @@ function c = finufft1d2(x,isign,eps,f,o) if nargin<5, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,2,1,x); o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,n_transf]=size(f); % if f a col vec, n_transf=1, but... diff --git a/matlab/finufft1d3.m b/matlab/finufft1d3.m index 106a64443..1c67fcc97 100644 --- a/matlab/finufft1d3.m +++ b/matlab/finufft1d3.m @@ -44,7 +44,7 @@ function f = finufft1d3(x,c,isign,eps,s,o) if nargin<6, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,3,1,x,[],[],s,[],[]); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft2d1.m b/matlab/finufft2d1.m index 6f2d36803..e5e662df3 100644 --- a/matlab/finufft2d1.m +++ b/matlab/finufft2d1.m @@ -52,7 +52,7 @@ function f = finufft2d1(x,y,c,isign,eps,ms,mt,o) if nargin<8, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,1,2,x,y); o.floatprec = underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft2d2.m b/matlab/finufft2d2.m index 026e3046f..4673e15a7 100644 --- a/matlab/finufft2d2.m +++ b/matlab/finufft2d2.m @@ -48,7 +48,7 @@ function c = finufft2d2(x,y,isign,eps,f,o) if nargin<6, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,2,2,x,y); o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,mt,n_transf] = size(f); % if f 2D array, n_transf=1 diff --git a/matlab/finufft2d3.m b/matlab/finufft2d3.m index 0f7c4dae1..c5f5c0455 100644 --- a/matlab/finufft2d3.m +++ b/matlab/finufft2d3.m @@ -45,7 +45,7 @@ function f = finufft2d3(x,y,c,isign,eps,s,t,o) if nargin<8, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,3,2,x,y,[],s,t,[]); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft3d1.m b/matlab/finufft3d1.m index 73be3a6ff..6ca971482 100644 --- a/matlab/finufft3d1.m +++ b/matlab/finufft3d1.m @@ -54,7 +54,7 @@ function f = finufft3d1(x,y,z,c,isign,eps,ms,mt,mu,o) if nargin<10, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,1,3,x,y,z); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft3d2.m b/matlab/finufft3d2.m index a0282b96c..f1516a3ce 100644 --- a/matlab/finufft3d2.m +++ b/matlab/finufft3d2.m @@ -50,7 +50,7 @@ function c = finufft3d2(x,y,z,isign,eps,f,o) if nargin<7, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,2,3,x,y,z); o.floatprec=underlyingType(x); % should be 'double' or 'single' [ms,mt,mu,n_transf] = size(f); % if f 3D array, n_transf=1 diff --git a/matlab/finufft3d3.m b/matlab/finufft3d3.m index 8219f3c5f..40e13755a 100644 --- a/matlab/finufft3d3.m +++ b/matlab/finufft3d3.m @@ -46,7 +46,7 @@ function f = finufft3d3(x,y,z,c,isign,eps,s,t,u,o) if nargin<10, o.dummy=1; end -is_gpuarray = isgpuarray(x); +is_gpuarray = finufft_isgpuarray(x); valid_setpts(is_gpuarray,3,3,x,y,z,s,t,u); o.floatprec=underlyingType(x); % should be 'double' or 'single' n_transf = valid_ntr(x,c); diff --git a/matlab/finufft_plan.m b/matlab/finufft_plan.m index c21083cda..3f654d127 100644 --- a/matlab/finufft_plan.m +++ b/matlab/finufft_plan.m @@ -125,7 +125,7 @@ function setpts(plan, xj, yj, zj, s, t, u) % EXECUTE execute single or many-vector FINUFFT transforms in a plan. % check if data_in is gpuArray - if isgpuarray(data_in) + if finufft_isgpuarray(data_in) error('FINUFFT:badDataDevice','input data must be a cpuArray'); end diff --git a/matlab/valid_ntr.m b/matlab/valid_ntr.m index e4fe36ecf..3f0b2c160 100644 --- a/matlab/valid_ntr.m +++ b/matlab/valid_ntr.m @@ -2,7 +2,7 @@ % VALID_NTR deduce n_transforms and validate the size of c, for types 1 and 3. % also check for array device consistency. -if isgpuarray(x) ~= isgpuarray(c) +if finufft_isgpuarray(x) ~= finufft_isgpuarray(c) error('FINUFFT:mixedDevice','FINUFFT: x and c must be both on GPU or CPU'); end diff --git a/matlab/valid_setpts.m b/matlab/valid_setpts.m index 5cdeafa53..4faaea286 100644 --- a/matlab/valid_setpts.m +++ b/matlab/valid_setpts.m @@ -12,34 +12,34 @@ % Barnett 6/19/20, split out from guru so simple ints can check before plan. % s,t,u are only checked for type 3. -% note that isvector([]) is false, isgpuarray([]) is false, isgpuarray(gpuArray([])) if true. +% note that isvector([]) is false, finufft_isgpuarray([]) is false, finufft_isgpuarray(gpuArray([])) if true. if ~isvector(x), error('FINUFFT:badXshape','FINUFFT x must be a vector'); end -if isgpuarray(x) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end +if finufft_isgpuarray(x) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end nj = numel(x); if type==3 nk = numel(s); if ~isvector(s), error('FINUFFT:badSshape','FINUFFT s must be a vector'); end - if isgpuarray(s) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end + if finufft_isgpuarray(s) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end else nk = 0; % dummy output end if dim>1 if ~isvector(y), error('FINUFFT:badYshape','FINUFFT y must be a vector'); end - if isgpuarray(y) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end + if finufft_isgpuarray(y) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(y)~=nj, error('FINUFFT:badYlen','FINUFFT y must have same length as x'); end if type==3 if ~isvector(t), error('FINUFFT:badTshape','FINUFFT t must be a vector'); end - if isgpuarray(t) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end + if finufft_isgpuarray(t) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(t)~=nk, error('FINUFFT:badTlen','FINUFFT t must have same length as s'); end end end if dim>2 if ~isvector(z), error('FINUFFT:badZshape','FINUFFT z must be a vector'); end - if isgpuarray(z) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end + if finufft_isgpuarray(z) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(z)~=nj, error('FINUFFT:badZlen','FINUFFT z must have same length as x'); end if type==3 if ~isvector(u), error('FINUFFT:badUshape','FINUFFT u must be a vector'); end - if isgpuarray(u) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end + if finufft_isgpuarray(u) ~= is_gpuarray, error('FINUFFT:badDataDevice', 'input data must be on the specified device'); end if numel(u)~=nk, error('FINUFFT:badUlen','FINUFFT u must have same length as s'); end end end From bd3d6198f42fe2f35387ad6440527a2438e5f02b Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 22:28:58 -0500 Subject: [PATCH 08/11] add finufft_isgpuarray function --- matlab/finufft_isgpuarray.m | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 matlab/finufft_isgpuarray.m diff --git a/matlab/finufft_isgpuarray.m b/matlab/finufft_isgpuarray.m new file mode 100644 index 000000000..5f4e63c4e --- /dev/null +++ b/matlab/finufft_isgpuarray.m @@ -0,0 +1,10 @@ +function is_gpuarray = finufft_isgpuarray(input) + % Check if the isgpuarray function is available + if exist('isgpuarray') == 0 + % return 0, since no parallel computing toolbox, can not use gpuarray + return logical(0); + else + % call the parallel computing toolbox isgpuarray function + return isgpuarray(input); + end +end From 60f56f3619e799615dd2890774d782f85e6d700e Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Thu, 13 Feb 2025 22:34:47 -0500 Subject: [PATCH 09/11] fix finufft_isgpuarray function --- matlab/finufft_isgpuarray.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/matlab/finufft_isgpuarray.m b/matlab/finufft_isgpuarray.m index 5f4e63c4e..d33943669 100644 --- a/matlab/finufft_isgpuarray.m +++ b/matlab/finufft_isgpuarray.m @@ -2,9 +2,9 @@ % Check if the isgpuarray function is available if exist('isgpuarray') == 0 % return 0, since no parallel computing toolbox, can not use gpuarray - return logical(0); + is_gpuarray = logical(0); else % call the parallel computing toolbox isgpuarray function - return isgpuarray(input); + is_gpuarray = isgpuarray(input); end end From baf6e21408fdf6d2f00d79bf9df0a0ebc8278276 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Tue, 18 Feb 2025 09:13:14 -0500 Subject: [PATCH 10/11] add back finufft_plan.m comments --- matlab/finufft_plan.m | 152 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/matlab/finufft_plan.m b/matlab/finufft_plan.m index 3f654d127..964f098c8 100644 --- a/matlab/finufft_plan.m +++ b/matlab/finufft_plan.m @@ -1,3 +1,155 @@ +% FINUFFT_PLAN is a class which wraps the guru interface to FINUFFT. +% +% Full documentation is given in ../finufft-manual.pdf and online at +% http://finufft.readthedocs.io +% Also see examples in the matlab/examples and matlab/test directories. +% +% PROPERTIES +% mwptr - opaque pointer to a C++ finufft_plan object (see MWrap manual), +% whose properties cannot be accessed directly +% floatprec - either 'double' or 'single', tracks what precision of C++ +% library is being called +% type, dim, n_modes, n_trans, nj, nk - other plan parameters +% Note: the user should never alter these plan properties directly! Rather, +% the below methods should be used to create, use, and destroy plans. +% +% METHODS +% finufft_plan - create guru plan object for one/many general nonuniform FFTs. +% setpts - process nonuniform points for general FINUFFT transform(s). +% execute - execute single or many-vector FINUFFT transforms in a plan. +% +% General notes: +% * use delete(plan) to remove a plan after use. +% * See ERRHANDLER, VALID_*, and this code for warning/error IDs. +% +% +% +% =========== Detailed description of guru methods ========================== +% +% 1) FINUFFT_PLAN create guru plan object for one/many general nonuniform FFTs. +% +% plan = finufft_plan(type, n_modes_or_dim, isign, ntrans, eps) +% plan = finufft_plan(type, n_modes_or_dim, isign, ntrans, eps, opts) +% +% Creates a finufft_plan MATLAB object in the guru interface to FINUFFT, of +% type 1, 2 or 3, and with given numbers of Fourier modes (unless type 3). +% +% Inputs: +% type transform type: 1, 2, or 3 +% n_modes_or_dim if type is 1 or 2, the number of Fourier modes in each +% dimension: [ms] in 1D, [ms mt] in 2D, or [ms mt mu] in 3D. +% Its length sets the dimension, which must be 1, 2 or 3. +% If type is 3, in contrast, its *value* fixes the dimension +% isign if >=0, uses + sign in exponential, otherwise - sign. +% eps relative precision requested (generally between 1e-15 and 1e-1) +% opts optional struct with optional fields controlling the following: +% opts.debug: 0 (silent, default), 1 (timing breakdown), 2 (debug info). +% opts.spread_debug: spreader: 0 (no text, default), 1 (some), or 2 (lots) +% opts.spread_sort: 0 (don't sort NU pts), 1 (do), 2 (auto, default) +% opts.spread_kerevalmeth: 0: exp(sqrt()), 1: Horner ppval (faster) +% opts.spread_kerpad: (iff kerevalmeth=0) 0: don't pad to mult of 4, 1: do +% opts.fftw: FFTW plan mode, 64=FFTW_ESTIMATE (default), 0=FFTW_MEASURE, etc +% opts.upsampfac: sigma. 2.0 (default), or 1.25 (low RAM, smaller FFT) +% opts.spread_thread: for ntrans>1 only. 0:auto, 1:seq multi, 2:par, etc +% opts.maxbatchsize: for ntrans>1 only. max blocking size, or 0 for auto. +% opts.nthreads: number of threads, or 0: use all available (default) +% opts.floatprec: library precision to use, 'double' (default) or 'single'. +% for type 1 and 2 only, the following opts fields are also relevant: +% opts.modeord: 0 (CMCL increasing mode ordering, default), 1 (FFT ordering) +% opts.spreadinterponly: 0 (perform NUFFT, default), 1 (only spread/interp) +% Outputs: +% plan finufft_plan object (opaque pointer) +% +% Notes: +% * For type 1 and 2, this does the FFTW planning and kernel-FT precomputation. +% * For type 3, this does very little, since the FFT sizes are not yet known. +% * Be default all threads are planned; control how many with opts.nthreads. +% * The vectorized (many vector) plan, ie ntrans>1, can be much faster +% than repeated calls with the same nonuniform points. Note that here the I/O +% data ordering is stacked rather than interleaved. See ../docs/matlab.rst +% * For more details about the opts fields, see ../docs/opts.rst +% +% +% 2) SETPTS process nonuniform points for general FINUFFT transform(s). +% +% plan.setpts(xj) +% plan.setpts(xj, yj) +% plan.setpts(xj, yj, zj) +% plan.setpts(xj, [], [], s) +% plan.setpts(xj, yj, [], s, t) +% plan.setpts(xj, yj, zj, s, t, u) +% +% When plan is a finufft_plan MATLAB object, brings in nonuniform point +% coordinates (xj,yj,zj), and additionally in the type 3 case, nonuniform +% frequency target points (s,t,u). Empty arrays may be passed in the case of +% unused dimensions. For all types, sorting is done to internally store a +% reindexing of points, and for type 3 the spreading and FFTs are planned. +% The nonuniform points may be used for multiple transforms. +% +% Inputs: +% xj vector of x-coords of all nonuniform points +% yj empty (if dim<2), or vector of y-coords of all nonuniform points +% zj empty (if dim<3), or vector of z-coords of all nonuniform points +% s vector of x-coords of all nonuniform frequency targets +% t empty (if dim<2), or vector of y-coords of all frequency targets +% u empty (if dim<3), or vector of z-coords of all frequency targets +% Input/Outputs: +% plan finufft_plan object +% +% Notes: +% * The values in xj (and if nonempty, yj and zj) are real-valued, and +% invariant under translations by multiples of 2pi. For type 1 +% they are "sources", whereas for type 2 they are "targets". +% For type 3 there is no periodicity, and no restrictions other +% than the resulting size of the internal fine grids. +% * s (and t and u) are only relevant for type 3, and may be omitted otherwise +% * The matlab vectors xj,... and s,... should not be changed before calling +% future execute calls, because the plan stores only pointers to the +% arrays (they are not duplicated internally). +% * The precision (double/single) of all inputs must match that chosen at the +% plan stage using opts.floatprec, otherwise an error is raised. +% +% +% 3) EXECUTE execute single or many-vector FINUFFT transforms in a plan. +% +% result = plan.execute(data_in); +% +% For plan a previously created finufft_plan object also containing all +% needed nonuniform point coordinates, do a single (or if ntrans>1 in the +% plan stage, multiple) NUFFT transform(s), with the strengths or Fourier +% coefficient inputs vector(s) from data_in. The result of the transform(s) +% is returned as a (possibly multidimensional) array. +% +% Inputs: +% plan finufft_plan object +% data_in strengths (types 1 or 3) or Fourier coefficients (type 2) +% vector, matrix, or array of appropriate size. For type 1 and 3, +% this is either a length-M vector (where M is the length of xj), +% or an (M,ntrans) matrix when ntrans>1. For type 2, in 1D this is +% length-ms, in 2D size (ms,mt), or in 3D size (ms,mt,mu), or +% each of these with an extra last dimension ntrans if ntrans>1. +% Outputs: +% result vector of output strengths at targets (types 2 or 3), or array +% of Fourier coefficients (type 1), or, if ntrans>1, a stack of +% such vectors or arrays, of appropriate size. +% Specifically, if ntrans=1, for type 1, in 1D +% this is a length-ms column vector, in 2D a matrix of size +% (ms,mt), or in 3D an array of size (ms,mt,mu); for types 2 and 3 +% it is a column vector of length M (the length of xj in type 2), +% or nk (the length of s in type 3). If ntrans>1 its is a stack +% of such objects, ie, it has an extra last dimension ntrans. +% +% Notes: +% * The precision (double/single) of all inputs must match that chosen at the +% plan stage using opts.floatprec, otherwise an error is raised. +% +% +% 4) To deallocate (delete) a nonuniform FFT plan, use delete(plan) +% +% This deallocates all stored FFTW plans, nonuniform point sorting arrays, +% kernel Fourier transforms arrays, etc. +% +% classdef finufft_plan < handle From 11ec5963f9e90e68666762c3f998c11acb36db86 Mon Sep 17 00:00:00 2001 From: Libin Lu Date: Tue, 18 Feb 2025 12:18:23 -0500 Subject: [PATCH 11/11] add some doc to cufinufft.mw and install_gpu.rst --- docs/install_gpu.rst | 36 ++++++++++++++++++++++++++++++++++-- matlab/cufinufft.mw | 24 +++++++++++++++++------- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/docs/install_gpu.rst b/docs/install_gpu.rst index 360543ac1..8c057aeac 100644 --- a/docs/install_gpu.rst +++ b/docs/install_gpu.rst @@ -39,12 +39,12 @@ In order to configure cuFINUFFT for a specific compute capability, use the ``CMA To find out your own device's compute capability without having to look it up on the web, use: .. code-block:: bash - + nvidia-smi --query-gpu=compute_cap --format=csv,noheader This will return a text string such as ``8.6`` which would incidate ``sm_86`` architecture, thus to use ``CMAKE_CUDA_ARCHITECTURES=86``. - + Testing ------- @@ -92,3 +92,35 @@ Assuming ``pytest`` is installed (otherwise, just run ``pip install pytest``), y In contrast to the C interface tests, these check for correctness, so a successful test run signifies that the library is working correctly. Note that you can specify other framework (``pycuda``, ``torch``, or ``numba``) for testing using the ``--framework`` argument. + + +Matlab interface +---------------- + +.. _install-matlab-gpu: + +In addition to the Python interface, cuFINUFFT also comes with a Matlab interface. To install this, you first build the shared library. +For example, assuming in the root directory of finufft, then run + +.. code-block:: bash + + cmake -S . -B build -D FINUFFT_USE_CUDA=ON -D FINUFFT_STATIC_LINKING=OFF -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON -D FINUFFT_CUDA_ARCHITECTURES="60;70;80;90" + +You may adjust ``FINUFFT_CUDA_ARCHITECTURES`` to generate the code for different compute capabilities. +Then build the binary library + +.. code-block:: bash + + cmake --build build + +Then, to compile the Matlab mexcuda file, open matlab in finufft root directory and run + +.. code-block:: matlab + + mexcuda -v 'LINKLIBS=$LINKLIBS -Wl,-rpath,/absolute/path/to/finufft/build -Lbuild -lcufinufft' matlab/cufinufft.cu -Iinclude -DR2008OO -largeArrayDims -output matlab/cufinufft + +``-Lbuild`` specifies the relative path where ``libcufinufft.so`` is during linking stage. ``-Wl,-rpath,/absolute/path/to/finufft/build`` specifies the absolute path where ``libcufinufft.so`` is so that Matlab can find it during runtime, change ``/absolute/path/to/finufft/build`` accordingly. You may remove ``-Wl,-rpath,/absolute/path/to/finufft/build``, you then need to export `LD_LIBRARY_PATH` to include path to `libcufinufft.so` so that Matlab can find it during runtime. + +.. note:: + + Depending on your Matlab version, mexcuda compiles the CUDA code using the NVIDIA nvcc compiler installed with MATLAB, if the Matlab default one does not work, you may specify the location of nvcc on your system by storing it in the environment variable MW_NVCC_PATH, ``setenv("MW_NVCC_PATH","/path/to/CUDA/bin")`` and ``setenv("MW_ALLOW_ANY_CUDA","true")``. You may also check `toolbox/parallel/gpu/extern/src/mex/glnxa64/nvcc_g++.xml` to see how Matlab finds the nvcc compiler. diff --git a/matlab/cufinufft.mw b/matlab/cufinufft.mw index e2b1457f2..77928c512 100644 --- a/matlab/cufinufft.mw +++ b/matlab/cufinufft.mw @@ -11,17 +11,27 @@ % % % Hints for linux/GNU build (see ../makefile for definitive build): -% first build libcufinufft.so -% cmake -S . -B build -D FINUFFT_USE_CUDA=ON -D FINUFFT_STATIC_LINKING=OFF -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON -D FINUFFT_CUDA_ARCHITECTURES="60;70;80" +% Firstly, we need to build libcufinufft.so using cmake. +% Assuming we are in the root directory of finufft and want to generate libcufinufft.so inside build: +% cmake -S . -B build -D FINUFFT_USE_CUDA=ON -D FINUFFT_STATIC_LINKING=OFF -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON -D FINUFFT_CUDA_ARCHITECTURES="60;70;80;90" +% You may adjust the FINUFFT_CUDA_ARCHITECTURES to generate the code you want. +% Then build the binary library: % cmake --build build --verbose -% To generate the MEX C++ file, run: % +% For users who are familiar with mwrap, to generate the MEX C++ file, run: % mwrap -mex cufinufft -c cufinufft.cu -mb -cppcomplex cufinufft.mw +% For now, before merged to offical repo, +% you may need the forked mwrap version to support gpuArray +% https://github.com/lu1and10/mwrap/tree/gpu % -% Then to compile for matlab: -% mexcuda -v matlab/cufinufft.cu build/src/cuda/libcufinufft.so -Iinclude -DR2008OO -largeArrayDims -output matlab/cufinufft - -% export LD_LIBRARY_PATH to include where libcufinufft.so is if dylink cufinufft +% Then to compile for matlab, open matlab in finufft root directory and run: +% mexcuda -v 'LINKLIBS=$LINKLIBS -Wl,-rpath,/absolute/path/to/finufft/build -Lbuild -lcufinufft' matlab/cufinufft.cu -Iinclude -DR2008OO -largeArrayDims -output matlab/cufinufft +% '-Lbuild' specifies the relative path where libcufinufft.so is when linking. +% '-Wl,-rpath,/absolute/path/to/finufft/build' specifies the absolute path where libcufinufft.so is. +% You may remove '-Wl,-rpath,/absolute/path/to/finufft/build', +% while you then need to export LD_LIBRARY_PATH to include path to libcufinufft.so +% to make generated mex file find libcufinufft.so at runtime. +% To support mexcuda do static linking need more investigation. % both precisions... $ #include