<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractGrid.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkExtractGrid.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------
vtkExtractGrid* vtkExtractGrid::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkExtractGrid");
  if(ret)
    {
    return (vtkExtractGrid*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkExtractGrid;
}

// Construct object to extract all of the input data.
vtkExtractGrid::vtkExtractGrid()
{
  this->VOI[0] = this->VOI[2] = this->VOI[4] = 0;
  this->VOI[1] = this->VOI[3] = this->VOI[5] = VTK_LARGE_INTEGER;

  this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1;

  this->IncludeBoundary = 0;
}

void vtkExtractGrid::ComputeInputUpdateExtents(vtkDataObject *vtkNotUsed(out))
{
  vtkStructuredGrid *input = this->GetInput();
  vtkStructuredGrid *output = this->GetOutput();
  int ext[6];
  int *wholeExt;

  output->GetUpdateExtent(ext);
  ext[0] = ext[0] * this->SampleRate[0];
  ext[1] = ext[1] * this->SampleRate[0];
  ext[2] = ext[2] * this->SampleRate[1];
  ext[3] = ext[3] * this->SampleRate[1];
  ext[4] = ext[4] * this->SampleRate[2];
  ext[5] = ext[5] * this->SampleRate[2];

  wholeExt = input->GetWholeExtent();

  if (ext[0] < wholeExt[0])
    {
    ext[0] = wholeExt[0];
    }
  if (ext[1] > wholeExt[1])
    {
    ext[1] = wholeExt[1];
    }

  if (ext[2] < wholeExt[2])
    {
    ext[2] = wholeExt[2];
    }
  if (ext[3] > wholeExt[3])
    {
    ext[3] = wholeExt[3];
    }

  if (ext[4] < wholeExt[4])
    {
    ext[4] = wholeExt[4];
    }
  if (ext[5] > wholeExt[5])
    {
    ext[5] = wholeExt[5];
    }

  input->SetUpdateExtent(ext);

}

void vtkExtractGrid::ExecuteInformation()
{
  vtkStructuredGrid *input= this->GetInput();
  vtkStructuredGrid *output= this->GetOutput();
  int i, dims[3], outDims[3], voi[6], wholeExtent[6];
  int rate[3];

  if (this->GetInput() == NULL)
    {
    vtkErrorMacro("Missing input");
    return;
    }

  this->vtkStructuredGridToStructuredGridFilter::ExecuteInformation();

  input->GetWholeExtent(wholeExtent);
  dims[0] = wholeExtent[1] - wholeExtent[0] + 1;
  dims[1] = wholeExtent[3] - wholeExtent[2] + 1;
  dims[2] = wholeExtent[5] - wholeExtent[4] + 1;

  for ( i=0; i < 6; i++ )
    {
    voi[i] = this->VOI[i];
    }

  for ( i=0; i < 3; i++ )
    {
    if ( voi[2*i+1] >= dims[i] )
      {
      voi[2*i+1] = dims[i] - 1;
      }
    else if ( voi[2*i+1] < 0 )
      {
      voi[2*i+1] = 0;
      }

    if ( voi[2*i] > voi[2*i+1] )
      {
      voi[2*i] = voi[2*i+1];
      }
    else if ( voi[2*i] < 0 )
      {
      voi[2*i] = 0;
      }

    if ( (rate[i] = this->SampleRate[i]) < 1 )
      {
      rate[i] = 1;
      }

    outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1;
    if ( outDims[i] < 1 )
      {
      outDims[i] = 1;
      }
    }

  // Adjust the output dimensions if the boundaries are to be
  // included and the sample rate is not 1.
  if ( this->IncludeBoundary &&
       (rate[0] != 1 || rate[1] != 1 || rate[2] != 1) )
    {
    int diff;
    for (i=0; i<3; i++)
      {
      if ( ((diff=voi[2*i+1]-voi[2*i]) > 0) && rate[i] != 1 &&
           ((diff % rate[i]) != 0) )
        {
        outDims[i]++;
        }
      }
    }

  // Set the whole extent of the output
  wholeExtent[0] = 0;
  wholeExtent[1] = outDims[0] - 1;
  wholeExtent[2] = 0;
  wholeExtent[3] = outDims[1] - 1;
  wholeExtent[4] = 0;
  wholeExtent[5] = outDims[2] - 1;

  output->SetWholeExtent(wholeExtent);
}

void vtkExtractGrid::Execute()
{
  vtkStructuredGrid *input= this->GetInput();
  vtkPointData *pd=input->GetPointData();
  vtkCellData *cd=input->GetCellData();
  vtkStructuredGrid *output= this->GetOutput();
  vtkPointData *outPD=output->GetPointData();
  vtkCellData *outCD=output->GetCellData();
  int i, j, k, dims[3], outDims[3], voi[6], dim;
  vtkIdType idx, newIdx, newCellId;
  int sliceSize, outSize, jOffset, kOffset, rate[3];
  vtkPoints *newPts, *inPts;
  int includeBoundary[3], diff;

  vtkDebugMacro(<< "Extracting Grid");

  inPts = input->GetPoints();
  input->GetDimensions(dims);

  // Get the volume of interest.
  // Make sure parameters are consistent.
  for ( i=0; i < 6; i++ )
    {
    voi[i] = this->VOI[i];
    }

  includeBoundary[0] = includeBoundary[1] = includeBoundary[2] = 0;
  for ( outSize=1, dim=0, i=0; i < 3; i++ )
    {
    if ( voi[2*i+1] >= dims[i] )
      {
      voi[2*i+1] = dims[i] - 1;
      }
    else if ( voi[2*i+1] < 0 )
      {
      voi[2*i+1] = 0;
      }

    if ( voi[2*i] > voi[2*i+1] )
      {
      voi[2*i] = voi[2*i+1];
      }
    else if ( voi[2*i] < 0 )
      {
      voi[2*i] = 0;
      }

    if ( (voi[2*i+1]-voi[2*i]) > 0 )
      {
      dim++;
      }

    if ( (rate[i] = this->SampleRate[i]) < 1 )
      {
      rate[i] = 1;
      }

    outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1;
    if ( outDims[i] < 1 )
      {
      outDims[i] = 1;
      }

    if ( this->IncludeBoundary && rate[i] != 1 )
      {
      if ( ((diff=voi[2*i+1]-voi[2*i]) > 0) && ((diff % rate[i]) != 0) )
        {
        outDims[i]++;
        includeBoundary[i] = 1;
        }
      }

    outSize *= outDims[i];
    }

  output->SetDimensions(outDims);

  // If output same as input, just pass data through
  //
  if ( outDims[0] == dims[0] && outDims[1] == dims[1] && outDims[2] == dims[2] &&
  rate[0] == 1 && rate[1] == 1 && rate[2] == 1 )
    {
    output->SetPoints(inPts);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    vtkDebugMacro(<<"Passed data through bacause input and output are the same");
    return;
    }

  // Allocate necessary objects
  //
  newPts = (vtkPoints *) inPts->MakeObject();
  newPts->SetNumberOfPoints(outSize);
  outPD->CopyAllocate(pd,outSize,outSize);
  outCD->CopyAllocate(cd,outSize,outSize);

  // Traverse input data and copy point attributes to output
  //
  sliceSize = dims[0]*dims[1];
  newIdx = 0;
  for ( k=voi[4]; k <= voi[5]; )
    {
    kOffset = k * sliceSize;
    for ( j=voi[2]; j <= voi[3]; )
      {
      jOffset = j * dims[0];
      for ( i=voi[0]; i <= voi[1]; )
        {
        idx = i + jOffset + kOffset;
        newPts->SetPoint(newIdx,inPts->GetPoint(idx));
        outPD->CopyData(pd, idx, newIdx++);

        i += rate[0]; //adjust for boundary
        if ( includeBoundary[0] && i > voi[1] && (i-rate[0]) != voi[1] )
          {
          i = voi[1];
          }
        }
      j += rate[1]; //adjust for boundary
      if ( includeBoundary[1] && j > voi[3] && (j-rate[1]) != voi[3] )
        {
        j = voi[3];
        }
      }
    k += rate[2]; //adjust for boundary
    if ( includeBoundary[2] && k > voi[5] && (k-rate[2]) != voi[5] )
      {
      k = voi[5];
      }
    }

  // Traverse input data and copy cell attributes to output
  //
  newCellId = 0;
  sliceSize = (dims[0]-1)*(dims[1]-1);
  for ( k=voi[4]; k < voi[5]; )
    {
    kOffset = k * sliceSize;
    for ( j=voi[2]; j < voi[3]; )
      {
      jOffset = j * (dims[0] - 1);
      for ( i=voi[0]; i < voi[1]; )
        {
        idx = i + jOffset + kOffset;
        outCD->CopyData(cd, idx, newCellId++);

        i += rate[0]; //adjust for boundary
        if ( includeBoundary[0] && i >= voi[1] && (i-rate[0]) != (voi[1]-1) )
          {
          i = voi[1] - 1;
          }
        }
      j += rate[1]; //adjust for boundary
      if ( includeBoundary[1] && j >= voi[3] && (j-rate[1]) != (voi[3]-1) )
        {
        j = voi[3] - 1;
        }
      }
    k += rate[2]; //adjust for boundary
    if ( includeBoundary[2] && k >= voi[5] && (k-rate[2]) != (voi[5]-1) )
      {
      k = voi[5] - 1;
      }
    }

  vtkDebugMacro(<<"Extracted " << newIdx << " point attributes on "
                << dim << "-D dataset\n\tDimensions are (" << outDims[0]
                << "," << outDims[1] << "," << outDims[2] <<")");

  output->SetPoints(newPts);
  newPts->Delete();
}

void vtkExtractGrid::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredGridToStructuredGridFilter::PrintSelf(os,indent);

  os << indent << "VOI: \n";
  os << indent << "  Imin,Imax: (" << this->VOI[0] << ", "
     << this->VOI[1] << ")\n";
  os << indent << "  Jmin,Jmax: (" << this->VOI[2] << ", "
     << this->VOI[3] << ")\n";
  os << indent << "  Kmin,Kmax: (" << this->VOI[4] << ", "
     << this->VOI[5] << ")\n";

  os << indent << "Sample Rate: (" << this->SampleRate[0] << ", "
               << this->SampleRate[1] << ", "
               << this->SampleRate[2] << ")\n";

  os << indent << "Include Boundary: "
     << (this->IncludeBoundary ? "On\n" : "Off\n");
}

