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

  Program:   Visualization Toolkit
  Module:    vtkBooleanOperationPolyDataFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkBooleanOperationPolyDataFilter.h"

#include "vtkCellData.h"
#include "vtkDistancePolyDataFilter.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkGenericCell.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntersectionPolyDataFilter.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkBooleanOperationPolyDataFilter);

//-----------------------------------------------------------------------------
vtkBooleanOperationPolyDataFilter::vtkBooleanOperationPolyDataFilter() :
  vtkPolyDataAlgorithm()
{
  this->Tolerance = 1e-6;
  this->Operation = UNION;
  this->ReorientDifferenceCells = 1;

  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(2);

}

//-----------------------------------------------------------------------------
vtkBooleanOperationPolyDataFilter::~vtkBooleanOperationPolyDataFilter()
{
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter::SortPolyData(vtkPolyData* input,
                                                     vtkIdList* interList,
                                                     vtkIdList* unionList)
{
  int numCells = input->GetNumberOfCells();

  vtkDoubleArray *distArray = vtkDoubleArray::SafeDownCast
    ( input->GetCellData()->GetArray("Distance") );

  for (int cid = 0; cid < numCells; cid++)
    {

    if ( distArray->GetValue( cid ) > this->Tolerance )
      {
      unionList->InsertNextId( cid );
      }
    else
      {
      interList->InsertNextId( cid );
      }
    }
}

//-----------------------------------------------------------------------------
int vtkBooleanOperationPolyDataFilter::RequestData(vtkInformation*        vtkNotUsed(request),
                                                   vtkInformationVector** inputVector,
                                                   vtkInformationVector*  outputVector)
{
  vtkInformation* inInfo0 = inputVector[0]->GetInformationObject(0);
  vtkInformation* inInfo1 = inputVector[1]->GetInformationObject(0);
  vtkInformation* outInfo0 = outputVector->GetInformationObject(0);
  vtkInformation* outInfo1 = outputVector->GetInformationObject(1);

  if (!inInfo0 || !inInfo1 || !outInfo0 || !outInfo1)
    {
    return 0;
    }

  vtkPolyData* input0 =
    vtkPolyData::SafeDownCast(inInfo0->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData* input1 =
    vtkPolyData::SafeDownCast(inInfo1->Get(vtkDataObject::DATA_OBJECT()));

  vtkPolyData* outputSurface =
    vtkPolyData::SafeDownCast(outInfo0->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData* outputIntersection =
    vtkPolyData::SafeDownCast(outInfo1->Get(vtkDataObject::DATA_OBJECT()));

  if (!input0 || !input1 || !outputSurface || !outputIntersection)
    {
    return 0;
    }

  // Get intersected versions
  vtkSmartPointer<vtkIntersectionPolyDataFilter> PolyDataIntersection =
    vtkSmartPointer<vtkIntersectionPolyDataFilter>::New();
  PolyDataIntersection->SetInputConnection
    (0, this->GetInputConnection(0, 0));
  PolyDataIntersection->SetInputConnection
    (1, this->GetInputConnection(1, 0));
  PolyDataIntersection->SplitFirstOutputOn();
  PolyDataIntersection->SplitSecondOutputOn();
  PolyDataIntersection->Update();

  outputIntersection->CopyStructure(PolyDataIntersection->GetOutput());
  outputIntersection->GetPointData()->PassData(PolyDataIntersection->GetOutput()->GetPointData());
  outputIntersection->GetCellData()->PassData(PolyDataIntersection->GetOutput()->GetCellData());

  // Compute distances
  vtkSmartPointer<vtkDistancePolyDataFilter> PolyDataDistance =
    vtkSmartPointer<vtkDistancePolyDataFilter>::New();

  PolyDataDistance->SetInputConnection
    (0, PolyDataIntersection->GetOutputPort( 1 ));
  PolyDataDistance->SetInputConnection
    (1, PolyDataIntersection->GetOutputPort( 2 ));
  PolyDataDistance->ComputeSecondDistanceOn();
  PolyDataDistance->Update();

  vtkPolyData* pd0 = PolyDataDistance->GetOutput();
  vtkPolyData* pd1 = PolyDataDistance->GetSecondDistanceOutput();

  pd0->BuildCells();
  pd0->BuildLinks();
  pd1->BuildCells();
  pd1->BuildLinks();

  // Set up field lists of both points and cells that are shared by
  // the input data sets.
  vtkDataSetAttributes::FieldList pointFields(2);
  pointFields.InitializeFieldList( pd0->GetPointData() );
  pointFields.IntersectFieldList(  pd1->GetPointData() );

  vtkDataSetAttributes::FieldList cellFields(2);
  cellFields.InitializeFieldList( pd0->GetCellData() );
  cellFields.IntersectFieldList(  pd1->GetCellData() );

  // Sort union/intersection.
  vtkSmartPointer< vtkIdList > interList = vtkSmartPointer< vtkIdList >::New();
  vtkSmartPointer< vtkIdList > unionList = vtkSmartPointer< vtkIdList >::New();

  this->SortPolyData(pd0, interList, unionList);

  outputSurface->Allocate(pd0);
  outputSurface->GetPointData()->CopyAllocate(pointFields);
  outputSurface->GetCellData()->CopyAllocate(cellFields);

  if ( this->Operation == UNION || this->Operation == DIFFERENCE )
    {
    this->CopyCells(pd0, outputSurface, 0, pointFields, cellFields, unionList,
                    false);
    }
  else if ( this->Operation == INTERSECTION )
    {
    this->CopyCells(pd0, outputSurface, 0, pointFields, cellFields, interList,
                    false);
    }

  // Label sources for each point and cell.
  vtkSmartPointer< vtkIntArray > pointSourceLabel =
    vtkSmartPointer< vtkIntArray >::New();
  pointSourceLabel->SetNumberOfComponents(1);
  pointSourceLabel->SetName("PointSource");
  pointSourceLabel->SetNumberOfTuples(outputSurface->GetNumberOfPoints());
  for (vtkIdType i = 0; i < outputSurface->GetNumberOfPoints(); i++)
    {
    pointSourceLabel->InsertValue(i, 0);
    }

  vtkSmartPointer< vtkIntArray > cellSourceLabel =
    vtkSmartPointer< vtkIntArray >::New();
  cellSourceLabel->SetNumberOfComponents(1);
  cellSourceLabel->SetName("CellSource");
  cellSourceLabel->SetNumberOfValues(outputSurface->GetNumberOfCells());
  for (vtkIdType ii = 0; ii < outputSurface->GetNumberOfCells(); ii++)
    {
    cellSourceLabel->InsertValue(ii, 0);
    }

  interList->Reset();
  unionList->Reset();

  this->SortPolyData(pd1, interList, unionList);

  if ( this->Operation == UNION )
    {
    this->CopyCells(pd1, outputSurface, 1, pointFields, cellFields, unionList,
                    false);
    }
  else if ( this->Operation == INTERSECTION || this->Operation == DIFFERENCE )
    {
    this->CopyCells(pd1, outputSurface, 1, pointFields, cellFields, interList,
                    (this->ReorientDifferenceCells == 1 &&
                     this->Operation == DIFFERENCE));
    }

  vtkIdType i;
  i = pointSourceLabel->GetNumberOfTuples();
  pointSourceLabel->Resize(outputSurface->GetNumberOfPoints());
  for ( ; i < outputSurface->GetNumberOfPoints(); i++)
    {
    pointSourceLabel->InsertValue(i, 1);
    }

  i = cellSourceLabel->GetNumberOfTuples();
  cellSourceLabel->Resize(outputSurface->GetNumberOfCells());
  for ( ; i < outputSurface->GetNumberOfCells(); i++)
    {
    cellSourceLabel->InsertValue(i, 1);
    }

  outputSurface->GetPointData()->AddArray(pointSourceLabel);
  outputSurface->GetCellData()->AddArray(cellSourceLabel);

  outputSurface->Squeeze();
  outputSurface->GetPointData()->Squeeze();
  outputSurface->GetCellData()->Squeeze();

  return 1;
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Tolerance: " << this->Tolerance << "\n";
  os << indent << "Operation: ";
  switch ( this->Operation )
    {
    case UNION:
      os << "UNION";
      break;

    case INTERSECTION:
      os << "INTERSECTION";
      break;

    case DIFFERENCE:
      os << "DIFFERENCE";
      break;
    }
  os << "\n";
  os << indent << "ReorientDifferenceCells: " << this->ReorientDifferenceCells << "\n";
}

//-----------------------------------------------------------------------------
int vtkBooleanOperationPolyDataFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if (!this->Superclass::FillInputPortInformation(port, info))
    {
    return 0;
    }
  if (port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
    }
  else if (port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 0);
    }
  return 1;
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter
::CopyCells(vtkPolyData* in, vtkPolyData* out, int idx,
            vtkDataSetAttributes::FieldList & pointFieldList,
            vtkDataSetAttributes::FieldList & cellFieldList,
            vtkIdList* cellIds, bool reverseCells)
{
  // Largely copied from vtkPolyData::CopyCells, but modified to
  // use the special form of CopyData that uses a field list to
  // determine which data values to copy over.

  vtkPointData* outPD = out->GetPointData();
  vtkCellData*  outCD = out->GetCellData();

  vtkFloatArray *outNormals = NULL;
  if ( reverseCells )
    {
    outNormals = vtkFloatArray::SafeDownCast( outPD->GetArray("Normals") );
    }

  vtkIdType numPts = in->GetNumberOfPoints();

  if ( out->GetPoints() == NULL)
    {
    vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints >::New();
    out->SetPoints( points );
    }

  vtkPoints *newPoints = out->GetPoints();

  vtkSmartPointer< vtkIdList > pointMap = vtkSmartPointer< vtkIdList >::New();
  pointMap->SetNumberOfIds( numPts );
  for ( vtkIdType i = 0; i < numPts; i++ )
    {
    pointMap->SetId(i, -1);
    }

  // Filter the cells
  vtkSmartPointer< vtkGenericCell > cell =
    vtkSmartPointer< vtkGenericCell> ::New();
  vtkSmartPointer< vtkIdList > newCellPts =
    vtkSmartPointer< vtkIdList >::New();
  for ( vtkIdType cellId = 0; cellId < cellIds->GetNumberOfIds(); cellId++ )
    {
    in->GetCell( cellIds->GetId( cellId ), cell );
    vtkIdList *cellPts = cell->GetPointIds();
    vtkIdType numCellPts = cell->GetNumberOfPoints();

    for ( vtkIdType i = 0; i < numCellPts; i++ )
      {
      vtkIdType ptId = cellPts->GetId( i );
      vtkIdType newId = pointMap->GetId( ptId );
      if ( newId < 0 )
        {
        double x[3];
        in->GetPoint( ptId, x );
        newId = newPoints->InsertNextPoint( x );
        pointMap->SetId( ptId, newId );
        outPD->CopyData( pointFieldList, in->GetPointData(), idx, ptId, newId );

        if ( reverseCells && outNormals )
          {
          float normal[3];
          outNormals->GetTupleValue( newId, normal );
          normal[0] *= -1.0;
          normal[1] *= -1.0;
          normal[2] *= -1.0;
          outNormals->SetTupleValue( newId, normal );
          }

        }
      newCellPts->InsertId( i, newId );
      }
    if ( reverseCells )
      {
      for (vtkIdType i = 0; i < newCellPts->GetNumberOfIds() / 2; i++)
        {
        vtkIdType i1 = i;
        vtkIdType i2 = newCellPts->GetNumberOfIds()-i-1;

        vtkIdType id = newCellPts->GetId( i1 );
        newCellPts->SetId( i1, newCellPts->GetId( i2 ) );
        newCellPts->SetId( i2, id );
        }
      }

    vtkIdType newCellId = out->InsertNextCell( cell->GetCellType(), newCellPts );
    outCD->CopyData( cellFieldList, in->GetCellData(), idx,
                     cellIds->GetId( cellId ), newCellId );

    newCellPts->Reset();
    } // for all cells

}
<commit_msg>COMP: VS warnings<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBooleanOperationPolyDataFilter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkBooleanOperationPolyDataFilter.h"

#include "vtkCellData.h"
#include "vtkDistancePolyDataFilter.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkGenericCell.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntersectionPolyDataFilter.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkBooleanOperationPolyDataFilter);

//-----------------------------------------------------------------------------
vtkBooleanOperationPolyDataFilter::vtkBooleanOperationPolyDataFilter() :
  vtkPolyDataAlgorithm()
{
  this->Tolerance = 1e-6;
  this->Operation = UNION;
  this->ReorientDifferenceCells = 1;

  this->SetNumberOfInputPorts(2);
  this->SetNumberOfOutputPorts(2);

}

//-----------------------------------------------------------------------------
vtkBooleanOperationPolyDataFilter::~vtkBooleanOperationPolyDataFilter()
{
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter::SortPolyData(vtkPolyData* input,
                                                     vtkIdList* interList,
                                                     vtkIdList* unionList)
{
  int numCells = input->GetNumberOfCells();

  vtkDoubleArray *distArray = vtkDoubleArray::SafeDownCast
    ( input->GetCellData()->GetArray("Distance") );

  for (int cid = 0; cid < numCells; cid++)
    {

    if ( distArray->GetValue( cid ) > this->Tolerance )
      {
      unionList->InsertNextId( cid );
      }
    else
      {
      interList->InsertNextId( cid );
      }
    }
}

//-----------------------------------------------------------------------------
int vtkBooleanOperationPolyDataFilter::RequestData(vtkInformation*        vtkNotUsed(request),
                                                   vtkInformationVector** inputVector,
                                                   vtkInformationVector*  outputVector)
{
  vtkInformation* inInfo0 = inputVector[0]->GetInformationObject(0);
  vtkInformation* inInfo1 = inputVector[1]->GetInformationObject(0);
  vtkInformation* outInfo0 = outputVector->GetInformationObject(0);
  vtkInformation* outInfo1 = outputVector->GetInformationObject(1);

  if (!inInfo0 || !inInfo1 || !outInfo0 || !outInfo1)
    {
    return 0;
    }

  vtkPolyData* input0 =
    vtkPolyData::SafeDownCast(inInfo0->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData* input1 =
    vtkPolyData::SafeDownCast(inInfo1->Get(vtkDataObject::DATA_OBJECT()));

  vtkPolyData* outputSurface =
    vtkPolyData::SafeDownCast(outInfo0->Get(vtkDataObject::DATA_OBJECT()));
  vtkPolyData* outputIntersection =
    vtkPolyData::SafeDownCast(outInfo1->Get(vtkDataObject::DATA_OBJECT()));

  if (!input0 || !input1 || !outputSurface || !outputIntersection)
    {
    return 0;
    }

  // Get intersected versions
  vtkSmartPointer<vtkIntersectionPolyDataFilter> PolyDataIntersection =
    vtkSmartPointer<vtkIntersectionPolyDataFilter>::New();
  PolyDataIntersection->SetInputConnection
    (0, this->GetInputConnection(0, 0));
  PolyDataIntersection->SetInputConnection
    (1, this->GetInputConnection(1, 0));
  PolyDataIntersection->SplitFirstOutputOn();
  PolyDataIntersection->SplitSecondOutputOn();
  PolyDataIntersection->Update();

  outputIntersection->CopyStructure(PolyDataIntersection->GetOutput());
  outputIntersection->GetPointData()->PassData(PolyDataIntersection->GetOutput()->GetPointData());
  outputIntersection->GetCellData()->PassData(PolyDataIntersection->GetOutput()->GetCellData());

  // Compute distances
  vtkSmartPointer<vtkDistancePolyDataFilter> PolyDataDistance =
    vtkSmartPointer<vtkDistancePolyDataFilter>::New();

  PolyDataDistance->SetInputConnection
    (0, PolyDataIntersection->GetOutputPort( 1 ));
  PolyDataDistance->SetInputConnection
    (1, PolyDataIntersection->GetOutputPort( 2 ));
  PolyDataDistance->ComputeSecondDistanceOn();
  PolyDataDistance->Update();

  vtkPolyData* pd0 = PolyDataDistance->GetOutput();
  vtkPolyData* pd1 = PolyDataDistance->GetSecondDistanceOutput();

  pd0->BuildCells();
  pd0->BuildLinks();
  pd1->BuildCells();
  pd1->BuildLinks();

  // Set up field lists of both points and cells that are shared by
  // the input data sets.
  vtkDataSetAttributes::FieldList pointFields(2);
  pointFields.InitializeFieldList( pd0->GetPointData() );
  pointFields.IntersectFieldList(  pd1->GetPointData() );

  vtkDataSetAttributes::FieldList cellFields(2);
  cellFields.InitializeFieldList( pd0->GetCellData() );
  cellFields.IntersectFieldList(  pd1->GetCellData() );

  // Sort union/intersection.
  vtkSmartPointer< vtkIdList > interList = vtkSmartPointer< vtkIdList >::New();
  vtkSmartPointer< vtkIdList > unionList = vtkSmartPointer< vtkIdList >::New();

  this->SortPolyData(pd0, interList, unionList);

  outputSurface->Allocate(pd0);
  outputSurface->GetPointData()->CopyAllocate(pointFields);
  outputSurface->GetCellData()->CopyAllocate(cellFields);

  if ( this->Operation == UNION || this->Operation == DIFFERENCE )
    {
    this->CopyCells(pd0, outputSurface, 0, pointFields, cellFields, unionList,
                    false);
    }
  else if ( this->Operation == INTERSECTION )
    {
    this->CopyCells(pd0, outputSurface, 0, pointFields, cellFields, interList,
                    false);
    }

  // Label sources for each point and cell.
  vtkSmartPointer< vtkIntArray > pointSourceLabel =
    vtkSmartPointer< vtkIntArray >::New();
  pointSourceLabel->SetNumberOfComponents(1);
  pointSourceLabel->SetName("PointSource");
  pointSourceLabel->SetNumberOfTuples(outputSurface->GetNumberOfPoints());
  for (vtkIdType ii = 0; ii < outputSurface->GetNumberOfPoints(); ii++)
    {
    pointSourceLabel->InsertValue(ii, 0);
    }

  vtkSmartPointer< vtkIntArray > cellSourceLabel =
    vtkSmartPointer< vtkIntArray >::New();
  cellSourceLabel->SetNumberOfComponents(1);
  cellSourceLabel->SetName("CellSource");
  cellSourceLabel->SetNumberOfValues(outputSurface->GetNumberOfCells());
  for (vtkIdType ii = 0; ii < outputSurface->GetNumberOfCells(); ii++)
    {
    cellSourceLabel->InsertValue(ii, 0);
    }

  interList->Reset();
  unionList->Reset();

  this->SortPolyData(pd1, interList, unionList);

  if ( this->Operation == UNION )
    {
    this->CopyCells(pd1, outputSurface, 1, pointFields, cellFields, unionList,
                    false);
    }
  else if ( this->Operation == INTERSECTION || this->Operation == DIFFERENCE )
    {
    this->CopyCells(pd1, outputSurface, 1, pointFields, cellFields, interList,
                    (this->ReorientDifferenceCells == 1 &&
                     this->Operation == DIFFERENCE));
    }

  vtkIdType i;
  i = pointSourceLabel->GetNumberOfTuples();
  pointSourceLabel->Resize(outputSurface->GetNumberOfPoints());
  for ( ; i < outputSurface->GetNumberOfPoints(); i++)
    {
    pointSourceLabel->InsertValue(i, 1);
    }

  i = cellSourceLabel->GetNumberOfTuples();
  cellSourceLabel->Resize(outputSurface->GetNumberOfCells());
  for ( ; i < outputSurface->GetNumberOfCells(); i++)
    {
    cellSourceLabel->InsertValue(i, 1);
    }

  outputSurface->GetPointData()->AddArray(pointSourceLabel);
  outputSurface->GetCellData()->AddArray(cellSourceLabel);

  outputSurface->Squeeze();
  outputSurface->GetPointData()->Squeeze();
  outputSurface->GetCellData()->Squeeze();

  return 1;
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Tolerance: " << this->Tolerance << "\n";
  os << indent << "Operation: ";
  switch ( this->Operation )
    {
    case UNION:
      os << "UNION";
      break;

    case INTERSECTION:
      os << "INTERSECTION";
      break;

    case DIFFERENCE:
      os << "DIFFERENCE";
      break;
    }
  os << "\n";
  os << indent << "ReorientDifferenceCells: " << this->ReorientDifferenceCells << "\n";
}

//-----------------------------------------------------------------------------
int vtkBooleanOperationPolyDataFilter::FillInputPortInformation(int port, vtkInformation *info)
{
  if (!this->Superclass::FillInputPortInformation(port, info))
    {
    return 0;
    }
  if (port == 0)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
    }
  else if (port == 1)
    {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 0);
    }
  return 1;
}

//-----------------------------------------------------------------------------
void vtkBooleanOperationPolyDataFilter
::CopyCells(vtkPolyData* in, vtkPolyData* out, int idx,
            vtkDataSetAttributes::FieldList & pointFieldList,
            vtkDataSetAttributes::FieldList & cellFieldList,
            vtkIdList* cellIds, bool reverseCells)
{
  // Largely copied from vtkPolyData::CopyCells, but modified to
  // use the special form of CopyData that uses a field list to
  // determine which data values to copy over.

  vtkPointData* outPD = out->GetPointData();
  vtkCellData*  outCD = out->GetCellData();

  vtkFloatArray *outNormals = NULL;
  if ( reverseCells )
    {
    outNormals = vtkFloatArray::SafeDownCast( outPD->GetArray("Normals") );
    }

  vtkIdType numPts = in->GetNumberOfPoints();

  if ( out->GetPoints() == NULL)
    {
    vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints >::New();
    out->SetPoints( points );
    }

  vtkPoints *newPoints = out->GetPoints();

  vtkSmartPointer< vtkIdList > pointMap = vtkSmartPointer< vtkIdList >::New();
  pointMap->SetNumberOfIds( numPts );
  for ( vtkIdType i = 0; i < numPts; i++ )
    {
    pointMap->SetId(i, -1);
    }

  // Filter the cells
  vtkSmartPointer< vtkGenericCell > cell =
    vtkSmartPointer< vtkGenericCell> ::New();
  vtkSmartPointer< vtkIdList > newCellPts =
    vtkSmartPointer< vtkIdList >::New();
  for ( vtkIdType cellId = 0; cellId < cellIds->GetNumberOfIds(); cellId++ )
    {
    in->GetCell( cellIds->GetId( cellId ), cell );
    vtkIdList *cellPts = cell->GetPointIds();
    vtkIdType numCellPts = cell->GetNumberOfPoints();

    for ( vtkIdType i = 0; i < numCellPts; i++ )
      {
      vtkIdType ptId = cellPts->GetId( i );
      vtkIdType newId = pointMap->GetId( ptId );
      if ( newId < 0 )
        {
        double x[3];
        in->GetPoint( ptId, x );
        newId = newPoints->InsertNextPoint( x );
        pointMap->SetId( ptId, newId );
        outPD->CopyData( pointFieldList, in->GetPointData(), idx, ptId, newId );

        if ( reverseCells && outNormals )
          {
          float normal[3];
          outNormals->GetTupleValue( newId, normal );
          normal[0] *= -1.0;
          normal[1] *= -1.0;
          normal[2] *= -1.0;
          outNormals->SetTupleValue( newId, normal );
          }

        }
      newCellPts->InsertId( i, newId );
      }
    if ( reverseCells )
      {
      for (vtkIdType i = 0; i < newCellPts->GetNumberOfIds() / 2; i++)
        {
        vtkIdType i1 = i;
        vtkIdType i2 = newCellPts->GetNumberOfIds()-i-1;

        vtkIdType id = newCellPts->GetId( i1 );
        newCellPts->SetId( i1, newCellPts->GetId( i2 ) );
        newCellPts->SetId( i2, id );
        }
      }

    vtkIdType newCellId = out->InsertNextCell( cell->GetCellType(), newCellPts );
    outCD->CopyData( cellFieldList, in->GetCellData(), idx,
                     cellIds->GetId( cellId ), newCellId );

    newCellPts->Reset();
    } // for all cells

}
<|endoftext|>


<commit_before>#include "texture_loader.hpp"

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h> // GLfloat, GLuint etc.
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <cstdio>   // std::FILE, std::fclose, std::fopen, std::fread, std::getchar, std::printf etc.
#include <cstring>  // std::memcmp, std::strcmp, std::strlen, std::strncmp
#include <iostream> // std::cout, std::cin, std::cerr
#include <stdint.h> // uint32_t etc.
#include <stdlib.h> // free, malloc

namespace loaders
{
    GLuint load_BMP_texture(const char* imagepath)
    {
        std::printf("Reading image %s\n", imagepath);

        // Data read from the header of the BMP file
        unsigned char header[54];
        uint32_t dataPos;
        uint32_t imageSize;
        uint32_t width, height;
        // Actual RGB data
        unsigned char* data;

        // Open the file
        std::FILE* file = std::fopen(imagepath,"rb");
        if (!file)
        {
            std::printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath);
            return 0;
        }

        // Read the header, i.e. the 54 first bytes

        // If less than 54 bytes are read, problem
        if (std::fread(header, 1, 54, file) != 54)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // A BMP files always begins with "BM"
        if ((header[0] != 'B') || (header[1] != 'M'))
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // Make sure this is a 24bpp file
        if (*(int*) &header[0x1e] != 0)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        if (*(int*) &header[0x1c] != 24)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // Read the information about the image
        dataPos    = *(int*) &header[0x0a];
        imageSize  = *(int*) &header[0x22];
        width      = *(int*) &header[0x12];
        height     = *(int*) &header[0x16];

        // Some BMP files are misformatted, guess missing information
        if (imageSize == 0)
        {
            imageSize = width * height * 3; // 3 : one byte for each Red, Green and Blue component
        }

        if (dataPos == 0)
        {
            dataPos = 54; // The BMP header is done that way
        }

        // Create a buffer
        data = new unsigned char [imageSize];

        if (data == nullptr)
        {
            std::cerr << "Reserving memory for texture data failed.\n";
            std::fclose(file);
            return 0;
        }

        // Read the actual data from the file into the buffer
        std::fread(data, 1, imageSize, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        // Create one OpenGL texture
        GLuint textureID;
        glGenTextures(1, &textureID);

        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);

        // Give the image to OpenGL
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);

        // OpenGL has now copied the data. Free our own version
        delete [] data;

        // Poor filtering, or ...
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

#define CLAMP_TEXTURES
        // #define REPEAT_TEXTURES

#ifdef CLAMP_TEXTURES
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif

#ifdef REPEAT_TEXTURES
        // ... nice trilinear filtering.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#endif

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glGenerateMipmap(GL_TEXTURE_2D);

        // Return the ID of the texture we just created
        return textureID;
    }

    // Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library,
    // or do it yourself (just like load_BMP_texture and load_DDS_texture)
    //GLuint loadTGA_glfw(const char*  imagepath){
    //
    //    // Create one OpenGL texture
    //    GLuint textureID;
    //    glGenTextures(1, &textureID);
    //
    //    // "Bind" the newly created texture : all future texture functions will modify this texture
    //    glBindTexture(GL_TEXTURE_2D, textureID);
    //
    //    // Read the file, call glTexImage2D with the right parameters
    //    glfwLoadTexture2D(imagepath, 0);
    //
    //    // Nice trilinear filtering.
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    //    glGenerateMipmap(GL_TEXTURE_2D);
    //
    //    // Return the ID of the texture we just created
    //    return textureID;
    //}

#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII

    GLuint load_DDS_texture(const char* imagepath)
    {
        unsigned char header[124];
        std::FILE* fp;

        /* try to open the file */
        fp = std::fopen(imagepath, "rb");
        if (fp == nullptr)
        {
            std::printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath);
            return 0;
        }

        /* verify the type of file */
        char filecode[4];
        std::fread(filecode, 1, 4, fp);
        if (std::strncmp(filecode, "DDS ", 4) != 0)
        {
            std::fclose(fp);
            return 0;
        }

        /* get the surface desc */
        std::fread(&header, 124, 1, fp);

        uint32_t height      = *(uint32_t*) &header[8];
        uint32_t width       = *(uint32_t*) &header[12];
        uint32_t linearSize  = *(uint32_t*) &header[16];
        uint32_t mipMapCount = *(uint32_t*) &header[24];
        uint32_t fourCC      = *(uint32_t*) &header[80];

        unsigned char* buffer;
        uint32_t bufsize;
        /* how big is it going to be including all mipmaps? */
        bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
        buffer = (unsigned char*) malloc(bufsize * sizeof(unsigned char));
        std::fread(buffer, 1, bufsize, fp);
        /* close the file pointer */
        std::fclose(fp);

        uint32_t components = (fourCC == FOURCC_DXT1) ? 3 : 4;
        uint32_t format;
        switch(fourCC)
        {
            case FOURCC_DXT1:
                format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            default:
                free(buffer);
                return 0;
        }

        // Create one OpenGL texture
        GLuint textureID;
        glGenTextures(1, &textureID);

        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        uint32_t blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
        uint32_t offset = 0;

        /* load the mipmaps */
        for (uint32_t level = 0; level < mipMapCount && (width || height); ++level)
        {
            uint32_t size = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
            glCompressedTexImage2D(
                    GL_TEXTURE_2D,
                    level,
                    format,
                    width,
                    height,
                    0,
                    size,
                    buffer + offset);

            offset += size;
            width  /= 2;
            height /= 2;

            // Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
            if (width < 1)
            {
                width = 1;
            }
            if (height < 1)
            {
                height = 1;
            }
        }
        free(buffer);

        return textureID;
    }
}
<commit_msg>`delete []` -> `delete[]`.<commit_after>#include "texture_loader.hpp"

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h> // GLfloat, GLuint etc.
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <cstdio>   // std::FILE, std::fclose, std::fopen, std::fread, std::getchar, std::printf etc.
#include <cstring>  // std::memcmp, std::strcmp, std::strlen, std::strncmp
#include <iostream> // std::cout, std::cin, std::cerr
#include <stdint.h> // uint32_t etc.
#include <stdlib.h> // free, malloc

