/* *****************************************************
   THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
   *****************************************************

   Generated by:
     cctbx.source_generators.eltbx.generate_sasaki_cpp
 */

#include <cctbx/eltbx/sasaki.h>
#include <scitbx/constants.h>

namespace cctbx { namespace eltbx { namespace sasaki {

namespace table_data {

using namespace detail;

/*
  Sasaki Tables

  Scattering factors based on the Cromer and Liberman method.
  Original data can be downloaded from:
  ftp://pfweis.kek.jp/pub/Sasaki-table/
  Any reports or publications of these data will acknowledge
  its use by the citation:
    Anomalous scattering factors
        S.Sasaki (1989) Numerical Tables of Anomalous Scattering Factors
        Calculated by the Cromer and Liberman Method,
        KEK Report, 88-14, 1-136
  Questions about these data should be addressed to Dr.Satoshi Sasaki,
  Tokyo Institute of Technology.  Email: sasaki@nc.titech.ac.jp
 */

extern raw li[];
extern raw be[];
extern raw b[];
extern raw c[];
extern raw n[];
extern raw o[];
extern raw f[];
extern raw ne[];
extern raw na[];
extern raw mg[];
extern raw mg_k[];
extern raw al[];
extern raw al_k[];
extern raw si[];
extern raw si_k[];
extern raw p[];
extern raw p_k[];
extern raw s[];
extern raw s_k[];
extern raw cl[];
extern raw cl_k[];
extern raw ar[];
extern raw ar_k[];
extern raw k[];
extern raw k_k[];
extern raw ca[];
extern raw ca_k[];
extern raw sc[];
extern raw sc_k[];
extern raw ti[];
extern raw ti_k[];
extern raw v[];
extern raw v_k[];
extern raw cr[];
extern raw cr_k[];
extern raw mn[];
extern raw mn_k[];
extern raw fe[];
extern raw fe_k[];
extern raw co[];
extern raw co_k[];
extern raw ni[];
extern raw ni_k[];
extern raw cu[];
extern raw cu_k[];
extern raw zn[];
extern raw zn_k[];
extern raw ga[];
extern raw ga_k[];
extern raw ge[];
extern raw ge_k[];
extern raw as[];
extern raw as_k[];
extern raw se[];
extern raw se_k[];
extern raw br[];
extern raw br_k[];
extern raw kr[];
extern raw kr_k[];
extern raw rb[];
extern raw rb_k[];
extern raw sr[];
extern raw sr_k[];
extern raw y[];
extern raw y_k[];
extern raw zr[];
extern raw zr_k[];
extern raw nb[];
extern raw nb_k[];
extern raw mo[];
extern raw mo_k[];
extern raw tc[];
extern raw tc_k[];
extern raw ru[];
extern raw ru_k[];
extern raw rh[];
extern raw rh_k[];
extern raw pd[];
extern raw pd_k[];
extern raw ag[];
extern raw ag_k[];
extern raw ag_l1[];
extern raw ag_l2[];
extern raw ag_l3[];
extern raw cd[];
extern raw cd_k[];
extern raw cd_l1[];
extern raw cd_l2[];
extern raw cd_l3[];
extern raw in[];
extern raw in_k[];
extern raw in_l1[];
extern raw in_l2[];
extern raw in_l3[];
extern raw sn[];
extern raw sn_k[];
extern raw sn_l1[];
extern raw sn_l2[];
extern raw sn_l3[];
extern raw sb[];
extern raw sb_k[];
extern raw sb_l1[];
extern raw sb_l2[];
extern raw sb_l3[];
extern raw te[];
extern raw te_k[];
extern raw te_l1[];
extern raw te_l2[];
extern raw te_l3[];
extern raw i[];
extern raw i_k[];
extern raw i_l1[];
extern raw i_l2[];
extern raw i_l3[];
extern raw xe[];
extern raw xe_k[];
extern raw xe_l1[];
extern raw xe_l2[];
extern raw xe_l3[];
extern raw cs[];
extern raw cs_k[];
extern raw cs_l1[];
extern raw cs_l2[];
extern raw cs_l3[];
extern raw ba[];
extern raw ba_k[];
extern raw ba_l1[];
extern raw ba_l2[];
extern raw ba_l3[];
extern raw la[];
extern raw la_k[];
extern raw la_l1[];
extern raw la_l2[];
extern raw la_l3[];
extern raw ce[];
extern raw ce_k[];
extern raw ce_l1[];
extern raw ce_l2[];
extern raw ce_l3[];
extern raw pr[];
extern raw pr_k[];
extern raw pr_l1[];
extern raw pr_l2[];
extern raw pr_l3[];
extern raw nd[];
extern raw nd_k[];
extern raw nd_l1[];
extern raw nd_l2[];
extern raw nd_l3[];
extern raw pm[];
extern raw pm_k[];
extern raw pm_l1[];
extern raw pm_l2[];
extern raw pm_l3[];
extern raw sm[];
extern raw sm_k[];
extern raw sm_l1[];
extern raw sm_l2[];
extern raw sm_l3[];
extern raw eu[];
extern raw eu_k[];
extern raw eu_l1[];
extern raw eu_l2[];
extern raw eu_l3[];
extern raw gd[];
extern raw gd_k[];
extern raw gd_l1[];
extern raw gd_l2[];
extern raw gd_l3[];
extern raw tb[];
extern raw tb_k[];
extern raw tb_l1[];
extern raw tb_l2[];
extern raw tb_l3[];
extern raw dy[];
extern raw dy_k[];
extern raw dy_l1[];
extern raw dy_l2[];
extern raw dy_l3[];
extern raw ho[];
extern raw ho_k[];
extern raw ho_l1[];
extern raw ho_l2[];
extern raw ho_l3[];
extern raw er[];
extern raw er_k[];
extern raw er_l1[];
extern raw er_l2[];
extern raw er_l3[];
extern raw tm[];
extern raw tm_k[];
extern raw tm_l1[];
extern raw tm_l2[];
extern raw tm_l3[];
extern raw yb[];
extern raw yb_k[];
extern raw yb_l1[];
extern raw yb_l2[];
extern raw yb_l3[];
extern raw lu[];
extern raw lu_k[];
extern raw lu_l1[];
extern raw lu_l2[];
extern raw lu_l3[];
extern raw hf[];
extern raw hf_k[];
extern raw hf_l1[];
extern raw hf_l2[];
extern raw hf_l3[];
extern raw ta[];
extern raw ta_k[];
extern raw ta_l1[];
extern raw ta_l2[];
extern raw ta_l3[];
extern raw w[];
extern raw w_k[];
extern raw w_l1[];
extern raw w_l2[];
extern raw w_l3[];
extern raw re[];
extern raw re_k[];
extern raw re_l1[];
extern raw re_l2[];
extern raw re_l3[];
extern raw os[];
extern raw os_k[];
extern raw os_l1[];
extern raw os_l2[];
extern raw os_l3[];
extern raw ir[];
extern raw ir_k[];
extern raw ir_l1[];
extern raw ir_l2[];
extern raw ir_l3[];
extern raw pt[];
extern raw pt_k[];
extern raw pt_l1[];
extern raw pt_l2[];
extern raw pt_l3[];
extern raw au[];
extern raw au_l1[];
extern raw au_l2[];
extern raw au_l3[];
extern raw hg[];
extern raw hg_l1[];
extern raw hg_l2[];
extern raw hg_l3[];
extern raw tl[];
extern raw tl_l1[];
extern raw tl_l2[];
extern raw tl_l3[];
extern raw pb[];
extern raw pb_l1[];
extern raw pb_l2[];
extern raw pb_l3[];
extern raw bi[];
extern raw bi_l1[];
extern raw bi_l2[];
extern raw bi_l3[];
extern raw u[];

static const detail::info all[] = {
{"Li", 3, li, 0., 0, 0., 0, 0., 0, 0., 0},
{"Be", 4, be, 0., 0, 0., 0, 0., 0, 0., 0},
{"B", 5, b, 0., 0, 0., 0, 0., 0, 0., 0},
{"C", 6, c, 0., 0, 0., 0, 0., 0, 0., 0},
{"N", 7, n, 0., 0, 0., 0, 0., 0, 0., 0},
{"O", 8, o, 0., 0, 0., 0, 0., 0, 0., 0},
{"F", 9, f, 0., 0, 0., 0, 0., 0, 0., 0},
{"Ne", 10, ne, 0., 0, 0., 0, 0., 0, 0., 0},
{"Na", 11, na, 0., 0, 0., 0, 0., 0, 0., 0},
{"Mg", 12, mg, 9.4860, mg_k, 0., 0, 0., 0, 0., 0},
{"Al", 13, al, 7.9350, al_k, 0., 0, 0., 0, 0., 0},
{"Si", 14, si, 6.7280, si_k, 0., 0, 0., 0, 0., 0},
{"P", 15, p, 5.7640, p_k, 0., 0, 0., 0, 0., 0},
{"S", 16, s, 5.0010, s_k, 0., 0, 0., 0, 0., 0},
{"Cl", 17, cl, 4.3790, cl_k, 0., 0, 0., 0, 0., 0},
{"Ar", 18, ar, 3.8570, ar_k, 0., 0, 0., 0, 0., 0},
{"K", 19, k, 3.4230, k_k, 0., 0, 0., 0, 0., 0},
{"Ca", 20, ca, 3.0560, ca_k, 0., 0, 0., 0, 0., 0},
{"Sc", 21, sc, 2.7450, sc_k, 0., 0, 0., 0, 0., 0},
{"Ti", 22, ti, 2.4820, ti_k, 0., 0, 0., 0, 0., 0},
{"V", 23, v, 2.2550, v_k, 0., 0, 0., 0, 0., 0},
{"Cr", 24, cr, 2.0560, cr_k, 0., 0, 0., 0, 0., 0},
{"Mn", 25, mn, 1.8820, mn_k, 0., 0, 0., 0, 0., 0},
{"Fe", 26, fe, 1.7290, fe_k, 0., 0, 0., 0, 0., 0},
{"Co", 27, co, 1.5940, co_k, 0., 0, 0., 0, 0., 0},
{"Ni", 28, ni, 1.4740, ni_k, 0., 0, 0., 0, 0., 0},
{"Cu", 29, cu, 1.3670, cu_k, 0., 0, 0., 0, 0., 0},
{"Zn", 30, zn, 1.2700, zn_k, 0., 0, 0., 0, 0., 0},
{"Ga", 31, ga, 1.1820, ga_k, 0., 0, 0., 0, 0., 0},
{"Ge", 32, ge, 1.1030, ge_k, 0., 0, 0., 0, 0., 0},
{"As", 33, as, 1.0310, as_k, 0., 0, 0., 0, 0., 0},
{"Se", 34, se, 0.9650, se_k, 0., 0, 0., 0, 0., 0},
{"Br", 35, br, 0.9060, br_k, 0., 0, 0., 0, 0., 0},
{"Kr", 36, kr, 0.8520, kr_k, 0., 0, 0., 0, 0., 0},
{"Rb", 37, rb, 0.8020, rb_k, 0., 0, 0., 0, 0., 0},
{"Sr", 38, sr, 0.7560, sr_k, 0., 0, 0., 0, 0., 0},
{"Y", 39, y, 0.7140, y_k, 0., 0, 0., 0, 0., 0},
{"Zr", 40, zr, 0.6750, zr_k, 0., 0, 0., 0, 0., 0},
{"Nb", 41, nb, 0.6390, nb_k, 0., 0, 0., 0, 0., 0},
{"Mo", 42, mo, 0.6060, mo_k, 0., 0, 0., 0, 0., 0},
{"Tc", 43, tc, 0.5750, tc_k, 0., 0, 0., 0, 0., 0},
{"Ru", 44, ru, 0.5470, ru_k, 0., 0, 0., 0, 0., 0},
{"Rh", 45, rh, 0.5200, rh_k, 0., 0, 0., 0, 0., 0},
{"Pd", 46, pd, 0.4950, pd_k, 0., 0, 0., 0, 0., 0},
{"Ag", 47, ag, 0.4720, ag_k, 3.2420, ag_l1, 3.5020, ag_l2, 3.6860, ag_l3},
{"Cd", 48, cd, 0.4500, cd_k, 3.0710, cd_l1, 3.3120, cd_l2, 3.4910, cd_l3},
{"In", 49, in, 0.4300, in_k, 2.9120, in_l1, 3.1330, in_l2, 3.3100, in_l3},
{"Sn", 50, sn, 0.4110, sn_k, 2.7630, sn_l1, 2.9680, sn_l2, 3.1420, sn_l3},
{"Sb", 51, sb, 0.3930, sb_k, 2.6250, sb_l1, 2.8150, sb_l2, 2.9860, sb_l3},
{"Te", 52, te, 0.3760, te_k, 2.4960, te_l1, 2.6740, te_l2, 2.8420, te_l3},
{"I", 53, i, 0.3600, i_k, 2.3740, i_l1, 2.5400, i_l2, 2.7070, i_l3},
{"Xe", 54, xe, 0.3450, xe_k, 2.2600, xe_l1, 2.4150, xe_l2, 2.5780, xe_l3},
{"Cs", 55, cs, 0.3310, cs_k, 2.1530, cs_l1, 2.3000, cs_l2, 2.4600, cs_l3},
{"Ba", 56, ba, 0.3170, ba_k, 2.0540, ba_l1, 2.1910, ba_l2, 2.3490, ba_l3},
{"La", 57, la, 0.3050, la_k, 1.9640, la_l1, 2.0910, la_l2, 2.2470, la_l3},
{"Ce", 58, ce, 0.2930, ce_k, 1.8790, ce_l1, 1.9980, ce_l2, 2.1520, ce_l3},
{"Pr", 59, pr, 0.2810, pr_k, 1.8000, pr_l1, 1.9120, pr_l2, 2.0650, pr_l3},
{"Nd", 60, nd, 0.2710, nd_k, 1.7250, nd_l1, 1.8300, nd_l2, 1.9830, nd_l3},
{"Pm", 61, pm, 0.2600, pm_k, 1.6530, pm_l1, 1.7540, pm_l2, 1.9050, pm_l3},
{"Sm", 62, sm, 0.2510, sm_k, 1.5860, sm_l1, 1.6810, sm_l2, 1.8320, sm_l3},
{"Eu", 63, eu, 0.2420, eu_k, 1.5240, eu_l1, 1.6130, eu_l2, 1.7630, eu_l3},
{"Gd", 64, gd, 0.2330, gd_k, 1.4640, gd_l1, 1.5490, gd_l2, 1.6980, gd_l3},
{"Tb", 65, tb, 0.2240, tb_k, 1.4080, tb_l1, 1.4880, tb_l2, 1.6350, tb_l3},
{"Dy", 66, dy, 0.2160, dy_k, 1.3550, dy_l1, 1.4310, dy_l2, 1.5770, dy_l3},
{"Ho", 67, ho, 0.2090, ho_k, 1.3050, ho_l1, 1.3770, ho_l2, 1.5220, ho_l3},
{"Er", 68, er, 0.2020, er_k, 1.2570, er_l1, 1.3250, er_l2, 1.4690, er_l3},
{"Tm", 69, tm, 0.1950, tm_k, 1.2110, tm_l1, 1.2750, tm_l2, 1.4200, tm_l3},
{"Yb", 70, yb, 0.1880, yb_k, 1.1680, yb_l1, 1.2290, yb_l2, 1.3720, yb_l3},
{"Lu", 71, lu, 0.1820, lu_k, 1.1260, lu_l1, 1.1850, lu_l2, 1.3270, lu_l3},
{"Hf", 72, hf, 0.1760, hf_k, 1.0860, hf_l1, 1.1410, hf_l2, 1.2830, hf_l3},
{"Ta", 73, ta, 0.1700, ta_k, 1.0470, ta_l1, 1.1000, ta_l2, 1.2410, ta_l3},
{"W", 74, w, 0.1640, w_k, 1.0110, w_l1, 1.0610, w_l2, 1.2010, w_l3},
{"Re", 75, re, 0.1590, re_k, 0.9750, re_l1, 1.0230, re_l2, 1.1630, re_l3},
{"Os", 76, os, 0.1540, os_k, 0.9420, os_l1, 0.9870, os_l2, 1.1260, os_l3},
{"Ir", 77, ir, 0.1490, ir_k, 0.9100, ir_l1, 0.9530, ir_l2, 1.0910, ir_l3},
{"Pt", 78, pt, 0.1440, pt_k, 0.8790, pt_l1, 0.9200, pt_l2, 1.0580, pt_l3},
{"Au", 79, au, 0., 0, 0.8500, au_l1, 0.8890, au_l2, 1.0260, au_l3},
{"Hg", 80, hg, 0., 0, 0.8210, hg_l1, 0.8580, hg_l2, 0.9950, hg_l3},
{"Tl", 81, tl, 0., 0, 0.7940, tl_l1, 0.8290, tl_l2, 0.9650, tl_l3},
{"Pb", 82, pb, 0., 0, 0.7680, pb_l1, 0.8010, pb_l2, 0.9370, pb_l3},
{"Bi", 83, bi, 0., 0, 0.7430, bi_l1, 0.7750, bi_l2, 0.9100, bi_l3},
{"U", 92, u, 0., 0, 0., 0, 0., 0, 0., 0},
{0, 0, 0, 0., 0, 0., 0, 0., 0, 0., 0}
};

  } // namespace table_data