<commit_msg>Removing the 'electric slide' of the extents.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractGrid.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkExtractGrid.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------
vtkExtractGrid* vtkExtractGrid::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkExtractGrid");
  if(ret)
    {
    return (vtkExtractGrid*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkExtractGrid;
}

// Construct object to extract all of the input data.
vtkExtractGrid::vtkExtractGrid()
{
  this->VOI[0] = this->VOI[2] = this->VOI[4] = 0;
  this->VOI[1] = this->VOI[3] = this->VOI[5] = VTK_LARGE_INTEGER;

  this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1;

  this->IncludeBoundary = 0;
}

void vtkExtractGrid::ComputeInputUpdateExtents(vtkDataObject *vtkNotUsed(out))
{
  vtkStructuredGrid *input = this->GetInput();
  vtkStructuredGrid *output = this->GetOutput();
  int i, ext[6], voi[6];
  int *inWholeExt, *outWholeExt, *updateExt;

  inWholeExt = input->GetWholeExtent();
  outWholeExt = output->GetWholeExtent();
  updateExt = output->GetUpdateExtent();

  // Once again, clip the VOI with the input whole extent.
  for (i = 0; i < 3; ++i)
    {
    voi[i*2] = this->VOI[2*i];
    if (voi[2*i] < inWholeExt[2*i])
      {
      voi[2*i] = inWholeExt[2*i];
      }
    voi[i*2+1] = this->VOI[2*i+1];
    if (voi[2*i+1] > inWholeExt[2*i+1])
      {
      voi[2*i+1] = inWholeExt[2*i+1];
      }
    }

  ext[0] = voi[0] + (updateExt[0]-outWholeExt[0])*this->SampleRate[0];
  ext[1] = voi[0] + (updateExt[1]-outWholeExt[0])*this->SampleRate[0];
  if (ext[1] > voi[1])
    { // This handles the IncludeBoundary condition.
    ext[1] = voi[1];
    }
  ext[2] = voi[2] + (updateExt[2]-outWholeExt[2])*this->SampleRate[1];
  ext[3] = voi[2] + (updateExt[3]-outWholeExt[2])*this->SampleRate[1];
  if (ext[3] > voi[3])
    { // This handles the IncludeBoundary condition.
    ext[3] = voi[3];
    }
  ext[4] = voi[4] + (updateExt[4]-outWholeExt[4])*this->SampleRate[2];
  ext[5] = voi[4] + (updateExt[5]-outWholeExt[4])*this->SampleRate[2];
  if (ext[5] > voi[5])
    { // This handles the IncludeBoundary condition.
    ext[5] = voi[5];
    }

  // I do not think we need this extra check, but it cannot hurt.
  if (ext[0] < inWholeExt[0])
    {
    ext[0] = inWholeExt[0];
    }
  if (ext[1] > inWholeExt[1])
    {
    ext[1] = inWholeExt[1];
    }

  if (ext[2] < inWholeExt[2])
    {
    ext[2] = inWholeExt[2];
    }
  if (ext[3] > inWholeExt[3])
    {
    ext[3] = inWholeExt[3];
    }

  if (ext[4] < inWholeExt[4])
    {
    ext[4] = inWholeExt[4];
    }
  if (ext[5] > inWholeExt[5])
    {
    ext[5] = inWholeExt[5];
    }

  input->SetUpdateExtent(ext);

}

void vtkExtractGrid::ExecuteInformation()
{
  vtkStructuredGrid *input= this->GetInput();
  vtkStructuredGrid *output= this->GetOutput();
  int i, dims[3], outDims[3], voi[6], wholeExtent[6];
  int mins[3];
  int rate[3];

  if (this->GetInput() == NULL)
    {
    vtkErrorMacro("Missing input");
    return;
    }

  this->vtkStructuredGridToStructuredGridFilter::ExecuteInformation();

  input->GetWholeExtent(wholeExtent);
  dims[0] = wholeExtent[1] - wholeExtent[0] + 1;
  dims[1] = wholeExtent[3] - wholeExtent[2] + 1;
  dims[2] = wholeExtent[5] - wholeExtent[4] + 1;

  for ( i=0; i < 6; i++ )
    {
    voi[i] = this->VOI[i];
    }

  for ( i=0; i < 3; i++ )
    {
    // Empty request.
    if (voi[2*i+1] < voi[2*i] || voi[2*i+1] < wholeExtent[2*i] ||
        voi[2*i] > wholeExtent[2*i+1])
      {
      output->SetWholeExtent(0,-1,0,-1,0,-1);
      return;
      }

    // Make sure VOI is in the whole extent.
    if ( voi[2*i+1] > wholeExtent[2*i+1] )
      {
      voi[2*i+1] = wholeExtent[2*i+1];
      }
    else if ( voi[2*i+1] < wholeExtent[2*i] )
      {
      voi[2*i+1] = wholeExtent[2*i];
      }
    if ( voi[2*i] > wholeExtent[2*i+1] )
      {
      voi[2*i] = wholeExtent[2*i+1];
      }
    else if ( voi[2*i] < wholeExtent[2*i] )
      {
      voi[2*i] = wholeExtent[2*i];
      }

    if ( (rate[i] = this->SampleRate[i]) < 1 )
      {
      rate[i] = 1;
      }

    outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1;
    if ( outDims[i] < 1 )
      {
      outDims[i] = 1;
      }
    mins[i] = voi[2*i] / rate[i];
    }

  // Adjust the output dimensions if the boundaries are to be
  // included and the sample rate is not 1.
  if ( this->IncludeBoundary &&
       (rate[0] != 1 || rate[1] != 1 || rate[2] != 1) )
    {
    int diff;
    for (i=0; i<3; i++)
      {
      if ( ((diff=voi[2*i+1]-voi[2*i]) > 0) && rate[i] != 1 &&
           ((diff % rate[i]) != 0) )
        {
        outDims[i]++;
        }
      }
    }

  // Set the whole extent of the output
  wholeExtent[0] = mins[0];
  wholeExtent[1] = mins[0] + outDims[0] - 1;
  wholeExtent[2] = mins[1];
  wholeExtent[3] = mins[1] + outDims[1] - 1;
  wholeExtent[4] = mins[2];
  wholeExtent[5] = mins[2] + outDims[2] - 1;

  output->SetWholeExtent(wholeExtent);
}

void vtkExtractGrid::Execute()
{
  vtkStructuredGrid *input= this->GetInput();
  vtkPointData *pd=input->GetPointData();
  vtkCellData *cd=input->GetCellData();
  vtkStructuredGrid *output= this->GetOutput();
  vtkPointData *outPD=output->GetPointData();
  vtkCellData *outCD=output->GetCellData();
  int i, j, k, dims[3], *uExt, voi[6];
  int *inExt;
  int iIn, jIn, kIn;
  int outSize, jOffset, kOffset, *rate;
  vtkIdType idx, newIdx, newCellId;
  vtkPoints *newPts, *inPts;
  int inInc1, inInc2;

  vtkDebugMacro(<< "Extracting Grid");

  inPts = input->GetPoints();

  uExt = output->GetUpdateExtent();
  dims[0] = uExt[1]-uExt[0]+1;
  dims[1] = uExt[3]-uExt[2]+1;
  dims[2] = uExt[5]-uExt[4]+1;
  rate = this->SampleRate;
  inExt = input->GetExtent();
  inInc1 = (inExt[1]-inExt[0]+1);
  inInc2 = inInc1*(inExt[3]-inExt[2]+1);

  // Clip the VOI by thge input extent
  for (i = 0; i < 3; ++i)
    {
    voi[i*2] = this->VOI[2*i];
    if (voi[2*i] < inExt[2*i])
      {
      voi[2*i] = inExt[2*i];
      }
    voi[i*2+1] = this->VOI[2*i+1];
    if (voi[2*i+1] > inExt[2*i+1])
      {
      voi[2*i+1] = inExt[2*i+1];
      }
    }

  output->SetExtent(uExt);

  // If output same as input, just pass data through
  if ( voi[0] <= inExt[0] && voi[1] >= inExt[1] &&
       voi[2] <= inExt[2] && voi[3] >= inExt[3] &&
       voi[4] <= inExt[4] && voi[5] >= inExt[5] &&
       rate[0] == 1 && rate[1] == 1 && rate[2] == 1)
    {
    output->SetPoints(inPts);
    output->GetPointData()->PassData(input->GetPointData());
    output->GetCellData()->PassData(input->GetCellData());
    vtkDebugMacro(<<"Passed data through bacause input and output are the same");
    return;
    }

  // Allocate necessary objects
  //
  outSize = (uExt[1]-uExt[0]+1)*(uExt[3]-uExt[2]+1)*(uExt[5]-uExt[4]+1);
  newPts = (vtkPoints *) inPts->MakeObject();
  newPts->SetNumberOfPoints(outSize);
  outPD->CopyAllocate(pd,outSize,outSize);
  outCD->CopyAllocate(cd,outSize,outSize);

  // Traverse input data and copy point attributes to output
  // iIn,jIn,kIn are in input grid coordinates.
  newIdx = 0;
  for ( k=uExt[4]; k <= uExt[5]; ++k)
    {
    kIn = k*rate[2];
    if (kIn > voi[5])
      { // This handles the IncludeBoundaryOn condition.
      kIn = voi[5];
      }
    kOffset = (kIn-inExt[4]) * inInc2;
    for ( j=uExt[2]; j <= uExt[3]; ++j)
      {
      jIn = j*rate[1];
      if (jIn > voi[3])
        { // This handles the IncludeBoundaryOn condition.
        jIn = voi[3];
        }
      jOffset = (jIn-inExt[2]) * inInc1;
      for ( i=uExt[0]; i <= uExt[1]; ++i)
        {
        iIn = i*rate[0];
        if (iIn > voi[1])
          { // This handles the IncludeBoundaryOn condition.
          iIn = voi[1];
          }
        idx = (iIn-inExt[0]) + jOffset + kOffset;
        newPts->SetPoint(newIdx,inPts->GetPoint(idx));
        outPD->CopyData(pd, idx, newIdx++);

        }
      }
    }

  // Traverse input data and copy cell attributes to output
  //
  newCellId = 0;
  inInc1 = (inExt[1]-inExt[0]);
  inInc2 = inInc1*(inExt[3]-inExt[2]);
  // No need to consider IncludeBoundary for cell data.
  for ( k=uExt[4]; k < uExt[5]; ++k )
    {
    kIn = k*rate[2];
    kOffset = (kIn-inExt[4]) * inInc2;
    for ( j=uExt[2]; j < uExt[3]; ++j )
      {
      jIn = j*rate[1];
      jOffset = (jIn-inExt[2]) * inInc1;
      for ( i=uExt[0]; i < uExt[1]; ++i )
        {
        iIn = voi[0] + i*rate[0];
        idx = (iIn-inExt[0]) + jOffset + kOffset;
        outCD->CopyData(cd, idx, newCellId++);
        }
      }
    }

  output->SetPoints(newPts);
  newPts->Delete();
}

void vtkExtractGrid::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredGridToStructuredGridFilter::PrintSelf(os,indent);

  os << indent << "VOI: \n";
  os << indent << "  Imin,Imax: (" << this->VOI[0] << ", "
     << this->VOI[1] << ")\n";
  os << indent << "  Jmin,Jmax: (" << this->VOI[2] << ", "
     << this->VOI[3] << ")\n";
  os << indent << "  Kmin,Kmax: (" << this->VOI[4] << ", "
     << this->VOI[5] << ")\n";

  os << indent << "Sample Rate: (" << this->SampleRate[0] << ", "
               << this->SampleRate[1] << ", "
               << this->SampleRate[2] << ")\n";

  os << indent << "Include Boundary: "
     << (this->IncludeBoundary ? "On\n" : "Off\n");
}

