import type { NumberArray } from 'cheminfo-types';

/**
 * add the provided weights to a particular given system matrix (lD'D) in the triplet form and y data. This function is not general
 * it assumes that diagonal coefficients are in the even indexes, it is the case of the matrix generated by createSystemMatrix function.
 * It simulates the matrix operation W + lD'D and Wy.
 * @param leftHandSide - the original system matrix to be updated, a lower triangular non-zeros of the system matrix (lambda D'D).
 * @param rightHandSide - the original vector to be updated.
 * @param weights - the weights to apply to the system matrix and vector.
 * @returns an object that contains the new left and right hand-side of the system.
 */
export function addWeights(
  leftHandSide: number[][],
  rightHandSide: NumberArray,
  weights: NumberArray,
) {
  const nbPoints = rightHandSide.length;
  const l = nbPoints - 1;
  const newLeftHandSide: number[][] = new Array(leftHandSide.length);
  const newRightHandSide: Float64Array = new Float64Array(nbPoints);
  for (let i = 0; i < l; i++) {
    const w = weights[i];
    const diag = i * 2;
    const next = diag + 1;
    newLeftHandSide[diag] = leftHandSide[diag].slice();
    newLeftHandSide[next] = leftHandSide[next].slice();

    newRightHandSide[i] = rightHandSide[i] * w;
    newLeftHandSide[diag][2] += w;
  }
  newRightHandSide[l] = rightHandSide[l] * weights[l];
  newLeftHandSide[l * 2] = leftHandSide[l * 2].slice();
  newLeftHandSide[l * 2][2] += weights[l];

  return {
    leftHandSide: newLeftHandSide,
    rightHandSide: newRightHandSide,
  };
}
