function [cpu,gpu_notransfer,gpu_withtransfer,gpu_notransfer_arrayfun,gpu_withtransfer_arrayfun] = trigseries_test(numrepeats,num_elems,opt)
%TRIGSERIES_TEST benchmarks elementwise calculation of trig series on the
%GPU
%
% usage: [cpu,gpu_notransfer,gpu_withtransfer,gpu_notransfer_arrayfun,gpu_withtransfer_arrayfun] = trigseries_test(numrepeats,num_elements,opt]
%
% If opt is empty or set to 'mean', trigseries_test will return the mean for each
% case.  Any other value for opt will result in all test values being
% returned.
%
% OUTPUTS:
% cpu - CPU timings
% gpu_notransfer - GPU timings, using calling syntax: myseries(xdata), without considering data transfer between host and GPU
% gpu_withtransfer - GPU timings, using calling syntax: myseries(xdata), including data transfer between host and GPU
% gpu_notransfer_arrayfun - GPU timings, using arrayfun, without considering data transfer between host and GPU
% gpu_withtransfer_arrayfun - GPU timings, using arrayfun, including data transfer between host and GPU

if nargin<2
    error('usage: [cpu,gpu_notransfer,gpu_withtransfer,gpu_notransfer_arrayfun,gpu_withtransfer_arrayfun] = sine_test(numrepeats,num_elements,opt]');
end

%If no option has been chosen, set default
if nargin<3
 opt = 'mean';
end

cpu = zeros(1,numrepeats);
gpu_notransfer = zeros(1,numrepeats);
gpu_withtransfer = zeros(1,numrepeats);
gpu_notransfer_arrayfun = zeros(1,numrepeats);
gpu_withtransfer_arrayfun = zeros(1,numrepeats);

%CPU
for i=1:numrepeats
 cpu_x = rand(1,num_elems)*10*pi;
 tic;cpu_y = myseries(cpu_x);
 cpu(i) = toc;
end

%GPU timings, using calling syntax: myseries(xdata), without considering data transfer between host and GPU
for i=1:numrepeats
  cpu_x = rand(1,num_elems)*10*pi;
  %transfer to GPU
  gpu_x = gpuArray(cpu_x);
  %Do calculation
  tic;gpu_y = myseries(gpu_x);
  gpu_notransfer(i) = toc;
  %Get result from GPU. Not included in timing here
  x = gather(gpu_y);
end

%GPU timings, using calling syntax: myseries(xdata), including data transfer between host and GPU
for i=1:numrepeats
  cpu_x = rand(1,num_elems)*10*pi;
  %transfer to GPU
  tic;
  gpu_x = gpuArray(cpu_x);
  %Do calculation
  gpu_y = myseries(gpu_x);
  %Get result from GPU and put in main memory.  Now included in timing.
  x = gather(gpu_y);
  gpu_withtransfer(i) = toc;
end

%quick call to arrayfun to get compilation out of the way
temp = arrayfun(@myseries,gpuArray(1));

%gpu_notransfer_arrayfun - GPU timings, using arrayfun, without considering data transfer between host and GPU
for i=1:numrepeats
  cpu_x = rand(1,num_elems)*10*pi;
  %transfer to GPU
  gpu_x = gpuArray(cpu_x);
  %Do calculation
  tic;gpu_y = arrayfun(@myseries,gpu_x);
  gpu_notransfer_arrayfun(i) = toc;
  %Get result from GPU. Not included in timing here
  x = gather(gpu_y);
end

%GPU timings, using arrayfun, including data transfer between host and GPU
for i=1:numrepeats
  cpu_x = rand(1,num_elems)*10*pi;
  %transfer to GPU
  tic;
  gpu_x = gpuArray(cpu_x);
  %Do calculation
  gpu_y = arrayfun(@myseries,gpu_x);
  %Get result from GPU and put in main memory.  Now included in timing.
  x = gather(gpu_y);
  gpu_withtransfer_arrayfun = toc;
end

if strcmp(opt,'mean')
  cpu = mean(cpu);
  gpu_notransfer = mean(gpu_notransfer);
  gpu_withtransfer = mean(gpu_withtransfer);
  gpu_notransfer_arrayfun = mean(gpu_notransfer_arrayfun);
  gpu_withtransfer_arrayfun = mean(gpu_withtransfer_arrayfun);
end

end