<|endoftext|>


<commit_before>//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Tri-valued logic

#ifndef WHEELS_TRIBOOL_HPP
#define WHEELS_TRIBOOL_HPP

#include <boost/logic/tribool.hpp>

namespace wheels {
    using boost::indeterminate;

    struct tribool;
    constexpr bool is_true(tribool t);
    constexpr bool is_false(tribool t);
    constexpr bool is_indeterminate(tribool t);

    struct tribool {
    public:
        constexpr tribool() : tribool(false_value) {}
        constexpr tribool(bool value) : value(value? true_value : false_value) {}
        constexpr tribool(decltype(boost::indeterminate)) : value(indeterminate_value) {}
        /*constexpr*/ tribool(boost::tribool t) : value(t? true_value : !t? false_value : indeterminate_value) {}

        constexpr tribool operator!() const {
            return is_indeterminate(*this)? *this : !value;
        }

        constexpr tribool operator==(tribool that) const {
            return is_indeterminate(*this) || is_indeterminate(that)
                    ? indeterminate
                    : tribool(value == that.value);
        }
        constexpr tribool operator!=(tribool that) const {
            return is_indeterminate(*this) || is_indeterminate(that)
                    ? indeterminate
                    : tribool(value != that.value);
        }

        /*constexpr*/ operator boost::tribool() const {
            return is_indeterminate(*this)
                    ? boost::indeterminate
                    : tribool(value == true_value);
        }

        constexpr tribool operator&&(tribool that) const {
            return is_false(*this) || is_false(that)
                    ? false
                    : is_indeterminate(*this) || is_indeterminate(that)
                        ? indeterminate
                        : tribool(true);
        }

        constexpr tribool operator||(tribool that) const {
            return is_true(*this) || is_true(that)
                    ? true
                    : is_indeterminate(*this) || is_indeterminate(that)
                        ? indeterminate
                        : tribool(false);
        }

    private:
        enum { false_value, true_value, indeterminate_value } value;

        friend constexpr bool is_true(tribool t) { return t.value == true_value; }
        friend constexpr bool is_false(tribool t) { return t.value == false_value; }
        friend constexpr bool is_indeterminate(tribool t) { return t.value == indeterminate_value; }
    };

} // namespace wheels

#endif // WHEELS_TRIBOOL_HPP
<commit_msg>Fix stack overflow on tribool::op boost<commit_after>//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Tri-valued logic

#ifndef WHEELS_TRIBOOL_HPP
#define WHEELS_TRIBOOL_HPP

#include <boost/logic/tribool.hpp>

namespace wheels {
    using boost::indeterminate;

    struct tribool;
    constexpr bool is_true(tribool t);
    constexpr bool is_false(tribool t);
    constexpr bool is_indeterminate(tribool t);

    struct tribool {
    public:
        constexpr tribool() : tribool(false_value) {}
        constexpr tribool(bool value) : value(value? true_value : false_value) {}
        constexpr tribool(decltype(boost::indeterminate)) : value(indeterminate_value) {}
        /*constexpr*/ tribool(boost::tribool t) : value(t? true_value : !t? false_value : indeterminate_value) {}

        constexpr tribool operator!() const {
            return is_indeterminate(*this)? *this : !value;
        }

        constexpr tribool operator==(tribool that) const {
            return is_indeterminate(*this) || is_indeterminate(that)
                    ? indeterminate
                    : tribool(value == that.value);
        }
        constexpr tribool operator!=(tribool that) const {
            return is_indeterminate(*this) || is_indeterminate(that)
                    ? indeterminate
                    : tribool(value != that.value);
        }

        /*constexpr*/ operator boost::tribool() const {
            return is_indeterminate(*this)
                    ? boost::indeterminate
                    : boost::tribool(value == true_value);
        }

        constexpr tribool operator&&(tribool that) const {
            return is_false(*this) || is_false(that)
                    ? false
                    : is_indeterminate(*this) || is_indeterminate(that)
                        ? indeterminate
                        : tribool(true);
        }

        constexpr tribool operator||(tribool that) const {
            return is_true(*this) || is_true(that)
                    ? true
                    : is_indeterminate(*this) || is_indeterminate(that)
                        ? indeterminate
                        : tribool(false);
        }

    private:
        enum { false_value, true_value, indeterminate_value } value;

        friend constexpr bool is_true(tribool t) { return t.value == true_value; }
        friend constexpr bool is_false(tribool t) { return t.value == false_value; }
        friend constexpr bool is_indeterminate(tribool t) { return t.value == indeterminate_value; }
    };

} // namespace wheels

#endif // WHEELS_TRIBOOL_HPP
<|endoftext|>


<commit_before>#include "window.hh"

