
% <TestDescription>
%
% Tests the arithmetic operators rule 2.
%
% </TestDescription>
function result = utp_generic_aop_rule2(fcn)
  
  % <SyntaxDescription>
  %
  % Tests the arithmetic operators rule 2 for each data type: xydata,
  % fsdata, tsdata, cdata and useful combinations.
  %
  % </SyntaxDescription>
  
  % Test AOs
  % tsdata
%   a_ts = ao(1:12,randn(12,1), 12.1);
%   a_ts.setDx(ones(12,1)*1.1);
%   a_ts.setDy((1:12)*2.2);
%   a_ts.setYunits('Hz^(-1/2) V^2');
%   a_ts.setName();
%   
%   b_ts = ao(1:12,randn(12,1), 12.1);
%   b_ts.setDx(7);
%   b_ts.setDy(9);
%   b_ts.setYunits('Hz^(-1/2) V^2');
%   b_ts.setName();

  n = 12;
  fs = 12.1;
  x = 0:(1/fs):(n/fs)-1/fs;
  a_ts = ao(x, ones(n,1), fs);
  a_ts.setName();
  
  b_ts = ao(x, ones(n,1)*5, fs);
  b_ts.setName();
  
  c_ts = ao(x, ones(n,1)*13, fs);
  c_ts.setName();
  
  V_N_ts = [copy(a_ts, 1), copy(b_ts, 1), copy(c_ts, 1)];
  V_M_ts = [copy(a_ts, 1), copy(b_ts, 1), copy(a_ts, 1), copy(b_ts, 1)];
  
  % fsdata
  a_fs = ao(plist('xvals', 1:12, 'yvals', abs(randn(12,1)), 'type', 'fsdata'));
  a_fs.setDx(ones(12,1)*1.1);
  a_fs.setDy((1:12)*2.2);
  a_fs.setName();
  
  b_fs = ao(plist('xvals', 1:12, 'yvals', abs(randn(12,1)), 'type', 'fsdata'));
  b_fs.setDx(7);
  b_fs.setDy(9);
  b_fs.setName();
  
  V_N_fs = [copy(a_fs, 1), copy(a_fs, 1), copy(b_fs, 1)];
  V_M_fs = [copy(a_fs, 1), copy(b_fs, 1), copy(a_fs, 1), copy(b_fs, 1)];
  
  % xydata
  a_xy = ao(plist('xvals', 1:12, 'yvals', abs(randn(12,1)), 'type', 'xydata'));
  a_xy.setDx(ones(12,1)*1.1);
  a_xy.setDy((1:12)*2.2);
  a_xy.setYunits('Hz^(-1/2) V^2');
  a_xy.setName();
  
  b_xy = ao(plist('xvals', 1:12, 'yvals', abs(randn(12,1)), 'type', 'xydata'));
  b_xy.setDx(7);
  b_xy.setDy(9);
  b_xy.setName();
  
  V_N_xy = [copy(a_xy, 1), copy(a_xy, 1), copy(b_xy, 1)];
  V_M_xy = [copy(a_xy, 1), copy(b_xy, 1), copy(a_xy, 1), copy(b_xy, 1)];
  
  % cdata
  a_c = ao(8);
  a_c.setDy(2);
  a_c.setName();
  
  b_c = ao(111:122);
  b_c.setDy((111:122)/100);
  b_c.setName();
  
  V_M_c = [copy(a_c, 1), copy(b_c, 1), copy(a_c, 1), copy(b_c, 1)];
  
  % Define check functions
  checkFcns = {...
    @checkDataObjectRule2, ...
    @checkValuesRule2,     ...
    @checkErrorsRule2,     ...
    @checkUnitsRule2,      ...
    @check_aop_history};
  
  result = [];
  
  % <AlgoDescription>
  %
  % Here we test  element-wise operator rule2 as in S2-AEI-TN-3059.
  %
  % 1) Check the data type of the resulting object.
  % 2) Check the resulting object contains the correct values.
  % 3) Check the error propagation.
  % 4) Check the units of the output object.
  % 5) Check the resulting object can be rebuilt.
  %
  % </AlgoDescription>
  
  
  % <AlgoCode>
  % tsdata
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single tsdata and vector tsdata', b_ts, V_N_ts, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector tsdata and single tsdata', V_M_ts, a_ts, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single xydata and vector tsdata', b_xy, V_N_ts, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector tsdata and single xydata', V_M_ts, a_xy, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single cdata and vector tsdata', b_c, V_N_ts, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector tsdata and single cdata', V_M_ts, a_c, checkFcns)];
  
  % fsdata
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single fsdata and vector fsdata', b_fs, V_N_fs, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector fsdata and single fsdata', V_M_fs, a_fs, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single xydata and vector fsdata', b_xy, V_N_fs, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector fsdata and single xydata', V_M_fs, a_xy, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single cdata and vector fsdata', b_c, V_N_fs, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector fsdata and single cdata', V_M_fs, a_c, checkFcns)];
  
  % xydata
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single xydata and vector xydata', b_xy, V_N_xy, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector xydata and single xydata', V_M_xy, a_xy, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single cdata and vector xydata', b_c, V_N_xy, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector xydata and single cdata', V_M_xy, a_c, checkFcns)];
  
  % cdata
  result = [result utp_generic_aop_core(fcn, 'rule2', 'vector cdata and single cdata', V_M_c, a_c, checkFcns)];
  result = [result utp_generic_aop_core(fcn, 'rule2', 'single cdata and vector cdata', b_c, V_M_c, checkFcns)];
  % </AlgoCode>
  
end % END UTP_rule2

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                      Define here the checking functions                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%   Data object test   %%%%%%%%%%
function atest = checkDataObjectRule2(fcn, in1, in2, out)
  
  for ii = 1:max(numel(in1), numel(in2))
    if numel(in1) > numel(in2)
      atest = check_aop_data_object(fcn, in1(ii), in2, out(ii));
    else
      atest = check_aop_data_object(fcn, in1, in2(ii), out(ii));
    end
    if atest == 0
      break;
    end
  end
end

%%%%%%%%%%   Value test   %%%%%%%%%%
function atest = checkValuesRule2(fcn, in1, in2, out)
  
  atest = true;
  for ii = 1:max(numel(in1), numel(in2))
    if numel(in1) > numel(in2)
      if ~isequal(fcn(in1(ii).data.getY, in2.data.getY), out(ii).data.getY), atest = false; end
    else
      if ~isequal(fcn(in1.data.getY, in2(ii).data.getY), out(ii).data.getY), atest = false; end
    end
    if atest == 0
      break;
    end
  end
end

%%%%%%%%%%   Errors test   %%%%%%%%%%
function atest = checkErrorsRule2(fcn, in1, in2, out)
  
  atest = true;
  for ii = 1:max(numel(in1), numel(in2))
    if numel(in1) > numel(in2)
      atest = check_aop_errors(fcn, in1(ii), in2, out(ii));
    else
      atest = check_aop_errors(fcn, in1, in2(ii), out(ii));
    end
    if atest == 0
      break;
    end
  end
end

%%%%%%%%%%   Units test   %%%%%%%%%%
function atest = checkUnitsRule2(fcn, in1, in2, out)
  
  atest = true;
  for ii = 1:max(numel(in1), numel(in2))
    if numel(in1) > numel(in2)
      atest = check_aop_units(fcn, in1(ii), in2, out(ii));
    else
      atest = check_aop_units(fcn, in1, in2(ii), out(ii));
    end
    if atest == 0
      break;
    end
  end
end