namespace loaders
{
    GLuint load_BMP_texture(const char* imagepath)
    {
        std::printf("Reading image %s\n", imagepath);

        // Data read from the header of the BMP file
        unsigned char header[54];
        uint32_t dataPos;
        uint32_t imageSize;
        uint32_t width, height;
        // Actual RGB data
        unsigned char* data;

        // Open the file
        std::FILE* file = std::fopen(imagepath,"rb");
        if (!file)
        {
            std::printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath);
            return 0;
        }

        // Read the header, i.e. the 54 first bytes

        // If less than 54 bytes are read, problem
        if (std::fread(header, 1, 54, file) != 54)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // A BMP files always begins with "BM"
        if ((header[0] != 'B') || (header[1] != 'M'))
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // Make sure this is a 24bpp file
        if (*(int*) &header[0x1e] != 0)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        if (*(int*) &header[0x1c] != 24)
        {
            std::printf("Not a correct BMP file\n");
            return 0;
        }

        // Read the information about the image
        dataPos    = *(int*) &header[0x0a];
        imageSize  = *(int*) &header[0x22];
        width      = *(int*) &header[0x12];
        height     = *(int*) &header[0x16];

        // Some BMP files are misformatted, guess missing information
        if (imageSize == 0)
        {
            imageSize = width * height * 3; // 3 : one byte for each Red, Green and Blue component
        }

