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

  Program:   Visualization Toolkit
  Module:    vtkDataObjectTree.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 "vtkDataObjectTree.h"

#include "vtkDataObjectTreeIterator.h"
#include "vtkDataObjectTreeInternals.h"
#include "vtkDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationStringKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"

//----------------------------------------------------------------------------
vtkDataObjectTree::vtkDataObjectTree()
{
  this->Internals = new vtkDataObjectTreeInternals;
}

//----------------------------------------------------------------------------
vtkDataObjectTree::~vtkDataObjectTree()
{
  delete this->Internals;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetNumberOfChildren(unsigned int num)
{
  this->Internals->Children.resize(num);
  this->Modified();
}

//----------------------------------------------------------------------------
unsigned int vtkDataObjectTree::GetNumberOfChildren()
{
  return static_cast<unsigned int>(this->Internals->Children.size());
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetChild(unsigned int index, vtkDataObject* dobj)
{
  if (this->Internals->Children.size() <= index)
    {
    this->SetNumberOfChildren(index+1);
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  if(item.DataObject!=dobj)
    {
    item.DataObject = dobj;
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::RemoveChild(unsigned int index)
{
  if (this->Internals->Children.size() <= index)
    {
    vtkErrorMacro("The input index is out of range.");
    return;
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  item.DataObject = NULL;
  this->Internals->Children.erase(this->Internals->Children.begin()+index);
  this->Modified();
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataObjectTree::GetChild(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    return this->Internals->Children[index].DataObject;
    }

  return 0;
}

//----------------------------------------------------------------------------
vtkInformation* vtkDataObjectTree::GetChildMetaData(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    vtkDataObjectTreeItem& item = this->Internals->Children[index];
    if (!item.MetaData)
      {
      // New vtkInformation is allocated is none is already present.
      item.MetaData.TakeReference(vtkInformation::New());
      }
    return item.MetaData;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetChildMetaData(unsigned int index, vtkInformation* info)
{
  if (this->Internals->Children.size() <= index)
    {
    this->SetNumberOfChildren(index+1);
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  item.MetaData = info;
}

//----------------------------------------------------------------------------
int vtkDataObjectTree::HasChildMetaData(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    vtkDataObjectTreeItem& item = this->Internals->Children[index];
    return (item.MetaData.GetPointer() != NULL)? 1 : 0;
    }

  return 0;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::CopyStructure(vtkCompositeDataSet* compositeSource)
{
  if(!compositeSource)
    {
    return;
    }
  vtkDataObjectTree* source = vtkDataObjectTree::SafeDownCast(compositeSource);
  if (source == this)
    {
    return;
    }

  this->Internals->Children.clear();
  if (!source)
    {
    //WARNING:
    //If we copy the structure of from a non-tree composite data set
    //the "structure" is just is the total number of blocks (nill or not)
    //To do: We should probably also copy meta data as well.
    int totalNumBlocks=0;
    vtkCompositeDataIterator* iter = compositeSource->NewIterator();
    iter->SkipEmptyNodesOff();
    for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
      {
      totalNumBlocks++;
      }
    this->Internals->Children.resize(totalNumBlocks);
    iter->Delete();
    return;
    }

  this->Internals->Children.resize(source->Internals->Children.size());

  vtkDataObjectTreeInternals::Iterator srcIter =
    source->Internals->Children.begin();
  vtkDataObjectTreeInternals::Iterator myIter =
    this->Internals->Children.begin();
  for (; srcIter != source->Internals->Children.end(); ++srcIter, myIter++)
    {
    vtkDataObjectTree* compositeSrc =
      vtkDataObjectTree::SafeDownCast(srcIter->DataObject);
    if (compositeSrc)
      {
      vtkDataObjectTree* copy = compositeSrc->NewInstance();
      myIter->DataObject.TakeReference(copy);
      copy->CopyStructure(compositeSrc);
      }

    // shallow copy meta data.
    if (srcIter->MetaData)
      {
      vtkInformation* info = vtkInformation::New();
      info->Copy(srcIter->MetaData, /*deep=*/0);
      myIter->MetaData = info;
      info->FastDelete();
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
vtkCompositeDataIterator* vtkDataObjectTree::NewIterator()
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::New();
  iter->SetDataSet(this);
  return iter;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetDataSet(vtkCompositeDataIterator* iter,
  vtkDataObject* dataObj)
{
  vtkDataObjectTreeIterator* treeIter = vtkDataObjectTreeIterator::SafeDownCast(iter);
  if(treeIter)
    {
    this->SetDataSetFrom(treeIter,dataObj);
    return;
    }

  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return;
    }

  vtkDataObjectTree* parent = this;
  unsigned int index = iter->GetCurrentFlatIndex();
  parent->SetChild(index, dataObj);
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetDataSetFrom(vtkDataObjectTreeIterator* iter,
  vtkDataObject* dataObj)
{
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return;
    }

  parent->SetChild(index.back(), dataObj);
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataObjectTree::GetDataSet(vtkCompositeDataIterator* compositeIter)
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->GetChild(index.back());
}

//----------------------------------------------------------------------------
vtkInformation* vtkDataObjectTree::GetMetaData(vtkCompositeDataIterator* compositeIter)
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->GetChildMetaData(index.back());
}

//----------------------------------------------------------------------------
int vtkDataObjectTree::HasMetaData(vtkCompositeDataIterator* compositeIter)
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->HasChildMetaData(index.back());
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::ShallowCopy(vtkDataObject* src)
{
  if (src == this)
    {
    return;
    }

  this->Internals->Children.clear();
  this->Superclass::ShallowCopy(src);

  vtkDataObjectTree* from = vtkDataObjectTree::SafeDownCast(src);
  if (from)
    {
    unsigned int numChildren = from->GetNumberOfChildren();
    this->SetNumberOfChildren(numChildren);
    for (unsigned int cc=0; cc < numChildren; cc++)
      {
      vtkDataObject* child = from->GetChild(cc);
      if (child)
        {
        if (child->IsA("vtkDataObjectTree"))
          {
          vtkDataObject* clone = child->NewInstance();
          clone->ShallowCopy(child);
          this->SetChild(cc, clone);
          clone->FastDelete();
          }
        else
          {
          this->SetChild(cc, child);
          }
        }
      if (from->HasChildMetaData(cc))
        {
        vtkInformation* toInfo = this->GetChildMetaData(cc);
        toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/0);
        }
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::DeepCopy(vtkDataObject* src)
{
  if (src == this)
    {
    return;
    }

  this->Internals->Children.clear();
  this->Superclass::DeepCopy(src);

  vtkDataObjectTree* from = vtkDataObjectTree::SafeDownCast(src);
  if (from)
    {
    unsigned int numChildren = from->GetNumberOfChildren();
    this->SetNumberOfChildren(numChildren);
    for (unsigned int cc=0; cc < numChildren; cc++)
      {
      vtkDataObject* fromChild = from->GetChild(cc);
      if (fromChild)
        {
        vtkDataObject* toChild = fromChild->NewInstance();
        toChild->DeepCopy(fromChild);
        this->SetChild(cc, toChild);
        toChild->FastDelete();
        if (from->HasChildMetaData(cc))
          {
          vtkInformation* toInfo = this->GetChildMetaData(cc);
          toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/1);
          }
        }
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::Initialize()
{
  this->Internals->Children.clear();
  this->Superclass::Initialize();
}

//----------------------------------------------------------------------------
vtkIdType vtkDataObjectTree::GetNumberOfPoints()
{
  vtkIdType numPts = 0;
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(this->NewIterator());
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    vtkDataSet* ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
    if (ds)
      {
      numPts += ds->GetNumberOfPoints();
      }
    }
  iter->Delete();
  return numPts;
}

//----------------------------------------------------------------------------
unsigned long vtkDataObjectTree::GetActualMemorySize()
{
  unsigned long memSize = 0;
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(this->NewIterator());
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    vtkDataObject* dobj = iter->GetCurrentDataObject();
    memSize += dobj->GetActualMemorySize();
    }
  iter->Delete();
  return memSize;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Number Of Children: " << this->GetNumberOfChildren() << endl;
  for (unsigned int cc=0; cc < this->GetNumberOfChildren(); cc++)
    {
    vtkDataObject* child = this->GetChild(cc);
    if (child)
      {
      os << indent << "Child " << cc << ": " << child->GetClassName() << endl;
      child->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Child " << cc << ": NULL" << endl;
      }
    }
}
<commit_msg>Fix bug in vtkDataObjectTree::GetDataSet(vtkCompositeDataIterator*)<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDataObjectTree.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 "vtkDataObjectTree.h"

#include "vtkDataObjectTreeIterator.h"
#include "vtkDataObjectTreeInternals.h"
#include "vtkDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationStringKey.h"
#include "vtkInformationIntegerKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"

//----------------------------------------------------------------------------
vtkDataObjectTree::vtkDataObjectTree()
{
  this->Internals = new vtkDataObjectTreeInternals;
}

//----------------------------------------------------------------------------
vtkDataObjectTree::~vtkDataObjectTree()
{
  delete this->Internals;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetNumberOfChildren(unsigned int num)
{
  this->Internals->Children.resize(num);
  this->Modified();
}

//----------------------------------------------------------------------------
unsigned int vtkDataObjectTree::GetNumberOfChildren()
{
  return static_cast<unsigned int>(this->Internals->Children.size());
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetChild(unsigned int index, vtkDataObject* dobj)
{
  if (this->Internals->Children.size() <= index)
    {
    this->SetNumberOfChildren(index+1);
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  if(item.DataObject!=dobj)
    {
    item.DataObject = dobj;
    this->Modified();
    }
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::RemoveChild(unsigned int index)
{
  if (this->Internals->Children.size() <= index)
    {
    vtkErrorMacro("The input index is out of range.");
    return;
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  item.DataObject = NULL;
  this->Internals->Children.erase(this->Internals->Children.begin()+index);
  this->Modified();
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataObjectTree::GetChild(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    return this->Internals->Children[index].DataObject;
    }

  return 0;
}

//----------------------------------------------------------------------------
vtkInformation* vtkDataObjectTree::GetChildMetaData(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    vtkDataObjectTreeItem& item = this->Internals->Children[index];
    if (!item.MetaData)
      {
      // New vtkInformation is allocated is none is already present.
      item.MetaData.TakeReference(vtkInformation::New());
      }
    return item.MetaData;
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetChildMetaData(unsigned int index, vtkInformation* info)
{
  if (this->Internals->Children.size() <= index)
    {
    this->SetNumberOfChildren(index+1);
    }

  vtkDataObjectTreeItem& item = this->Internals->Children[index];
  item.MetaData = info;
}

//----------------------------------------------------------------------------
int vtkDataObjectTree::HasChildMetaData(unsigned int index)
{
  if (index < this->Internals->Children.size())
    {
    vtkDataObjectTreeItem& item = this->Internals->Children[index];
    return (item.MetaData.GetPointer() != NULL)? 1 : 0;
    }

  return 0;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::CopyStructure(vtkCompositeDataSet* compositeSource)
{
  if(!compositeSource)
    {
    return;
    }
  vtkDataObjectTree* source = vtkDataObjectTree::SafeDownCast(compositeSource);
  if (source == this)
    {
    return;
    }

  this->Internals->Children.clear();
  if (!source)
    {
    //WARNING:
    //If we copy the structure of from a non-tree composite data set
    //the "structure" is just is the total number of blocks (nill or not)
    //To do: We should probably also copy meta data as well.
    int totalNumBlocks=0;
    vtkCompositeDataIterator* iter = compositeSource->NewIterator();
    iter->SkipEmptyNodesOff();
    for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
      {
      totalNumBlocks++;
      }
    this->Internals->Children.resize(totalNumBlocks);
    iter->Delete();
    return;
    }

  this->Internals->Children.resize(source->Internals->Children.size());

  vtkDataObjectTreeInternals::Iterator srcIter =
    source->Internals->Children.begin();
  vtkDataObjectTreeInternals::Iterator myIter =
    this->Internals->Children.begin();
  for (; srcIter != source->Internals->Children.end(); ++srcIter, myIter++)
    {
    vtkDataObjectTree* compositeSrc =
      vtkDataObjectTree::SafeDownCast(srcIter->DataObject);
    if (compositeSrc)
      {
      vtkDataObjectTree* copy = compositeSrc->NewInstance();
      myIter->DataObject.TakeReference(copy);
      copy->CopyStructure(compositeSrc);
      }

    // shallow copy meta data.
    if (srcIter->MetaData)
      {
      vtkInformation* info = vtkInformation::New();
      info->Copy(srcIter->MetaData, /*deep=*/0);
      myIter->MetaData = info;
      info->FastDelete();
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
vtkCompositeDataIterator* vtkDataObjectTree::NewIterator()
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::New();
  iter->SetDataSet(this);
  return iter;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetDataSet(vtkCompositeDataIterator* iter,
  vtkDataObject* dataObj)
{
  vtkDataObjectTreeIterator* treeIter = vtkDataObjectTreeIterator::SafeDownCast(iter);
  if(treeIter)
    {
    this->SetDataSetFrom(treeIter,dataObj);
    return;
    }

  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return;
    }

  vtkDataObjectTree* parent = this;
  unsigned int index = iter->GetCurrentFlatIndex();
  parent->SetChild(index, dataObj);
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::SetDataSetFrom(vtkDataObjectTreeIterator* iter,
  vtkDataObject* dataObj)
{
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return;
    }

  parent->SetChild(index.back(), dataObj);
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataObjectTree::GetDataSet(vtkCompositeDataIterator* compositeIter)
{
  if (!compositeIter || compositeIter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter)
    {
    //It might be the case that the multiblock data set is a flat
    // tree with the same number of data sets as pointed by compsiteIter.
    //So we will try to work with it here.
    //To do: More clear check of structures here. At least something like this->Depth()==1
    unsigned int currentFlatIndex = compositeIter->GetCurrentFlatIndex();
    if(currentFlatIndex < this->GetNumberOfChildren())
      {
      return this->GetChild(currentFlatIndex);
      }
    else
      {
      return 0;
      }
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->GetChild(index.back());
}

//----------------------------------------------------------------------------
vtkInformation* vtkDataObjectTree::GetMetaData(vtkCompositeDataIterator* compositeIter)
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->GetChildMetaData(index.back());
}

//----------------------------------------------------------------------------
int vtkDataObjectTree::HasMetaData(vtkCompositeDataIterator* compositeIter)
{
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter);
  if (!iter || iter->IsDoneWithTraversal())
    {
    vtkErrorMacro("Invalid iterator location.");
    return 0;
    }

  vtkDataObjectTreeIndex index = iter->GetCurrentIndex();

  if (index.size() == 0)
    {
    // Sanity check.
    vtkErrorMacro("Invalid index returned by iterator.");
    return 0;
    }

  vtkDataObjectTree* parent = this;
  int numIndices = static_cast<int>(index.size());
  for (int cc=0; cc < numIndices-1; cc++)
    {
    if (!parent || parent->GetNumberOfChildren() <= index[cc])
      {
      vtkErrorMacro("Structure does not match. "
        "You must use CopyStructure before calling this method.");
      return 0;
      }
    parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc]));
    }

  if (!parent || parent->GetNumberOfChildren() <= index.back())
    {
    vtkErrorMacro("Structure does not match. "
      "You must use CopyStructure before calling this method.");
    return 0;
    }

  return parent->HasChildMetaData(index.back());
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::ShallowCopy(vtkDataObject* src)
{
  if (src == this)
    {
    return;
    }

  this->Internals->Children.clear();
  this->Superclass::ShallowCopy(src);

  vtkDataObjectTree* from = vtkDataObjectTree::SafeDownCast(src);
  if (from)
    {
    unsigned int numChildren = from->GetNumberOfChildren();
    this->SetNumberOfChildren(numChildren);
    for (unsigned int cc=0; cc < numChildren; cc++)
      {
      vtkDataObject* child = from->GetChild(cc);
      if (child)
        {
        if (child->IsA("vtkDataObjectTree"))
          {
          vtkDataObject* clone = child->NewInstance();
          clone->ShallowCopy(child);
          this->SetChild(cc, clone);
          clone->FastDelete();
          }
        else
          {
          this->SetChild(cc, child);
          }
        }
      if (from->HasChildMetaData(cc))
        {
        vtkInformation* toInfo = this->GetChildMetaData(cc);
        toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/0);
        }
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::DeepCopy(vtkDataObject* src)
{
  if (src == this)
    {
    return;
    }

  this->Internals->Children.clear();
  this->Superclass::DeepCopy(src);

  vtkDataObjectTree* from = vtkDataObjectTree::SafeDownCast(src);
  if (from)
    {
    unsigned int numChildren = from->GetNumberOfChildren();
    this->SetNumberOfChildren(numChildren);
    for (unsigned int cc=0; cc < numChildren; cc++)
      {
      vtkDataObject* fromChild = from->GetChild(cc);
      if (fromChild)
        {
        vtkDataObject* toChild = fromChild->NewInstance();
        toChild->DeepCopy(fromChild);
        this->SetChild(cc, toChild);
        toChild->FastDelete();
        if (from->HasChildMetaData(cc))
          {
          vtkInformation* toInfo = this->GetChildMetaData(cc);
          toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/1);
          }
        }
      }
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::Initialize()
{
  this->Internals->Children.clear();
  this->Superclass::Initialize();
}

//----------------------------------------------------------------------------
vtkIdType vtkDataObjectTree::GetNumberOfPoints()
{
  vtkIdType numPts = 0;
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(this->NewIterator());
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    vtkDataSet* ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
    if (ds)
      {
      numPts += ds->GetNumberOfPoints();
      }
    }
  iter->Delete();
  return numPts;
}

//----------------------------------------------------------------------------
unsigned long vtkDataObjectTree::GetActualMemorySize()
{
  unsigned long memSize = 0;
  vtkDataObjectTreeIterator* iter = vtkDataObjectTreeIterator::SafeDownCast(this->NewIterator());
  for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
    {
    vtkDataObject* dobj = iter->GetCurrentDataObject();
    memSize += dobj->GetActualMemorySize();
    }
  iter->Delete();
  return memSize;
}

//----------------------------------------------------------------------------
void vtkDataObjectTree::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Number Of Children: " << this->GetNumberOfChildren() << endl;
  for (unsigned int cc=0; cc < this->GetNumberOfChildren(); cc++)
    {
    vtkDataObject* child = this->GetChild(cc);
    if (child)
      {
      os << indent << "Child " << cc << ": " << child->GetClassName() << endl;
      child->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Child " << cc << ": NULL" << endl;
      }
    }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_conf.hpp"
#include "dll/contrastive_divergence.hpp"
#include "dll/watcher.hpp"
#include "dll/util/tmp.hpp"

namespace dll {

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_1, size_t NV_2, size_t K_T, size_t NW_1, size_t NW_2, typename... Parameters>
struct conv_rbm_desc {
    static constexpr size_t NV1 = NV_1; ///< The first dimension of the input
    static constexpr size_t NV2 = NV_2; ///< The second dimension of the input
    static constexpr size_t NW1 = NW_1; ///< The first dimension of the output
    static constexpr size_t NW2 = NW_2; ///< The second dimension of the output
    static constexpr size_t NC  = NC_T; ///< The number of input channels
    static constexpr size_t K   = K_T;  ///< The number of filters

    /*!
     * \brief A list of all the parameters of the descriptor
     */
    using parameters = cpp::type_list<Parameters...>;

    /*!
     * \brief The batch size for training this layer
     */
    static constexpr size_t BatchSize         = detail::get_value_v<batch_size<1>, Parameters...>;

    /*!
     * \brief The type of visible unit
     */
    static constexpr unit_type visible_unit   = detail::get_value_v<visible<unit_type::BINARY>, Parameters...>;

    /*!
     * \brief The type of hidden unit
     */
    static constexpr unit_type hidden_unit    = detail::get_value_v<hidden<unit_type::BINARY>, Parameters...>;

    /*!
     * \brief The sparsity penalty for pretraining
     */
    static constexpr sparsity_method Sparsity = detail::get_value_v<sparsity<sparsity_method::NONE>, Parameters...>;

    /*!
     * \brief The sparsity bias mode (LEE)
     */
    static constexpr bias_mode Bias           = detail::get_value_v<bias<bias_mode::SIMPLE>, Parameters...>;

    /*! The type used to store the weights */
    using weight = detail::get_type_t<weight_type<float>, Parameters...>;

    /*! The type of the trainer to use to train the RBM */
    template <typename RBM>
    using trainer_t = typename detail::get_template_type<trainer_rbm<cd1_trainer_t>, Parameters...>::template value<RBM>;

    /*! The type of the watched to use during training */
    template <typename RBM>
    using watcher_t = typename detail::get_template_type<watcher<default_rbm_watcher>, Parameters...>::template value<RBM>;

    /*! The layer type */
    using layer_t = conv_rbm_impl<conv_rbm_desc<NC_T, NV1, NV2, K_T, NW1, NW2, Parameters...>>;

private:
    template <typename... Args>
    struct dyn_layer_t_impl {
        using sequence = remove_type_id<batch_size_id, Args...>;

        using type = typename build_dyn_layer_t<dyn_conv_rbm_impl, dyn_conv_rbm_desc, sequence, Args...>::type;
    };

public:
    /*!
     * The dynamic layer type
     */
    using dyn_layer_t = typename dyn_layer_t_impl<Parameters...>::type;

    //Validate all parameters

    static_assert(NV1 > 0, "A matrix of at least 1x1 is necessary for the visible units");
    static_assert(NV2 > 0, "A matrix of at least 1x1 is necessary for the visible units");
    static_assert(NW1 > 0, "A matrix of at least 1x1 is necessary for the kernel");
    static_assert(NW2 > 0, "A matrix of at least 1x1 is necessary for the kernel");
    static_assert(NC > 0, "At least one channel is necessary");
    static_assert(K > 0, "At least one group is necessary");
    static_assert(BatchSize > 0, "Batch size must be at least 1");

    //Make sure only valid types are passed to the configuration list
    static_assert(
        detail::is_valid_v<cpp::type_list<
                             momentum_id, batch_size_id, visible_id, hidden_id, dbn_only_id,
                             weight_decay_id, sparsity_id, trainer_rbm_id, watcher_id, clip_gradients_id,
                             bias_id, weight_type_id, shuffle_id, verbose_id, nop_id>,
                         Parameters...>,
        "Invalid parameters type");

    static_assert(Sparsity == sparsity_method::NONE || hidden_unit == unit_type::BINARY,
                  "Sparsity only works with binary hidden units");
};

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine with square inputs and filters.
 *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::rbm_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_T, size_t K_T, size_t NW_T, typename... Parameters>
using conv_rbm_square_desc = conv_rbm_desc<NC_T, NV_T, NV_T, K_T, NW_T, NW_T, Parameters...>;

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_1, size_t NV_2, size_t K_T, size_t NW_1, size_t NW_2, typename... Parameters>
using conv_rbm = typename conv_rbm_desc<NC_T, NV_1, NV_2, K_T, NW_1, NW_2, Parameters...>::layer;

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine with square inputs and filters.
 *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::rbm_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_T, size_t K_T, size_t NW_T, typename... Parameters>
using conv_rbm_square = typename conv_rbm_desc<NC_T, NV_T, NV_T, K_T, NW_T, NW_T, Parameters...>::layer;

} //end of dll namespace
<commit_msg>Fix bug for conv_rbm<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/base_conf.hpp"
#include "dll/contrastive_divergence.hpp"
#include "dll/watcher.hpp"
#include "dll/util/tmp.hpp"

namespace dll {

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_1, size_t NV_2, size_t K_T, size_t NW_1, size_t NW_2, typename... Parameters>
struct conv_rbm_desc {
    static constexpr size_t NV1 = NV_1; ///< The first dimension of the input
    static constexpr size_t NV2 = NV_2; ///< The second dimension of the input
    static constexpr size_t NW1 = NW_1; ///< The first dimension of the output
    static constexpr size_t NW2 = NW_2; ///< The second dimension of the output
    static constexpr size_t NC  = NC_T; ///< The number of input channels
    static constexpr size_t K   = K_T;  ///< The number of filters

    /*!
     * \brief A list of all the parameters of the descriptor
     */
    using parameters = cpp::type_list<Parameters...>;

    /*!
     * \brief The batch size for training this layer
     */
    static constexpr size_t BatchSize         = detail::get_value_v<batch_size<1>, Parameters...>;

    /*!
     * \brief The type of visible unit
     */
    static constexpr unit_type visible_unit   = detail::get_value_v<visible<unit_type::BINARY>, Parameters...>;

    /*!
     * \brief The type of hidden unit
     */
    static constexpr unit_type hidden_unit    = detail::get_value_v<hidden<unit_type::BINARY>, Parameters...>;

    /*!
     * \brief The sparsity penalty for pretraining
     */
    static constexpr sparsity_method Sparsity = detail::get_value_v<sparsity<sparsity_method::NONE>, Parameters...>;

    /*!
     * \brief The sparsity bias mode (LEE)
     */
    static constexpr bias_mode Bias           = detail::get_value_v<bias<bias_mode::SIMPLE>, Parameters...>;

    /*! The type used to store the weights */
    using weight = detail::get_type_t<weight_type<float>, Parameters...>;

    /*! The type of the trainer to use to train the RBM */
    template <typename RBM>
    using trainer_t = typename detail::get_template_type<trainer_rbm<cd1_trainer_t>, Parameters...>::template value<RBM>;

    /*! The type of the watched to use during training */
    template <typename RBM>
    using watcher_t = typename detail::get_template_type<watcher<default_rbm_watcher>, Parameters...>::template value<RBM>;

    /*! The layer type */
    using layer_t = conv_rbm_impl<conv_rbm_desc<NC_T, NV1, NV2, K_T, NW1, NW2, Parameters...>>;

private:
    template <typename... Args>
    struct dyn_layer_t_impl {
        using sequence = remove_type_id<batch_size_id, Args...>;

        using type = typename build_dyn_layer_t<dyn_conv_rbm_impl, dyn_conv_rbm_desc, sequence, Args...>::type;
    };

public:
    /*!
     * The dynamic layer type
     */
    using dyn_layer_t = typename dyn_layer_t_impl<Parameters...>::type;

    //Validate all parameters

    static_assert(NV1 > 0, "A matrix of at least 1x1 is necessary for the visible units");
    static_assert(NV2 > 0, "A matrix of at least 1x1 is necessary for the visible units");
    static_assert(NW1 > 0, "A matrix of at least 1x1 is necessary for the kernel");
    static_assert(NW2 > 0, "A matrix of at least 1x1 is necessary for the kernel");
    static_assert(NC > 0, "At least one channel is necessary");
    static_assert(K > 0, "At least one group is necessary");
    static_assert(BatchSize > 0, "Batch size must be at least 1");

    //Make sure only valid types are passed to the configuration list
    static_assert(
        detail::is_valid_v<cpp::type_list<
                             momentum_id, batch_size_id, visible_id, hidden_id, dbn_only_id,
                             weight_decay_id, sparsity_id, trainer_rbm_id, watcher_id, clip_gradients_id,
                             bias_id, weight_type_id, shuffle_id, verbose_id, nop_id>,
                         Parameters...>,
        "Invalid parameters type");

    static_assert(Sparsity == sparsity_method::NONE || hidden_unit == unit_type::BINARY,
                  "Sparsity only works with binary hidden units");
};

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine with square inputs and filters.
 *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::rbm_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_T, size_t K_T, size_t NW_T, typename... Parameters>
using conv_rbm_square_desc = conv_rbm_desc<NC_T, NV_T, NV_T, K_T, NW_T, NW_T, Parameters...>;

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine.  *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::layer_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_1, size_t NV_2, size_t K_T, size_t NW_1, size_t NW_2, typename... Parameters>
using conv_rbm = typename conv_rbm_desc<NC_T, NV_1, NV_2, K_T, NW_1, NW_2, Parameters...>::layer_t;

/*!
 * \brief Describe a Convolutional Restricted Boltzmann Machine with square inputs and filters.
 *
 * This struct should be used to define a RBM either as standalone or for a DBN.
 * Once configured, the ::rbm_t member returns the type of the configured RBM.
 */
template <size_t NC_T, size_t NV_T, size_t K_T, size_t NW_T, typename... Parameters>
using conv_rbm_square = typename conv_rbm_desc<NC_T, NV_T, NV_T, K_T, NW_T, NW_T, Parameters...>::layer_t;

} //end of dll namespace
<|endoftext|>


<commit_before>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifdef __AVX__
#include "svd3x3_avx.h"

#include <cmath>
#include <algorithm>

#undef USE_SCALAR_IMPLEMENTATION
#undef USE_SSE_IMPLEMENTATION
#define USE_AVX_IMPLEMENTATION
#define COMPUTE_U_AS_MATRIX
#define COMPUTE_V_AS_MATRIX
#include "Singular_Value_Decomposition_Preamble.hpp"

#pragma runtime_checks( "u", off )  // disable runtime asserts on xor eax,eax type of stuff (doesn't always work, disable explicitly in compiler settings)
template<typename T>
IGL_INLINE void igl::svd3x3_avx(
  const Eigen::Matrix<T, 3*8, 3>& A,
  Eigen::Matrix<T, 3*8, 3> &U,
  Eigen::Matrix<T, 3*8, 1> &S,
  Eigen::Matrix<T, 3*8, 3>&V)
{
  // this code assumes USE_AVX_IMPLEMENTATION is defined
  float Ashuffle[9][8], Ushuffle[9][8], Vshuffle[9][8], Sshuffle[3][8];
  for (int i=0; i<3; i++)
  {
    for (int j=0; j<3; j++)
    {
      for (int k=0; k<8; k++)
      {
        Ashuffle[i + j*3][k] = A(i + 3*k, j);
      }
    }
  }

#include "Singular_Value_Decomposition_Kernel_Declarations.hpp"

  ENABLE_AVX_IMPLEMENTATION(Va11=_mm256_loadu_ps(Ashuffle[0]);)
  ENABLE_AVX_IMPLEMENTATION(Va21=_mm256_loadu_ps(Ashuffle[1]);)
  ENABLE_AVX_IMPLEMENTATION(Va31=_mm256_loadu_ps(Ashuffle[2]);)
  ENABLE_AVX_IMPLEMENTATION(Va12=_mm256_loadu_ps(Ashuffle[3]);)
  ENABLE_AVX_IMPLEMENTATION(Va22=_mm256_loadu_ps(Ashuffle[4]);)
  ENABLE_AVX_IMPLEMENTATION(Va32=_mm256_loadu_ps(Ashuffle[5]);)
  ENABLE_AVX_IMPLEMENTATION(Va13=_mm256_loadu_ps(Ashuffle[6]);)
  ENABLE_AVX_IMPLEMENTATION(Va23=_mm256_loadu_ps(Ashuffle[7]);)
  ENABLE_AVX_IMPLEMENTATION(Va33=_mm256_loadu_ps(Ashuffle[8]);)

#include "Singular_Value_Decomposition_Main_Kernel_Body.hpp"

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[0],Vu11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[1],Vu21);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[2],Vu31);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[3],Vu12);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[4],Vu22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[5],Vu32);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[6],Vu13);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[7],Vu23);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[8],Vu33);)

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[0],Vv11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[1],Vv21);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[2],Vv31);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[3],Vv12);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[4],Vv22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[5],Vv32);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[6],Vv13);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[7],Vv23);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[8],Vv33);)

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[0],Va11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[1],Va22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[2],Va33);)

  for (int i=0; i<3; i++)
  {
    for (int j=0; j<3; j++)
    {
      for (int k=0; k<8; k++)
      {
        U(i + 3*k, j) = Ushuffle[i + j*3][k];
        V(i + 3*k, j) = Vshuffle[i + j*3][k];
      }
    }
  }

  for (int i=0; i<3; i++)
  {
    for (int k=0; k<8; k++)
    {
      S(i + 3*k, 0) = Sshuffle[i][k];
    }
  }
}
#pragma runtime_checks( "u", restore )

// forced instantiation
template void igl::svd3x3_avx(const Eigen::Matrix<float, 3*8, 3>& A, Eigen::Matrix<float, 3*8, 3> &U, Eigen::Matrix<float, 3*8, 1> &S, Eigen::Matrix<float, 3*8, 3>&V);
// doesn't even make sense with double because the wunder-SVD code is only single precision anyway...
template void igl::svd3x3_avx<float>(Eigen::Matrix<float, 24, 3, 0, 24, 3> const&, Eigen::Matrix<float, 24, 3, 0, 24, 3>&, Eigen::Matrix<float, 24, 1, 0, 24, 1>&, Eigen::Matrix<float, 24, 3, 0, 24, 3>&);
#endif
<commit_msg>Fixed explicit instantiation problem when compiling as header-only.<commit_after>// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifdef __AVX__
#include "svd3x3_avx.h"

#include <cmath>
#include <algorithm>

#undef USE_SCALAR_IMPLEMENTATION
#undef USE_SSE_IMPLEMENTATION
#define USE_AVX_IMPLEMENTATION
#define COMPUTE_U_AS_MATRIX
#define COMPUTE_V_AS_MATRIX
#include "Singular_Value_Decomposition_Preamble.hpp"

#pragma runtime_checks( "u", off )  // disable runtime asserts on xor eax,eax type of stuff (doesn't always work, disable explicitly in compiler settings)
template<typename T>
IGL_INLINE void igl::svd3x3_avx(
  const Eigen::Matrix<T, 3*8, 3>& A,
  Eigen::Matrix<T, 3*8, 3> &U,
  Eigen::Matrix<T, 3*8, 1> &S,
  Eigen::Matrix<T, 3*8, 3>&V)
{
  // this code assumes USE_AVX_IMPLEMENTATION is defined
  float Ashuffle[9][8], Ushuffle[9][8], Vshuffle[9][8], Sshuffle[3][8];
  for (int i=0; i<3; i++)
  {
    for (int j=0; j<3; j++)
    {
      for (int k=0; k<8; k++)
      {
        Ashuffle[i + j*3][k] = A(i + 3*k, j);
      }
    }
  }

#include "Singular_Value_Decomposition_Kernel_Declarations.hpp"

  ENABLE_AVX_IMPLEMENTATION(Va11=_mm256_loadu_ps(Ashuffle[0]);)
  ENABLE_AVX_IMPLEMENTATION(Va21=_mm256_loadu_ps(Ashuffle[1]);)
  ENABLE_AVX_IMPLEMENTATION(Va31=_mm256_loadu_ps(Ashuffle[2]);)
  ENABLE_AVX_IMPLEMENTATION(Va12=_mm256_loadu_ps(Ashuffle[3]);)
  ENABLE_AVX_IMPLEMENTATION(Va22=_mm256_loadu_ps(Ashuffle[4]);)
  ENABLE_AVX_IMPLEMENTATION(Va32=_mm256_loadu_ps(Ashuffle[5]);)
  ENABLE_AVX_IMPLEMENTATION(Va13=_mm256_loadu_ps(Ashuffle[6]);)
  ENABLE_AVX_IMPLEMENTATION(Va23=_mm256_loadu_ps(Ashuffle[7]);)
  ENABLE_AVX_IMPLEMENTATION(Va33=_mm256_loadu_ps(Ashuffle[8]);)

#include "Singular_Value_Decomposition_Main_Kernel_Body.hpp"

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[0],Vu11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[1],Vu21);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[2],Vu31);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[3],Vu12);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[4],Vu22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[5],Vu32);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[6],Vu13);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[7],Vu23);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Ushuffle[8],Vu33);)

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[0],Vv11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[1],Vv21);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[2],Vv31);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[3],Vv12);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[4],Vv22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[5],Vv32);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[6],Vv13);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[7],Vv23);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Vshuffle[8],Vv33);)

  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[0],Va11);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[1],Va22);)
  ENABLE_AVX_IMPLEMENTATION(_mm256_storeu_ps(Sshuffle[2],Va33);)

  for (int i=0; i<3; i++)
  {
    for (int j=0; j<3; j++)
    {
      for (int k=0; k<8; k++)
      {
        U(i + 3*k, j) = Ushuffle[i + j*3][k];
        V(i + 3*k, j) = Vshuffle[i + j*3][k];
      }
    }
  }

  for (int i=0; i<3; i++)
  {
    for (int k=0; k<8; k++)
    {
      S(i + 3*k, 0) = Sshuffle[i][k];
    }
  }
}
#pragma runtime_checks( "u", restore )