#include "assert.hh"
#include "highlighter_registry.hh"
#include "hooks_manager.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

BufferIterator Selection::begin() const
{
    return std::min(m_first, m_last);
}

BufferIterator Selection::end() const
{
    return std::max(m_first, m_last) + 1;
}

void Selection::merge_with(const Selection& selection)
{
    if (m_first <= m_last)
        m_first = std::min(m_first, selection.m_first);
    else
        m_first = std::max(m_first, selection.m_first);
    m_last = selection.m_last;
}

BufferString Selection::capture(size_t index) const
{
    if (index < m_captures.size())
        return m_captures[index];
    return "";
}

struct scoped_undo_group
{
    scoped_undo_group(Buffer& buffer)
        : m_buffer(buffer) { m_buffer.begin_undo_group(); }

    ~scoped_undo_group()   { m_buffer.end_undo_group(); }
private:
    Buffer& m_buffer;
};

Window::Window(Buffer& buffer)
    : m_buffer(buffer),
      m_position(0, 0),
      m_dimensions(0, 0),
      m_current_inserter(nullptr)
{
    m_selections.push_back(Selection(buffer.begin(), buffer.begin()));

    HighlighterRegistry& registry = HighlighterRegistry::instance();

    HooksManager::instance().run_hook("WinCreate", buffer.name(),
                                      Context(*this));

    registry.add_highlighter_to_window(*this, "expand_tabs", HighlighterParameters());
    registry.add_highlighter_to_window(*this, "highlight_selections", HighlighterParameters());
}

void Window::check_invariant() const
{
    assert(not m_selections.empty());
}

DisplayCoord Window::cursor_position() const
{
    check_invariant();
    return line_and_column_at(cursor_iterator());
}

BufferIterator Window::cursor_iterator() const
{
    check_invariant();
    return m_selections.back().last();
}

void Window::erase()
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        erase_noundo();
    }
    else
        erase_noundo();
}

void Window::erase_noundo()
{
    check_invariant();
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
    scroll_to_keep_cursor_visible_ifn();
}

template<typename Iterator>
static DisplayCoord measure_string(Iterator begin, Iterator end)
{
    DisplayCoord result(0, 0);
    while (begin != end)
    {
        if (*begin == '\n')
        {
            ++result.line;
            result.column = 0;
        }
        else
            ++result.column;
        ++begin;
    }
    return result;
}

static DisplayCoord measure_string(const Window::String& string)
{
    return measure_string(string.begin(), string.end());
}

void Window::insert(const String& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        insert_noundo(string);
    }
    else
        insert_noundo(string);
}

void Window::insert_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.begin(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::append(const String& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        append_noundo(string);
    }
    else
        append_noundo(string);
}

void Window::append_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.end(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::replace(const std::string& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        erase_noundo();
        insert_noundo(string);
    }
    else
    {
        erase_noundo();
        insert_noundo(string);
    }
}

bool Window::undo()
{
    return m_buffer.undo();
}

bool Window::redo()
{
    return m_buffer.redo();
}

BufferIterator Window::iterator_at(const DisplayCoord& window_pos) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return m_buffer.begin();

    if (DisplayCoord(0,0) <= window_pos)
    {
        for (auto atom_it = m_display_buffer.begin();
             atom_it != m_display_buffer.end(); ++atom_it)
        {
            if (window_pos < atom_it->coord())
            {
                return (--atom_it)->iterator_at(window_pos);
            }
        }
    }

    return m_buffer.iterator_at(m_position + BufferCoord(window_pos));
}

DisplayCoord Window::line_and_column_at(const BufferIterator& iterator) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return DisplayCoord(0, 0);

    if (iterator >= m_display_buffer.front().begin() and
        iterator <  m_display_buffer.back().end())
    {
        for (auto& atom : m_display_buffer)
        {
            if (atom.end() > iterator)
            {
                assert(atom.begin() <= iterator);
                return atom.line_and_column_at(iterator);
            }
        }
    }
    BufferCoord coord = m_buffer.line_and_column_at(iterator);
    return DisplayCoord(coord.line - m_position.line,
                        coord.column - m_position.column);
}

void Window::clear_selections()
{
    check_invariant();
    BufferIterator pos = m_selections.back().last();

    if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
        --pos;

    Selection sel = Selection(pos, pos);
    m_selections.clear();
    m_selections.push_back(std::move(sel));
}

void Window::select(const Selector& selector, bool append)
{
    check_invariant();

    if (not append)
    {
        Selection sel = selector(m_selections.back().last());
        m_selections.clear();
        m_selections.push_back(std::move(sel));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            sel.merge_with(selector(sel.last()));
        }
    }
    scroll_to_keep_cursor_visible_ifn();
}

struct nothing_selected : public runtime_error
{
    nothing_selected() : runtime_error("nothing was selected") {}
};

void Window::multi_select(const MultiSelector& selector)
{
    check_invariant();

    SelectionList new_selections;
    for (auto& sel : m_selections)
    {
        SelectionList selections = selector(sel);
        std::copy(selections.begin(), selections.end(),
                  std::back_inserter(new_selections));
    }
    if (new_selections.empty())
        throw nothing_selected();

    m_selections = std::move(new_selections);
    scroll_to_keep_cursor_visible_ifn();
}

BufferString Window::selection_content() const
{
    check_invariant();

    return m_buffer.string(m_selections.back().begin(),
                           m_selections.back().end());
}

void Window::move_cursor(const DisplayCoord& offset, bool append)
{
    if (not append)
    {
        BufferCoord pos = m_buffer.line_and_column_at(cursor_iterator());
        move_cursor_to(m_buffer.iterator_at(pos + BufferCoord(offset)));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            BufferCoord pos = m_buffer.line_and_column_at(sel.last());
            sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset)));
        }
        scroll_to_keep_cursor_visible_ifn();
    }
}

void Window::move_cursor_to(const BufferIterator& iterator)
{
    m_selections.clear();
    m_selections.push_back(Selection(iterator, iterator));

    scroll_to_keep_cursor_visible_ifn();
}

void Window::update_display_buffer()
{
    m_display_buffer.clear();

    BufferIterator begin = m_buffer.iterator_at(m_position);
    BufferIterator end = m_buffer.iterator_at(m_position +
                                              BufferCoord(m_dimensions.line, m_dimensions.column))+1;
    if (begin == end)
        return;

    m_display_buffer.append(DisplayAtom(DisplayCoord(0,0), begin, end));

    for (auto& highlighter : m_highlighters)
    {
        highlighter.second(m_display_buffer);
        m_display_buffer.check_invariant();
    }
}

void Window::set_dimensions(const DisplayCoord& dimensions)
{
    m_dimensions = dimensions;
}

void Window::scroll_to_keep_cursor_visible_ifn()
{
    check_invariant();

    DisplayCoord cursor = line_and_column_at(m_selections.back().last());
    if (cursor.line < 0)
    {
        m_position.line = std::max(m_position.line + cursor.line, 0);
    }
    else if (cursor.line >= m_dimensions.line)
    {
        m_position.line += cursor.line - (m_dimensions.line - 1);
    }

    if (cursor.column < 0)
    {
        m_position.column = std::max(m_position.column + cursor.column, 0);
    }
    else if (cursor.column >= m_dimensions.column)
    {
        m_position.column += cursor.column - (m_dimensions.column - 1);
    }
}

std::string Window::status_line() const
{
    BufferCoord cursor = m_buffer.line_and_column_at(m_selections.back().last());
    std::ostringstream oss;
    oss << m_buffer.name();
    if (m_buffer.is_modified())
        oss << " [+]";
    oss << " -- " << cursor.line+1 << "," << cursor.column+1
        << " -- " << m_selections.size() << " sel -- ";
    if (m_current_inserter)
        oss << "[Insert]";
    return oss.str();
}

void Window::add_highlighter(HighlighterAndId&& highlighter)
{
    if (m_highlighters.contains(highlighter.first))
        throw id_not_unique(highlighter.first);
    m_highlighters.append(std::forward<HighlighterAndId>(highlighter));
}

void Window::remove_highlighter(const std::string& id)
{
    m_highlighters.remove(id);
}

CandidateList Window::complete_highlighterid(const std::string& prefix,
                                             size_t cursor_pos)
{
    return m_highlighters.complete_id<str_to_str>(prefix, cursor_pos);
}

void Window::add_filter(FilterAndId&& filter)
{
    if (m_filters.contains(filter.first))
        throw id_not_unique(filter.first);
    m_filters.append(std::forward<FilterAndId>(filter));
}

void Window::remove_filter(const std::string& id)
{
    m_filters.remove(id);
}

CandidateList Window::complete_filterid(const std::string& prefix,
                                        size_t cursor_pos)
{
    return m_filters.complete_id<str_to_str>(prefix, cursor_pos);
}

IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
    : m_window(window)
{
    assert(not m_window.m_current_inserter);
    m_window.m_current_inserter = this;
    m_window.check_invariant();

    m_window.m_buffer.begin_undo_group();

    if (mode == Mode::Change)
        window.erase_noundo();

    for (auto& sel : m_window.m_selections)
    {
        DynamicBufferIterator pos;
        switch (mode)
        {
        case Mode::Insert: pos = sel.begin(); break;
        case Mode::Append: pos = sel.end(); break;
        case Mode::Change: pos = sel.begin(); break;

        case Mode::OpenLineBelow:
        case Mode::AppendAtLineEnd:
            pos = m_window.m_buffer.iterator_at_line_end(sel.end() - 1) - 1;
            if (mode == Mode::OpenLineBelow)
                apply(Modification::make_insert(pos, "\n"));
            break;

        case Mode::OpenLineAbove:
        case Mode::InsertAtLineBegin:
            pos = m_window.m_buffer.iterator_at_line_begin(sel.begin());
            if (mode == Mode::OpenLineAbove)
                apply(Modification::make_insert(--pos, "\n"));
            break;
        }
        sel = Selection(pos, pos, sel.captures());
    }
}

IncrementalInserter::~IncrementalInserter()
{
    HooksManager::instance().run_hook("WinInsertEnd", "", Context(m_window));

    move_cursor(DisplayCoord(0, -1));
    assert(m_window.m_current_inserter == this);
    m_window.m_current_inserter = nullptr;

    m_window.m_buffer.end_undo_group();
}

void IncrementalInserter::apply(Modification&& modification) const
{
    for (auto filter : m_window.m_filters)
        filter.second(m_window.buffer(), modification);
    m_window.buffer().modify(std::move(modification));
}

void IncrementalInserter::insert(const Window::String& string)
{
    for (auto& sel : m_window.m_selections)
        apply(Modification::make_insert(sel.begin(), string));
}

void IncrementalInserter::insert_capture(size_t index)
{
    for (auto& sel : m_window.m_selections)
        m_window.m_buffer.modify(Modification::make_insert(sel.begin(),
                                                           sel.capture(index)));
    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::erase()
{
    for (auto& sel : m_window.m_selections)
    {
        sel = Selection(sel.first() - 1, sel.last() - 1);
        apply(Modification::make_erase(sel.begin(), sel.end()));
    }

    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::move_cursor(const DisplayCoord& offset)
{
    for (auto& sel : m_window.m_selections)
    {
        DisplayCoord pos = m_window.line_and_column_at(sel.last());
        BufferIterator it = m_window.iterator_at(pos + offset);
        sel = Selection(it, it);
    }
}

}
<commit_msg>IncrementalInserter: catch exception thrown by the hook<commit_after>#include "window.hh"

#include "assert.hh"
#include "highlighter_registry.hh"
#include "hooks_manager.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

BufferIterator Selection::begin() const
{
    return std::min(m_first, m_last);
}

BufferIterator Selection::end() const
{
    return std::max(m_first, m_last) + 1;
}

void Selection::merge_with(const Selection& selection)
{
    if (m_first <= m_last)
        m_first = std::min(m_first, selection.m_first);
    else
        m_first = std::max(m_first, selection.m_first);
    m_last = selection.m_last;
}

BufferString Selection::capture(size_t index) const
{
    if (index < m_captures.size())
        return m_captures[index];
    return "";
}

struct scoped_undo_group
{
    scoped_undo_group(Buffer& buffer)
        : m_buffer(buffer) { m_buffer.begin_undo_group(); }

    ~scoped_undo_group()   { m_buffer.end_undo_group(); }
private:
    Buffer& m_buffer;
};

Window::Window(Buffer& buffer)
    : m_buffer(buffer),
      m_position(0, 0),
      m_dimensions(0, 0),
      m_current_inserter(nullptr)
{
    m_selections.push_back(Selection(buffer.begin(), buffer.begin()));

    HighlighterRegistry& registry = HighlighterRegistry::instance();

    HooksManager::instance().run_hook("WinCreate", buffer.name(),
                                      Context(*this));

    registry.add_highlighter_to_window(*this, "expand_tabs", HighlighterParameters());
    registry.add_highlighter_to_window(*this, "highlight_selections", HighlighterParameters());
}

void Window::check_invariant() const
{
    assert(not m_selections.empty());
}

DisplayCoord Window::cursor_position() const
{
    check_invariant();
    return line_and_column_at(cursor_iterator());
}

BufferIterator Window::cursor_iterator() const
{
    check_invariant();
    return m_selections.back().last();
}

void Window::erase()
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        erase_noundo();
    }
    else
        erase_noundo();
}

void Window::erase_noundo()
{
    check_invariant();
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
    scroll_to_keep_cursor_visible_ifn();
}

template<typename Iterator>
static DisplayCoord measure_string(Iterator begin, Iterator end)
{
    DisplayCoord result(0, 0);
    while (begin != end)
    {
        if (*begin == '\n')
        {
            ++result.line;
            result.column = 0;
        }
        else
            ++result.column;
        ++begin;
    }
    return result;
}

static DisplayCoord measure_string(const Window::String& string)
{
    return measure_string(string.begin(), string.end());
}

void Window::insert(const String& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        insert_noundo(string);
    }
    else
        insert_noundo(string);
}

void Window::insert_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.begin(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::append(const String& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        append_noundo(string);
    }
    else
        append_noundo(string);
}

void Window::append_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.end(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::replace(const std::string& string)
{
    if (m_current_inserter == nullptr)
    {
        scoped_undo_group undo_group(m_buffer);
        erase_noundo();
        insert_noundo(string);
    }
    else
    {
        erase_noundo();
        insert_noundo(string);
    }
}

bool Window::undo()
{
    return m_buffer.undo();
}

bool Window::redo()
{
    return m_buffer.redo();
}

BufferIterator Window::iterator_at(const DisplayCoord& window_pos) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return m_buffer.begin();

    if (DisplayCoord(0,0) <= window_pos)
    {
        for (auto atom_it = m_display_buffer.begin();
             atom_it != m_display_buffer.end(); ++atom_it)
        {
            if (window_pos < atom_it->coord())
            {
                return (--atom_it)->iterator_at(window_pos);
            }
        }
    }

    return m_buffer.iterator_at(m_position + BufferCoord(window_pos));
}

DisplayCoord Window::line_and_column_at(const BufferIterator& iterator) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return DisplayCoord(0, 0);

    if (iterator >= m_display_buffer.front().begin() and
        iterator <  m_display_buffer.back().end())
    {
        for (auto& atom : m_display_buffer)
        {
            if (atom.end() > iterator)
            {
                assert(atom.begin() <= iterator);
                return atom.line_and_column_at(iterator);
            }
        }
    }
    BufferCoord coord = m_buffer.line_and_column_at(iterator);
    return DisplayCoord(coord.line - m_position.line,
                        coord.column - m_position.column);
}

void Window::clear_selections()
{
    check_invariant();
    BufferIterator pos = m_selections.back().last();

    if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
        --pos;

    Selection sel = Selection(pos, pos);
    m_selections.clear();
    m_selections.push_back(std::move(sel));
}

void Window::select(const Selector& selector, bool append)
{
    check_invariant();

    if (not append)
    {
        Selection sel = selector(m_selections.back().last());
        m_selections.clear();
        m_selections.push_back(std::move(sel));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            sel.merge_with(selector(sel.last()));
        }
    }
    scroll_to_keep_cursor_visible_ifn();
}

struct nothing_selected : public runtime_error
{
    nothing_selected() : runtime_error("nothing was selected") {}
};

void Window::multi_select(const MultiSelector& selector)
{
    check_invariant();

    SelectionList new_selections;
    for (auto& sel : m_selections)
    {
        SelectionList selections = selector(sel);
        std::copy(selections.begin(), selections.end(),
                  std::back_inserter(new_selections));
    }
    if (new_selections.empty())
        throw nothing_selected();

    m_selections = std::move(new_selections);
    scroll_to_keep_cursor_visible_ifn();
}

BufferString Window::selection_content() const
{
    check_invariant();

    return m_buffer.string(m_selections.back().begin(),
                           m_selections.back().end());
}

void Window::move_cursor(const DisplayCoord& offset, bool append)
{
    if (not append)
    {
        BufferCoord pos = m_buffer.line_and_column_at(cursor_iterator());
        move_cursor_to(m_buffer.iterator_at(pos + BufferCoord(offset)));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            BufferCoord pos = m_buffer.line_and_column_at(sel.last());
            sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset)));
        }
        scroll_to_keep_cursor_visible_ifn();
    }
}

void Window::move_cursor_to(const BufferIterator& iterator)
{
    m_selections.clear();
    m_selections.push_back(Selection(iterator, iterator));

    scroll_to_keep_cursor_visible_ifn();
}

void Window::update_display_buffer()
{
    m_display_buffer.clear();

    BufferIterator begin = m_buffer.iterator_at(m_position);
    BufferIterator end = m_buffer.iterator_at(m_position +
                                              BufferCoord(m_dimensions.line, m_dimensions.column))+1;
    if (begin == end)
        return;

    m_display_buffer.append(DisplayAtom(DisplayCoord(0,0), begin, end));

    for (auto& highlighter : m_highlighters)
    {
        highlighter.second(m_display_buffer);
        m_display_buffer.check_invariant();
    }
}

