示例#1
0
STATIC int write_lprow(lprec *lp, int rowno, void *userhandle, write_modeldata_func write_modeldata, int maxlen)
{
  int     i, ie, j, nchars;
  REAL    a;
  MATrec  *mat = lp->matA;
  MYBOOL  first = TRUE, elements;

  if(rowno == 0) {
    i = 1;
    ie = lp->columns+1;
  }
  else {
    i = mat->row_end[rowno-1];
    ie = mat->row_end[rowno];
  }
  elements = ie - i;
  if(write_modeldata != NULL) {
    nchars = 0;
    for(; i < ie; i++) {
      if(rowno == 0) {
	j = i;
	a = get_mat(lp, 0, i);
	if(a == 0)
	  continue;
      }
      else {
	j = ROW_MAT_COLNR(i);
	a = ROW_MAT_VALUE(i);
	a = my_chsign(is_chsign(lp, rowno), a);
	a = unscaled_mat(lp, a, rowno, j);
      }
      if(is_splitvar(lp, j))
	continue;
      if(!first)
	nchars += write_data(userhandle, write_modeldata, " ");
      else
	first = FALSE;
      if(a == -1)
	nchars += write_data(userhandle, write_modeldata, "-");
      else if(a == 1)
	nchars += write_data(userhandle, write_modeldata, "+");
      else
	nchars += write_data(userhandle, write_modeldata, "%+.12g ", (double)a);
      nchars += write_data(userhandle, write_modeldata, "%s", get_col_name(lp, j));
      /* Check if we should add a linefeed */
      if((maxlen > 0) && (nchars >= maxlen) && (i < ie-1)) {
	write_data(userhandle, write_modeldata, "%s", "\n");
	nchars = 0;
      }
    }
  }
  return(elements);
}
示例#2
0
/* List the current user data matrix columns over the selected row range */
void blockWriteAMAT(FILE *output, const char *label, lprec* lp, int first, int last)
{
  int    i, j, k = 0;
  int    nzb, nze, jb;
  double hold;
  MATrec *mat = lp->matA;

  if(!mat_validate(mat))
    return;
  if(first < 0)
    first = 0;
  if(last < 0)
    last = lp->rows;

  fprintf(output, "%s", label);
  fprintf(output, "\n");

  if(first == 0) {
    for(j = 1; j <= lp->columns; j++) {
      hold = get_mat(lp, 0, j);
      fprintf(output, " %18g", hold);
      k++;
      if(my_mod(k, 4) == 0) {
        fprintf(output, "\n");
        k = 0;
      }
    }
    if(my_mod(k, 4) != 0) {
      fprintf(output, "\n");
      k = 0;
    }
    first++;
  }
  nze = mat->row_end[first-1];
  for(i = first; i <= last; i++) {
    nzb = nze;
    nze = mat->row_end[i];
    if(nzb >= nze)
      jb = lp->columns+1;
    else
      jb = ROW_MAT_COLNR(nzb);
    for(j = 1; j <= lp->columns; j++) {
      if(j < jb)
        hold = 0;
      else {
        hold = get_mat(lp, i, j);
        nzb++;
        if(nzb < nze)
          jb = ROW_MAT_COLNR(nzb);
        else
          jb = lp->columns+1;
      }
      fprintf(output, " %18g", hold);
      k++;
      if(my_mod(k, 4) == 0) {
        fprintf(output, "\n");
        k = 0;
      }
    }
    if(my_mod(k, 4) != 0) {
      fprintf(output, "\n");
      k = 0;
    }
  }
  if(my_mod(k, 4) != 0)
    fprintf(output, "\n");
}
示例#3
0
MYBOOL crash_basis(lprec *lp)
{
  int     i;
  MATrec  *mat = lp->matA;
  MYBOOL  ok = TRUE;

  /* Initialize basis indicators */
  if(lp->basis_valid)
    lp->var_basic[0] = FALSE;
  else
    default_basis(lp);

  /* Set initial partial pricing blocks */
  if(lp->rowblocks != NULL)
    lp->rowblocks->blocknow = 1;
  if(lp->colblocks != NULL)
    lp->colblocks->blocknow = ((lp->crashmode == CRASH_NONE) || (lp->colblocks->blockcount == 1) ? 1 : 2);

  /* Construct a basis that is in some measure the "most feasible" */
  if((lp->crashmode == CRASH_MOSTFEASIBLE) && mat_validate(mat)) {
    /* The logic here follows Maros */
    LLrec   *rowLL = NULL, *colLL = NULL;
    int     ii, rx, cx, ix, nz;
    REAL    wx, tx, *rowMAX = NULL, *colMAX = NULL;
    int     *rowNZ = NULL, *colNZ = NULL, *rowWT = NULL, *colWT = NULL;
    REAL    *value;
    int     *rownr, *colnr;

    report(lp, NORMAL, "crash_basis: 'Most feasible' basis crashing selected\n");

    /* Tally row and column non-zero counts */
    ok = allocINT(lp,  &rowNZ, lp->rows+1,     TRUE) &&
         allocINT(lp,  &colNZ, lp->columns+1,  TRUE) &&
         allocREAL(lp, &rowMAX, lp->rows+1,    FALSE) &&
         allocREAL(lp, &colMAX, lp->columns+1, FALSE);
    if(!ok)
      goto Finish;

    nz = mat_nonzeros(mat);
    rownr = &COL_MAT_ROWNR(0);
    colnr = &COL_MAT_COLNR(0);
    value = &COL_MAT_VALUE(0);
    for(i = 0; i < nz;
        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {
      rx = *rownr;
      cx = *colnr;
      wx = fabs(*value);
      rowNZ[rx]++;
      colNZ[cx]++;
      if(i == 0) {
        rowMAX[rx] = wx;
        colMAX[cx] = wx;
        colMAX[0]  = wx;
      }
      else {
        SETMAX(rowMAX[rx], wx);
        SETMAX(colMAX[cx], wx);
        SETMAX(colMAX[0],  wx);
      }
    }
    /* Reduce counts for small magnitude to preserve stability */
    rownr = &COL_MAT_ROWNR(0);
    colnr = &COL_MAT_COLNR(0);
    value = &COL_MAT_VALUE(0);
    for(i = 0; i < nz;
        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {
      rx = *rownr;
      cx = *colnr;
      wx = fabs(*value);
#ifdef CRASH_SIMPLESCALE
      if(wx < CRASH_THRESHOLD * colMAX[0]) {
        rowNZ[rx]--;
        colNZ[cx]--;
      }
#else
      if(wx < CRASH_THRESHOLD * rowMAX[rx])
        rowNZ[rx]--;
      if(wx < CRASH_THRESHOLD * colMAX[cx])
        colNZ[cx]--;
#endif
    }

    /* Set up priority tables */
    ok = allocINT(lp, &rowWT, lp->rows+1, TRUE);
    createLink(lp->rows,    &rowLL, NULL);
    ok &= (rowLL != NULL);
    if(!ok)
      goto Finish;
    for(i = 1; i <= lp->rows; i++) {
      if(get_constr_type(lp, i)==EQ)
        ii = 3;
      else if(lp->upbo[i] < lp->infinite)
        ii = 2;
      else if(fabs(lp->rhs[i]) < lp->infinite)
        ii = 1;
      else
        ii = 0;
      rowWT[i] = ii;
      if(ii > 0)
        appendLink(rowLL, i);
    }
    ok = allocINT(lp, &colWT, lp->columns+1, TRUE);
    createLink(lp->columns, &colLL, NULL);
    ok &= (colLL != NULL);
    if(!ok)
      goto Finish;
    for(i = 1; i <= lp->columns; i++) {
      ix = lp->rows+i;
      if(is_unbounded(lp, i))
        ii = 3;
      else if(lp->upbo[ix] >= lp->infinite)
        ii = 2;
      else if(fabs(lp->upbo[ix]-lp->lowbo[ix]) > lp->epsmachine)
        ii = 1;
      else
        ii = 0;
      colWT[i] = ii;
      if(ii > 0)
        appendLink(colLL, i);
    }

    /* Loop over all basis variables */
    for(i = 1; i <= lp->rows; i++) {

      /* Select row */
      rx = 0;
      wx = -lp->infinite;
      for(ii = firstActiveLink(rowLL); ii > 0; ii = nextActiveLink(rowLL, ii)) {
        tx = rowWT[ii] - CRASH_SPACER*rowNZ[ii];
        if(tx > wx) {
          rx = ii;
          wx = tx;
        }
      }
      if(rx == 0)
        break;
      removeLink(rowLL, rx);

      /* Select column */
      cx = 0;
      wx = -lp->infinite;
      for(ii = mat->row_end[rx-1]; ii < mat->row_end[rx]; ii++) {

        /* Update NZ column counts for row selected above */
        tx = fabs(ROW_MAT_VALUE(ii));
        ix = ROW_MAT_COLNR(ii);
#ifdef CRASH_SIMPLESCALE
        if(tx >= CRASH_THRESHOLD * colMAX[0])
#else
        if(tx >= CRASH_THRESHOLD * colMAX[ix])
#endif
          colNZ[ix]--;
        if(!isActiveLink(colLL, ix) || (tx < CRASH_THRESHOLD * rowMAX[rx]))
          continue;

        /* Now do the test for best pivot */
        tx = my_sign(lp->orig_obj[ix]) - my_sign(ROW_MAT_VALUE(ii));
        tx = colWT[ix] + CRASH_WEIGHT*tx - CRASH_SPACER*colNZ[ix];
        if(tx > wx) {
          cx = ix;
          wx = tx;
        }
      }
      if(cx == 0)
        break;
      removeLink(colLL, cx);

      /* Update row NZ counts */
      ii = mat->col_end[cx-1];
      rownr = &COL_MAT_ROWNR(ii);
      value = &COL_MAT_VALUE(ii);
      for(; ii < mat->col_end[cx];
          ii++, rownr += matRowColStep, value += matValueStep) {
        wx = fabs(*value);
        ix = *rownr;
#ifdef CRASH_SIMPLESCALE
        if(wx >= CRASH_THRESHOLD * colMAX[0])
#else
        if(wx >= CRASH_THRESHOLD * rowMAX[ix])
#endif
          rowNZ[ix]--;
      }

      /* Set new basis variable */
      set_basisvar(lp, rx, lp->rows+cx);
    }

    /* Clean up */
Finish:
    FREE(rowNZ);
    FREE(colNZ);
    FREE(rowMAX);
    FREE(colMAX);
    FREE(rowWT);
    FREE(colWT);
    freeLink(&rowLL);
    freeLink(&colLL);
  }

  /* Construct a basis that is in some measure the "least degenerate" */
  else if((lp->crashmode == CRASH_LEASTDEGENERATE) && mat_validate(mat)) {
    /* The logic here follows Maros */
    LLrec   *rowLL = NULL, *colLL = NULL;
    int     ii, rx, cx, ix, nz, *merit = NULL;
    REAL    *value, wx, hold, *rhs = NULL, *eta = NULL;
    int     *rownr, *colnr;

    report(lp, NORMAL, "crash_basis: 'Least degenerate' basis crashing selected\n");

    /* Create temporary arrays */
    ok = allocINT(lp,  &merit, lp->columns + 1, FALSE) &&
         allocREAL(lp, &eta, lp->rows + 1, FALSE) &&
         allocREAL(lp, &rhs, lp->rows + 1, FALSE);
    createLink(lp->columns, &colLL, NULL);
    createLink(lp->rows, &rowLL, NULL);
    ok &= (colLL != NULL) && (rowLL != NULL);
    if(!ok)
      goto FinishLD;
    MEMCOPY(rhs, lp->orig_rhs, lp->rows + 1);
    for(i = 1; i <= lp->columns; i++)
      appendLink(colLL, i);
    for(i = 1; i <= lp->rows; i++)
      appendLink(rowLL, i);

    /* Loop until we have found enough new bases */
    while(colLL->count > 0) {

      /* Tally non-zeros matching in RHS and each active column */
      nz = mat_nonzeros(mat);
      rownr = &COL_MAT_ROWNR(0);
      colnr = &COL_MAT_COLNR(0);
      ii = 0;
      MEMCLEAR(merit, lp->columns + 1);
      for(i = 0; i < nz;
          i++, rownr += matRowColStep, colnr += matRowColStep) {
        rx = *rownr;
        cx = *colnr;
        if(isActiveLink(colLL, cx) && (rhs[rx] != 0)) {
          merit[cx]++;
          ii++;
        }
      }
      if(ii == 0)
        break;

      /* Find maximal match; break ties with column length */
      i = firstActiveLink(colLL);
      cx = i;
      for(i = nextActiveLink(colLL, i); i != 0; i = nextActiveLink(colLL, i)) {
        if(merit[i] >= merit[cx]) {
          if((merit[i] > merit[cx]) || (mat_collength(mat, i) > mat_collength(mat, cx)))
            cx = i;
        }
      }

      /* Determine the best pivot row */
      i = mat->col_end[cx-1];
      nz = mat->col_end[cx];
      rownr = &COL_MAT_ROWNR(i);
      value = &COL_MAT_VALUE(i);
      rx = 0;
      wx = 0;
      MEMCLEAR(eta, lp->rows + 1);
      for(; i < nz;
          i++, rownr += matRowColStep, value += matValueStep) {
        ix = *rownr;
        hold = *value;
        eta[ix] = rhs[ix] / hold;
        hold = fabs(hold);
        if(isActiveLink(rowLL, ix) && (hold > wx)) {
          wx = hold;
          rx = ix;
        }
      }

      /* Set new basis variable */
      if(rx > 0) {

        /* We have to update the rhs vector for the implied transformation
          in order to be able to find the new RHS non-zero pattern */
        for(i = 1; i <= lp->rows; i++)
           rhs[i] -= wx * eta[i];
        rhs[rx] = wx;

        /* Do the exchange */
        set_basisvar(lp, rx, lp->rows+cx);
        removeLink(rowLL, rx);
      }
      removeLink(colLL, cx);

    }

    /* Clean up */
FinishLD:
    FREE(merit);
    FREE(rhs);
    freeLink(&rowLL);
    freeLink(&colLL);

  }
  return( ok );
}
示例#4
0
int CurtisReidScales(lprec *lp, MYBOOL _Advanced, REAL *FRowScale, REAL *FColScale)
{
  int    i, row, col, ent, nz;
  REAL   *RowScalem2, *ColScalem2,
         *RowSum, *ColSum,
         *residual_even, *residual_odd;
  REAL   sk,   qk,     ek,
         skm1, qkm1,   ekm1,
         qkm2, qkqkm1, ekm2, ekekm1,
         absvalue, logvalue,
         StopTolerance;
  int    *RowCount, *ColCount, colMax;
  int    Result;
  MATrec *mat = lp->matA;
  REAL   *value;
  int    *rownr, *colnr;

  if(CurtisReidMeasure(lp, _Advanced, FRowScale, FColScale)<0.1*get_nonzeros(lp))
  return(0);

  /* Allocate temporary memory and find RowSum and ColSum measures */
  nz = get_nonzeros(lp);
  colMax = lp->columns;

  allocREAL(lp, &RowSum, lp->rows+1, TRUE);
  allocINT(lp,  &RowCount, lp->rows+1, TRUE);
  allocREAL(lp, &residual_odd, lp->rows+1, TRUE);

  allocREAL(lp, &ColSum, colMax+1, TRUE);
  allocINT(lp,  &ColCount, colMax+1, TRUE);
  allocREAL(lp, &residual_even, colMax+1, TRUE);

  allocREAL(lp, &RowScalem2, lp->rows+1, FALSE);
  allocREAL(lp, &ColScalem2, colMax+1, FALSE);

  /* Set origin for row scaling */
  for(i = 1; i <= colMax; i++) {
    absvalue=fabs(lp->orig_obj[i]);
    if(absvalue>0) {
      logvalue = log(absvalue);
      ColSum[i] += logvalue;
      RowSum[0] += logvalue;
      ColCount[i]++;
      RowCount[0]++;
    }
  }

  value = &(COL_MAT_VALUE(0));
  rownr = &(COL_MAT_ROWNR(0));
  colnr = &(COL_MAT_COLNR(0));
  for(i = 0; i < nz;
      i++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) {
    absvalue=fabs(*value);
    if(absvalue>0) {
      logvalue = log(absvalue);
      ColSum[*colnr] += logvalue;
      RowSum[*rownr] += logvalue;
      ColCount[*colnr]++;
      RowCount[*rownr]++;
    }
  }

  /* Make sure we dont't have division by zero errors */
  for(row = 0; row <= lp->rows; row++)
    if(RowCount[row] == 0)
      RowCount[row] = 1;
  for(col = 1; col <= colMax; col++)
    if(ColCount[col] == 0)
      ColCount[col] = 1;

  /* Initialize to RowScale = RowCount-1 RowSum
                   ColScale = 0.0
                   residual = ColSum - ET RowCount-1 RowSum */

  StopTolerance= MAX(lp->scalelimit-floor(lp->scalelimit), DEF_SCALINGEPS);
  StopTolerance *= (REAL) nz;
  for(row = 0; row <= lp->rows; row++) {
    FRowScale[row] = RowSum[row] / (REAL) RowCount[row];
    RowScalem2[row] = FRowScale[row];
  }

  /* Compute initial residual */
  for(col = 1; col <= colMax; col++) {
    FColScale[col] = 0;
    ColScalem2[col] = 0;
    residual_even[col] = ColSum[col];

    if(lp->orig_obj[col] != 0)
      residual_even[col] -= RowSum[0] / (REAL) RowCount[0];

    i = mat->col_end[col-1];
    rownr = &(COL_MAT_ROWNR(i));
    ent = mat->col_end[col];
    for(; i < ent;
        i++, rownr += matRowColStep) {
      residual_even[col] -= RowSum[*rownr] / (REAL) RowCount[*rownr];
    }
  }

  /* Compute sk */
  sk = 0;
  skm1 = 0;
  for(col = 1; col <= colMax; col++)
    sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col];

  Result = 0;
  qk=1; qkm1=0; qkm2=0;
  ek=0; ekm1=0; ekm2=0;

  while(sk>StopTolerance) {
  /* Given the values of residual and sk, construct
     ColScale (when pass is even)
     RowScale (when pass is odd)  */

    qkqkm1 = qk * qkm1;
    ekekm1 = ek * ekm1;
    if((Result % 2) == 0) { /* pass is even; construct RowScale[pass+1] */
      if(Result != 0) {
        for(row = 0; row <= lp->rows; row++)
          RowScalem2[row] = FRowScale[row];
        if(qkqkm1 != 0) {
          for(row = 0; row <= lp->rows; row++)
            FRowScale[row]*=(1 + ekekm1 / qkqkm1);
          for(row = 0; row<=lp->rows; row++)
            FRowScale[row]+=(residual_odd[row] / (qkqkm1 * (REAL) RowCount[row]) -
                             RowScalem2[row] * ekekm1 / qkqkm1);
        }
      }
    }
    else { /* pass is odd; construct ColScale[pass+1] */
      for(col = 1; col <= colMax; col++)
        ColScalem2[col] = FColScale[col];
      if(qkqkm1 != 0) {
        for(col = 1; col <= colMax; col++)
          FColScale[col] *= (1 + ekekm1 / qkqkm1);
        for(col = 1; col <= colMax; col++)
          FColScale[col] += (residual_even[col] / ((REAL) ColCount[col] * qkqkm1) -
                             ColScalem2[col] * ekekm1 / qkqkm1);
      }
    }

    /* update residual and sk (pass + 1) */
    if((Result % 2) == 0) { /* even */
       /* residual */
      for(row = 0; row <= lp->rows; row++)
        residual_odd[row] *= ek;

      for(i = 1; i <= colMax; i++)
        if(lp->orig_obj[i] != 0)
          residual_odd[0] += (residual_even[i] / (REAL) ColCount[i]);

      rownr = &(COL_MAT_ROWNR(0));
      colnr = &(COL_MAT_COLNR(0));
      for(i = 0; i < nz;
          i++, rownr += matRowColStep, colnr += matRowColStep) {
        residual_odd[*rownr] += (residual_even[*colnr] / (REAL) ColCount[*colnr]);
      }
      for(row = 0; row <= lp->rows; row++)
        residual_odd[row] *= (-1 / qk);

      /* sk */
      skm1 = sk;
      sk = 0;
      for(row = 0; row <= lp->rows; row++)
        sk += (residual_odd[row]*residual_odd[row]) / (REAL) RowCount[row];
    }
    else { /* odd */
      /* residual */
      for(col = 1; col <= colMax; col++)
        residual_even[col] *= ek;

      for(i = 1; i <= colMax; i++)
        if(lp->orig_obj[i] != 0)
          residual_even[i] += (residual_odd[0] / (REAL) RowCount[0]);

      rownr = &(COL_MAT_ROWNR(0));
      colnr = &(COL_MAT_COLNR(0));
      for(i = 0; i < nz;
          i++, rownr += matRowColStep, colnr += matRowColStep) {
        residual_even[*colnr] += (residual_odd[*rownr] / (REAL) RowCount[*rownr]);
      }
      for(col = 1; col <= colMax; col++)
        residual_even[col] *= (-1 / qk);

      /* sk */
      skm1 = sk;
      sk = 0;
      for(col = 1; col <= colMax; col++)
        sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col];
    }

    /* Compute ek and qk */
    ekm2=ekm1;
    ekm1=ek;
    ek=qk * sk / skm1;

    qkm2=qkm1;
    qkm1=qk;
    qk=1-ek;

    Result++;
  }

  /* Synchronize the RowScale and ColScale vectors */
  ekekm1 = ek * ekm1;
  if(qkm1 != 0) {
  if((Result % 2) == 0) { /* pass is even, compute RowScale */
    for(row = 0; row<=lp->rows; row++)
      FRowScale[row]*=(1.0 + ekekm1 / qkm1);
    for(row = 0; row<=lp->rows; row++)
      FRowScale[row]+=(residual_odd[row] / (qkm1 * (REAL) RowCount[row]) -
                      RowScalem2[row] * ekekm1 / qkm1);
  }
  else { /* pass is odd, compute ColScale */
    for(col=1; col<=colMax; col++)
      FColScale[col]*=(1 + ekekm1 / qkm1);
    for(col=1; col<=colMax; col++)
      FColScale[col]+=(residual_even[col] / ((REAL) ColCount[col] * qkm1) -
                       ColScalem2[col] * ekekm1 / qkm1);
  }
  }

  /* Do validation, if indicated */
  if(FALSE && mat_validate(mat)){
    double check, error;

    /* CHECK: M RowScale + E ColScale = RowSum */
    error = 0;
    for(row = 0; row <= lp->rows; row++) {
      check = (REAL) RowCount[row] * FRowScale[row];
      if(row == 0) {
        for(i = 1; i <= colMax; i++) {
          if(lp->orig_obj[i] != 0)
            check += FColScale[i];
        }
      }
      else {
        i = mat->row_end[row-1];
        ent = mat->row_end[row];
        for(; i < ent; i++) {
          col = ROW_MAT_COLNR(i);
          check += FColScale[col];
        }
      }
      check -= RowSum[row];
      error += check*check;
    }

    /* CHECK: E^T RowScale + N ColScale = ColSum */
    error = 0;
    for(col = 1; col <= colMax; col++) {
      check = (REAL) ColCount[col] * FColScale[col];

      if(lp->orig_obj[col] != 0)
        check += FRowScale[0];

      i = mat->col_end[col-1];
      ent = mat->col_end[col];
      rownr = &(COL_MAT_ROWNR(i));
      for(; i < ent;
          i++, rownr += matRowColStep) {
        check += FRowScale[*rownr];
      }
      check -= ColSum[col];
      error += check*check;
    }
  }

  /* Convert to scaling factors (rounding to nearest power
     of 2 can optionally be done as a separate step later) */
  for(col = 1; col <= colMax; col++) {
    absvalue = exp(-FColScale[col]);
    if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR;
    if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR;
    if(!is_int(lp,col) || is_integerscaling(lp))
        FColScale[col] = absvalue;
    else
        FColScale[col] = 1;
  }
  for(row = 0; row <= lp->rows; row++) {
    absvalue = exp(-FRowScale[row]);
    if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR;
    if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR;
    FRowScale[row] = absvalue;
  }

 /* free temporary memory */
  FREE(RowSum);
  FREE(ColSum);
  FREE(RowCount);
  FREE(ColCount);
  FREE(residual_even);
  FREE(residual_odd);
  FREE(RowScalem2);
  FREE(ColScalem2);

  return(Result);

}