#ifdef IGL_STATIC_LIBRARY
// forced instantiation
template void igl::svd3x3_avx(const Eigen::Matrix<float, 3*8, 3>& A, Eigen::Matrix<float, 3*8, 3> &U, Eigen::Matrix<float, 3*8, 1> &S, Eigen::Matrix<float, 3*8, 3>&V);
// doesn't even make sense with double because the wunder-SVD code is only single precision anyway...
template void igl::svd3x3_avx<float>(Eigen::Matrix<float, 24, 3, 0, 24, 3> const&, Eigen::Matrix<float, 24, 3, 0, 24, 3>&, Eigen::Matrix<float, 24, 1, 0, 24, 1>&, Eigen::Matrix<float, 24, 3, 0, 24, 3>&);
#endif
#endif
<|endoftext|>


<commit_before>///
/// @file  pod_vector.hpp
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef POD_VECTOR_HPP
#define POD_VECTOR_HPP

#include "macros.hpp"

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <type_traits>
#include <utility>

namespace primesieve {

/// pod_vector is a dynamically growing array.
/// It has the same API (though not complete) as std::vector but its
/// resize() method does not default initialize memory for built-in
/// integer types. It does however default initialize classes and
/// struct types if they have a constructor. It also prevents
/// bounds checks which is important for primesieve's performance, e.g.
/// the Fedora Linux distribution compiles with -D_GLIBCXX_ASSERTIONS
/// which enables std::vector bounds checks.
///
template <typename T>
class pod_vector
{
public:
  static_assert(std::is_trivially_destructible<T>::value,
                "pod_vector<T> only supports types with trivial destructors!");