void Window::set_dimensions(const DisplayCoord& dimensions)
{
    m_dimensions = dimensions;
}

void Window::scroll_to_keep_cursor_visible_ifn()
{
    check_invariant();

    DisplayCoord cursor = line_and_column_at(m_selections.back().last());
    if (cursor.line < 0)
    {
        m_position.line = std::max(m_position.line + cursor.line, 0);
    }
    else if (cursor.line >= m_dimensions.line)
    {
        m_position.line += cursor.line - (m_dimensions.line - 1);
    }

    if (cursor.column < 0)
    {
        m_position.column = std::max(m_position.column + cursor.column, 0);
    }
    else if (cursor.column >= m_dimensions.column)
    {
        m_position.column += cursor.column - (m_dimensions.column - 1);
    }
}

std::string Window::status_line() const
{
    BufferCoord cursor = m_buffer.line_and_column_at(m_selections.back().last());
    std::ostringstream oss;
    oss << m_buffer.name();
    if (m_buffer.is_modified())
        oss << " [+]";
    oss << " -- " << cursor.line+1 << "," << cursor.column+1
        << " -- " << m_selections.size() << " sel -- ";
    if (m_current_inserter)
        oss << "[Insert]";
    return oss.str();
}

void Window::add_highlighter(HighlighterAndId&& highlighter)
{
    if (m_highlighters.contains(highlighter.first))
        throw id_not_unique(highlighter.first);
    m_highlighters.append(std::forward<HighlighterAndId>(highlighter));
}

void Window::remove_highlighter(const std::string& id)
{
    m_highlighters.remove(id);
}

CandidateList Window::complete_highlighterid(const std::string& prefix,
                                             size_t cursor_pos)
{
    return m_highlighters.complete_id<str_to_str>(prefix, cursor_pos);
}

void Window::add_filter(FilterAndId&& filter)
{
    if (m_filters.contains(filter.first))
        throw id_not_unique(filter.first);
    m_filters.append(std::forward<FilterAndId>(filter));
}

void Window::remove_filter(const std::string& id)
{
    m_filters.remove(id);
}

CandidateList Window::complete_filterid(const std::string& prefix,
                                        size_t cursor_pos)
{
    return m_filters.complete_id<str_to_str>(prefix, cursor_pos);
}

IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
    : m_window(window)
{
    assert(not m_window.m_current_inserter);
    m_window.m_current_inserter = this;
    m_window.check_invariant();

    m_window.m_buffer.begin_undo_group();

    if (mode == Mode::Change)
        window.erase_noundo();

    for (auto& sel : m_window.m_selections)
    {
        DynamicBufferIterator pos;
        switch (mode)
        {
        case Mode::Insert: pos = sel.begin(); break;
        case Mode::Append: pos = sel.end(); break;
        case Mode::Change: pos = sel.begin(); break;

        case Mode::OpenLineBelow:
        case Mode::AppendAtLineEnd:
            pos = m_window.m_buffer.iterator_at_line_end(sel.end() - 1) - 1;
            if (mode == Mode::OpenLineBelow)
                apply(Modification::make_insert(pos, "\n"));
            break;

        case Mode::OpenLineAbove:
        case Mode::InsertAtLineBegin:
            pos = m_window.m_buffer.iterator_at_line_begin(sel.begin());
            if (mode == Mode::OpenLineAbove)
                apply(Modification::make_insert(--pos, "\n"));
            break;
        }
        sel = Selection(pos, pos, sel.captures());
    }
}

IncrementalInserter::~IncrementalInserter()
{
    move_cursor(DisplayCoord(0, -1));

    try
    {
        HooksManager::instance().run_hook("WinInsertEnd", "", Context(m_window));
    }
    catch (runtime_error& e) {}

    assert(m_window.m_current_inserter == this);
    m_window.m_current_inserter = nullptr;
    m_window.m_buffer.end_undo_group();
}

void IncrementalInserter::apply(Modification&& modification) const
{
    for (auto filter : m_window.m_filters)
        filter.second(m_window.buffer(), modification);
    m_window.buffer().modify(std::move(modification));
}

void IncrementalInserter::insert(const Window::String& string)
{
    for (auto& sel : m_window.m_selections)
        apply(Modification::make_insert(sel.begin(), string));
}

void IncrementalInserter::insert_capture(size_t index)
{
    for (auto& sel : m_window.m_selections)
        m_window.m_buffer.modify(Modification::make_insert(sel.begin(),
                                                           sel.capture(index)));
    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::erase()
{
    for (auto& sel : m_window.m_selections)
    {
        sel = Selection(sel.first() - 1, sel.last() - 1);
        apply(Modification::make_erase(sel.begin(), sel.end()));
    }

    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::move_cursor(const DisplayCoord& offset)
{
    for (auto& sel : m_window.m_selections)
    {
        DisplayCoord pos = m_window.line_and_column_at(sel.last());
        BufferIterator it = m_window.iterator_at(pos + offset);
        sel = Selection(it, it);
    }
}

}
<|endoftext|>


<commit_before>inline
grass_points::grass_points( const std::string in_path,
			    const std::string in_actionNames,
			    const int in_scale_factor,
			    const int in_shift,
			    const int in_scene, //only for kth
			    const int in_segment_length,
			    const int in_p
)
:path(in_path), actionNames(in_actionNames), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), p(in_p)
{
  actions.load( actionNames );
}

// One Grassmann Point per Video

inline
void
grass_points::calculate_onepervideo( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,3);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;

      load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = ss1.str();
      parallel_names(k,2) = ss2.str();
      k++;

    }
  }

  omp_set_num_threads(8); //Use only 8 processors

  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);

    int pe   = atoi( parallel_names(k,1).c_str() );
    int act  = atoi( parallel_names(k,2).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video_one_point(load_feat_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video_one_point( std::string load_feat_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-one-dim" << dim << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  mat U; vec s;   mat V;
  svd(U,s,V,mat_features_video_i);
  mat Gnp = U.cols(0,p-1);

  std::stringstream save_Gnp;
  //cout << save_folder.str() << endl;
  save_Gnp << save_folder.str() << "/grass_pt_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
  //cout << save_Gnp.str() << endl;

  #pragma omp critical
  Gnp.save( save_Gnp.str(), hdf5_binary );

}

// Several Grasmann Poits per Video
inline
void
grass_points::calculate( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,4);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;
      std::stringstream load_labels_video_i;

      load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      load_labels_video_i << load_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = load_labels_video_i.str();
      parallel_names(k,2) = ss1.str();
      parallel_names(k,3) = ss2.str();
      k++;

    }
  }

  //Aca podria hacer el paparelo

  omp_set_num_threads(4); //Use only 8 processors
  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);
    std::string load_labels_video_i = parallel_names(k,1);

    int pe   = atoi( parallel_names(k,2).c_str() );
    int act  = atoi( parallel_names(k,3).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video(load_feat_video_i, load_labels_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video( std::string load_feat_video_i,	std::string load_labels_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;
  vec lab_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );
  lab_video_i.load( load_labels_video_i, hdf5_binary );
  int n_vec = lab_video_i.n_elem;
  int last = lab_video_i( n_vec - 1 );
  //cout << last << endl;

  int seg = 0;

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-dim"<< dim << "-L" << segment_length << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  for (int l=2; l<last-segment_length; l = l+4 )
  {
    std::vector<vec> feat_seg;

    for (int j=l; j< l + segment_length; ++j)
    {
      //k++;
      //cout << " " << j;
      uvec indices = find(lab_video_i == j);
      mat feat_fr = mat_features_video_i.cols(indices);

      for (int v=0; v < feat_fr.n_cols; ++v)
      {
	vec sample = feat_fr.col(v);
	feat_seg.push_back(sample);
      }

    }
    //cout << feat_seg.size() << endl;
    if (feat_seg.size()>100) // Cuando en el segmento hay mas de 100 vectores
    {
      mat mat_feat_seg(dim,feat_seg.size());

      for (uword i = 0; i < feat_seg.size(); ++i)
      {
	mat_feat_seg.col(i) = feat_seg.at(i);

      }

      mat U; vec s;   mat V;
      svd(U,s,V,mat_feat_seg);
      mat Gnp = U.cols(0,p-1);

      std::stringstream save_Gnp;
      //cout << save_folder.str() << endl;
      save_Gnp << save_folder.str() << "/grass_pt" << seg << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      //cout << save_Gnp.str() << endl;
      #pragma omp critical
      Gnp.save( save_Gnp.str(), hdf5_binary );
      seg++;
    }
    else {
      //cout << " " << stat_seg.count();
      //getchar();

    }

  }

  std::stringstream save_seg;
  vec total_seg;
  total_seg.zeros(1);
  total_seg( 0 ) = seg;
  save_seg << save_folder.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
  #pragma omp critical
  {
    total_seg.save( save_seg.str(), raw_ascii );
    //cout <<  all_people (pe) << "_" << actions(act) << ". Total # of segments " << seg << endl;
  }
  //cout << "press a key " ;
  //getchar();

}

<commit_msg>Run Grassman Points<commit_after>inline
grass_points::grass_points( const std::string in_path,
			    const std::string in_actionNames,
			    const int in_scale_factor,
			    const int in_shift,
			    const int in_scene, //only for kth
			    const int in_segment_length,
			    const int in_p
)
:path(in_path), actionNames(in_actionNames), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), p(in_p)
{
  actions.load( actionNames );
}