        if (dataPos == 0)
        {
            dataPos = 54; // The BMP header is done that way
        }

        // Create a buffer
        data = new unsigned char [imageSize];

        if (data == nullptr)
        {
            std::cerr << "Reserving memory for texture data failed.\n";
            std::fclose(file);
            return 0;
        }

        // Read the actual data from the file into the buffer
        std::fread(data, 1, imageSize, file);

        // Everything is in memory now, the file can be closed
        std::fclose(file);

        // Create one OpenGL texture
        GLuint textureID;
        glGenTextures(1, &textureID);

        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);

        // Give the image to OpenGL
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);

        // OpenGL has now copied the data. Free our own version
        delete[] data;

        // Poor filtering, or ...
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

#define CLAMP_TEXTURES
        // #define REPEAT_TEXTURES

#ifdef CLAMP_TEXTURES
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif

#ifdef REPEAT_TEXTURES
        // ... nice trilinear filtering.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#endif

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glGenerateMipmap(GL_TEXTURE_2D);

        // Return the ID of the texture we just created
        return textureID;
    }

    // Since GLFW 3, glfwLoadTexture2D() has been removed. You have to use another texture loading library,
    // or do it yourself (just like load_BMP_texture and load_DDS_texture)
    //GLuint loadTGA_glfw(const char*  imagepath){
    //
    //    // Create one OpenGL texture
    //    GLuint textureID;
    //    glGenTextures(1, &textureID);
    //
    //    // "Bind" the newly created texture : all future texture functions will modify this texture
    //    glBindTexture(GL_TEXTURE_2D, textureID);
    //
    //    // Read the file, call glTexImage2D with the right parameters
    //    glfwLoadTexture2D(imagepath, 0);
    //
    //    // Nice trilinear filtering.
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    //    glGenerateMipmap(GL_TEXTURE_2D);
    //
    //    // Return the ID of the texture we just created
    //    return textureID;
    //}