  using value_type = T;
  pod_vector() noexcept = default;

  pod_vector(std::size_t size)
  {
    resize(size);
  }

  ~pod_vector()
  {
    delete [] array_;
  }

  /// Free all memory, the pod_vector
  /// can be reused afterwards.
  void free() noexcept
  {
    delete [] array_;
    array_ = nullptr;
    end_ = nullptr;
    capacity_ = nullptr;
  }

  /// Reset the pod_vector, but do not free its
  /// memory. Same as std::vector.clear().
  void clear() noexcept
  {
    end_ = array_;
  }

  /// Copying is slow, we prevent it
  pod_vector(const pod_vector&) = delete;
  pod_vector& operator=(const pod_vector&) = delete;

  /// Move constructor
  pod_vector(pod_vector&& other) noexcept
  {
    std::swap(array_, other.array_);
    std::swap(end_, other.end_);
    std::swap(capacity_, other.capacity_);
  }

  /// Move assignment operator
  pod_vector& operator=(pod_vector&& other) noexcept
  {
    if (this != &other)
    {
      std::swap(array_, other.array_);
      std::swap(end_, other.end_);
      std::swap(capacity_, other.capacity_);
    }

    return *this;
  }

  bool empty() const noexcept
  {
    return array_ == end_;
  }

