#ifndef RF_CDL_UTIL_H
#define RF_CDL_UTIL_H
#include "cdlInfo.h"
void allocInitLambdaFirstPrinciples(uint     xSize,
                                    uint     n,
                                    double **xArray,
                                    double  *yArray,
                                    double  *weightNorm,
                                    double  *lambdaUser,
                                    uint     lambdaGridSize,
                                    double   lambdaMinRatio,
                                    double   lambdaEpsilon,
                                    double **lambdaGrid,
                                    uint    *lambdaGridSizeThinned);
void allocInitLambda(uint     xSize,
                     double  *lambdaUser,
                     uint     lambdaGridSize,
                     double   lambdaMinRatio,
                     double   lambdaEpsilon,
                     double  *innerProductXY,
                     double **lambdaGrid,
                     uint    *lambdaGridSizeThinned);
void deallocLambda(double  *lambdaUser,
                   uint     lambdaGridSize,
                   double  *lambdaGrid);
double updateBetaFirstPrinciples(uint j,
                                 uint p,
                                 double    lambda,
                                 double   *beta,
                                 double   *innerProductXY,
                                 double  **innerProductXX);
double updateBetaEfficient(uint      j,
                           uint      nDummy,
                           double    lambda,
                           double   *beta,
                           double  **xArray,
                           double   *gradientVector);
double updateBetaNaive(uint      j,
                       uint      n,
                       double    lambda,
                       double   *beta,
                       double  **xArray,
                       double   *residualVector);
void initializeGradient(uint p,
                        double   *beta,
                        double   *innerProductXY,
                        double  **innerProductXX,
                        double   *gradientVector);
void initializeResidual(uint n,
                        uint p,
                        double   *beta,
                        double   *yRecastStandard,
                        double  **xRecastStandard,
                        double   *residualVector);
void calculateGradient(uint j,
                       uint p,
                       double   *beta,
                       double   *innerProductXY,
                       double  **innerProductXX,
                       double   *gradientVector);
double updateGradient(uint l,
                      uint p,
                      uint nDummy,
                      double    lambda,
                      double    betaOld,
                      double    betaNew,
                      double  **xArrayDummy,
                      double  **innerProductXX,
                      double   *gradientVector);
double updateResidual(uint l,
                      uint pDummy,
                      uint n,
                      double    lambda,
                      double    betaOld,
                      double    betaNew,
                      double  **xArray,
                      double  **innerProductXXDummy,
                      double   *residualVector);
void recastY(uint    n,
             double *response,
             double  *weight,
             double  *responseRecast);
void recastX(uint    p,
             uint    n,
             double **observation,
             double  *weight,
             double **observationRecast);
void initializeXY(uint p,
                   uint n,
                   double **observation,
                   double  *response,
                   double  *weightDummy,
                   double   weightSumDummy,
                   double  *innerProductXY);
void initializeXX(uint p,
                  uint n,
                  double **observation,
                  double  *weight,
                  double   weightSum,
                  double **innerProductXX);
uint cdlFast(uint p,
             uint n,
             double lambdaCurrent,
             uint   maxIter,
             double convergThreshold,
             double  **xArray,
             char     *masterActiveX,
             char     *previouslyActiveX,
             char     *currentlyActiveX,
             double  **innerProductXX,
             double   *gradientResidualVector,
             double   *beta);
void cdlFastComplete(uint p,
                     uint n,
                     double lambdaCurrent,
                     double  **xArray,
                     char     *masterActiveX,
                     char     *currentlyActiveX,
                     double  **innerProductXX,
                     double   *gradientResidualVector,
                     double   *beta);
void cdlFastActive(uint p,
                   uint n,
                   double lambdaCurrent,
                   uint   maxIter,
                   double convergThreshold,
                   double  **xArray,
                   double  **innerProductXX,
                   char     *currentlyActiveX,
                   double   *gradientResidualVector,
                   double   *beta);
CDLInfo *makeCDLInfo(uint p, uint lambdaCnt);
void freeCDLInfo(CDLInfo *obj);
double **predictCDL(CDLInfo *obj,
                    uint     tstMembrSize,
                    uint    *tstMembrIndx,
                    double **xArray,
                    uint     lambdaCntMaster,
                    double  *lambdaMaster);
#endif
