#include <Riostream.h>

#include "NdbDefs.h"
#include "NdbEndfIO.h"
#include "NdbMTReactionXS.h"

ClassImp(NdbMTReactionXS);

/* -------- LoadENDF -------- */
Bool_t
NdbMTReactionXS::LoadENDF( char *filename )
{
   NdbEndfIO   endf(filename,TENDF_READ);
   Bool_t      error;

   if (!endf.IsOpen()) return kTRUE;

   minxs = MAX_REAL;
   maxxs = -MAX_REAL;

   endf.FindMFMT(3,MT());      // Find total cross section
   endf.ReadReal(&error);   // ??
   endf.ReadReal(&error);
   endf.ReadLine();
   QM  = endf.ReadReal(&error);
   QI  = endf.ReadReal(&error);
   endf.ReadInt(&error);     // Skip number

   LR = endf.ReadInt(&error); if (error) return error;
   NR = endf.ReadInt(&error); if (error) return error;
   NP = endf.ReadInt(&error); if (error) return error;
   endf.ReadLine();          // Skip line

   IT = endf.ReadInt(&error,2);   // Interpolation type
   endf.ReadLine();          // Skip line

   ene.Set(NP);
   xs.Set(NP);

   for (int i=0; i<NP; i++) {
      Float_t   f;
      ene.AddAt(endf.ReadReal(&error), i);
      xs.AddAt( f = endf.ReadReal(&error), i);
      minxs = MIN(minxs,f);
      maxxs = MAX(maxxs,f);
   }
   return kFALSE;
} // loadENDF

/* -------- BinSearch -------- */
Int_t
NdbMTReactionXS::BinSearch( Float_t e )
{
   Int_t   low = 0;
   Int_t   high = NP-1;
   Int_t   mid;

   if (e < ene[low])  return NOTFOUND;
   if (e > ene[high]) return NOTFOUND;

   while (1) {
      mid = (low+high)/2;
      if (mid==low) return mid;
      if (e > ene[mid])
      low = mid;
      else
      if (e < ene[mid])
      high = mid;
      else
      return mid;
   }
} // BinSearch

/* -------- Interpolate -------- */
Float_t
NdbMTReactionXS::Interpolate( Float_t e )
{
   Int_t   p = BinSearch(e);

   if (p==NOTFOUND)
   return xs[ e<ene[0]? 0 : NP-1 ];

   if (p==NP-1)
   return xs[p];

   Float_t   el = ene[p];
   Float_t   xl = xs[p];
   p++;

   switch (IT) {
      case IT_LINLOG:
      cout << "Linear-Log interpolation" << endl;
      return 0.0;

      case IT_LOGLIN:
      cout << "Log-Linear interpolation" << endl;
      return 0.0;

      case IT_LOGLOG:
      cout << "Log-Log interpolation" << endl;
      return 0.0;

      case IT_GAMOW:
      cout << "GAMOW interpolation" << endl;
      return 0.0;

      case IT_LINLIN:
      return xs[p] + (e-el) * (xs[p]-xl) / (ene[p]-el);

      default:
      break;
   }
   return 0.0;
} // interpolate