  T& operator[] (std::size_t pos) noexcept
  {
    // For performance reasons primesieve is allowed to access
    // memory with pos > size() but <= capacity().
    assert(pos <= capacity());
    return array_[pos];
  }

  T& operator[] (std::size_t pos) const noexcept
  {
    // For performance reasons primesieve is allowed to access
    // memory with pos > size() but <= capacity().
    assert(pos <= capacity());
    return array_[pos];
  }

  T* data() noexcept
  {
    return array_;
  }

  T* data() const noexcept
  {
    return array_;
  }

  std::size_t size() const noexcept
  {
    assert(end_ >= array_);
    return (std::size_t)(end_ - array_);
  }

  std::size_t capacity() const noexcept
  {
    assert(capacity_ >= array_);
    return (std::size_t)(capacity_ - array_);
  }

  T* begin() noexcept
  {
    return array_;
  }

  T* begin() const noexcept
  {
    return array_;
  }

  T* end() noexcept
  {
    return end_;
  }

  T* end() const noexcept
  {
    return end_;
  }

  T& front() noexcept
  {
    return *array_;
  }

  T& front() const noexcept
  {
    return *array_;
  }

  T& back() noexcept
  {
    assert(end_ != nullptr);
    return *(end_ - 1);
  }

  T& back() const noexcept
  {
    assert(end_ != nullptr);
    return *(end_ - 1);
  }