#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII

    GLuint load_DDS_texture(const char* imagepath)
    {
        unsigned char header[124];
        std::FILE* fp;

        /* try to open the file */
        fp = std::fopen(imagepath, "rb");
        if (fp == nullptr)
        {
            std::printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath);
            return 0;
        }

        /* verify the type of file */
        char filecode[4];
        std::fread(filecode, 1, 4, fp);
        if (std::strncmp(filecode, "DDS ", 4) != 0)
        {
            std::fclose(fp);
            return 0;
        }

        /* get the surface desc */
        std::fread(&header, 124, 1, fp);

        uint32_t height      = *(uint32_t*) &header[8];
        uint32_t width       = *(uint32_t*) &header[12];
        uint32_t linearSize  = *(uint32_t*) &header[16];
        uint32_t mipMapCount = *(uint32_t*) &header[24];
        uint32_t fourCC      = *(uint32_t*) &header[80];

        unsigned char* buffer;
        uint32_t bufsize;
        /* how big is it going to be including all mipmaps? */
        bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
        buffer = (unsigned char*) malloc(bufsize * sizeof(unsigned char));
        std::fread(buffer, 1, bufsize, fp);
        /* close the file pointer */
        std::fclose(fp);

        uint32_t components = (fourCC == FOURCC_DXT1) ? 3 : 4;
        uint32_t format;
        switch(fourCC)
        {
            case FOURCC_DXT1:
                format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            default:
                free(buffer);
                return 0;
        }

        // Create one OpenGL texture
        GLuint textureID;
        glGenTextures(1, &textureID);

        // "Bind" the newly created texture : all future texture functions will modify this texture
        glBindTexture(GL_TEXTURE_2D, textureID);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        uint32_t blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
        uint32_t offset = 0;

        /* load the mipmaps */
        for (uint32_t level = 0; level < mipMapCount && (width || height); ++level)
        {
            uint32_t size = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
            glCompressedTexImage2D(
                    GL_TEXTURE_2D,
                    level,
                    format,
                    width,
                    height,
                    0,
                    size,
                    buffer + offset);

            offset += size;
            width  /= 2;
            height /= 2;

            // Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
            if (width < 1)
            {
                width = 1;
            }
            if (height < 1)
            {
                height = 1;
            }
        }
        free(buffer);

        return textureID;
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_ddr_phy_reset.C
/// @brief Reset the DDR PHY
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <stdint.h>
#include <string.h>

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_ddr_phy_reset.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{

///
/// @brief Perform a phy reset on all the PHY related to this half-chip (mcbist)
/// @param[in] the mcbist representing the PHY
/// @return FAPI2_RC_SUCCESS iff OK
///
    fapi2::ReturnCode p9_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
    {
        // Cache the name of our target. We can't just keep the pointer from c_str as
        // it points to thread-local space and anything we call might change the string.
        char l_name[fapi2::MAX_ECMD_STRING_LEN];
        strncpy(l_name, mss::c_str(i_target), fapi2::MAX_ECMD_STRING_LEN);

        FAPI_INF("********* %s start *********", __func__);

        // Initialize via scoms. Could be put in to p9_mss_scominit.C if that ever exists BRS.
        FAPI_TRY( mss::phy_scominit(i_target) );

        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::HIGH),
                 "force_mclk_low (set high) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        //
        // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value.
        FAPI_TRY( mss::dp16::setup_sysclk(i_target) );

        //    (Note: The chip should already be in this state.)
        FAPI_DBG("All control signals to the PHYs should already be set to their inactive state, idle state, or inactive values");

        // 2. Assert reset to PHY for 32 memory clocks
        FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", l_name );
        fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32));

        // 3. Deassert reset_n
        FAPI_TRY( mss::change_resetn(i_target, mss::LOW), "change_resetn for %s failed", l_name );

        // 4, 5, 6.
        FAPI_TRY( mss::toggle_zctl(i_target), "toggle_zctl for %s failed", l_name );

        // 7, 8.
        FAPI_TRY( mss::deassert_pll_reset(i_target), "deassert_pll_reset failed for %s", l_name );

        // 9, 10, 11, 12 & 13. Lock dphy_gckn and sysclk
        FAPI_TRY( mss::bang_bang_lock(i_target) );

        // 14?

        //
        //
        //
        //FIXME:    Need to code..      FAPI_TRY(mss_slew_cal(i_target),
        //      "mss_slew_cal Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
        // slew cal successful
//    FAPI_TRY( mss::slew_cal(i_target), "slew_cal for %s failed", l_name);

        FAPI_TRY( mss::ddr_phy_flush(i_target), "ddr_phy_flush failed for %s", l_name );

#ifdef LEAVES_OUTPUT_TO_DIMM_TRISTATE
        // Per J. Bialas, force_mclk_low can be dasserted.
        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::LOW),
                 "force_mclk_low (set low) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
#endif

        // If mss_unmask_ddrphy_errors gets it's own bad rc,
        // it will commit the passed in rc (if non-zero), and return it's own bad rc.
        // Else if mss_unmask_ddrphy_errors runs clean,
        // it will just return the passed in rc.
        //FIXME:    Need to code..   FAPI_TRY(mss_unmask_ddrphy_errors(i_target, rc));

        FAPI_INF("********* %s complete *********", __func__);

    fapi_try_exit:
        return fapi2::current_err;

    }

}
<commit_msg>Add phy control error checking, clean up dp16, apb<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_ddr_phy_reset.C
/// @brief Reset the DDR PHY
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <stdint.h>
#include <string.h>

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_ddr_phy_reset.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{

///
/// @brief Perform a phy reset on all the PHY related to this half-chip (mcbist)
/// @param[in] the mcbist representing the PHY
/// @return FAPI2_RC_SUCCESS iff OK
///
    fapi2::ReturnCode p9_mss_ddr_phy_reset(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
    {
        // Cache the name of our target. We can't just keep the pointer from c_str as
        // it points to thread-local space and anything we call might change the string.
        char l_name[fapi2::MAX_ECMD_STRING_LEN];
        strncpy(l_name, mss::c_str(i_target), fapi2::MAX_ECMD_STRING_LEN);

        FAPI_INF("********* %s start *********", __func__);

        // Initialize via scoms. Could be put in to p9_mss_scominit.C if that ever exists BRS.
        FAPI_TRY( mss::phy_scominit(i_target) );

        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::HIGH),
                 "force_mclk_low (set high) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );

        //
        // 1. Drive all control signals to the PHY to their inactive state, idle state, or inactive value.
        FAPI_TRY( mss::dp16<fapi2::TARGET_TYPE_MCA>().setup_sysclk(i_target) );

        //    (Note: The chip should already be in this state.)
        FAPI_DBG("All control signals to the PHYs should already be set to their inactive state, idle state, or inactive values");

        // 2. Assert reset to PHY for 32 memory clocks
        FAPI_TRY( mss::change_resetn(i_target, mss::HIGH), "change_resetn for %s failed", l_name );
        fapi2::delay(mss::cycles_to_ns(i_target, 32), mss::cycles_to_simcycles(32));

        // 3. Deassert reset_n
        FAPI_TRY( mss::change_resetn(i_target, mss::LOW), "change_resetn for %s failed", l_name );

        // 4, 5, 6.
        FAPI_TRY( mss::toggle_zctl(i_target), "toggle_zctl for %s failed", l_name );

        // 7, 8.
        FAPI_TRY( mss::deassert_pll_reset(i_target), "deassert_pll_reset failed for %s", l_name );

        // 9, 10, 11, 12 & 13. Lock dphy_gckn and sysclk
        FAPI_TRY( mss::bang_bang_lock(i_target) );

        // 14?

        //
        //
        //
        //FIXME:    Need to code..      FAPI_TRY(mss_slew_cal(i_target),
        //      "mss_slew_cal Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
        // slew cal successful
//    FAPI_TRY( mss::slew_cal(i_target), "slew_cal for %s failed", l_name);

        FAPI_TRY( mss::ddr_phy_flush(i_target), "ddr_phy_flush failed for %s", l_name );

#ifdef LEAVES_OUTPUT_TO_DIMM_TRISTATE
        // Per J. Bialas, force_mclk_low can be dasserted.
        FAPI_TRY(mss::change_force_mclk_low(i_target, mss::LOW),
                 "force_mclk_low (set low) Failed rc = 0x%08X", uint64_t(fapi2::current_err) );
#endif

        // If mss_unmask_ddrphy_errors gets it's own bad rc,
        // it will commit the passed in rc (if non-zero), and return it's own bad rc.
        // Else if mss_unmask_ddrphy_errors runs clean,
        // it will just return the passed in rc.
        //FIXME:    Need to code..   FAPI_TRY(mss_unmask_ddrphy_errors(i_target, rc));

        FAPI_INF("********* %s complete *********", __func__);

    fapi_try_exit:
        return fapi2::current_err;

    }

}
<|endoftext|>


<commit_before>// Catch
#include <catch.hpp>
#include <helper.hpp>

// C++ Standard Library
#include <cmath>
#include <array>

// Mantella
#include <mantella>

TEST_CASE("geometry: get2DRotationMatrix(...)", "") {
  const std::array<double, 15>& angles = {{0.0,  45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0, 360.0, -0.0, -45.0, -90.0, -180.0, -225.0, -315.0}};

  for (const auto& angle : angles) {
    arma::Mat<double>::fixed<2, 2> expected({
      std::cos(angle), -std::sin(angle),
      std::sin(angle), std::cos(angle)
    });

    compare(mant::get2DRotationMatrix(angle), expected);
  }
}

TEST_CASE("geometry: get3DRotationMatrix(...)", "") {
  const std::array<double, 14>& rollAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -45, 276, -56, -45.89}};
  const std::array<double, 14>& pitchAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -90, -89, 78, -245}};
  const std::array<double, 14>& yawAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -225, -310, -90, 345}};

  for (const auto& rollAngle : rollAngles) {
    for (const auto& pitchAngle : pitchAngles) {
      for (const auto& yawAngle : yawAngles) {
        arma::Mat<double>::fixed<3, 3> expectedRoll({
          1.0, 0.0, 0.0,
          0.0, std::cos(rollAngle), -std::sin(rollAngle),
          0.0, std::sin(rollAngle), std::cos(rollAngle),
        });

        arma::Mat<double>::fixed<3, 3> expectedPitch({
          std::cos(pitchAngle), 0.0, std::sin(pitchAngle),
          0.0, 1.0, 0.0,
          -std::sin(pitchAngle), 0.0, std::cos(pitchAngle)
        });

        arma::Mat<double>::fixed<3, 3> expectedYaw({
          std::cos(yawAngle), -std::sin(yawAngle), 0.0,
          std::sin(yawAngle), std::cos(yawAngle), 0.0,
          0.0, 0.0, 1.0
        });

        compare<double>(mant::get3DRotationMatrix(rollAngle, pitchAngle, yawAngle), expectedRoll * expectedPitch * expectedYaw);
      }
    }
  }
}

