StVKReducedStiffnessMatrix::StVKReducedStiffnessMatrix(StVKReducedInternalForces * stVKReducedInternalForces, int verbose) : shallowCopy(0)
{
  r = stVKReducedInternalForces->Getr();
  r2 = r*r;

  if (verbose)
    printf("Building the reduced stiffness matrix quadratic polynomials... r is %d\n",r);

  int i,j,k;

  int output;

  if (verbose)
    printf("Building free terms:");

  // free terms
  // allocate room for coefficients, 1 coefficient per each of the r x r components
  freeCoef_ = (double*) malloc (sizeof(double) * r * (r+1) / 2);

  // obtain free terms by analytic derivation of the linear force terms
  for(output=0; output<r; output++)
  {
    if (verbose)
      printf(" %d",output);
    for(i=output; i<r; i++)
    {
      freeCoef_[freeCoefPos(output,i)] = stVKReducedInternalForces->linearCoef(output,i);
    }
  }

  if (verbose)
    printf("\nBuilding linear terms:");

  // linear terms
  // allocate room for coefficients, r coefficients per each of the r x r components
  linearSize = StVKReducedInternalForces::GetLinearSize(r);
  linearCoef_ = (double*) malloc (sizeof(double) * r * (r+1) / 2 * linearSize);

  // obtain linear coefficients by analytic derivation of the quadratic force terms
  for(output=0; output<r; output++)
  {
    if (verbose)
      printf(" %d",output);
    for(i=output; i<r; i++)
      for(j=0; j<r; j++)
      {
        // (i1,j1) will be (i,j) sorted in ascending order
        int i1 = i;
        int j1 = j;
        if (j1 < i1) // swap them
        {
          j1 = i;
          i1 = j;
        }

        double value = stVKReducedInternalForces->quadraticCoef(output,i1,j1);

        if (i == j)
          value *= 2;

        //int pos = linearCoefPos(output,i,j);
        linearCoef_[linearCoefPos(output,i,j)] = value;
    }
  }

  if (verbose)
    printf("\nBuilding quadratic terms:");

  // quadratic terms
  // allocate room for coefficients, r*(r+1)/2 coefficients per each of the r x r components
  quadraticSize = StVKReducedInternalForces::GetQuadraticSize(r);
  quadraticCoef_ = (double*) malloc (sizeof(double) * r * (r+1) / 2 * quadraticSize);

  // obtain quadratic coefficients by analytic derivation of the cubic force terms
  for(output=0; output<r; output++)
  {
    if (verbose)
      printf(" %d",output);

    for(i=output; i<r; i++)
      for(j=0; j<r; j++)
        for(k=j; k<r; k++)
        {
          // (i1,j1,k1) will be (i,j,k) sorted in ascending order

          int i1 = i;
          int j1 = j;
          int k1 = k;

          int buffer;
          #define SWAP(i,j)\
             buffer = i;\
             i = j;\
             j = buffer;

          // bubble sort on 3 elements
          if (j1 < i1) 
          {
            SWAP(i1,j1);
          }

          if (k1 < j1) 
          {
            SWAP(j1,k1);
          }

          if (j1 < i1)
          {
            SWAP(i1,j1);
          }

          double value = stVKReducedInternalForces->cubicCoef(output,i1,j1,k1);

          if ((i == j) && (i == k)) // q_i^3
            value *= 3;
          else if ((i == j) || (i == k)) // q_i^2 * q_j
            value *= 2;

          quadraticCoef_[quadraticCoefPos(output,i,j,k)] = value;
        }
  }

  if (verbose)
    printf("\n");
  
  InitBuffers();
}
StVKReducedHessianTensor::StVKReducedHessianTensor(StVKReducedStiffnessMatrix * stVKReducedStiffnessMatrix) : shallowCopy(0)
{
  r = stVKReducedStiffnessMatrix->Getr();
  r2 = r*r;

  InitBuffers();

  printf("Building the reduced Hessian tensor linear polynomials... r is %d\n",r);

  int i;

  int output,input,deriv;

  linearSize = StVKReducedInternalForces::GetLinearSize(r);
  quadraticSize = StVKReducedInternalForces::GetQuadraticSize(r);

  printf("Building free terms:");

  // free terms
  // allocate room for coefficients
  freeCoef_ = (double*) malloc (sizeof(double) * quadraticSize * r);

  // obtain free terms by analytic derivation of the linear stiffness matrix terms
  for(output=0; output<r; output++)
  {
    printf(" %d",output);
    for(input=output; input<r; input++)
    {
      for(deriv=0; deriv<r; deriv++)
      {
        int pos = freeCoefPos(output,input,deriv);
        freeCoef_[pos] = stVKReducedStiffnessMatrix->linearCoef(output,input,deriv);
      }
    }
  }

  printf("\nBuilding linear terms:");

  // linear terms
  // allocate room for coefficients, r coefficients per each of cubicSize components
  linearCoef_ = (double*) malloc (sizeof(double) * quadraticSize * r * r);

  // obtain linear coefficients by analytic derivation of the quadratic stiffness matrix terms
  for(output=0; output<r; output++)
  {
    printf(" %d",output);
    for(input=output; input<r; input++)
      for(deriv=0; deriv<r; deriv++)
      {
        for(i=0; i<r; i++)
        {
          // (i1,j1) will be (i,deriv) sorted in ascending order
          int i1 = i;
          int j1 = deriv;
          if (j1 < i1) // swap them
          {
            j1 = i;
            i1 = deriv;
          }

          double value = stVKReducedStiffnessMatrix->quadraticCoef(output,input,i1,j1);

          if (i == deriv)
            value *= 2;

          int pos = linearCoefPos(output,input,deriv,i);

          linearCoef_[pos] = value;
        }
      }
  }

  printf("\n");
}