  ALWAYS_INLINE void push_back(const T& value)
  {
    if_unlikely(end_ == capacity_)
      reserve(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = value;
  }

  ALWAYS_INLINE void push_back(T&& value)
  {
    if_unlikely(end_ == capacity_)
      reserve(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = value;
  }

  template <class... Args>
  ALWAYS_INLINE void emplace_back(Args&&... args)
  {
    if_unlikely(end_ == capacity_)
      reserve(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = T(std::forward<Args>(args)...);
  }

  void reserve(std::size_t n)
  {
    if (n > capacity())
    {
      T* old = array_;
      std::size_t old_size = size();
      std::size_t new_capacity = get_new_capacity<T>(n);
      assert(new_capacity >= n);
      assert(new_capacity > old_size);

      // This default initializes memory of classes and
      // structs with constructors. But it does not default
      // initialize memory for POD types like int, long.
      array_ = new T[new_capacity];
      end_ = array_ + old_size;
      capacity_ = array_ + new_capacity;

      if (old)
      {
        std::copy_n(old, old_size, array_);
        delete [] old;
      }
    }
  }

  /// Resize without default initializing memory.
  /// If the pod_vector is not empty the current content
  /// will be copied into the new array.
  ///
  void resize(std::size_t n)
  {
    if (n == size())
      return;
    else if (n <= capacity())
    {
      assert(capacity() > 0);

      // This will only be used for classes
      // and structs with constructors.
      if (n > size())
        default_initialize_range(end_, array_ + n);

      end_ = array_ + n;
    }
    else
    {
      T* old = array_;
      std::size_t old_size = size();
      std::size_t new_capacity = get_new_capacity<T>(n);
      assert(new_capacity >= n);
      assert(new_capacity > old_size);

      // This default initializes memory of classes and
      // structs with constructors. But it does not default
      // initialize memory for POD types like int, long.
      array_ = new T[new_capacity];
      end_ = array_ + n;
      capacity_ = array_ + new_capacity;

      if (old)
      {
        std::copy_n(old, old_size, array_);
        delete [] old;
      }
    }
  }

private:
  T* array_ = nullptr;
  T* end_ = nullptr;
  T* capacity_ = nullptr;

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<std::is_trivial<U>::value>::type
  default_initialize_range(U*, U*)
  { }

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<!std::is_trivial<U>::value>::type
  default_initialize_range(U* first, U* last)
  {
    std::fill(first, last, U());
  }

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<std::is_trivial<U>::value, std::size_t>::type
  get_new_capacity(std::size_t size)
  {
    assert(size > 0);
    // GCC & Clang's std::vector grow the capacity by at least
    // 2x for every call to resize() with n > capacity(). We
    // grow by at least 1.5x as we tend to accurately calculate
    // the amount of memory we need upfront.
    std::size_t new_capacity = (std::size_t)(capacity() * 1.5);
    constexpr std::size_t min_alignment = sizeof(long) * 2;
    constexpr std::size_t min_capacity = min_alignment / sizeof(U);
    return std::max({min_capacity, size, new_capacity});
  }

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<!std::is_trivial<U>::value, std::size_t>::type
  get_new_capacity(std::size_t size)
  {
    assert(size > 0);
    // GCC & Clang's std::vector grow the capacity by at least
    // 2x for every call to resize() with n > capacity(). We
    // grow by at least 1.5x as we tend to accurately calculate
    // the amount of memory we need upfront.
    std::size_t new_capacity = (std::size_t)(capacity() * 1.5);
    return std::max(size, new_capacity);
  }
};

} // namespace

#endif
<commit_msg>Refactor resize()<commit_after>///
/// @file  pod_vector.hpp
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef POD_VECTOR_HPP
#define POD_VECTOR_HPP

#include "macros.hpp"

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <type_traits>
#include <utility>

namespace primesieve {

/// pod_vector is a dynamically growing array.
/// It has the same API (though not complete) as std::vector but its
/// resize() method does not default initialize memory for built-in
/// integer types. It does however default initialize classes and
/// struct types if they have a constructor. It also prevents
/// bounds checks which is important for primesieve's performance, e.g.
/// the Fedora Linux distribution compiles with -D_GLIBCXX_ASSERTIONS
/// which enables std::vector bounds checks.
///
template <typename T>
class pod_vector
{
public:
  static_assert(std::is_trivially_destructible<T>::value,
                "pod_vector<T> only supports types with trivial destructors!");

  using value_type = T;
  pod_vector() noexcept = default;

  pod_vector(std::size_t size)
  {
    resize(size);
  }

  ~pod_vector()
  {
    delete [] array_;
  }

  /// Free all memory, the pod_vector
  /// can be reused afterwards.
  void free() noexcept
  {
    delete [] array_;
    array_ = nullptr;
    end_ = nullptr;
    capacity_ = nullptr;
  }

  /// Reset the pod_vector, but do not free its
  /// memory. Same as std::vector.clear().
  void clear() noexcept
  {
    end_ = array_;
  }

  /// Copying is slow, we prevent it
  pod_vector(const pod_vector&) = delete;
  pod_vector& operator=(const pod_vector&) = delete;

  /// Move constructor
  pod_vector(pod_vector&& other) noexcept
  {
    std::swap(array_, other.array_);
    std::swap(end_, other.end_);
    std::swap(capacity_, other.capacity_);
  }

  /// Move assignment operator
  pod_vector& operator=(pod_vector&& other) noexcept
  {
    if (this != &other)
    {
      std::swap(array_, other.array_);
      std::swap(end_, other.end_);
      std::swap(capacity_, other.capacity_);
    }

    return *this;
  }

  bool empty() const noexcept
  {
    return array_ == end_;
  }

  T& operator[](std::size_t pos) noexcept
  {
    // For performance reasons primesieve is allowed to access
    // memory with pos > size() but <= capacity().
    assert(pos <= capacity());
    return array_[pos];
  }

  T& operator[](std::size_t pos) const noexcept
  {
    // For performance reasons primesieve is allowed to access
    // memory with pos > size() but <= capacity().
    assert(pos <= capacity());
    return array_[pos];
  }

  T* data() noexcept
  {
    return array_;
  }

  T* data() const noexcept
  {
    return array_;
  }

  std::size_t size() const noexcept
  {
    assert(end_ >= array_);
    return (std::size_t)(end_ - array_);
  }

  std::size_t capacity() const noexcept
  {
    assert(capacity_ >= array_);
    return (std::size_t)(capacity_ - array_);
  }

  T* begin() noexcept
  {
    return array_;
  }

  T* begin() const noexcept
  {
    return array_;
  }

  T* end() noexcept
  {
    return end_;
  }

  T* end() const noexcept
  {
    return end_;
  }

  T& front() noexcept
  {
    return *array_;
  }

  T& front() const noexcept
  {
    return *array_;
  }

  T& back() noexcept
  {
    assert(end_ != nullptr);
    return *(end_ - 1);
  }

  T& back() const noexcept
  {
    assert(end_ != nullptr);
    return *(end_ - 1);
  }

  ALWAYS_INLINE void push_back(const T& value)
  {
    if_unlikely(end_ == capacity_)
      reserve_unchecked(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = value;
  }

  ALWAYS_INLINE void push_back(T&& value)
  {
    if_unlikely(end_ == capacity_)
      reserve_unchecked(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = value;
  }

  template <class... Args>
  ALWAYS_INLINE void emplace_back(Args&&... args)
  {
    if_unlikely(end_ == capacity_)
      reserve_unchecked(std::max((std::size_t) 1, capacity() * 2));
    *end_++ = T(std::forward<Args>(args)...);
  }

  void reserve(std::size_t n)
  {
    if (n > capacity())
      reserve_unchecked(n);
  }

  /// Resize without default initializing memory.
  /// If the pod_vector is not empty the current content
  /// will be copied into the new array.
  ///
  void resize(std::size_t n)
  {
    if (n > capacity())
      reserve_unchecked(n);
    else if (!std::is_trivial<T>::value && n > size())
    {
      // This will only be used for classes
      // and structs with constructors.
      assert(n <= capacity());
      std::fill(end_, array_ + n, T());
    }

    end_ = array_ + n;
  }

private:
  T* array_ = nullptr;
  T* end_ = nullptr;
  T* capacity_ = nullptr;

  void reserve_unchecked(std::size_t n)
  {
    assert(n > capacity());
    std::size_t new_capacity = get_new_capacity<T>(n);
    std::size_t old_size = size();
    assert(new_capacity >= n);
    assert(new_capacity > old_size);

    // This default initializes memory of classes and
    // structs with constructors. But it does not default
    // initialize memory for POD types like int, long.
    T* old = array_;
    array_ = new T[new_capacity];
    end_ = array_ + old_size;
    capacity_ = array_ + new_capacity;

    if (old)
    {
      std::copy_n(old, old_size, array_);
      delete [] old;
    }
  }

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<std::is_trivial<U>::value, std::size_t>::type
  get_new_capacity(std::size_t size)
  {
    assert(size > 0);
    // GCC & Clang's std::vector grow the capacity by at least
    // 2x for every call to resize() with n > capacity(). We
    // grow by at least 1.5x as we tend to accurately calculate
    // the amount of memory we need upfront.
    std::size_t new_capacity = (std::size_t)(capacity() * 1.5);
    constexpr std::size_t min_alignment = sizeof(long) * 2;
    constexpr std::size_t min_capacity = min_alignment / sizeof(U);
    return std::max({min_capacity, size, new_capacity});
  }

  template <typename U>
  ALWAYS_INLINE typename std::enable_if<!std::is_trivial<U>::value, std::size_t>::type
  get_new_capacity(std::size_t size)
  {
    assert(size > 0);
    // GCC & Clang's std::vector grow the capacity by at least
    // 2x for every call to resize() with n > capacity(). We
    // grow by at least 1.5x as we tend to accurately calculate
    // the amount of memory we need upfront.
    std::size_t new_capacity = (std::size_t)(capacity() * 1.5);
    return std::max(size, new_capacity);
  }
};

} // namespace

#endif
<|endoftext|>


<commit_before>#ifndef TWISTEDCPP_PROTOCOL_CORE
#define TWISTEDCPP_PROTOCOL_CORE

#include "detail/sockets.hpp"

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/optional.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <boost/ref.hpp>

#ifndef NDEBUG
#include <iostream>
#endif

namespace twisted {

template <typename ChildProtocol, typename BufferType>
class protocol_core : public std::enable_shared_from_this<ChildProtocol> {
public:
    typedef detail::socket_base socket_type;
    typedef boost::asio::steady_timer timer_type;
    typedef boost::asio::io_service::strand strand_type;
    typedef BufferType buffer_type;
    typedef typename buffer_type::iterator buffer_iterator;
    typedef typename buffer_type::const_iterator const_buffer_iterator;

    protocol_core() = default;
    protocol_core(protocol_core&&) = default;
    protocol_core& operator=(protocol_core&&) = default;

    void set_socket(std::unique_ptr<socket_type> socket) {
        _socket = std::move(socket);
    }

    void run_protocol() {
        auto self = this_protocol().shared_from_this();
        boost::asio::spawn(_socket->get_io_service(),
                           [this, self](boost::asio::yield_context yield) {
            _yield = boost::in_place(yield);

            try {
                _socket->do_handshake(*_yield);

                while (_socket->is_open()) {
                    auto bytes_read =
                        _socket->async_read_some(asio_buffer(), yield);
                    this_protocol().on_message(
                        buffer_begin(), std::next(buffer_begin(), bytes_read));
                }
            }
            catch (boost::system::system_error& connection_error) {
                handle_network_error(connection_error);
            }
            catch (...) {
                handle_user_error(std::current_exception());
            }
        });
    }

    template <typename Duration, typename Callable>
    void call_later(Duration duration, Callable callable) {
        auto self = this_protocol().shared_from_this();
        // we pass our existing yield_context and not the io_service such that
        // both contexts run under the same strand
        boost::asio::spawn(*_yield, [this, duration, callable, self](
                                        boost::asio::yield_context yield) {
            boost::asio::high_resolution_timer timer(_socket->get_io_service(),
                                                     duration);
            timer.async_wait(yield);

            // we need to exchange the yield context so that that the user can
            // use the send_message function in the right context
            boost::optional<boost::asio::yield_context> old_yield(
                boost::in_place(*_yield));
            _yield = boost::in_place(yield);
            callable();
            _yield = boost::in_place(*old_yield);
        });
    }

    template <typename Callable, typename... Args>
    void call_from_thread(Callable&& callable, Args&&... args) {
        _socket->get_io_service().post(std::bind(
            std::forward<Callable>(callable), std::forward<Args>(args)...));
    }

    template <typename Duration>
    void wait_for(const Duration& duration) const {
        boost::asio::high_resolution_timer timer(_socket->get_io_service(),
                                                 duration);
        timer.async_wait(*_yield);
    }

    template <typename Iter>
    void send_message(Iter begin, Iter end) {
        _socket->async_write(
            boost::asio::buffer(&*begin, std::distance(begin, end)), *_yield);
    }

    void send_buffers(const std::array<boost::asio::const_buffer, 2>& buffers) {
        _socket->async_write(buffers, *_yield);
    }

    /*
     * @brief default on_disconnect implementation; does nothing
     */
    void on_disconnect() {}

    /*
     * @brief default on_error implementation; swallows everything
     */
    void on_error(std::exception_ptr eptr) {
        try {
            std::rethrow_exception(eptr);
        }
        catch (const std::exception& excep) {
            print_exception_what(excep);
        }
    }

    void lose_connection() { _socket->close(); }

    /*
     * @brief CRTP wrapper for derived class access
     */
    ChildProtocol& this_protocol() {
        return *static_cast<ChildProtocol*>(this);
    }

    /*
     * @brief CRTP wrapper for derived class access
     */
    const ChildProtocol& this_protocol() const {
        return *static_cast<ChildProtocol*>(this);
    }

private:
#ifdef NDEBUG
    void handle_network_error(boost::system::system_error&) {
#else
    void handle_network_error(boost::system::system_error& connection_error) {
        print_connection_error(connection_error);
#endif
        this_protocol().on_disconnect();
    }

    void handle_user_error(const std::exception_ptr& excep) {
        this_protocol().on_error(excep);
    }

    void print_connection_error(
        const boost::system::system_error& connection_error) const {
        std::cerr << "Client disconnected with code " << connection_error.what()
                  << std::endl;
    }

    void print_exception_what(const std::exception& excep) {
        std::cerr << "Killing connection, exception in client handler: "
                  << excep.what() << std::endl;
    }

    buffer_iterator buffer_begin() {
        return this_protocol().read_buffer().begin();
    }

    buffer_iterator buffer_begin() const {
        return this_protocol().read_buffer().begin();
    }

    buffer_iterator buffer_end() { return this_protocol().read_buffer().end(); }

    buffer_iterator buffer_end() const {
        return this_protocol().read_buffer().end();
    }

    boost::asio::mutable_buffers_1 asio_buffer() {
        return boost::asio::buffer(&*buffer_begin(),
                                   std::distance(buffer_begin(), buffer_end()));
    }

private:
    boost::optional<boost::asio::yield_context> _yield;
    std::unique_ptr<socket_type> _socket;
};

} // namespace twisted

#endif
<commit_msg>added is_connected<commit_after>#ifndef TWISTEDCPP_PROTOCOL_CORE
#define TWISTEDCPP_PROTOCOL_CORE

#include "detail/sockets.hpp"

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/optional.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <boost/ref.hpp>

#ifndef NDEBUG
#include <iostream>
#endif

namespace twisted {

template <typename ChildProtocol, typename BufferType>
class protocol_core : public std::enable_shared_from_this<ChildProtocol> {
public:
    typedef detail::socket_base socket_type;
    typedef boost::asio::steady_timer timer_type;
    typedef boost::asio::io_service::strand strand_type;
    typedef BufferType buffer_type;
    typedef typename buffer_type::iterator buffer_iterator;
    typedef typename buffer_type::const_iterator const_buffer_iterator;

    protocol_core() = default;
    protocol_core(protocol_core&&) = default;
    protocol_core& operator=(protocol_core&&) = default;

    void set_socket(std::unique_ptr<socket_type> socket) {
        _socket = std::move(socket);
    }

    void run_protocol() {
        auto self = this_protocol().shared_from_this();
        boost::asio::spawn(_socket->get_io_service(),
                           [this, self](boost::asio::yield_context yield) {
            _yield = boost::in_place(yield);

            try {
                _socket->do_handshake(*_yield);

                while (_socket->is_open()) {
                    auto bytes_read =
                        _socket->async_read_some(asio_buffer(), yield);
                    this_protocol().on_message(
                        buffer_begin(), std::next(buffer_begin(), bytes_read));
                }
            }
            catch (boost::system::system_error& connection_error) {
                handle_network_error(connection_error);
            }
            catch (...) {
                handle_user_error(std::current_exception());
            }
        });
    }

    template <typename Duration, typename Callable>
    void call_later(Duration duration, Callable callable) {
        auto self = this_protocol().shared_from_this();
        // we pass our existing yield_context and not the io_service such that
        // both contexts run under the same strand
        boost::asio::spawn(*_yield, [this, duration, callable, self](
                                        boost::asio::yield_context yield) {
            boost::asio::high_resolution_timer timer(_socket->get_io_service(),
                                                     duration);
            timer.async_wait(yield);

            // we need to exchange the yield context so that that the user can
            // use the send_message function in the right context
            boost::optional<boost::asio::yield_context> old_yield(
                boost::in_place(*_yield));
            _yield = boost::in_place(yield);
            callable();
            _yield = boost::in_place(*old_yield);
        });
    }

    template <typename Callable, typename... Args>
    void call_from_thread(Callable&& callable, Args&&... args) {
        _socket->get_io_service().post(std::bind(
            std::forward<Callable>(callable), std::forward<Args>(args)...));
    }

    template <typename Duration>
    void wait_for(const Duration& duration) const {
        boost::asio::high_resolution_timer timer(_socket->get_io_service(),
                                                 duration);
        timer.async_wait(*_yield);
    }

    template <typename Iter>
    void send_message(Iter begin, Iter end) {
        _socket->async_write(
            boost::asio::buffer(&*begin, std::distance(begin, end)), *_yield);
    }

    void send_buffers(const std::array<boost::asio::const_buffer, 2>& buffers) {
        _socket->async_write(buffers, *_yield);
    }

    /*
     * @brief default on_disconnect implementation; does nothing
     */
    void on_disconnect() {}

    /*
     * @brief default on_error implementation; swallows everything
     */
    void on_error(std::exception_ptr eptr) {
        try {
            std::rethrow_exception(eptr);
        }
        catch (const std::exception& excep) {
            print_exception_what(excep);
        }
    }

    bool is_connected() const { return _socket->is_open(); }

    void lose_connection() { _socket->close(); }

    /*
     * @brief CRTP wrapper for derived class access
     */
    ChildProtocol& this_protocol() {
        return *static_cast<ChildProtocol*>(this);
    }

    /*
     * @brief CRTP wrapper for derived class access
     */
    const ChildProtocol& this_protocol() const {
        return *static_cast<ChildProtocol*>(this);
    }

private:
#ifdef NDEBUG
    void handle_network_error(boost::system::system_error&) {
#else
    void handle_network_error(boost::system::system_error& connection_error) {
        print_connection_error(connection_error);
#endif
        this_protocol().on_disconnect();
    }

    void handle_user_error(const std::exception_ptr& excep) {
        this_protocol().on_error(excep);
    }

    void print_connection_error(
        const boost::system::system_error& connection_error) const {
        std::cerr << "Client disconnected with code " << connection_error.what()
                  << std::endl;
    }

    void print_exception_what(const std::exception& excep) {
        std::cerr << "Killing connection, exception in client handler: "
                  << excep.what() << std::endl;
    }

    buffer_iterator buffer_begin() {
        return this_protocol().read_buffer().begin();
    }

    buffer_iterator buffer_begin() const {
        return this_protocol().read_buffer().begin();
    }

    buffer_iterator buffer_end() { return this_protocol().read_buffer().end(); }

    buffer_iterator buffer_end() const {
        return this_protocol().read_buffer().end();
    }

    boost::asio::mutable_buffers_1 asio_buffer() {
        return boost::asio::buffer(&*buffer_begin(),
                                   std::distance(buffer_begin(), buffer_end()));
    }

private:
    boost::optional<boost::asio::yield_context> _yield;
    std::unique_ptr<socket_type> _socket;
};

} // namespace twisted

#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */
#ifndef INCLUDED_UNOTOOLS_UCBLOCKBYTES_HXX
#define INCLUDED_UNOTOOLS_UCBLOCKBYTES_HXX

#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/ucb/XContent.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <unotools/unotoolsdllapi.h>

#include <osl/thread.hxx>
#include <osl/conditn.hxx>
#include <osl/mutex.hxx>
#include <rtl/ustring.hxx>
#include <tools/stream.hxx>
#include <tools/link.hxx>
#include <tools/errcode.hxx>
#include <tools/datetime.hxx>

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace task
            {
                class XInteractionHandler;
            }
            namespace io
            {
                class XStream;
                class XInputStream;
                class XOutputStream;
                class XSeekable;
            }
            namespace ucb
            {
                class XContent;
            }
            namespace beans
            {
                struct PropertyValue;
            }
        }
    }
}

namespace utl
{
SV_DECL_REF( UcbLockBytes )

class UcbLockBytesHandler : public SvRefBase
{
    bool            m_bActive;
public:
    enum LoadHandlerItem
    {
        DATA_AVAILABLE,
        DONE,
        CANCEL
    };

                    UcbLockBytesHandler()
                        : m_bActive( true )
                    {}

    virtual void    Handle( LoadHandlerItem nWhich, UcbLockBytesRef xLockBytes ) = 0;
    void            Activate( bool bActivate = true ) { m_bActive = bActivate; }
    bool            IsActive() const { return m_bActive; }
};

SV_DECL_IMPL_REF( UcbLockBytesHandler )

class UNOTOOLS_DLLPUBLIC UcbLockBytes : public virtual SvLockBytes
{
    osl::Condition          m_aInitialized;
    osl::Condition          m_aTerminated;
    osl::Mutex              m_aMutex;

    OUString                m_aContentType;
    OUString                m_aRealURL;
    DateTime                m_aExpireDate;

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream >  m_xInputStream;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > m_xOutputStream;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XSeekable >     m_xSeekable;
    void*                   m_pCommandThread; // is alive only for compatibility reasons
    UcbLockBytesHandlerRef  m_xHandler;

    sal_uInt32              m_nRead;
    sal_uInt32              m_nSize;
    ErrCode                 m_nError;

    bool                    m_bTerminated;
    bool                    m_bDontClose;
    bool                    m_bStreamValid;

    DECL_LINK(              DataAvailHdl, void * );

                            UcbLockBytes( UcbLockBytesHandler* pHandler=NULL );
protected:
    virtual                 ~UcbLockBytes (void);

public:
                            // properties: Referer, PostMimeType
    static UcbLockBytesRef  CreateLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::ucb::XContent >& xContent,
                                            const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& rProps,
                                            StreamMode eMode,
                                            const ::com::sun::star::uno::Reference < ::com::sun::star::task::XInteractionHandler >& xInter,
                                            UcbLockBytesHandler* pHandler=0 );

    static UcbLockBytesRef  CreateInputLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream >& xContent );
    static UcbLockBytesRef  CreateLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XStream >& xContent );

    // SvLockBytes
    virtual void            SetSynchronMode (bool bSynchron) SAL_OVERRIDE;
    virtual ErrCode         ReadAt(sal_uInt64 nPos, void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const SAL_OVERRIDE;
    virtual ErrCode         WriteAt(sal_uInt64, const void*, sal_uLong, sal_uLong *pWritten) SAL_OVERRIDE;
    virtual ErrCode         Flush() const SAL_OVERRIDE;
    virtual ErrCode         SetSize(sal_uInt64) SAL_OVERRIDE;
    virtual ErrCode         Stat ( SvLockBytesStat *pStat, SvLockBytesStatFlag) const SAL_OVERRIDE;

    void                    SetError( ErrCode nError )
                            { m_nError = nError; }

    ErrCode                 GetError() const
                            { return m_nError; }

    // the following properties are available when and after the first DataAvailable callback has been executed
    OUString                GetContentType() const;
    OUString                GetRealURL() const;
    DateTime                GetExpireDate() const;

    // calling this method delegates the responsibility to call closeinput to the caller!
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > getInputStream();

    bool                    setInputStream_Impl( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > &rxInputStream,
                                                 bool bSetXSeekable = true );
    bool                    setStream_Impl( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XStream > &rxStream );
    void                    terminate_Impl (void);

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > getInputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xInputStream;
                            }

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > getOutputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xOutputStream;
                            }

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XSeekable > getSeekable_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xSeekable;
                            }