TEST_CASE("geometry: getCircleCircleIntersection(...)", "") {
  arma::Col<double>::fixed<2> expected;

  expected = {-2.5522451636, 1.8231290303};
  compare(mant::getCircleCircleIntersection({-2.0, 3.0}, 1.3, {-1.5, 2.4}, 1.2), expected);

  expected = {-0.1804143359, 0.9753358195};
  compare(mant::getCircleCircleIntersection({1.8, -2.5}, 4.0, {-3.0, 2.0}, 3.0), expected);
}

TEST_CASE("geometry: getCircleSphereIntersection(...)", "") {
  arma::Col<double>::fixed<3> expected;

  expected = {-2.095, 1.1962336728, 0.0};
  compare(mant::getCircleSphereIntersection({-2.0, 0.0, 0.0}, 1.2, {0.0, 0.0, 1.0}, {-3.0, 0.0, 0.0}, 1.5), expected);

  expected = {-2.5522451636, 1.8231290303, 0.0};
  compare(mant::getCircleSphereIntersection({-2.0, 3.0, 0.0}, 1.3, {0.0, 0.0, 1.0}, {-1.5, 2.4, 0.0}, 1.2), expected);

  expected = {-0.1804143359, 0.9753358195, 0.0};
  compare(mant::getCircleSphereIntersection({1.8, -2.5, 0.0}, 4.0, {0.0, 0.0, 1.0}, {-3.0, 2.0, 0.0}, 3.0), expected);
}

<commit_msg>test: Organised geometry tests into sections<commit_after>// Catch
#include <catch.hpp>
#include <helper.hpp>

// C++ Standard Library
#include <cmath>
#include <array>

// Mantella
#include <mantella>

TEST_CASE("geometry: get2DRotationMatrix(...)", "") {
  SECTION("Generates 2D rotation matrix") {
    const std::array<double, 15>& angles = {{0.0,  45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0, 360.0, -0.0, -45.0, -90.0, -180.0, -225.0, -315.0}};

    for (const auto& angle : angles) {
      arma::Mat<double>::fixed<2, 2> expected({
        std::cos(angle), -std::sin(angle),
        std::sin(angle), std::cos(angle)
      });

      compare(mant::get2DRotationMatrix(angle), expected);
    }
  }
}

TEST_CASE("geometry: get3DRotationMatrix(...)", "") {
  SECTION("Generates 3D rotation matrix") {
    const std::array<double, 14>& rollAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -45, 276, -56, -45.89}};
    const std::array<double, 14>& pitchAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -90, -89, 78, -245}};
    const std::array<double, 14>& yawAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -225, -310, -90, 345}};

    for (const auto& rollAngle : rollAngles) {
      for (const auto& pitchAngle : pitchAngles) {
        for (const auto& yawAngle : yawAngles) {
          arma::Mat<double>::fixed<3, 3> expectedRoll({
            1.0, 0.0, 0.0,
            0.0, std::cos(rollAngle), -std::sin(rollAngle),
            0.0, std::sin(rollAngle), std::cos(rollAngle),
          });

          arma::Mat<double>::fixed<3, 3> expectedPitch({
            std::cos(pitchAngle), 0.0, std::sin(pitchAngle),
            0.0, 1.0, 0.0,
            -std::sin(pitchAngle), 0.0, std::cos(pitchAngle)
          });

          arma::Mat<double>::fixed<3, 3> expectedYaw({
            std::cos(yawAngle), -std::sin(yawAngle), 0.0,
            std::sin(yawAngle), std::cos(yawAngle), 0.0,
            0.0, 0.0, 1.0
          });

          compare<double>(mant::get3DRotationMatrix(rollAngle, pitchAngle, yawAngle), expectedRoll * expectedPitch * expectedYaw);
        }
      }
    }
  }
}

TEST_CASE("geometry: getCircleCircleIntersection(...)", "") {
  SECTION("Finds intersection") {
    arma::Col<double>::fixed<2> expected;

    expected = {-2.5522451636, 1.8231290303};
    compare(mant::getCircleCircleIntersection({-2.0, 3.0}, 1.3, {-1.5, 2.4}, 1.2), expected);

    expected = {-0.1804143359, 0.9753358195};
    compare(mant::getCircleCircleIntersection({1.8, -2.5}, 4.0, {-3.0, 2.0}, 3.0), expected);
  }

  expected = {-0.1804143359, 0.9753358195};
  compare(mant::getCircleCircleIntersection({1.8, -2.5}, 4.0, {-3.0, 2.0}, 3.0), expected);
}

TEST_CASE("geometry: getCircleSphereIntersection(...)", "") {
  SECTION("Finds intersection") {
    arma::Col<double>::fixed<3> expected;

    expected = {-2.095, 1.1962336728, 0.0};
    compare(mant::getCircleSphereIntersection({-2.0, 0.0, 0.0}, 1.2, {0.0, 0.0, 1.0}, {-3.0, 0.0, 0.0}, 1.5), expected);

    expected = {-2.5522451636, 1.8231290303, 0.0};
    compare(mant::getCircleSphereIntersection({-2.0, 3.0, 0.0}, 1.3, {0.0, 0.0, 1.0}, {-1.5, 2.4, 0.0}, 1.2), expected);

    expected = {-0.1804143359, 0.9753358195, 0.0};
    compare(mant::getCircleSphereIntersection({1.8, -2.5, 0.0}, 4.0, {0.0, 0.0, 1.0}, {-3.0, 2.0, 0.0}, 3.0), expected);
  }
}

<|endoftext|>


<commit_before>//
// Dll Inject Sample
//
// Copyright (c) 2014 Grigore Stefan, <g_stefan@yahoo.com>
// Created by Grigore Stefan <g_stefan@yahoo.com>
//
// The MIT License (MIT) <http://opensource.org/licenses/MIT>
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef SECURITY_WIN32
#define SECURITY_WIN32
#endif

#include <winsock2.h>
#include <windows.h>
#include <objbase.h>
#include <iads.h>
#include <adshlp.h>
#include <wininet.h>
#include <Iptypes.h>
#include <Iphlpapi.h>
#include <Security.h>
#include <ole2.h>
#include <shlobj.h>
#include <Shobjidl.h>
#include <docobj.h>
#include <mshtml.h>
#include <MsHtmHst.h>
#include <exdisp.h>
#include <exdispid.h>
#include <servprov.h>

static void OutputDebugStringXA(const char *text1,const char *text2) {
	char buf[2048];
	wsprintfA(buf,"%s%s",text1,text2);
	OutputDebugStringA(buf);
};

static void OutputDebugStringXW(const wchar_t *text1,const wchar_t *text2) {
	wchar_t buf[2048];
	wsprintfW(buf,L"%s%s",text1,text2);
	OutputDebugStringW(buf);
};

static void OutputDebugStringZA(const char *text1,HMODULE hmodule,const char *text2) {
	char buf[2048];
	char buf2[2048];

	GetModuleFileName(hmodule,buf2,MAX_PATH);
	wsprintf(buf,"%s %s - %s",text1,buf2,text2);
	OutputDebugStringA(buf);
};

#include "libxyo-win-inject.hpp"

#include "dll-inject-sample-copyright.hpp"
#include "dll-inject-sample-licence.hpp"
#include "dll-inject-sample-version.hpp"

static char             thisProcessFileName[MAX_PATH];
static char             thisModuleFileName[MAX_PATH];
static HINSTANCE        thisModule;
static size_t           loadedModulesSp;
static HMODULE          loadedModules[16384];
static void             thisHookInstance(HMODULE hInstance);
static DWORD		tlsIndex;
//
typedef struct SHookProcess{

	//WSARecv
	LPWSABUF WSARecv_lpBuffers;
	DWORD WSARecv_dwBufferCount;
	LPWSAOVERLAPPED WSARecv_lpOverlapped;

	//WSASend
	LPWSABUF WSASend_lpBuffers;
	DWORD WSASend_dwBufferCount;
	LPWSAOVERLAPPED WSASend_lpOverlapped;

	//
	FILE *recvLog;
	FILE *sendLog;

}HookProcess;

static HookProcess *newHookProcess(){
	HookProcess *hookProcess=new HookProcess();
	//
	hookProcess->WSARecv_lpBuffers=nullptr;
	hookProcess->WSARecv_dwBufferCount=0;
	hookProcess->WSARecv_lpOverlapped=nullptr;
	//
	hookProcess->WSASend_lpBuffers=nullptr;
	hookProcess->WSASend_dwBufferCount=0;
	hookProcess->WSASend_lpOverlapped=nullptr;
	//
	//

	char name[128];
	wsprintf(name,"c:\\tmp\\recv-%p.bin",GetCurrentThreadId());
	hookProcess->recvLog=fopen(name,"ab");
	OutputDebugStringA(name);
	wsprintf(name,"c:\\tmp\\send-%p.bin",GetCurrentThreadId());
	hookProcess->sendLog=fopen(name,"ab");
	OutputDebugStringA(name);
	return hookProcess;
};

static void deleteHookProcess(HookProcess *hookProcess){
	fclose(hookProcess->recvLog);
	fclose(hookProcess->sendLog);
	delete hookProcess;
};

static void checkHookProcess(HookProcess *&hookProcess){
	if(hookProcess==nullptr){
		hookProcess=newHookProcess();
		TlsSetValue(tlsIndex,hookProcess);
	};
};

static HookProcess *getHookProcess(){
	HookProcess *hookProcess=((HookProcess *)TlsGetValue(tlsIndex));
	if(hookProcess==nullptr){
		hookProcess=newHookProcess();
		TlsSetValue(tlsIndex,hookProcess);
	};
	return hookProcess;
};

static void recvHookProcess(HookProcess *hookProcess,char *buf,size_t len){
	checkHookProcess(hookProcess);

	OutputDebugStringA("recvHookProcess");
	fwrite(buf,1,len,hookProcess->recvLog);
	fflush(hookProcess->recvLog);
};

static void sendHookProcess(HookProcess *hookProcess,const char *buf,size_t len){
	checkHookProcess(hookProcess);

	OutputDebugStringA("sendHookProcess");
	fwrite(buf,1,len,hookProcess->sendLog);
	fflush(hookProcess->recvLog);
};

typedef FARPROC (WINAPI *PGetProcAddress)(HMODULE hModule,LPCSTR lpProcName);
static FARPROC WINAPI hook_GetProcAddress(FARPROC originalPorc,HMODULE hModule,LPCSTR lpProcName);
//
#include "new_kernel32.cpp"
#include "new_kernel32___proc.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___proc.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___proc.cpp"
#include "new_kernelbase.cpp"
#include "new_kernelbase___proc.cpp"
//
#include "new_wininet.cpp"
#include "new_wininet___proc.cpp"
#include "new_ws2_32.cpp"
#include "new_ws2_32___proc.cpp"
#include "new_wsock32.cpp"
#include "new_wsock32___proc.cpp"