// One Grassmann Point per Video

inline
void
grass_points::calculate_onepervideo( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,3);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;

      load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = ss1.str();
      parallel_names(k,2) = ss2.str();
      k++;

    }
  }

  omp_set_num_threads(8); //Use only 8 processors

  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);

    int pe   = atoi( parallel_names(k,1).c_str() );
    int act  = atoi( parallel_names(k,2).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video_one_point(load_feat_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video_one_point( std::string load_feat_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-one-dim" << dim << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  mat U; vec s;   mat V;
  svd(U,s,V,mat_features_video_i);
  mat Gnp = U.cols(0,p-1);

  std::stringstream save_Gnp;
  //cout << save_folder.str() << endl;
  save_Gnp << save_folder.str() << "/grass_pt_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
  //cout << save_Gnp.str() << endl;

  #pragma omp critical
  Gnp.save( save_Gnp.str(), hdf5_binary );

}

// Several Grasmann Poits per Video
inline
void
grass_points::calculate( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,4);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;
      std::stringstream load_labels_video_i;

      load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      load_labels_video_i << load_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = load_labels_video_i.str();
      parallel_names(k,2) = ss1.str();
      parallel_names(k,3) = ss2.str();
      k++;

    }
  }

  omp_set_num_threads(4); //Use only 8 processors
  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);
    std::string load_labels_video_i = parallel_names(k,1);

    int pe   = atoi( parallel_names(k,2).c_str() );
    int act  = atoi( parallel_names(k,3).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video(load_feat_video_i, load_labels_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video( std::string load_feat_video_i,	std::string load_labels_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;
  vec lab_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );
  lab_video_i.load( load_labels_video_i, hdf5_binary );
  int n_vec = lab_video_i.n_elem;
  int last = lab_video_i( n_vec - 1 );
  //cout << last << endl;

  int seg = 0;

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-dim"<< dim << "-L" << segment_length << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  for (int l=2; l<last-segment_length; l = l+4 )
  {
    std::vector<vec> feat_seg;

    for (int j=l; j< l + segment_length; ++j)
    {
      //k++;
      //cout << " " << j;
      uvec indices = find(lab_video_i == j);
      mat feat_fr = mat_features_video_i.cols(indices);

      for (int v=0; v < feat_fr.n_cols; ++v)
      {
	vec sample = feat_fr.col(v);
	feat_seg.push_back(sample);
      }

    }
    //cout << feat_seg.size() << endl;
    if (feat_seg.size()>100) // Cuando en el segmento hay mas de 100 vectores
    {
      mat mat_feat_seg(dim,feat_seg.size());

      for (uword i = 0; i < feat_seg.size(); ++i)
      {
	mat_feat_seg.col(i) = feat_seg.at(i);

      }

      mat U; vec s;   mat V;
      svd(U,s,V,mat_feat_seg);
      mat Gnp = U.cols(0,p-1);

      std::stringstream save_Gnp;
      //cout << save_folder.str() << endl;
      save_Gnp << save_folder.str() << "/grass_pt" << seg << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      //cout << save_Gnp.str() << endl;
      #pragma omp critical
      Gnp.save( save_Gnp.str(), hdf5_binary );
      seg++;
    }
    else {
      //cout << " " << stat_seg.count();
      //getchar();

    }

  }

  std::stringstream save_seg;
  vec total_seg;
  total_seg.zeros(1);
  total_seg( 0 ) = seg;
  save_seg << save_folder.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
  #pragma omp critical
  {
    total_seg.save( save_seg.str(), raw_ascii );
    //cout <<  all_people (pe) << "_" << actions(act) << ". Total # of segments " << seg << endl;
  }
  //cout << "press a key " ;
  //getchar();

}

<|endoftext|>


<commit_before>/**
 * \file dcs/testbed/rain_workload_driver.hpp
 *
 * \brief Workload driver based on the RAIN workload toolkit.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed.
 *
 * dcsxx-testbed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * dcsxx-testbed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with dcsxx-testbed. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
#define DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP

#include <boost/smart_ptr.hpp>
#include <cstdlib>
#include <dcs/exception.hpp>
#include <dcs/system/posix_process.hpp>
#include <dcs/system/process_status_category.hpp>
#include <dcs/testbed/base_workload_driver.hpp>
#include <string>
#include <vector>

namespace dcs { namespace testbed {

namespace detail { namespace /*<unnamed>*/ {

inline
::std::string make_java_command(::std::string const& java_home)
{
	return java_home + "/bin/java";
}

inline
::std::string make_java_command()
{
	char* java_path = ::std::getenv("JAVA_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	java_path = ::std::getenv("JRE_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	return ::std::string();
}

/**
 * \brief Build arguments to pass to RAIN workload toolkit.
 *
 * The basic structure of the RAIN command is:
 *

 *  java [<java-arg1> ... <java-argN>] \
 *       -cp "rain.jar:<path to workload JAR>" \
 *       radlab.rain.Benchmark <path to Rain JSON configuration file>
 *

 */
template <typename FwdIterT>
inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home,
											  FwdIterT arg_first,
											  FwdIterT arg_last)
{
	::std::vector< ::std::string > args(arg_first, arg_last);

	args.push_back("-cp \"" + rain_home + "/rain.jar:" + rain_home + "/workloads/" + workload + ".jar\"");
	args.push_back("radlab.rain.Benchmark");
	args.push_back(rain_home + "/config/rain.config." + workload + ".json");

	return args;
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home)
{
	::std::vector< ::std::string > java_args;
	java_args.push_back("-Xmx1g");
	java_args.push_back("-Xms256m");

	return make_rain_args(workload, rain_home, java_args.begin(), java_args.end());
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload)
{
	return make_rain_args(workload, ".");
}

}} // Namespace detail::<unnamed>

class rain_workload_driver: public base_workload_driver
{
	private: typedef ::dcs::system::posix_process sys_process_type;
	private: typedef ::boost::shared_ptr<sys_process_type> sys_process_pointer;

	public: enum workload_category
	{
		olio_workload
	};

	public: rain_workload_driver(workload_category wkl_cat)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat)))
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home))
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home))
	{
	}

	public: template <typename FwdIterT>
			rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home,
								 FwdIterT arg_first,
								 FwdIterT arg_last)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home, arg_first, arg_last))
	{
	}

	private: static ::std::string to_string(workload_category wkl_cat)
	{
		switch (wkl_cat)
		{
			case olio_workload:
				return "olio";
		}

		DCS_EXCEPTION_THROW(::std::invalid_argument,
							"Unknown workload category");
	}

	private: void do_start()
	{
		if (p_proc_ && p_proc_->alive())
		{
			p_proc_->terminate();
		}
		p_proc_ = ::boost::make_shared<sys_process_type>(cmd_);

		p_proc_->asynch(true);
		p_proc_->run(args_.begin(), args_.end());

		if (p_proc_->status() != ::dcs::system::running_process_status)
		{
		   DCS_EXCEPTION_THROW(::std::runtime_error,
							   "Unable to start RAIN workload driver");
		}
	}

	private: void do_stop()
	{
		p_proc_->terminate();
	}

	private: ::std::string cmd_;
	private: ::std::vector< ::std::string > args_;
	private: sys_process_pointer p_proc_;
}; // rain_workload_driver

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
<commit_msg>(bugfix:major) If java-related environment variables are not found, return the 'java' string instead of the empty string.<commit_after>/**
 * \file dcs/testbed/rain_workload_driver.hpp
 *
 * \brief Workload driver based on the RAIN workload toolkit.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed.
 *
 * dcsxx-testbed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * dcsxx-testbed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with dcsxx-testbed. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
#define DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP

#include <boost/smart_ptr.hpp>
#include <cstdlib>
#include <dcs/exception.hpp>
#include <dcs/system/posix_process.hpp>
#include <dcs/system/process_status_category.hpp>
#include <dcs/testbed/base_workload_driver.hpp>
#include <string>
#include <vector>

namespace dcs { namespace testbed {

namespace detail { namespace /*<unnamed>*/ {

inline
::std::string make_java_command(::std::string const& java_home)
{
	return java_home + "/bin/java";
}

inline
::std::string make_java_command()
{
	char* java_path = ::std::getenv("JAVA_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	java_path = ::std::getenv("JRE_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	return ::std::string("java");
}

/**
 * \brief Build arguments to pass to RAIN workload toolkit.
 *
 * The basic structure of the RAIN command is:
 *

 *  java [<java-arg1> ... <java-argN>] \
 *       -cp "rain.jar:<path to workload JAR>" \
 *       radlab.rain.Benchmark <path to Rain JSON configuration file>
 *

 */
template <typename FwdIterT>
inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home,
											  FwdIterT arg_first,
											  FwdIterT arg_last)
{
	::std::vector< ::std::string > args(arg_first, arg_last);

	args.push_back("-cp");
	args.push_back("\"" + rain_home + "/rain.jar:" + rain_home + "/workloads/" + workload + ".jar\"");
	args.push_back("radlab.rain.Benchmark");
	args.push_back(rain_home + "/config/rain.config." + workload + ".json");

	return args;
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home)
{
	::std::vector< ::std::string > java_args;
	java_args.push_back("-Xmx1g");
	java_args.push_back("-Xms256m");

	return make_rain_args(workload, rain_home, java_args.begin(), java_args.end());
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload)
{
	return make_rain_args(workload, ".");
}

}} // Namespace detail::<unnamed>