    bool                    hasInputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xInputStream.is();
                            }

    void                    setDontClose_Impl()
                            { m_bDontClose = true; }

    void                    SetContentType_Impl( const OUString& rType ) { m_aContentType = rType; }
    void                    SetRealURL_Impl( const OUString& rURL )  { m_aRealURL = rURL; }
    void                    SetExpireDate_Impl( const DateTime& rDateTime )  { m_aExpireDate = rDateTime; }
    void                    SetStreamValid_Impl();
};

SV_IMPL_REF( UcbLockBytes );

}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#708567 unused member variables<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */
#ifndef INCLUDED_UNOTOOLS_UCBLOCKBYTES_HXX
#define INCLUDED_UNOTOOLS_UCBLOCKBYTES_HXX

#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/ucb/XContent.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <unotools/unotoolsdllapi.h>

#include <osl/thread.hxx>
#include <osl/conditn.hxx>
#include <osl/mutex.hxx>
#include <rtl/ustring.hxx>
#include <tools/stream.hxx>
#include <tools/link.hxx>
#include <tools/errcode.hxx>
#include <tools/datetime.hxx>

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace task
            {
                class XInteractionHandler;
            }
            namespace io
            {
                class XStream;
                class XInputStream;
                class XOutputStream;
                class XSeekable;
            }
            namespace ucb
            {
                class XContent;
            }
            namespace beans
            {
                struct PropertyValue;
            }
        }
    }
}