static XYO::Win::Inject::Hook::HookProc *hookList[]={
//
#include "new_kernel32___hookProc.cpp"
#include "new_kernelbase___hookProc.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___hookProc.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___hookProc.cpp"
//
#include "new_wininet___hookProc.cpp"
#include "new_ws2_32___hookProc.cpp"
#include "new_wsock32___hookProc.cpp"
//

//
	nullptr
};

static void setOriginalFunction(){
#include "new_kernel32___setOriginalFunction.cpp"
#include "new_kernelbase___setOriginalFunction.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___setOriginalFunction.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___setOriginalFunction.cpp"
//
#include "new_wininet___setOriginalFunction.cpp"
#include "new_ws2_32___setOriginalFunction.cpp"
#include "new_wsock32___setOriginalFunction.cpp"
};

FARPROC WINAPI hook_GetProcAddress(FARPROC originalPorc,HMODULE hModule,LPCSTR lpProcName) {
FARPROC retV;
	retV=XYO::Win::Inject::Hook::getProcAddress(hModule,lpProcName,hookList);
	if(retV!=nullptr){
		return retV;
	};
	return (*((PGetProcAddress)originalPorc))(hModule,lpProcName);
};

static LPSTR dllHookSkip[]= {
	"NTDLL.DLL",
	"KERNEL32.DLL",
	"KERNELBASE.DLL",
	"ICMP.DLL",
	"WININET.DLL",
	"WS2_32.DLL",
	"WSOCK32.DLL",
	NULL
};

static void thisHookInstance(HMODULE hInstance) {
	if(XYO::Win::Inject::Hook::processModule(hInstance,hookList,loadedModules,loadedModulesSp,16380,dllHookSkip)){
		char buf[MAX_PATH];
		GetModuleFileName(hInstance,buf,MAX_PATH);
		OutputDebugStringXA("#hook: ",buf);
	};
};

static BOOL isAttached=FALSE;
BOOL APIENTRY DllMain (HINSTANCE hInstance,DWORD reason,LPVOID reserved) {
	reserved;
	hInstance;
	switch(reason) {
		case DLL_PROCESS_ATTACH: {
				OutputDebugString("DLL_PROCESS_ATTACH");
				if(!isAttached) {
					isAttached=TRUE;
					loadedModulesSp=0;
					thisModule=hInstance;
					GetModuleFileName(NULL,thisProcessFileName,MAX_PATH);
					GetModuleFileNameA(hInstance,thisModuleFileName,MAX_PATH);
					tlsIndex=TlsAlloc();
					if(tlsIndex==TLS_OUT_OF_INDEXES){
						return FALSE;
					};
					setOriginalFunction();
                                        //DisableThreadLibraryCalls((HMODULE)hInstance);

					//

					OutputDebugStringA("--- hook ---");
					OutputDebugStringA(thisProcessFileName);
					OutputDebugStringA(thisModuleFileName);
					//
					OutputDebugStringA("--- imports ---");
					thisHookInstance(GetModuleHandle(NULL));
				};
				break;
			};
			break;
		case DLL_PROCESS_DETACH: {
				TlsFree(tlsIndex);
				OutputDebugString("DLL_PROCESS_DETACH");
			};
			break;
		case DLL_THREAD_ATTACH: {
				OutputDebugString("DLL_THREAD_ATTACH");
				TlsSetValue(tlsIndex,newHookProcess());
			};
			break;
		case DLL_THREAD_DETACH: {
				OutputDebugString("DLL_THREAD_DETACH");
				deleteHookProcess((HookProcess *)TlsGetValue(tlsIndex));
			};
			break;
	};
	return TRUE;
};

<commit_msg>update<commit_after>//
// Dll Inject Sample
//
// Copyright (c) 2014 Grigore Stefan, <g_stefan@yahoo.com>
// Created by Grigore Stefan <g_stefan@yahoo.com>
//
// The MIT License (MIT) <http://opensource.org/licenses/MIT>
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef SECURITY_WIN32
#define SECURITY_WIN32
#endif

#include <winsock2.h>
#include <windows.h>
#include <objbase.h>
#include <iads.h>
#include <adshlp.h>
#include <wininet.h>
#include <Iptypes.h>
#include <Iphlpapi.h>
#include <Security.h>
#include <ole2.h>
#include <shlobj.h>
#include <Shobjidl.h>
#include <docobj.h>
#include <mshtml.h>
#include <MsHtmHst.h>
#include <exdisp.h>
#include <exdispid.h>
#include <servprov.h>

static void OutputDebugStringXA(const char *text1,const char *text2) {
	char buf[2048];
	wsprintfA(buf,"%s%s",text1,text2);
	OutputDebugStringA(buf);
};

static void OutputDebugStringXW(const wchar_t *text1,const wchar_t *text2) {
	wchar_t buf[2048];
	wsprintfW(buf,L"%s%s",text1,text2);
	OutputDebugStringW(buf);
};

static void OutputDebugStringZA(const char *text1,HMODULE hmodule,const char *text2) {
	char buf[2048];
	char buf2[2048];

	GetModuleFileName(hmodule,buf2,MAX_PATH);
	wsprintf(buf,"%s %s - %s",text1,buf2,text2);
	OutputDebugStringA(buf);
};

#include "libxyo-win-inject.hpp"

#include "dll-inject-sample-copyright.hpp"
#include "dll-inject-sample-licence.hpp"
#include "dll-inject-sample-version.hpp"

static char             thisProcessFileName[MAX_PATH];
static char             thisModuleFileName[MAX_PATH];
static HINSTANCE        thisModule;
static size_t           loadedModulesSp;
static HMODULE          loadedModules[16384];
static void             thisHookInstance(HMODULE hInstance);
static DWORD		tlsIndex;
//
typedef struct SHookProcess{

	//WSARecv
	LPWSABUF WSARecv_lpBuffers;
	DWORD WSARecv_dwBufferCount;
	LPWSAOVERLAPPED WSARecv_lpOverlapped;

	//WSASend
	LPWSABUF WSASend_lpBuffers;
	DWORD WSASend_dwBufferCount;
	LPWSAOVERLAPPED WSASend_lpOverlapped;

	//
	FILE *recvLog;
	FILE *sendLog;

}HookProcess;

static HookProcess *newHookProcess(){
	HookProcess *hookProcess=new HookProcess();
	//
	hookProcess->WSARecv_lpBuffers=nullptr;
	hookProcess->WSARecv_dwBufferCount=0;
	hookProcess->WSARecv_lpOverlapped=nullptr;
	//
	hookProcess->WSASend_lpBuffers=nullptr;
	hookProcess->WSASend_dwBufferCount=0;
	hookProcess->WSASend_lpOverlapped=nullptr;
	//
	//

	char name[128];
	wsprintf(name,"c:\\tmp\\recv-%p.bin",GetCurrentThreadId());
	hookProcess->recvLog=fopen(name,"ab");
	OutputDebugStringA(name);
	wsprintf(name,"c:\\tmp\\send-%p.bin",GetCurrentThreadId());
	hookProcess->sendLog=fopen(name,"ab");
	OutputDebugStringA(name);
	return hookProcess;
};

static void deleteHookProcess(HookProcess *hookProcess){
	fclose(hookProcess->recvLog);
	fclose(hookProcess->sendLog);
	delete hookProcess;
};

static void checkHookProcess(HookProcess *&hookProcess){
	if(hookProcess==nullptr){
		hookProcess=newHookProcess();
		TlsSetValue(tlsIndex,hookProcess);
	};
};

static HookProcess *getHookProcess(){
	HookProcess *hookProcess=((HookProcess *)TlsGetValue(tlsIndex));
	if(hookProcess==nullptr){
		hookProcess=newHookProcess();
		TlsSetValue(tlsIndex,hookProcess);
	};
	return hookProcess;
};

static void recvHookProcess(HookProcess *hookProcess,char *buf,size_t len){
	checkHookProcess(hookProcess);

	OutputDebugStringA("recvHookProcess");
	fwrite(buf,1,len,hookProcess->recvLog);
	fflush(hookProcess->recvLog);
};

static void sendHookProcess(HookProcess *hookProcess,const char *buf,size_t len){
	checkHookProcess(hookProcess);

	OutputDebugStringA("sendHookProcess");
	fwrite(buf,1,len,hookProcess->sendLog);
	fflush(hookProcess->recvLog);
};

typedef FARPROC (WINAPI *PGetProcAddress)(HMODULE hModule,LPCSTR lpProcName);
static FARPROC WINAPI hook_GetProcAddress(FARPROC originalPorc,HMODULE hModule,LPCSTR lpProcName);
//
#include "new_kernel32.cpp"
#include "new_kernel32___proc.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___proc.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___proc.cpp"
#include "new_kernelbase.cpp"
#include "new_kernelbase___proc.cpp"
//
#include "new_wininet.cpp"
#include "new_wininet___proc.cpp"
#include "new_ws2_32.cpp"
#include "new_ws2_32___proc.cpp"
#include "new_wsock32.cpp"
#include "new_wsock32___proc.cpp"

static XYO::Win::Inject::Hook::HookProc *hookList[]={
//
#include "new_kernel32___hookProc.cpp"
#include "new_kernelbase___hookProc.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___hookProc.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___hookProc.cpp"
//
#include "new_wininet___hookProc.cpp"
#include "new_ws2_32___hookProc.cpp"
#include "new_wsock32___hookProc.cpp"
//

//
	nullptr
};

static void setOriginalFunction(){
#include "new_kernel32___setOriginalFunction.cpp"
#include "new_kernelbase___setOriginalFunction.cpp"
#include "new_api-ms-win-core-libraryloader-l1-2-0___setOriginalFunction.cpp"
#include "new_api-ms-win-core-processthreads-l1-1-2___setOriginalFunction.cpp"
//
#include "new_wininet___setOriginalFunction.cpp"
#include "new_ws2_32___setOriginalFunction.cpp"
#include "new_wsock32___setOriginalFunction.cpp"
};

FARPROC WINAPI hook_GetProcAddress(FARPROC originalPorc,HMODULE hModule,LPCSTR lpProcName) {
FARPROC retV;
	retV=XYO::Win::Inject::Hook::getProcAddress(hModule,lpProcName,hookList);
	if(retV!=nullptr){
		return retV;
	};
	return (*((PGetProcAddress)originalPorc))(hModule,lpProcName);
};

static LPSTR dllHookSkip[]= {
	"NTDLL.DLL",
	"KERNEL32.DLL",
	"KERNELBASE.DLL",
	"ICMP.DLL",
	"WININET.DLL",
	"WS2_32.DLL",
	"WSOCK32.DLL",
	NULL
};

static void thisHookInstance(HMODULE hInstance) {
	if(XYO::Win::Inject::Hook::processModule(hInstance,hookList,loadedModules,loadedModulesSp,16380,dllHookSkip)){
		char buf[MAX_PATH];
		GetModuleFileName(hInstance,buf,MAX_PATH);
		OutputDebugStringXA("#hook: ",buf);
	};
};

