static CSSRet ARIMA_CSS(
      double[] sy, int[] sarma, TransParsRet trarma, int sncond, boolean giveResid) {
    double[] sResid;
    double ssq = 0.0;
    double[] y = (sy);
    double tmp;
    double[] phi = (trarma.getsPhi());
    double[] theta = (trarma.getsTheta());
    double[] w;
    double[] resid;
    int n = (sy.length);
    int[] arma = (sarma);
    int p = (trarma.getsPhi().length);
    int q = (trarma.getsTheta().length);
    int ncond = (sncond);
    int l, i, j, ns, nu = 0;
    boolean useResid = (giveResid);

    w = new double[n];
    for (l = 0; l < n; l++) w[l] = y[l];
    for (i = 0; i < arma[5]; i++) for (l = n - 1; l > 0; l--) w[l] -= w[l - 1];
    ns = arma[4];
    for (i = 0; i < arma[6]; i++) for (l = n - 1; l >= ns; l--) w[l] -= w[l - ns];
    sResid = new double[n];
    resid = (sResid);
    if (useResid) for (l = 0; l < ncond && l < n; l++) resid[l] = 0;

    for (l = ncond; l < n; l++) {
      tmp = w[l];
      for (j = 0; j < p; j++) tmp -= phi[j] * w[l - j - 1];
      for (j = 0; j < Math.min(l - ncond, q); j++) tmp -= theta[j] * resid[l - j - 1];
      resid[l] = tmp;
      if (!Double.isNaN(tmp)) {
        nu++;
        ssq += tmp * tmp;
      }
    }
    CSSRet res = new CSSRet();
    res.setUseResid(useResid);
    if (useResid) {
      res.setValue(ssq / nu);
      res.setsResid(sResid);
      return res;
    } else {
      res.setValue(ssq / nu);
    }
    return res;
  }
  private ARIMARet arima() {
    double[] x = analyticData;
    int[] order = new int[] {p, d, q};
    int[] seasonalOrder = new int[] {0, 0, 0};
    int seasonalPeriod = 1;
    int n = x.length;
    arma =
        new int[] {
          order[0],
          order[2],
          seasonalOrder[0],
          seasonalOrder[2],
          seasonalPeriod,
          order[1],
          seasonalOrder[1]
        };
    int narma = 0;
    for (int i = 0; i < 4; i++) {
      narma += arma[i];
    }
    double[] delta = new double[1];
    delta[0] = 1;
    double[] tmp = new double[] {1, -1};
    for (int i = 0; i < order[1]; i++) {
      delta = TSconv(delta, tmp);
    }
    tmp = new double[2 + seasonalPeriod - 1];
    tmp[0] = 1;
    tmp[tmp.length - 1] = -1;
    for (int i = 0; i < seasonalPeriod - 1; i++) {
      tmp[i] = 0;
    }
    for (int i = 0; i < seasonalOrder[1]; i++) {
      delta = TSconv(delta, tmp);
    }
    double[] deltaOld = delta;
    delta = new double[deltaOld.length - 1];
    for (int i = 0; i < delta.length; i++) {
      delta[i] = -deltaOld[i + 1];
    }
    int nUsed = n;

    nUsed = n - delta.length;
    int nd = order[1] + seasonalOrder[1];
    ncxreg = 0;
    boolean includeMean = true; // false;
    double[] xreg = null;
    if (includeMean && (nd == 0)) {
      xreg = new double[n];
      for (int i = 0; i < n; i++) {
        xreg[i] = 1;
      }
      ncxreg = ncxreg + 1;
    }

    int ncond = order[1] + seasonalOrder[1] * seasonalPeriod;
    int ncond1 = order[0] + seasonalPeriod * seasonalOrder[0];

    Integer nCond = null;

    if (nCond != null) ncond = ncond + Math.max(nCond, ncond1);
    else ncond = ncond + ncond1;
    double[] fixed = new double[narma + ncxreg];
    for (int i = 0; i < fixed.length; i++) {
      fixed[i] = Double.NaN;
    }
    boolean[] mask = new boolean[fixed.length];
    for (int i = 0; i < mask.length; i++) {
      if (Double.isNaN(fixed[i])) {
        mask[i] = true;
      } else {
        mask[i] = false;
      }
    }
    boolean noOptim = false;

    double[] init0 = new double[narma];
    double[] parscale = new double[narma];
    for (int i = 0; i < parscale.length; i++) {
      parscale[i] = 1;
    }

    if (ncxreg != 0) {
      double[][] lmxreg = new double[1][];
      lmxreg[0] = new double[xreg.length];
      for (int i = 0; i < lmxreg[0].length; i++) {
        lmxreg[0][i] = xreg[i];
      }
      int lmp = lmxreg.length;
      double[][] lmy = new double[1][];
      lmy[0] = new double[x.length];
      System.arraycopy(x, 0, lmy[0], 0, lmy[0].length);
      int lmny = lmy.length;

      double[][] work = new double[2][lmp];

      double[][] b = new double[lmny][lmp];
      double[][] residuals = new double[lmy.length][lmy[0].length];
      double[][] effects = new double[lmy.length][lmy[0].length];
      double[] qraux = new double[lmp];
      for (int i = 0; i < lmy.length; i++) {
        System.arraycopy(lmy[i], 0, residuals[i], 0, residuals[i].length);
        System.arraycopy(lmy[i], 0, effects[i], 0, effects[i].length);
      }
      int[] jpvt = new int[lmp];
      for (int i = 0; i < jpvt.length; i++) {
        jpvt[i] = i + 1;
      }
      LMRet lmRet =
          LM.dqrls(lmxreg, n, 1, lmy, 1, 1e-07, b, residuals, effects, 1, jpvt, qraux, work);

      //	        n.used <- sum(!is.na(resid(fit))) - length(Delta)
      double coefFit = lmRet.getCoefficient()[0];
      double[] init0New = new double[init0.length + 1];
      System.arraycopy(init0, 0, init0New, 0, init0.length);

      init0New[init0.length] = coefFit;
      init0 = init0New;
      double ses = lmRet.getSes()[0];
      double[] parscaleNew = new double[parscale.length + 1];
      System.arraycopy(parscale, 0, parscaleNew, 0, parscale.length);
      parscaleNew[parscale.length] = 10 * ses;
      parscale = parscaleNew;
    }

    double[] init = init0;
    double[] coef = fixed;
    XReg xReg = new XReg();
    xReg.setNcxreg(ncxreg);
    xReg.setNarma(narma);
    xReg.setXreg(xreg);
    if (ncond >= n) {

      // TODO
      //			throw new WrongUsedException(this,AlpineAnalysisErrorName.DATASET_TOO_SMALL);
    }
    OptimResHessRet res = Optimization.optim(init, arma, ncond, true, x, xReg, parscale);

    coef = res.getRes().getPar();
    TransParsRet trarma = ARIMA_transPars(coef, arma, false);
    double kappa = 1e6;
    MakeARIMARet mod = makeARIMA(coef, trarma.getsPhi(), trarma.getsTheta(), delta, kappa);
    if (ncxreg > 0) {
      for (int i = 0; i < x.length; i++) {
        x[i] = x[i] - xreg[i] * coef[narma];
      }
    }
    double[] P = new double[mod.getP().length * mod.getP()[0].length];
    for (int i = 0; i < mod.getP().length; i++) {
      for (int j = 0; j < mod.getP()[0].length; j++) {
        P[i * mod.getP()[0].length + j] = mod.getP()[i][j];
      }
    }
    double[] Pn = new double[mod.getPn().length * mod.getPn()[0].length];
    for (int i = 0; i < mod.getPn().length; i++) {
      for (int j = 0; j < mod.getPn()[0].length; j++) {
        Pn[i * mod.getPn()[0].length + j] = mod.getPn()[i][j];
      }
    }

    ARIMA_Like(x, mod.getPhi(), mod.getTheta(), mod.getDelta(), mod.getA(), P, Pn, 0, true);

    CSSRet val = ARIMA_CSS(x, arma, trarma, ncond, true);
    sigma2 = val.getValue();
    Matrix var = null;
    if (noOptim) {
      //			var = 0;
    } else {
      //			try {
      try {
        var = res.getHess().times(nUsed).SVDInverse();
      } catch (Exception e) {
        // TODO Auto-generated catch block
        return null;
        //					e.printStackTrace();
      }
      //			} catch (OperatorException e) {
      //				logger.error("svd exception:"+e.getLocalizedMessage());  //TODO
      //			}
    }
    double[] varCoef = new double[coef.length];
    String varString = new String();
    if (var != null) {
      for (int i = 0; i < var.getColumnDimension(); i++) {
        varCoef[i] = Math.sqrt(var.get(i, i));
        varString += "," + varCoef[i];
      }
    }
    double value = 2 * nUsed * res.getRes().getValue() + nUsed + nUsed * Math.log(2 * Math.PI);
    double aic = Double.NaN;

    ARIMARet aRIMARes = new ARIMARet();
    aRIMARes.setCoef(coef);
    aRIMARes.setSigma2(sigma2);
    aRIMARes.setLoglik(-0.5 * value);
    likelihood = aRIMARes.getLoglik();
    aRIMARes.setAic(aic);
    aRIMARes.setArma(arma);
    aRIMARes.setX(x);
    aRIMARes.setnCond(ncond);
    aRIMARes.setModel(mod);
    aRIMARes.setVarCoef(varCoef);
    aRIMARes.setResiduals(val.getsResid());
    return aRIMARes;
  }