#This work is licensed under the
#Creative Commons Attribution-Share Alike 3.0 United States License.
#To view a copy of this license, visit
#http://creativecommons.org/licenses/by-sa/3.0/us/ or send a letter to
#Creative Commons,
#171 Second Street, Suite 300,
#San Francisco, California, 94105, USA.

INPUT QLP_shift, QLP_coeff_count, QLP_coeff,
residual, sample_size, sample_count;
OUTPUT "a list of signed subframe samples";
VAR QLP_shift "QLP shift needed";
VAR QLP_coeff_count "QLP coefficient count";
VAR QLP_coeff "QLP coefficient";
VAR QLP_sum "QLP sum";
VAR residual "residual";
VAR sample_size "sample size";
VAR sample_count "sample count";
VAR base_sample "base sample";
VAR sample "sample";
VAR diff "diff";
VAR sign "sign";
sample[0] <- residual[0] /*first residual always copied verbatim*/;
for i <- 1 to QLP_coeff_count + 1 {
    sample[i] <- truncate(residual[i] + sample[i - 1], sample_size);
}
for i <- QLP_coeff_count + 1 to sample_count {
    base_sample[i] <- sample[i - QLP_coeff_count - 1];
    QLP_sum[i] <- sum j <- 0 to QLP_coeff_count - 1
                  {QLP_coeff[j] * (sample[i - j - 1] - base_sample[i])};
    sample[i] <- truncate(floor(frac(QLP_sum[i] + 2 ^ {QLP_shift - 1},
                                     2 ^ QLP_shift)) +
                          residual[i] + base_sample[i],
                          sample_size);
    /*adjust coefficients based on residual*/;
    if residual[i] > 0 {
        for j <- QLP_coeff_count downto 0 {
            diff <- base_sample[i];

            sign <- sign(diff);

            QLP_coeff[j] <- QLP_coeff[j] - sign;

            residual <- residual - floor(frac(diff * sign,
                                              2 ^ QLP_shift)) *
                                   (QLP_coeff_count - j);

            if (residual <= 0) {
                break;
            }
        }
     } elif residual[i] < 0 {
        for j <- QLP_coeff_count downto 0 {
            diff <- base_sample[i];

            sign <- sign(diff);

            QLP_coeff[j] <- QLP_coeff[j] + sign;

            residual <- residual - floor(frac(diff * -sign,
                                              2 ^ QLP_shift)) *
                                   (QLP_coeff_count - j);

            if (residual >= 0) {
                break;
            }
        }
    }
}
return sample;