static BOOL isAttached=FALSE;
BOOL APIENTRY DllMain (HINSTANCE hInstance,DWORD reason,LPVOID reserved) {
	reserved;
	hInstance;
	switch(reason) {
		case DLL_PROCESS_ATTACH: {
				OutputDebugString("DLL_PROCESS_ATTACH");
				if(!isAttached) {
					isAttached=TRUE;
					loadedModulesSp=0;
					thisModule=hInstance;
					GetModuleFileName(NULL,thisProcessFileName,MAX_PATH);
					GetModuleFileNameA(hInstance,thisModuleFileName,MAX_PATH);
					tlsIndex=TlsAlloc();
					if(tlsIndex==TLS_OUT_OF_INDEXES){
						return FALSE;
					};
					setOriginalFunction();
                                        //DisableThreadLibraryCalls((HMODULE)hInstance);

					//

					OutputDebugStringA("--- hook ---");
					OutputDebugStringA(thisProcessFileName);
					OutputDebugStringA(thisModuleFileName);
					//
					OutputDebugStringA("--- imports ---");
					thisHookInstance(GetModuleHandle(NULL));
				};
				break;
			};
			break;
		case DLL_PROCESS_DETACH: {
				OutputDebugString("DLL_PROCESS_DETACH");
				TlsFree(tlsIndex);
			};
			break;
		case DLL_THREAD_ATTACH: {
				OutputDebugString("DLL_THREAD_ATTACH");
				TlsSetValue(tlsIndex,newHookProcess());
			};
			break;
		case DLL_THREAD_DETACH: {
				OutputDebugString("DLL_THREAD_DETACH");
				deleteHookProcess((HookProcess *)TlsGetValue(tlsIndex));
			};
			break;
	};
	return TRUE;
};

<|endoftext|>


<commit_before>#include <Python.h>
#include "Quantuccia/ql/time/calendar.hpp"
#include "Quantuccia/ql/time/date.hpp"
#include "Quantuccia/ql/time/calendars/unitedkingdom.hpp"

static PyObject*
united_kingdom_is_business_day(PyObject *self, PyObject *args)
{
	int year;
	int month;
	int day;
	if (!PyArg_ParseTuple(args, "bbb|", &year, &month, &day))
        return NULL;
	QuantLib::Day d(day);
	QuantLib::Month m = static_cast<QuantLib::Month>(month);
	QuantLib::Year y(year);
	QuantLib::Date date(d, m, y);
	QuantLib::UnitedKingdom calendar(QuantLib::UnitedKingdom::Exchange);
    return Py_True;
	bool result = calendar.isBusinessDay(&date);
	if (result) {
		return Py_True;
	} else {
		return Py_False;
	}
}

static PyMethodDef QuantucciaMethods[] = {
	{"united_kingdom_is_business_day", (PyCFunction)united_kingdom_is_business_day, METH_VARARGS, NULL},
	{NULL, NULL, 0, NULL}
};

static struct PyModuleDef quantuccia_module_def = {
	PyModuleDef_HEAD_INIT,
	"quantuccia",
	NULL,
	-1,
	QuantucciaMethods,
	NULL,
	NULL,
	NULL,
	NULL
};

PyMODINIT_FUNC PyInit_quantuccia(void){
    PyObject *m;
    m = PyModule_Create(&quantuccia_module_def);
    return m;
}
<commit_msg>Return statement bisection.<commit_after>#include <Python.h>
#include "Quantuccia/ql/time/calendar.hpp"
#include "Quantuccia/ql/time/date.hpp"
#include "Quantuccia/ql/time/calendars/unitedkingdom.hpp"

static PyObject*
united_kingdom_is_business_day(PyObject *self, PyObject *args)
{
	int year;
	int month;
	int day;
	if (!PyArg_ParseTuple(args, "bbb|", &year, &month, &day))
        return NULL;
	QuantLib::Day d(day);
	QuantLib::Month m = static_cast<QuantLib::Month>(month);
	QuantLib::Year y(year);
	return Py_True;
	QuantLib::Date date(d, m, y);
	QuantLib::UnitedKingdom calendar(QuantLib::UnitedKingdom::Exchange);
    return Py_True;
	bool result = calendar.isBusinessDay(&date);
	if (result) {
		return Py_True;
	} else {
		return Py_False;
	}
}

static PyMethodDef QuantucciaMethods[] = {
	{"united_kingdom_is_business_day", (PyCFunction)united_kingdom_is_business_day, METH_VARARGS, NULL},
	{NULL, NULL, 0, NULL}
};

static struct PyModuleDef quantuccia_module_def = {
	PyModuleDef_HEAD_INIT,
	"quantuccia",
	NULL,
	-1,
	QuantucciaMethods,
	NULL,
	NULL,
	NULL,
	NULL
};

