class BasisFunctionKnots {

  public static BasisFunctionKnots fromUniform(double xa, double xb, int nKnots, int degree) {
    ArgumentChecker.isTrue(xb > xa, "Require xb > xa, values are xa = {}, xb = {}", xa, xb);
    ArgumentChecker.notNegative(degree, "degree");
    ArgumentChecker.isTrue(nKnots - degree > 0, "Require at least {} knots for degree {}, only given {}", degree + 1, degree, nKnots);

    int nTotalKnots = nKnots + 2 * degree; // this is the total number of knots, including those outside the range
    int nSplines = nKnots + degree - 1;
    double[] knots = new double[nTotalKnots];
    double dx = (xb - xa) / (nKnots - 1);

    // knots to the left and right of the range
    for (int i = 0; i < degree; i++) {
      knots[i] = (i - degree) * dx + xa;
      knots[degree + nKnots + i] = xb + dx * (i + 1);
    }
    // knots in the main range
    for (int i = 0; i < nKnots - 1; i++) {
      knots[i + degree] = xa + i * dx;
    }
    knots[nKnots + degree - 1] = xb;
    return new BasisFunctionKnots(knots, degree, nSplines);
  }

  private  BasisFunctionKnots(double[] knots, int degree, int nSplines);

}