% Script to make C++ header for looped Horner eval of kernels of all widths,
% for a particular opts.upsampfac (user to hand-choose below).
% C++ version (now writes .h), uses constexpr to switch by width w.

% Barnett 4/23/18; now calling Ludvig's loop version from 4/25/18.
% version including low upsampfac, 6/17/18.
% Ludvig put in w=4n padding, 1/31/20. Mystery about why d was bigger 2/6/20.
% C++ header using constexpr of Barbone, replacing *_C_code.m. Barnett 7/16/24.
% simplified to kill nc200() etc functions, Barbone + Barnett 7/22/24.
clear
%opts = struct();  % not needed yet

for upsampfac = [2.0, 1.25]   % sigma: either 2 (default) or low (eg 5/4)
  fprintf('upsampfac = %g...\n',upsampfac)
  
  ws = 2:16;           % list of widths (the driver, rather than tols)
                       % (must match MIN and MAX NSPREAD in source headers)
  if upsampfac==2
    fid = fopen('../src/ker_horner_allw_loop_constexpr.h','w');
  elseif upsampfac==1.25
    fid = fopen('../src/ker_lowupsampfac_horner_allw_loop_constexpr.h','w');
  end
  fwrite(fid,sprintf('// Header of static arrays of monomial coeffs of spreading kernel function in each\n'));
  fwrite(fid,sprintf('// fine-grid interval. Generated by gen_all_horner_cpp_header.m in devel/\n'));
  fwrite(fid,sprintf('// Authors: Alex Barnett, Ludvig af Klinteberg, Marco Barbone & Libin Lu.\n// (C) 2018--2024 The Simons Foundation, Inc.\n'));
  fwrite(fid,sprintf('#include <array>\n\n'));
  
  usf_tag = sprintf('%d',100*upsampfac);  % string, follow Barbone convention: 200 or 125
  fwrite(fid,sprintf('template<class T, uint8_t w>\nconstexpr auto get_horner_coeffs_%s() noexcept {\n',usf_tag));

  for j=1:numel(ws)
    w = ws(j);
    [d,beta] = get_degree_and_beta(w,upsampfac);
    fprintf('w=%d\td=%d\tbeta=%.3g\n',w,d,beta);
    str = gen_ker_horner_loop_cpp_code(w,d,beta);  % code strings for this w (nc hardcoded)
    
    if j==1                                % write switch statement
      fwrite(fid,sprintf('    if constexpr (w == %d) {\n',w));
    else
      fwrite(fid,sprintf('    } else if constexpr (w == %d) {\n',w));
    end
    for i=1:numel(str); fwrite(fid,['    ',str{i}]); end   % format 4 extra spaces
  end

  % handle bad w at compile time...
  fwrite(fid,sprintf('    }\n'));
  fwrite(fid,sprintf('    static_assert(w >= %d, "w must be >= %d");\n',ws(1),ws(1)));
  fwrite(fid,sprintf('    static_assert(w <= %d, "w must be <= %d");\n',ws(end),ws(end)));
  fwrite(fid,sprintf('  };\n'));    % close all brackets
  fclose(fid);
  
end