PyMODINIT_FUNC PyInit_quantuccia(void){
    PyObject *m;
    m = PyModule_Create(&quantuccia_module_def);
    return m;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <random>
#include <chrono>
#include <algorithm>
#include <stack>

using namespace std;

template <typename T>
class AVLNode {
public:
	T data;
	AVLNode *left, *right;
	int height;

	AVLNode()
		:left(NULL), right(NULL), height(1)
	{}
	AVLNode(const T &data)
		:data(data), left(NULL), right(NULL), height(1)
	{}
};

template <typename T>
class AVLTree {
private:
	AVLNode<T> *vRoot;
	AVLNode<T> *root;
	int nodeCnt;

public:
	AVLTree() {
		this->vRoot = new AVLNode<T>();
		this->root = NULL;
		this->nodeCnt = 0;
	}

	~AVLTree() {
		delete this->vRoot;
	}

	/* General Methods of AVL Tree. */

public:
	AVLNode<T>* insert(const T &data) {
		stack<AVLNode<T>*> route;
		AVLNode<T> *pNew = new AVLNode<T>(data);

		if(root == NULL) {
			vRoot->right = root = pNew;
		} else {
			AVLNode<T> *parent = vRoot, *cur = root;

			route.push(vRoot);

			while(cur) {
				route.push(cur);

				parent = cur;

				if(data < cur->data)
					cur = cur->left;
				else if(data > cur->data)
					cur = cur->right;
				else {
					delete pNew;
					return NULL;
				}
			}

			if(data < parent->data)
				parent->left = pNew;
			else
				parent->right = pNew;
		}

		balance(route);

		++nodeCnt;
		return pNew;
	}

	bool remove(const T &data) {
		stack<AVLNode<T>*> route1, route2;
		AVLNode<T> *parent = vRoot, *cur = root;

		route1.push(vRoot);

		while(cur) {
			AVLNode<T> *tmp = cur;

			if(data < cur->data)
				cur = cur->left;
			else if(data > cur->data)
				cur = cur->right;
			else
				break;

			route1.push(tmp);

			parent = tmp;
		}

		if(!cur) {
			return false;
		} else {
			bool r2Flag = false;
			AVLNode<T> *pDel = cur, *pRep;

			if(!pDel->right) {
				pRep = pDel->left;
			} else {
				AVLNode<T> *p = pDel, *c = pDel->right;

				route2.push(pDel);

				while(c->left) {
					route2.push(c);
					p = c;
					c = c->left;
				}
				route1.push(c);

				if(pDel->right == c) {
					c->left = pDel->left;
				} else {
					r2Flag = true;
					p->left = c->right;
					c->left = pDel->left;
					c->right = pDel->right;
				}
				pRep = c;
			}

			if(parent->left == pDel)
				parent->left = pRep;
			else
				parent->right = pRep;

			if(pDel == root) {
				vRoot->right = root = pRep;
			}

			if(r2Flag) {
				balance(route2);
				pRep->right = pDel->right;
			}
			balance(route1);

			delete pDel;
			--nodeCnt;

			return true;
		}
	}

	AVLNode<T>* search(const T &data) {
		AVLNode<T> *cur = root;
		while(cur) {
			if(data < cur->data)
				cur = cur->left;
			else if(data > cur->data)
				cur = cur->right;
			else
				break;
		}
		return cur;
	}

	inline int count(void) {
		return nodeCnt;
	}

	inline int getHeight(void) {
		return getHeight(root);
	}

private:
	inline int getHeight(AVLNode<T> *node) {
		return (node ? node->height : 0);
	}

	/* Methods that balance AVL Tree. */

private:
	void balance(stack<AVLNode<T>*> &route) {
		if(route.empty())
			return;

		AVLNode<T> *parent, *cur = route.top(); route.pop();

		while(!route.empty()) {
			updateHeight(cur);
			parent = route.top(); route.pop();

			if(parent->left == cur)
				parent->left = balance(cur);
			else
				parent->right = balance(cur);

			if(cur == root)
				root = vRoot->right;

			cur = parent;
		}
	}

	AVLNode<T>* balance(AVLNode<T> *node) {
		int bf = balanceFactor(node);
		if(bf > 1) {
			if(balanceFactor(node->left) > 0) {
				node = rotateLL(node);
			} else {
				node = rotateLR(node);
			}
		} else if(bf < -1) {
			if(balanceFactor(node->right) > 0) {
				node = rotateRL(node);
			} else {
				node = rotateRR(node);
			}
		}
		return node;
	}

	void updateHeight(AVLNode<T> *node) {
		int h1 = getHeight(node->left);
		int h2 = getHeight(node->right);
		node->height = (h1 > h2 ? h1 : h2) + 1;
	}

	inline int balanceFactor(AVLNode<T> *node) {
		return getHeight(node->left) - getHeight(node->right);
	}

	AVLNode<T>* rotateLL(AVLNode<T> *node) {
		AVLNode<T> *child = node->left;
		node->left = child->right;
		child->right = node;

		updateHeight(node);
		updateHeight(child);

		return child;
	}
	AVLNode<T>* rotateRR(AVLNode<T> *node) {
		AVLNode<T> *child = node->right;
		node->right = child->left;
		child->left = node;

		updateHeight(node);
		updateHeight(child);

		return child;
	}
	AVLNode<T>* rotateLR(AVLNode<T> *node) {
		node->left = rotateRR(node->left);
		return rotateLL(node);
	}
	AVLNode<T>* rotateRL(AVLNode<T> *node) {
		node->right = rotateLL(node->right);
		return rotateRR(node);
	}

	/* Methods that visualize AVL Tree. */

public:
	void visualizeTree(void) {
		int h = getHeight();
		bool *flag = new bool[h];
		visualizeTree(root, flag, 0);
		delete[] flag;
	}

private:
	void visualizeTree(AVLNode<T> *root, bool *flag, int level) {
		for(int i=0; i<level-1; ++i) {
			if(flag[i])	cout << "│  ";
			else		cout << "   ";
		}
		if(level > 0) {
			if(root) {
				if(flag[level-1]) cout << "├──" << root->data << endl;
				else			  cout << "└──" << root->data << endl;
			} else {
				if(flag[level-1]) cout << "├──" << "nil" << endl;
				else			  cout << "└──" << "nil" << endl;
				return;
			}
		} else {
			if(root) cout << root->data << endl;
			else return;
		}
		flag[level] = true;
		visualizeTree(root->left, flag, level+1);
		flag[level] = false;
		visualizeTree(root->right, flag, level+1);
	}
};

template <typename T>
void print_array(T arr[], int N) {
	if(N > 1000) {
		cout << "Omission of print_array for preventing tainted stdout." << endl;
		return;
	}
	for(int i=0; i<N; ++i)
		cout << arr[i] << " ";
	cout << endl;
}

int main(void)
{
	int N;
	int mode, detail;
	int *data;
	AVLTree<int> tree;
	time_t start_time, end_time;

	ios::sync_with_stdio(false);

	cout << endl;
	cout << "*******************************************" << endl;
	cout << "****** AVL Tree and Tester By taeguk ******" << endl;
	cout << "*******************************************" << endl;
	cout << endl;

	cout << "Enter # of data >> ";
	cin >> N;

	cout << "Select mode * 1(random), 0(worst) >> ";
	cin >> mode;

	cout << "Detail Information * 1(yes), 0(no) >> ";
	cin >> detail;

	data = new int[N];
	for(int i=0; i<N; ++i)
		data[i] = i+1;

	if(mode) {
		unsigned seed = chrono::system_clock::now().time_since_epoch().count();
		shuffle(data, data+N, default_random_engine(seed));
	}

	cout << endl;
	if(detail) {
		cout << "Array of data -------------" << endl;
		print_array(data, N);
		cout << endl;
	}

	cout << "Insert Test ------------" << endl;
	start_time = clock();
	for(int i=0; i<N; ++i)
		tree.insert(data[i]);
	end_time = clock();
	if(detail) tree.visualizeTree();
	cout << "[I] Count of node : " << tree.count() << endl;
	cout << "[I] Height of tree : " << tree.getHeight() << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "Remove Test (odd number) ------------" << endl;
	start_time = clock();
	for(int i=1; i<=N; i+=2)
		tree.remove(i);
	end_time = clock();
	if(detail) tree.visualizeTree();
	cout << "[I] Count of node : " << tree.count() << endl;
	cout << "[I] Height of tree : " << tree.getHeight() << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "Search Test ------------" << endl;
	bool searchSuccess = true;
	start_time = clock();
	for(int i=1; i<=N; ++i) {
		if(i%2 == (tree.search(i)?1:0)) {
			searchSuccess = false;
			break;
		}
	}
	end_time = clock();
	if(searchSuccess)
		cout << "[*] Search Test PASS!" << endl;
	else
		cout << "[!] Search Test FAIL!" << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "            Thank you!" << endl << endl;

	return 0;
}

<commit_msg>change to key-value<commit_after>#include <iostream>
#include <random>
#include <chrono>
#include <algorithm>
#include <stack>

using namespace std;

template <typename K, typename V>
class AVLNode {
public:
	K key;
	V value;
	AVLNode *left, *right;
	int height;

	AVLNode()
		:left(NULL), right(NULL), height(1)
	{}
	AVLNode(const K &key, const V &value)
		:key(key), value(value), left(NULL), right(NULL), height(1)
	{}
};

template <typename K, typename V>
class AVLTree {
private:
	AVLNode<K,V> *vRoot;
	AVLNode<K,V> *root;
	int nodeCnt;

public:
	AVLTree() {
		this->vRoot = new AVLNode<K,V>();
		this->root = NULL;
		this->nodeCnt = 0;
	}

	~AVLTree() {
		delete this->vRoot;
	}

	/* General Methods of AVL Tree. */

public:
	const AVLNode<K,V>* insert(const K &key, const V &value) {
		stack<AVLNode<K,V>*> route;
		auto pNew = new AVLNode<K,V>(key, value);

		if(root == NULL) {
			vRoot->right = root = pNew;
		} else {
			auto parent = vRoot, cur = root;

			route.push(vRoot);

			while(cur) {
				route.push(cur);

				parent = cur;

				if(key < cur->key)
					cur = cur->left;
				else if(key > cur->key)
					cur = cur->right;
				else {
					delete pNew;
					return NULL;
				}
			}

			if(key < parent->key)
				parent->left = pNew;
			else
				parent->right = pNew;
		}

		balance(route);

		++nodeCnt;
		return pNew;
	}

	bool remove(const K &key) {
		stack<AVLNode<K,V>*> route1, route2;
		auto parent = vRoot, cur = root;

		route1.push(vRoot);

		while(cur) {
			auto tmp = cur;

			if(key < cur->key)
				cur = cur->left;
			else if(key > cur->key)
				cur = cur->right;
			else
				break;

			route1.push(tmp);

			parent = tmp;
		}

		if(!cur) {
			return false;
		} else {
			bool r2Flag = false;
			auto *pDel = cur;
			decltype(pDel) pRep;

			if(!pDel->right) {
				pRep = pDel->left;
			} else {
				auto *p = pDel, *c = pDel->right;

				route2.push(pDel);

				while(c->left) {
					route2.push(c);
					p = c;
					c = c->left;
				}
				route1.push(c);

				if(pDel->right == c) {
					c->left = pDel->left;
				} else {
					r2Flag = true;
					p->left = c->right;
					c->left = pDel->left;
					c->right = pDel->right;
				}
				pRep = c;
			}

			if(parent->left == pDel)
				parent->left = pRep;
			else
				parent->right = pRep;

			if(pDel == root) {
				vRoot->right = root = pRep;
			}

			if(r2Flag) {
				balance(route2);
				pRep->right = pDel->right;
			}
			balance(route1);

			delete pDel;
			--nodeCnt;

			return true;
		}
	}

	const AVLNode<K,V>* search(const K &key) {
		auto cur = root;
		while(cur) {
			if(key < cur->key)
				cur = cur->left;
			else if(key > cur->key)
				cur = cur->right;
			else
				break;
		}
		return cur;
	}

	inline int count(void) {
		return nodeCnt;
	}

	inline int getHeight(void) {
		return getHeight(root);
	}

private:
	inline int getHeight(AVLNode<K,V> *node) {
		return (node ? node->height : 0);
	}

	/* Methods that balance AVL Tree. */

private:
	void balance(stack<AVLNode<K,V>*> &route) {
		if(route.empty())
			return;

		AVLNode<K,V> *parent, *cur = route.top(); route.pop();

		while(!route.empty()) {
			updateHeight(cur);
			parent = route.top(); route.pop();

			if(parent->left == cur)
				parent->left = balance(cur);
			else
				parent->right = balance(cur);

			if(cur == root)
				root = vRoot->right;

			cur = parent;
		}
	}

	AVLNode<K,V>* balance(AVLNode<K,V> *node) {
		int bf = balanceFactor(node);
		if(bf > 1) {
			if(balanceFactor(node->left) > 0) {
				node = rotateLL(node);
			} else {
				node = rotateLR(node);
			}
		} else if(bf < -1) {
			if(balanceFactor(node->right) > 0) {
				node = rotateRL(node);
			} else {
				node = rotateRR(node);
			}
		}
		return node;
	}

	void updateHeight(AVLNode<K,V> *node) {
		int h1 = getHeight(node->left);
		int h2 = getHeight(node->right);
		node->height = (h1 > h2 ? h1 : h2) + 1;
	}

	inline int balanceFactor(AVLNode<K,V> *node) {
		return getHeight(node->left) - getHeight(node->right);
	}

	AVLNode<K,V>* rotateLL(AVLNode<K,V> *node) {
		auto *child = node->left;
		node->left = child->right;
		child->right = node;

		updateHeight(node);
		updateHeight(child);

		return child;
	}
	AVLNode<K,V>* rotateRR(AVLNode<K,V> *node) {
		auto *child = node->right;
		node->right = child->left;
		child->left = node;

		updateHeight(node);
		updateHeight(child);

		return child;
	}
	AVLNode<K,V>* rotateLR(AVLNode<K,V> *node) {
		node->left = rotateRR(node->left);
		return rotateLL(node);
	}
	AVLNode<K,V>* rotateRL(AVLNode<K,V> *node) {
		node->right = rotateLL(node->right);
		return rotateRR(node);
	}

	/* Methods that visualize AVL Tree. */

public:
	void visualizeTree(void) {
		int h = getHeight();
		bool *flag = new bool[h];
		visualizeTree(root, flag, 0);
		delete[] flag;
	}

private:
	void visualizeTree(AVLNode<K,V> *root, bool *flag, int level) {
		for(int i=0; i<level-1; ++i) {
			if(flag[i])	cout << "│  ";
			else		cout << "   ";
		}
		if(level > 0) {
			if(root) {
				if(flag[level-1]) cout << "├──" << root->key << endl;
				else			  cout << "└──" << root->key << endl;
			} else {
				if(flag[level-1]) cout << "├──" << "nil" << endl;
				else			  cout << "└──" << "nil" << endl;
				return;
			}
		} else {
			if(root) cout << root->key << endl;
			else return;
		}
		flag[level] = true;
		visualizeTree(root->left, flag, level+1);
		flag[level] = false;
		visualizeTree(root->right, flag, level+1);
	}
};

template <typename T>
void print_array(T arr[], int N) {
	if(N > 1000) {
		cout << "Omission of print_array for preventing tainted stdout." << endl;
		return;
	}
	for(int i=0; i<N; ++i)
		cout << arr[i] << " ";
	cout << endl;
}

int main(void)
{
	int N;
	int mode, detail;
	int *data;
	AVLTree<int,int> tree;
	time_t start_time, end_time;

	ios::sync_with_stdio(false);

	cout << endl;
	cout << "*******************************************" << endl;
	cout << "****** AVL Tree and Tester By taeguk ******" << endl;
	cout << "*******************************************" << endl;
	cout << endl;

	cout << "Enter # of data >> ";
	cin >> N;

	cout << "Select mode * 1(random), 0(worst) >> ";
	cin >> mode;

	cout << "Detail Information * 1(yes), 0(no) >> ";
	cin >> detail;

	data = new int[N];
	for(int i=0; i<N; ++i)
		data[i] = i+1;

	if(mode) {
		unsigned seed = chrono::system_clock::now().time_since_epoch().count();
		shuffle(data, data+N, default_random_engine(seed));
	}

	cout << endl;
	if(detail) {
		cout << "Array of data -------------" << endl;
		print_array(data, N);
		cout << endl;
	}

	cout << "Insert Test ------------" << endl;
	start_time = clock();
	for(int i=0; i<N; ++i)
		tree.insert(data[i], data[i]);
	end_time = clock();
	if(detail) tree.visualizeTree();
	cout << "[I] Count of node : " << tree.count() << endl;
	cout << "[I] Height of tree : " << tree.getHeight() << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "Remove Test (odd number) ------------" << endl;
	start_time = clock();
	for(int i=1; i<=N; i+=2)
		tree.remove(i);
	end_time = clock();
	if(detail) tree.visualizeTree();
	cout << "[I] Count of node : " << tree.count() << endl;
	cout << "[I] Height of tree : " << tree.getHeight() << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "Search Test ------------" << endl;
	bool searchSuccess = true;
	start_time = clock();
	for(int i=1; i<=N; ++i) {
		if(i%2 == (tree.search(i)?1:0)) {
			searchSuccess = false;
			break;
		}
	}
	end_time = clock();
	if(searchSuccess)
		cout << "[*] Search Test PASS!" << endl;
	else
		cout << "[!] Search Test FAIL!" << endl;
	cout << "[I] Progress Time : " << (float)(end_time-start_time)/CLOCKS_PER_SEC << "sec" << endl << endl;

	cout << "            Thank you!" << endl << endl;

	return 0;
}

<|endoftext|>