class rain_workload_driver: public base_workload_driver
{
	private: typedef ::dcs::system::posix_process sys_process_type;
	private: typedef ::boost::shared_ptr<sys_process_type> sys_process_pointer;

	public: enum workload_category
	{
		olio_workload
	};

	public: rain_workload_driver(workload_category wkl_cat)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat)))
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home))
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home))
	{
	}

	public: template <typename FwdIterT>
			rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home,
								 FwdIterT arg_first,
								 FwdIterT arg_last)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home, arg_first, arg_last))
	{
	}

	private: static ::std::string to_string(workload_category wkl_cat)
	{
		switch (wkl_cat)
		{
			case olio_workload:
				return "olio";
		}

		DCS_EXCEPTION_THROW(::std::invalid_argument,
							"Unknown workload category");
	}

	private: void do_start()
	{
		if (p_proc_ && p_proc_->alive())
		{
			p_proc_->terminate();
		}
		p_proc_ = ::boost::make_shared<sys_process_type>(cmd_);

		p_proc_->asynch(true);
		p_proc_->run(args_.begin(), args_.end());

		if (p_proc_->status() != ::dcs::system::running_process_status)
		{
		   DCS_EXCEPTION_THROW(::std::runtime_error,
							   "Unable to start RAIN workload driver");
		}
	}

	private: void do_stop()
	{
		p_proc_->terminate();
	}

	private: ::std::string cmd_;
	private: ::std::vector< ::std::string > args_;
	private: sys_process_pointer p_proc_;
}; // rain_workload_driver

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
<|endoftext|>


<commit_before>#ifndef GNR_MEMFUN_HPP
# define GNR_MEMFUN_HPP
# pragma once

#include <functional>

#include <type_traits>

#include <utility>

#define MEMFUN(f) decltype(&f),&f

namespace gnr
{

namespace mem_fun
{

namespace detail
{

template <typename>
struct signature
{
};

//
template <typename>
struct class_ref;

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...)>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) &>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const &>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile &>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) &&>
{
  using type = C&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const &&>
{
  using type = C const&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile &&>
{
  using type = C const volatile&&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) noexcept>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const noexcept>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile noexcept>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) & noexcept>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const & noexcept>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile & noexcept>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) && noexcept>
{
  using type = C&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const && noexcept>
{
  using type = C const &&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile && noexcept>
{
  using type = C const volatile &&;
};

template <typename F>
using class_ref_t = typename class_ref<F>::type;

//
template <typename>
struct remove_cv_seq;

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...)>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile noexcept>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile &>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) & noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const & noexcept >
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile & noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile & noexcept>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile &&>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile && noexcept>
{
  using type = R(A...);
};

template <typename F>
constexpr inline auto extract_signature(F* const) noexcept
{
  return signature<typename remove_cv_seq<F>::type>();
}

template <typename C, typename F>
constexpr inline auto extract_signature(F C::* const) noexcept
{
  return signature<typename remove_cv_seq<F>::type>();
}

template <typename F>
constexpr inline auto extract_signature(F const&) noexcept ->
  decltype(&F::operator(), extract_signature(&F::operator()))
{
  return extract_signature(&F::operator());
}

template <typename FP, FP fp, typename REF, typename R, typename ...A>
inline auto member_delegate(REF& ref, signature<R(A...)>) noexcept
{
  return [&ref](A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

template <typename FP, FP fp, typename REF, typename R, typename ...A>
inline auto member_delegate(REF* ref, signature<R(A...)>) noexcept
{
  return [ref](A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

template <typename FP, FP fp, typename R, typename ...A>
inline auto member_delegate_ref(signature<R(A...)>) noexcept
{
  return [](class_ref_t<FP> ref, A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

}

}

template <typename FP, FP fp, typename REF,
  typename = std::enable_if_t<std::is_member_function_pointer<FP>{} ||
    std::is_reference<REF>{} || std::is_pointer<REF>{}
  >
>
inline auto memfun(REF&& ref) noexcept
{
  return mem_fun::detail::member_delegate<FP, fp>(std::forward<REF>(ref),
    mem_fun::detail::extract_signature(fp));
}

template <typename FP, FP fp,
  typename = std::enable_if_t<std::is_member_function_pointer<FP>{}>
>
inline auto memfun_ref() noexcept
{
  return mem_fun::detail::member_delegate_ref<FP, fp>(
    mem_fun::detail::extract_signature(fp));
}

}

#endif // GNR_MEMFUN_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_MEMFUN_HPP
# define GNR_MEMFUN_HPP
# pragma once

#include <functional>

#include <type_traits>

#include <utility>

#define MEMFUN(f) decltype(&f),&f

namespace gnr
{

namespace mem_fun
{

namespace detail
{

template <typename>
struct signature
{
};

//
template <typename>
struct class_ref;

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...)>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) &>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const &>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile &>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) &&>
{
  using type = C&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const &&>
{
  using type = C const&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile &&>
{
  using type = C const volatile&&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) noexcept>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const noexcept>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile noexcept>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) & noexcept>
{
  using type = C&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const & noexcept>
{
  using type = C const&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile & noexcept>
{
  using type = C const volatile&;
};

//
template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) && noexcept>
{
  using type = C&&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const && noexcept>
{
  using type = C const &&;
};

template <typename R, typename C, typename ...A>
struct class_ref<R (C::*)(A...) const volatile && noexcept>
{
  using type = C const volatile &&;
};

template <typename F>
using class_ref_t = typename class_ref<F>::type;

//
template <typename>
struct remove_cv_seq;

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...)>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile noexcept>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile &>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile &>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) & noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const & noexcept >
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile & noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile & noexcept>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile &&>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile &&>
{
  using type = R(A...);
};

//
template <typename R, typename ...A>
struct remove_cv_seq<R(A...) && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) volatile && noexcept>
{
  using type = R(A...);
};

template <typename R, typename ...A>
struct remove_cv_seq<R(A...) const volatile && noexcept>
{
  using type = R(A...);
};

template <typename F>
constexpr inline auto extract_signature(F* const) noexcept
{
  return signature<typename remove_cv_seq<F>::type>();
}

template <typename C, typename F>
constexpr inline auto extract_signature(F C::* const) noexcept
{
  return signature<typename remove_cv_seq<F>::type>();
}

template <typename F>
constexpr inline auto extract_signature(F const&) noexcept ->
  decltype(&F::operator(), extract_signature(&F::operator()))
{
  return extract_signature(&F::operator());
}

template <typename FP, FP fp, typename REF, typename R, typename ...A>
inline auto member_delegate(REF& ref, signature<R(A...)>) noexcept
{
  return [&ref](A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

template <typename FP, FP fp, typename REF, typename R, typename ...A>
inline auto member_delegate(REF* ref, signature<R(A...)>) noexcept
{
  return [ref](A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

template <typename FP, FP fp, typename R, typename ...A>
inline auto member_delegate_ref(signature<R(A...)>) noexcept
{
  return [](class_ref_t<FP> ref, A&& ...args) noexcept(
    noexcept(std::invoke(fp, ref, std::forward<A>(args)...))
  )
  {
    return std::invoke(fp, ref, std::forward<A>(args)...);
  };
}

}

}

template <typename FP, FP fp, typename REF,
  typename = std::enable_if_t<std::is_member_function_pointer<FP>{} ||
    std::is_reference<REF>{} || std::is_pointer<REF>{}
  >
>
inline auto memfun(REF&& ref) noexcept
{
  return mem_fun::detail::member_delegate<FP, fp>(std::forward<REF>(ref),
    mem_fun::detail::extract_signature(fp));
}

template <typename FP, FP fp,
  typename = std::enable_if_t<std::is_member_function_pointer<FP>{}>
>
inline auto memfun_ref() noexcept
{
  return mem_fun::detail::member_delegate_ref<FP, fp>(
    mem_fun::detail::extract_signature(fp));
}

}

#endif // GNR_MEMFUN_HPP
<|endoftext|>