  table::table(
    std::string const& label,
    bool exact,
    bool exception_if_no_match)
  {
    std::string work_label = basic::strip_label(label, exact);
    info_ = anomalous::find_entry(
      table_data::all, work_label, exact, exception_if_no_match);
  }

  namespace detail {
  namespace {

    long
    find_table_interval(double given, double first, double incr,
                        double tolerance = 1.e-8)
    {
      double span = (n_raw - 1) * incr;
      double f = (given - first) / span;
      if (f < -tolerance || f > (1.+tolerance)) return -1;
      long i = static_cast<long>(f * (n_raw - 1));
      if (i == n_raw - 1) i--;
      return i;
    }

    bool
    interpolate(double given, double first, const raw* table, bool edge,
                fp_fdp& result)
    {
      if (!table) return false;
      double incr;
      if (!edge) incr = wide_incr;
      else       incr = edge_incr;
      long i = find_table_interval(given, first, incr);
      if (i < 0) return false;
      double x = (given - first) / incr - double(i);
      double fp  = table[i].fp  + x * (table[i+1].fp  - table[i].fp);
      double fdp = table[i].fdp + x * (table[i+1].fdp - table[i].fdp);
      result = fp_fdp(fp, fdp);
      return true;
    }

  } // namespace <anonymous>
  } // namespace detail

  fp_fdp
  table::at_ev(double energy) const
  {
    using detail::interpolate;
    fp_fdp result(fp_fdp_undefined, fp_fdp_undefined);
    double given = scitbx::constants::factor_ev_angstrom / energy;
    if (interpolate(given, info_->first_k, info_->k, true, result)) {
      return result;
    }
    if (interpolate(given, info_->first_l1, info_->l1, true, result)) {
      return result;
    }
    if (interpolate(given, info_->first_l2, info_->l2, true, result)) {
      return result;
    }
    if (interpolate(given, info_->first_l3, info_->l3, true, result)) {
      return result;
    }
    interpolate(given, detail::first_wide, info_->wide, false, result);
    return result;
  }

  table_iterator::table_iterator()
  :
    current_("Li", true)
  {}

  table
  table_iterator::next()
  {
    table result = current_;
    if (current_.is_valid()) current_.info_++;
    return result;
  }

}}} // namespace cctbx::eltbx::sasaki