namespace utl
{
SV_DECL_REF( UcbLockBytes )

class UcbLockBytesHandler : public SvRefBase
{
    bool            m_bActive;
public:
    enum LoadHandlerItem
    {
        DATA_AVAILABLE,
        DONE,
        CANCEL
    };

                    UcbLockBytesHandler()
                        : m_bActive( true )
                    {}

    virtual void    Handle( LoadHandlerItem nWhich, UcbLockBytesRef xLockBytes ) = 0;
    void            Activate( bool bActivate = true ) { m_bActive = bActivate; }
    bool            IsActive() const { return m_bActive; }
};

SV_DECL_IMPL_REF( UcbLockBytesHandler )

class UNOTOOLS_DLLPUBLIC UcbLockBytes : public virtual SvLockBytes
{
    osl::Condition          m_aInitialized;
    osl::Condition          m_aTerminated;
    osl::Mutex              m_aMutex;

    OUString                m_aContentType;
    OUString                m_aRealURL;
    DateTime                m_aExpireDate;

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream >  m_xInputStream;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > m_xOutputStream;
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XSeekable >     m_xSeekable;
    void*                   m_pCommandThread; // is alive only for compatibility reasons
    UcbLockBytesHandlerRef  m_xHandler;

    ErrCode                 m_nError;

