/*

  Half-Sample Symmetric Lifting: Prediction Step

  hslpredict( u[], N, dq, coeff ):
  [0] Let i=dq
  [1] While i<N, do [2] to [3]
  [2]    Accumulate  u[i] += coeff*u[i-dq]
  [3]    Increment  i += 2*dq  

  Half-Sample Symmetric Lifting: Updating Step

  hslupdate( u[], N, dq, coeff ):
  [1] Let i=0
  [2] While i+dq<N, do [2] to [3]
  [3]    Accumulate  u[i] += coeff*u[i+dq]
  [4]    Increment  i += 2*dq  


  Lifting: Normalization Step

  onormalize( u[], N, dq, coeff ):
  [0] Let i=0
  [1] While i+dq<N, do [2] to [4]
  [2]    Replace  u[i] *= coeff
  [3]    Replace  u[i+dq] /= coeff
  [4]    Increment  i += 2*dq  

*/

void
hslpredict(float u[], int N, int dq, float coeff)
{
  int i;
  i = dq;
  while(i<N) {
    u[i] += coeff*u[i-dq];
    i += 2*dq;
  }
  return;
}

void
hslupdate(float u[], int N, int dq, float coeff)
{
  int i;
  i = 0;
  while(i+dq<N) {
    u[i] += coeff*u[i+dq];
    i += 2*dq;
  }
  return;
}

void
onormalize(float u[], int N, int dq, float coeff)
{
  int i;
  i = 0;
  while(i+dq<N) {
    u[i] *= coeff;
    u[i+dq] /= coeff;
    i += 2*dq;
  }
  return;
}

/*

  Half-Sample Symmetric Lifting: Haar Filter Transform

  hslhaarfilter( u[], N, dq ):
  [0] Compute hslpredict ( u[], N, dq, alpha )
  [1] Compute hslupdate ( u[], N, dq, beta )
  [2] Compute lnormalize ( u[], N, dq, zeta )
  [3] Return

  Half-Sample Symmetric Lifting: Inverse Haar Filter Transform

  hslihaarfilter( u[], N, dq ):
  [0] Compute lnormalize ( u[], N, dq, 1/zeta )
  [1] Compute hslupdate ( u[], N, dq, -beta )
  [2] Compute hslpredict ( u[], N, dq, -alpha )
  [3] Return

*/

/*  Lifting coefficients for lifting implementation of DHT (exact values) */
const float	alpha = { (float)  -1.0000 },	/*  -1  */
		beta  = { (float)   0.5000 },	/* 1/2  */
		zeta  = { (float)   1.414213562373095 }; /* sqrt(2) */

void
hslhaarfilter(float u[], int N, int dq )
{
  hslpredict ( u, N, dq, alpha );
  hslupdate  ( u, N, dq, beta );
  onormalize ( u, N, dq, zeta );
  return;
}

void
hslihaarfilter(float u[], int N, int dq )
{
  onormalize ( u, N, dq, 1/zeta );
  hslupdate  ( u, N, dq, -beta );
  hslpredict ( u, N, dq, -alpha );
  return;
}



/*
  Half-Sample Symmetric Lifting Discrete Haar Transform

  hsldht( u[], N, dq, J ):
  [0] If J>0, then  do [1] and [2]
  [1]    Compute hslhaarfilter( u[], N, dq )
  [2]    Compute hsldht( u[], N, 2*dq, J-1 )
  [3] Return


  Half-Sample Symmetric Lifting Inverse Discrete Haar Transform

  hslidht( u[], N, dq, J ):
  [0] If J>0, then  do [1] and [2]
  [1]    Compute hslidht( u[], N, 2*dq, J-1 )
  [2]    Compute hslihaarfilter( u[], N, dq )
  [3] Return

*/


void
hsldht( float u[], int N, int dq, int J)
{
  if(J>0) {
    hslhaarfilter( u, N, dq);
    hsldht( u, N, 2*dq, J-1);
  }
  return;
}

void
hslidht( float u[], int N, int dq, int J)
{
  if(J>0) {
    hslidht( u, N, 2*dq, J-1);
    hslihaarfilter( u, N, dq);
  }
  return;
}
