function myIntegral(cases)
% function myIntegral(cases)
% n (Input) -- number of intervals between limits of integration, [a,b]
% varargout -- returns integrated solution
% Start with "matlabpool open 4" before running this code
% This program uses Integral.m for local integration (using less-efficient for-loops)
% Usage example: >> myIntegral;   % default; runs m=10000
% Usage example: >> myIntegral([10000 20000 40000 80000]);

fid = fopen('outputfile','w');

disp(' '); disp('See outputfile for the integrated values.'); disp(' ')

if nargin > 0
  mm = cases;
else
  mm = 10000;
  disp(['mm = ' num2str(mm)])
end
disp(['  Size  Serial  Serialv   spmd1  parfor1  drange1  parfor2  drange2'])
a = 0;        % lower limit of integration
b = pi*0.5;   % upper limit of integration

ntasks = 100;

for k=1:numel(mm)
m = mm(k);
dx = (b-a)/m;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% serial for-loop integration %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
   intSerial1 = 0;
   for i=1:m
     x = a+(i-0.5)*dx;
     intSerial1 = intSerial1 + cos(x)*dx;
   end
end
tserial1 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% serial vector-form integration %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
   x = a+dx/2:dx:b-dx/2;
   intSerial2 = sum(cos(x)*dx);
end
tserial2 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parallel integration (spmd 1) %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
spmd
   deltax = (b - a)/numlabs;
   dx = (b - a)/m;
   ai = a + (labindex - 1)*deltax;
   bi = a + labindex*deltax;
   x = ai+dx/2:dx:bi-dx/2;
   intSPMD1 = sum(cos(x)*dx);
   intSPMD1 = gplus(intSPMD1);   % sum all intSPMD1 and broadcast
end  % spmd
end
tspmd1 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parallel integration (parfor 1) %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
   nworkers = matlabpool('size');
   n = m/nworkers;
   deltax = (b - a)/nworkers;
   dx = deltax/n;
   intParfor1 = 0;
   parfor i=1:nworkers
     ai = a + (i-1)*deltax;
     bi = a + i*deltax;
     x = ai+dx/2:dx:bi-dx/2;
     intParfor1 = intParfor1 + sum(cos(x)*dx);
   end
end
tparfor1 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parallel integration (parfor 2)  %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
   dx = (b - a)/m;
   intParfor2 = 0;
   parfor i=1:m
     ai = a + (i-1)*dx;
     intParfor2 = intParfor2 + cos(ai+dx/2)*dx;
   end
end
tparfor2 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parallel integration (drange 1) %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
spmd
   n = m/numlabs;
   deltax = (b-a)/numlabs;
   for i=drange(1:numlabs)
     ai = a + (i-1)*deltax;
     bi = a + i*deltax;
     dx = deltax/n;
     x = ai+dx/2:dx:bi-dx/2;
     intDrange1 = sum(cos(x)*dx);
   end
   intDrange1 = gplus(intDrange1);
end  % spmd
end
tdrange1 = toc/ntasks;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parallel integration (drange) 2 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic
for itask=1:ntasks
spmd
   dx = (b-a)/m;
   intDrange2 = 0;  % initialize local sum for each worker
   for i=drange(1:m)
     intDrange2 = intDrange2 + cos(a+(i-0.5)*dx)*dx;
   end
   intDrange2 = gplus(intDrange2);
end  % spmd
end
tdrange2 = toc/ntasks;

txt=sprintf('%6d %7.4f %8.4f %7.4f %8.4f %8.4f %8.4f %8.4f', ...
m,tserial1,tserial2,tspmd1,tparfor1,tdrange1,tparfor2,tdrange2);
disp(txt)
% write integrated results to file
fprintf(fid,'For m = %d\n', m);
fprintf(fid,'intSerial1 = %f\n',intSerial1);
fprintf(fid,'intSerial2 = %f\n',intSerial2);
fprintf(fid,'intSPMD1 = %f\n',intSPMD1{1});
fprintf(fid,'intParfor1 = %f\n',intParfor1);
fprintf(fid,'intParfor2 = %f\n',intParfor2);
fprintf(fid,'intDrange1 = %f\n',intDrange1{1});
fprintf(fid,'intDrange2 = %f\n',intDrange2{1});
end

fclose(fid);

end