    bool                    m_bTerminated;
    bool                    m_bDontClose;
    bool                    m_bStreamValid;

    DECL_LINK(              DataAvailHdl, void * );

                            UcbLockBytes( UcbLockBytesHandler* pHandler=NULL );
protected:
    virtual                 ~UcbLockBytes (void);

public:
                            // properties: Referer, PostMimeType
    static UcbLockBytesRef  CreateLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::ucb::XContent >& xContent,
                                            const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& rProps,
                                            StreamMode eMode,
                                            const ::com::sun::star::uno::Reference < ::com::sun::star::task::XInteractionHandler >& xInter,
                                            UcbLockBytesHandler* pHandler=0 );

    static UcbLockBytesRef  CreateInputLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream >& xContent );
    static UcbLockBytesRef  CreateLockBytes( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XStream >& xContent );

    // SvLockBytes
    virtual void            SetSynchronMode (bool bSynchron) SAL_OVERRIDE;
    virtual ErrCode         ReadAt(sal_uInt64 nPos, void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const SAL_OVERRIDE;
    virtual ErrCode         WriteAt(sal_uInt64, const void*, sal_uLong, sal_uLong *pWritten) SAL_OVERRIDE;
    virtual ErrCode         Flush() const SAL_OVERRIDE;
    virtual ErrCode         SetSize(sal_uInt64) SAL_OVERRIDE;
    virtual ErrCode         Stat ( SvLockBytesStat *pStat, SvLockBytesStatFlag) const SAL_OVERRIDE;

    void                    SetError( ErrCode nError )
                            { m_nError = nError; }

    ErrCode                 GetError() const
                            { return m_nError; }

    // the following properties are available when and after the first DataAvailable callback has been executed
    OUString                GetContentType() const;
    OUString                GetRealURL() const;
    DateTime                GetExpireDate() const;

    // calling this method delegates the responsibility to call closeinput to the caller!
    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > getInputStream();

    bool                    setInputStream_Impl( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > &rxInputStream,
                                                 bool bSetXSeekable = true );
    bool                    setStream_Impl( const ::com::sun::star::uno::Reference < ::com::sun::star::io::XStream > &rxStream );
    void                    terminate_Impl (void);

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > getInputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xInputStream;
                            }

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > getOutputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xOutputStream;
                            }

    ::com::sun::star::uno::Reference < ::com::sun::star::io::XSeekable > getSeekable_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xSeekable;
                            }

    bool                    hasInputStream_Impl() const
                            {
                                osl::MutexGuard aGuard( (const_cast< UcbLockBytes* >(this))->m_aMutex );
                                return m_xInputStream.is();
                            }

    void                    setDontClose_Impl()
                            { m_bDontClose = true; }

    void                    SetContentType_Impl( const OUString& rType ) { m_aContentType = rType; }
    void                    SetRealURL_Impl( const OUString& rURL )  { m_aRealURL = rURL; }
    void                    SetExpireDate_Impl( const DateTime& rDateTime )  { m_aExpireDate = rDateTime; }
    void                    SetStreamValid_Impl();
};

SV_IMPL_REF( UcbLockBytes );

}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>