<commit_before>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#ifndef __rtkCudaWarpForwardProjectionImageFilter_hxx
#define __rtkCudaWarpForwardProjectionImageFilter_hxx

#include "rtkCudaWarpForwardProjectionImageFilter.h"
#include "rtkCudaUtilities.hcu"
#include "rtkCudaWarpForwardProjectionImageFilter.hcu"
#include "rtkHomogeneousMatrix.h"
#include "rtkMacro.h"

#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkMacro.h>
#include <itkImageRegionIterator.h>
#include <itkImageAlgorithm.h>
#include "itkCudaUtil.h"

namespace rtk
{

CudaWarpForwardProjectionImageFilter
::CudaWarpForwardProjectionImageFilter():
  m_StepSize(1)
{
  this->SetNumberOfRequiredInputs(2);
}

void
CudaWarpForwardProjectionImageFilter
::SetInputProjectionStack(const InputImageType* ProjectionStack)
{
  this->SetInput(0, const_cast<InputImageType*>(ProjectionStack));
}

void
CudaWarpForwardProjectionImageFilter
::SetInputVolume(const InputImageType* Volume)
{
  this->SetInput(1, const_cast<InputImageType*>(Volume));
}

void
CudaWarpForwardProjectionImageFilter
::SetDisplacementField(const DVFType* DVF)
{
  this->SetInput("DisplacementField", const_cast<DVFType*>(DVF));
}

CudaWarpForwardProjectionImageFilter::InputImageType::Pointer
CudaWarpForwardProjectionImageFilter
::GetInputProjectionStack()
{
  return static_cast< InputImageType * >
          ( this->itk::ProcessObject::GetInput(0) );
}

CudaWarpForwardProjectionImageFilter::InputImageType::Pointer
CudaWarpForwardProjectionImageFilter
::GetInputVolume()
{
  return static_cast< InputImageType * >
          ( this->itk::ProcessObject::GetInput(1) );
}

CudaWarpForwardProjectionImageFilter::DVFType::Pointer
CudaWarpForwardProjectionImageFilter
::GetDisplacementField()
{
  return static_cast< DVFType * >
          ( this->itk::ProcessObject::GetInput("DisplacementField") );
}

void
CudaWarpForwardProjectionImageFilter
::GenerateInputRequestedRegion()
{
  Superclass::GenerateInputRequestedRegion();

  // Since we do not know where the DVF points, the
  // whole input volume is required.
  this->GetInputVolume()->SetRequestedRegionToLargestPossibleRegion();

  // The requested region on the projection stack input is the same as the output requested region
  this->GetInputProjectionStack()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());

#if ITK_VERSION_MAJOR < 4 || (ITK_VERSION_MAJOR == 4 && ITK_VERSION_MINOR < 8)
  this->GetDisplacementField()->SetRequestedRegionToLargestPossibleRegion();
#else
  // Determine the smallest region of the deformation field that fully
  // contains the physical space covered by the input volume's requested
  // region
  DVFType::Pointer    fieldPtr = this->GetDisplacementField();
  InputImageType::Pointer  inputPtr = this->GetInputVolume();
  if ( fieldPtr.IsNotNull() )
    {
    // tolerance for origin and spacing depends on the size of pixel
    // tolerance for direction is a fraction of the unit cube.
    const itk::SpacePrecisionType coordinateTol = this->GetCoordinateTolerance() * inputPtr->GetSpacing()[0]; // use first dimension spacing

    bool DefFieldSameInformation =
       (inputPtr->GetOrigin().GetVnlVector().is_equal(fieldPtr->GetOrigin().GetVnlVector(), coordinateTol))
    && (inputPtr->GetSpacing().GetVnlVector().is_equal(fieldPtr->GetSpacing().GetVnlVector(), coordinateTol))
    && (inputPtr->GetDirection().GetVnlMatrix().as_ref().is_equal(fieldPtr->GetDirection().GetVnlMatrix(), this->GetDirectionTolerance()));

    if (DefFieldSameInformation)
      {
      fieldPtr->SetRequestedRegion( inputPtr->GetRequestedRegion() );
      }
    else
      {
      typedef DVFType::RegionType DisplacementRegionType;

      DisplacementRegionType fieldRequestedRegion = itk::ImageAlgorithm::EnlargeRegionOverBox(inputPtr->GetRequestedRegion(),
                                                                                inputPtr.GetPointer(),
                                                                                fieldPtr.GetPointer());
      fieldPtr->SetRequestedRegion( fieldRequestedRegion );
      }
    if ( !fieldPtr->VerifyRequestedRegion() )
      {
      fieldPtr->SetRequestedRegion( fieldPtr->GetLargestPossibleRegion() );
      }
    }
#endif
}

void
CudaWarpForwardProjectionImageFilter
::GPUGenerateData()
{
  itk::Matrix<double, 4, 4> matrixIdxInputVol;
  itk::Matrix<double, 4, 4> indexInputToPPInputMatrix;
  itk::Matrix<double, 4, 4> indexInputToIndexDVFMatrix;
  itk::Matrix<double, 4, 4> PPInputToIndexInputMatrix;
  matrixIdxInputVol.SetIdentity();
  for(unsigned int i=0; i<3; i++)
    {
    matrixIdxInputVol[i][3] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i]; // Should 0.5 be added here ?
    }

  const Superclass::GeometryType::Pointer geometry = this->GetGeometry();
  const unsigned int Dimension = InputImageType::ImageDimension;
  const unsigned int iFirstProj = this->GetInputProjectionStack()->GetRequestedRegion().GetIndex(Dimension-1);
  const unsigned int nProj = this->GetInputProjectionStack()->GetRequestedRegion().GetSize(Dimension-1);
  const unsigned int nPixelsPerProj = this->GetOutput()->GetBufferedRegion().GetSize(0) *
    this->GetOutput()->GetBufferedRegion().GetSize(1);

  itk::Vector<double, 4> source_position;

  // Setting BoxMin and BoxMax
  // SR: we are using cuda textures where the pixel definition is not center but corner.
  // Therefore, we set the box limits from index to index+size instead of, for ITK,
  // index-0.5 to index+size-0.5.
  float boxMin[3];
  float boxMax[3];
  for(unsigned int i=0; i<3; i++)
    {
    boxMin[i] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i]+0.5;
    boxMax[i] = boxMin[i] + this->GetInputVolume()->GetBufferedRegion().GetSize()[i]-1.0;
    }

  // Getting Spacing
  float spacing[3];
  for(unsigned int i=0; i<3; i++)
    {
    spacing[i] = this->GetInputVolume()->GetSpacing()[i];
    }

  // Cuda convenient format for dimensions
  int projectionSize[2];
  projectionSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];
  projectionSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];

  int volumeSize[3];
  volumeSize[0] = this->GetInputVolume()->GetBufferedRegion().GetSize()[0];
  volumeSize[1] = this->GetInputVolume()->GetBufferedRegion().GetSize()[1];
  volumeSize[2] = this->GetInputVolume()->GetBufferedRegion().GetSize()[2];

  int inputDVFSize[3];
  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];
  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];
  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];

  float *pin = *(float**)( this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pout = *(float**)( this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pvol = *(float**)( this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pDVF = *(float**)( this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer() );

  // Transform matrices that we will need during the warping process
  indexInputToPPInputMatrix = rtk::GetIndexToPhysicalPointMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix()
                              * matrixIdxInputVol.GetVnlMatrix();

  indexInputToIndexDVFMatrix = rtk::GetPhysicalPointToIndexMatrix( this->GetDisplacementField().GetPointer() ).GetVnlMatrix()
                              * rtk::GetIndexToPhysicalPointMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix()
                              * matrixIdxInputVol.GetVnlMatrix();

  PPInputToIndexInputMatrix = rtk::GetPhysicalPointToIndexMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix();

  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)
  float fIndexInputToIndexDVFMatrix[12];
  float fPPInputToIndexInputMatrix[12];
  float fIndexInputToPPInputMatrix[12];
  for (int j = 0; j < 12; j++)
    {
    fIndexInputToIndexDVFMatrix[j] = (float) indexInputToIndexDVFMatrix[j/4][j%4];
    fPPInputToIndexInputMatrix[j] = (float) PPInputToIndexInputMatrix[j/4][j%4];
    fIndexInputToPPInputMatrix[j] = (float) indexInputToPPInputMatrix[j/4][j%4];
    }

  // Account for system rotations
  Superclass::GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;
  volPPToIndex = GetPhysicalPointToIndexMatrix( this->GetInputVolume().GetPointer() );

  // Compute matrix to translate the pixel indices on the volume and the detector
  // if the Requested region has non-zero index
  Superclass::GeometryType::ThreeDHomogeneousMatrixType projIndexTranslation, volIndexTranslation;
  projIndexTranslation.SetIdentity();
  volIndexTranslation.SetIdentity();
  for(unsigned int i=0; i<3; i++)
    {
    projIndexTranslation[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex(i);
    volIndexTranslation[i][3] = -this->GetInputVolume()->GetBufferedRegion().GetIndex(i);

    // Adding 0.5 offset to change from the centered pixel convention (ITK)
    // to the corner pixel convention (CUDA).
    volPPToIndex[i][3] += 0.5;
    }

  // Compute matrices to transform projection index to volume index, one per projection
  float* matrices = new float[12 * nProj];
  float* source_positions = new float[4 * nProj];

  // Go over each projection
  for(unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)
    {
    Superclass::GeometryType::ThreeDHomogeneousMatrixType d_matrix;
    d_matrix =
      volIndexTranslation.GetVnlMatrix() *
      volPPToIndex.GetVnlMatrix() *
      geometry->GetProjectionCoordinatesToFixedSystemMatrix(iProj).GetVnlMatrix() *
      rtk::GetIndexToPhysicalPointMatrix( this->GetInput() ).GetVnlMatrix() *
      projIndexTranslation.GetVnlMatrix();
    for (int j=0; j<3; j++) // Ignore the 4th row
      for (int k=0; k<4; k++)
        matrices[(j + 3 * (iProj-iFirstProj))*4+k] = (float)d_matrix[j][k];

    // Compute source position in volume indices
    source_position= volPPToIndex * geometry->GetSourcePosition(iProj);

    // Copy it into a single large array
    for (unsigned int d=0; d<3; d++)
      source_positions[(iProj-iFirstProj)*3 + d] = source_position[d]; // Ignore the 4th component
    }

  int projectionOffset = 0;
  for (unsigned int i=0; i<nProj; i+=SLAB_SIZE)
    {
    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections
    projectionSize[2] = std::min(nProj-i, (unsigned int)SLAB_SIZE);
    projectionOffset = iFirstProj + i - this->GetOutput()->GetBufferedRegion().GetIndex(2);

    CUDA_warp_forward_project(projectionSize,
                        volumeSize,
                        inputDVFSize,
                        (float*)&(matrices[12 * i]),
                        pin + nPixelsPerProj * projectionOffset,
                        pout + nPixelsPerProj * projectionOffset,
                        pvol,
                        m_StepSize,
                        (float*)&(source_positions[3 * i]),
                        boxMin,
                        boxMax,
                        spacing,
                        pDVF,
                        fIndexInputToIndexDVFMatrix,
                        fPPInputToIndexInputMatrix,
                        fIndexInputToPPInputMatrix
                        );
    }
}

} // end namespace rtk

#endif
<commit_msg>Fixed memory leak in code/rtkCudaWarpForwardProjectionImageFilter.cxx<commit_after>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#ifndef __rtkCudaWarpForwardProjectionImageFilter_hxx
#define __rtkCudaWarpForwardProjectionImageFilter_hxx

#include "rtkCudaWarpForwardProjectionImageFilter.h"
#include "rtkCudaUtilities.hcu"
#include "rtkCudaWarpForwardProjectionImageFilter.hcu"
#include "rtkHomogeneousMatrix.h"
#include "rtkMacro.h"

#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkMacro.h>
#include <itkImageRegionIterator.h>
#include <itkImageAlgorithm.h>
#include "itkCudaUtil.h"

namespace rtk
{

CudaWarpForwardProjectionImageFilter
::CudaWarpForwardProjectionImageFilter():
  m_StepSize(1)
{
  this->SetNumberOfRequiredInputs(2);
}

void
CudaWarpForwardProjectionImageFilter
::SetInputProjectionStack(const InputImageType* ProjectionStack)
{
  this->SetInput(0, const_cast<InputImageType*>(ProjectionStack));
}

void
CudaWarpForwardProjectionImageFilter
::SetInputVolume(const InputImageType* Volume)
{
  this->SetInput(1, const_cast<InputImageType*>(Volume));
}

void
CudaWarpForwardProjectionImageFilter
::SetDisplacementField(const DVFType* DVF)
{
  this->SetInput("DisplacementField", const_cast<DVFType*>(DVF));
}

CudaWarpForwardProjectionImageFilter::InputImageType::Pointer
CudaWarpForwardProjectionImageFilter
::GetInputProjectionStack()
{
  return static_cast< InputImageType * >
          ( this->itk::ProcessObject::GetInput(0) );
}

CudaWarpForwardProjectionImageFilter::InputImageType::Pointer
CudaWarpForwardProjectionImageFilter
::GetInputVolume()
{
  return static_cast< InputImageType * >
          ( this->itk::ProcessObject::GetInput(1) );
}

CudaWarpForwardProjectionImageFilter::DVFType::Pointer
CudaWarpForwardProjectionImageFilter
::GetDisplacementField()
{
  return static_cast< DVFType * >
          ( this->itk::ProcessObject::GetInput("DisplacementField") );
}

void
CudaWarpForwardProjectionImageFilter
::GenerateInputRequestedRegion()
{
  Superclass::GenerateInputRequestedRegion();

  // Since we do not know where the DVF points, the
  // whole input volume is required.
  this->GetInputVolume()->SetRequestedRegionToLargestPossibleRegion();

  // The requested region on the projection stack input is the same as the output requested region
  this->GetInputProjectionStack()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());

#if ITK_VERSION_MAJOR < 4 || (ITK_VERSION_MAJOR == 4 && ITK_VERSION_MINOR < 8)
  this->GetDisplacementField()->SetRequestedRegionToLargestPossibleRegion();
#else
  // Determine the smallest region of the deformation field that fully
  // contains the physical space covered by the input volume's requested
  // region
  DVFType::Pointer    fieldPtr = this->GetDisplacementField();
  InputImageType::Pointer  inputPtr = this->GetInputVolume();
  if ( fieldPtr.IsNotNull() )
    {
    // tolerance for origin and spacing depends on the size of pixel
    // tolerance for direction is a fraction of the unit cube.
    const itk::SpacePrecisionType coordinateTol = this->GetCoordinateTolerance() * inputPtr->GetSpacing()[0]; // use first dimension spacing

    bool DefFieldSameInformation =
       (inputPtr->GetOrigin().GetVnlVector().is_equal(fieldPtr->GetOrigin().GetVnlVector(), coordinateTol))
    && (inputPtr->GetSpacing().GetVnlVector().is_equal(fieldPtr->GetSpacing().GetVnlVector(), coordinateTol))
    && (inputPtr->GetDirection().GetVnlMatrix().as_ref().is_equal(fieldPtr->GetDirection().GetVnlMatrix(), this->GetDirectionTolerance()));

    if (DefFieldSameInformation)
      {
      fieldPtr->SetRequestedRegion( inputPtr->GetRequestedRegion() );
      }
    else
      {
      typedef DVFType::RegionType DisplacementRegionType;

      DisplacementRegionType fieldRequestedRegion = itk::ImageAlgorithm::EnlargeRegionOverBox(inputPtr->GetRequestedRegion(),
                                                                                inputPtr.GetPointer(),
                                                                                fieldPtr.GetPointer());
      fieldPtr->SetRequestedRegion( fieldRequestedRegion );
      }
    if ( !fieldPtr->VerifyRequestedRegion() )
      {
      fieldPtr->SetRequestedRegion( fieldPtr->GetLargestPossibleRegion() );
      }
    }
#endif
}

void
CudaWarpForwardProjectionImageFilter
::GPUGenerateData()
{
  itk::Matrix<double, 4, 4> matrixIdxInputVol;
  itk::Matrix<double, 4, 4> indexInputToPPInputMatrix;
  itk::Matrix<double, 4, 4> indexInputToIndexDVFMatrix;
  itk::Matrix<double, 4, 4> PPInputToIndexInputMatrix;
  matrixIdxInputVol.SetIdentity();
  for(unsigned int i=0; i<3; i++)
    {
    matrixIdxInputVol[i][3] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i]; // Should 0.5 be added here ?
    }

  const Superclass::GeometryType::Pointer geometry = this->GetGeometry();
  const unsigned int Dimension = InputImageType::ImageDimension;
  const unsigned int iFirstProj = this->GetInputProjectionStack()->GetRequestedRegion().GetIndex(Dimension-1);
  const unsigned int nProj = this->GetInputProjectionStack()->GetRequestedRegion().GetSize(Dimension-1);
  const unsigned int nPixelsPerProj = this->GetOutput()->GetBufferedRegion().GetSize(0) *
    this->GetOutput()->GetBufferedRegion().GetSize(1);

  itk::Vector<double, 4> source_position;

  // Setting BoxMin and BoxMax
  // SR: we are using cuda textures where the pixel definition is not center but corner.
  // Therefore, we set the box limits from index to index+size instead of, for ITK,
  // index-0.5 to index+size-0.5.
  float boxMin[3];
  float boxMax[3];
  for(unsigned int i=0; i<3; i++)
    {
    boxMin[i] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i]+0.5;
    boxMax[i] = boxMin[i] + this->GetInputVolume()->GetBufferedRegion().GetSize()[i]-1.0;
    }

  // Getting Spacing
  float spacing[3];
  for(unsigned int i=0; i<3; i++)
    {
    spacing[i] = this->GetInputVolume()->GetSpacing()[i];
    }

  // Cuda convenient format for dimensions
  int projectionSize[2];
  projectionSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];
  projectionSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];

  int volumeSize[3];
  volumeSize[0] = this->GetInputVolume()->GetBufferedRegion().GetSize()[0];
  volumeSize[1] = this->GetInputVolume()->GetBufferedRegion().GetSize()[1];
  volumeSize[2] = this->GetInputVolume()->GetBufferedRegion().GetSize()[2];

  int inputDVFSize[3];
  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];
  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];
  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];

  float *pin = *(float**)( this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pout = *(float**)( this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pvol = *(float**)( this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pDVF = *(float**)( this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer() );

  // Transform matrices that we will need during the warping process
  indexInputToPPInputMatrix = rtk::GetIndexToPhysicalPointMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix()
                              * matrixIdxInputVol.GetVnlMatrix();

  indexInputToIndexDVFMatrix = rtk::GetPhysicalPointToIndexMatrix( this->GetDisplacementField().GetPointer() ).GetVnlMatrix()
                              * rtk::GetIndexToPhysicalPointMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix()
                              * matrixIdxInputVol.GetVnlMatrix();

  PPInputToIndexInputMatrix = rtk::GetPhysicalPointToIndexMatrix( this->GetInputVolume().GetPointer() ).GetVnlMatrix();

  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)
  float fIndexInputToIndexDVFMatrix[12];
  float fPPInputToIndexInputMatrix[12];
  float fIndexInputToPPInputMatrix[12];
  for (int j = 0; j < 12; j++)
    {
    fIndexInputToIndexDVFMatrix[j] = (float) indexInputToIndexDVFMatrix[j/4][j%4];
    fPPInputToIndexInputMatrix[j] = (float) PPInputToIndexInputMatrix[j/4][j%4];
    fIndexInputToPPInputMatrix[j] = (float) indexInputToPPInputMatrix[j/4][j%4];
    }

  // Account for system rotations
  Superclass::GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;
  volPPToIndex = GetPhysicalPointToIndexMatrix( this->GetInputVolume().GetPointer() );

  // Compute matrix to translate the pixel indices on the volume and the detector
  // if the Requested region has non-zero index
  Superclass::GeometryType::ThreeDHomogeneousMatrixType projIndexTranslation, volIndexTranslation;
  projIndexTranslation.SetIdentity();
  volIndexTranslation.SetIdentity();
  for(unsigned int i=0; i<3; i++)
    {
    projIndexTranslation[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex(i);
    volIndexTranslation[i][3] = -this->GetInputVolume()->GetBufferedRegion().GetIndex(i);

    // Adding 0.5 offset to change from the centered pixel convention (ITK)
    // to the corner pixel convention (CUDA).
    volPPToIndex[i][3] += 0.5;
    }

  // Compute matrices to transform projection index to volume index, one per projection
  float* matrices = new float[12 * nProj];
  float* source_positions = new float[4 * nProj];

  // Go over each projection
  for(unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)
    {
    Superclass::GeometryType::ThreeDHomogeneousMatrixType d_matrix;
    d_matrix =
      volIndexTranslation.GetVnlMatrix() *
      volPPToIndex.GetVnlMatrix() *
      geometry->GetProjectionCoordinatesToFixedSystemMatrix(iProj).GetVnlMatrix() *
      rtk::GetIndexToPhysicalPointMatrix( this->GetInput() ).GetVnlMatrix() *
      projIndexTranslation.GetVnlMatrix();
    for (int j=0; j<3; j++) // Ignore the 4th row
      for (int k=0; k<4; k++)
        matrices[(j + 3 * (iProj-iFirstProj))*4+k] = (float)d_matrix[j][k];

    // Compute source position in volume indices
    source_position= volPPToIndex * geometry->GetSourcePosition(iProj);

    // Copy it into a single large array
    for (unsigned int d=0; d<3; d++)
      source_positions[(iProj-iFirstProj)*3 + d] = source_position[d]; // Ignore the 4th component
    }

  int projectionOffset = 0;
  for (unsigned int i=0; i<nProj; i+=SLAB_SIZE)
    {
    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections
    projectionSize[2] = std::min(nProj-i, (unsigned int)SLAB_SIZE);
    projectionOffset = iFirstProj + i - this->GetOutput()->GetBufferedRegion().GetIndex(2);

    CUDA_warp_forward_project(projectionSize,
                        volumeSize,
                        inputDVFSize,
                        (float*)&(matrices[12 * i]),
                        pin + nPixelsPerProj * projectionOffset,
                        pout + nPixelsPerProj * projectionOffset,
                        pvol,
                        m_StepSize,
                        (float*)&(source_positions[3 * i]),
                        boxMin,
                        boxMax,
                        spacing,
                        pDVF,
                        fIndexInputToIndexDVFMatrix,
                        fPPInputToIndexInputMatrix,
                        fIndexInputToPPInputMatrix
                        );
    }

  delete[] matrices;
  delete[] source_positions;
}

} // end namespace rtk

#endif
<|endoftext|>


<commit_before>/*
 * BLITSineHardSync_processor.cpp
 *
 * Copyright (c) 2016, fukuroda (https://github.com/fukuroder)
 * Released under the MIT license
 */

#include "BLITSineHardSync_processor.h"
#include "BLITSineHardSync_voice.h"
#include "BLITSineHardSync_sound.h"

//
BLITSineHardSync_processor::BLITSineHardSync_processor()
{
    _slaveParam = new AudioParameterFloat ("Slave", "Slave", 1.0f, 2.0f, 1.2f);
    addParameter(_slaveParam);

    const int numVoices = 1;

    // add voices
    for (int i = 0; i < numVoices; i++)
    {
        _synth.addVoice (new BLITSineHardSync_voice());
    }

    // add sound
    _synth.addSound (new BLITSineHardSync_sound());
}

//
BLITSineHardSync_processor::~BLITSineHardSync_processor()
{
}

//
const String BLITSineHardSync_processor::getName() const
{
    return JucePlugin_Name;
}

//
bool BLITSineHardSync_processor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
    return true;
#else
    return false;
#endif
}

//
bool BLITSineHardSync_processor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
    return true;
#else
    return false;
#endif
}

//
double BLITSineHardSync_processor::getTailLengthSeconds() const
{
    return 0.0;
}

//
int BLITSineHardSync_processor::getNumPrograms()
{
    return 1;
}

//
int BLITSineHardSync_processor::getCurrentProgram()
{
    return 0;
}

//
void BLITSineHardSync_processor::setCurrentProgram (int index)
{
}

//
const String BLITSineHardSync_processor::getProgramName (int index)
{
    return String();
}

//
void BLITSineHardSync_processor::changeProgramName (int index, const String& newName)
{
}

//
void BLITSineHardSync_processor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    _synth.setCurrentPlaybackSampleRate(sampleRate);
}

//
void BLITSineHardSync_processor::releaseResources()
{
}

//
void BLITSineHardSync_processor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    //-------------------
    // update parameters
    //-------------------
    BLITSineHardSync_sound* sound = static_cast<BLITSineHardSync_sound*>(_synth.getSound(0));
    jassert(sound != nullptr);

    sound->setSlave(static_cast<double>(_slaveParam->get()));

    //----------------
    // process events
    //----------------
    _synth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
}

//
bool BLITSineHardSync_processor::hasEditor() const
{
    return false;
}

//
AudioProcessorEditor* BLITSineHardSync_processor::createEditor()
{
    return nullptr;
}

//
void BLITSineHardSync_processor::getStateInformation (MemoryBlock& destData)
{
}

//
void BLITSineHardSync_processor::setStateInformation (const void* data, int sizeInBytes)
{
}

// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new BLITSineHardSync_processor();
}
<commit_msg>同時発音数を8に変更<commit_after>/*
 * BLITSineHardSync_processor.cpp
 *
 * Copyright (c) 2016, fukuroda (https://github.com/fukuroder)
 * Released under the MIT license
 */

#include "BLITSineHardSync_processor.h"
#include "BLITSineHardSync_voice.h"
#include "BLITSineHardSync_sound.h"

//
BLITSineHardSync_processor::BLITSineHardSync_processor()
{
    _slaveParam = new AudioParameterFloat ("Slave", "Slave", 1.0f, 2.0f, 1.2f);
    addParameter(_slaveParam);

    const int numVoices = 8;

    // add voices
    for (int i = 0; i < numVoices; i++)
    {
        _synth.addVoice (new BLITSineHardSync_voice());
    }

    // add sound
    _synth.addSound (new BLITSineHardSync_sound());
}

//
BLITSineHardSync_processor::~BLITSineHardSync_processor()
{
}

//
const String BLITSineHardSync_processor::getName() const
{
    return JucePlugin_Name;
}

//
bool BLITSineHardSync_processor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
    return true;
#else
    return false;
#endif
}

//
bool BLITSineHardSync_processor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
    return true;
#else
    return false;
#endif
}

//
double BLITSineHardSync_processor::getTailLengthSeconds() const
{
    return 0.0;
}

//
int BLITSineHardSync_processor::getNumPrograms()
{
    return 1;
}

//
int BLITSineHardSync_processor::getCurrentProgram()
{
    return 0;
}

//
void BLITSineHardSync_processor::setCurrentProgram (int index)
{
}

//
const String BLITSineHardSync_processor::getProgramName (int index)
{
    return String();
}

//
void BLITSineHardSync_processor::changeProgramName (int index, const String& newName)
{
}

//
void BLITSineHardSync_processor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    _synth.setCurrentPlaybackSampleRate(sampleRate);
}

//
void BLITSineHardSync_processor::releaseResources()
{
}

//
void BLITSineHardSync_processor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    //-------------------
    // update parameters
    //-------------------
    BLITSineHardSync_sound* sound = static_cast<BLITSineHardSync_sound*>(_synth.getSound(0));
    jassert(sound != nullptr);

    sound->setSlave(static_cast<double>(_slaveParam->get()));

    //----------------
    // process events
    //----------------
    _synth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
}

//
bool BLITSineHardSync_processor::hasEditor() const
{
    return false;
}

//
AudioProcessorEditor* BLITSineHardSync_processor::createEditor()
{
    return nullptr;
}

//
void BLITSineHardSync_processor::getStateInformation (MemoryBlock& destData)
{
}

//
void BLITSineHardSync_processor::setStateInformation (const void* data, int sizeInBytes)
{
}

// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new BLITSineHardSync_processor();
}
<|endoftext|>


<commit_before>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "commonRobotModelTest.h"

#include <kitBase/robotModel/robotParts/touchSensor.h>
#include <kitBase/robotModel/robotParts/rangeSensor.h>

#include <testUtils/signalsTester.h>

using namespace qrTest;
using namespace qrTest::robotsTests::kitBaseTests;

using namespace kitBase;
using namespace kitBase::robotModel;

using namespace ::testing;

/// Basic model constructor check.
TEST_F(CommonRobotModelTest, initializationTest)
{
	CommonRobotModelDescendantMock model;
	Q_UNUSED(model)
}

/// Test for general model lifecycle --- creation, initialization, connecting, configuration and disconnecting, if all
/// is well.
TEST_F(CommonRobotModelTest, lifecycleTest)
{
	CommonRobotModelDescendantMock model;

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::disconnected, "disconnected");

	QObject::connect(&model, &CommonRobotModel::connected, [&] () {
		model.configureDevice(PortInfo("1", input)
				, DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>());
		model.applyConfiguration();
	});
	QObject::connect(&model, &CommonRobotModel::allDevicesConfigured, [&] () { model.disconnectFromRobot(); });

	model.init();

	model.connectToRobot();

	protocolTester.wait(120);

	/// @todo We can not configure devices when model is not connected, or it will not configure them on reconnect.

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("disconnected"));
}

/// Test for 2d model lifecycle --- it does not need connection to robot, but still has to emit correct signals.
TEST_F(CommonRobotModelTest, twoDLifecycleTest)
{
	CommonRobotModelDescendantMock model(true);

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	model.configureDevice(PortInfo("1", input)
			, DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>());
	model.applyConfiguration();

	model.connectToRobot();

	protocolTester.wait(1);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::disconnected, "disconnected");
	model.disconnectFromRobot();

	ASSERT_TRUE(protocolTester.isSignalEmitted("disconnected"));
}

/// Check "real" model behavior when there are no devices to configure.
TEST_F(CommonRobotModelTest, realNoSensorsLifecycleTest)
{
	CommonRobotModelDescendantMock model;

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	QObject::connect(&model, &CommonRobotModel::connected, [&] () { model.applyConfiguration(); });

	model.connectToRobot();

	protocolTester.wait(120);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
}

/// Check "2d" model behavior when there are no devices to configure.
TEST_F(CommonRobotModelTest, twoDNoSensorsLifecycleTest)
{
	CommonRobotModelDescendantMock model(true);

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	model.applyConfiguration();

	model.connectToRobot();

	protocolTester.wait(1);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
}

CommonRobotModelTest::CommonRobotModelDescendantMock::CommonRobotModelDescendantMock(bool immediateConnection)
	: CommonRobotModel("test", "testRobot")
	, mImmediateConnection(immediateConnection)
{
	addAllowedConnection(PortInfo("1", input)
			, { DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>()
					, DeviceInfo::create<kitBase::robotModel::robotParts::RangeSensor>()});

	if (!immediateConnection) {
		mConnectionTimer.setInterval(100);
		mConnectionTimer.setSingleShot(true);
		QObject::connect(&mConnectionTimer, &QTimer::timeout, [&] () {
			emit connected(true, "");
		});
	}
}

void CommonRobotModelTest::CommonRobotModelDescendantMock::connectToRobot()
{
	if (!mImmediateConnection) {
		mConnectionTimer.start();
	} else {
		emit connected(true, "");
	}
}

robotParts::Device *CommonRobotModelTest::CommonRobotModelDescendantMock::createDevice(PortInfo const &port
		, DeviceInfo const &deviceInfo)
{
	Q_UNUSED(deviceInfo)

	return new DummyDevice(port);
}
<commit_msg>just increasing waiting time<commit_after>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "commonRobotModelTest.h"

#include <kitBase/robotModel/robotParts/touchSensor.h>
#include <kitBase/robotModel/robotParts/rangeSensor.h>

#include <testUtils/signalsTester.h>

using namespace qrTest;
using namespace qrTest::robotsTests::kitBaseTests;

using namespace kitBase;
using namespace kitBase::robotModel;

using namespace ::testing;

/// Basic model constructor check.
TEST_F(CommonRobotModelTest, initializationTest)
{
	CommonRobotModelDescendantMock model;
	Q_UNUSED(model)
}

/// Test for general model lifecycle --- creation, initialization, connecting, configuration and disconnecting, if all
/// is well.
TEST_F(CommonRobotModelTest, lifecycleTest)
{
	CommonRobotModelDescendantMock model;

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::disconnected, "disconnected");

	QObject::connect(&model, &CommonRobotModel::connected, [&] () {
		model.configureDevice(PortInfo("1", input)
				, DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>());
		model.applyConfiguration();
	});
	QObject::connect(&model, &CommonRobotModel::allDevicesConfigured, [&] () { model.disconnectFromRobot(); });

	model.init();

	model.connectToRobot();

	protocolTester.wait(250);

	/// @todo We can not configure devices when model is not connected, or it will not configure them on reconnect.

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("disconnected"));
}

/// Test for 2d model lifecycle --- it does not need connection to robot, but still has to emit correct signals.
TEST_F(CommonRobotModelTest, twoDLifecycleTest)
{
	CommonRobotModelDescendantMock model(true);

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	model.configureDevice(PortInfo("1", input)
			, DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>());
	model.applyConfiguration();

	model.connectToRobot();

	protocolTester.wait(1);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::disconnected, "disconnected");
	model.disconnectFromRobot();

	ASSERT_TRUE(protocolTester.isSignalEmitted("disconnected"));
}

/// Check "real" model behavior when there are no devices to configure.
TEST_F(CommonRobotModelTest, realNoSensorsLifecycleTest)
{
	CommonRobotModelDescendantMock model;

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	QObject::connect(&model, &CommonRobotModel::connected, [&] () { model.applyConfiguration(); });

	model.connectToRobot();

	protocolTester.wait(250);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
}

/// Check "2d" model behavior when there are no devices to configure.
TEST_F(CommonRobotModelTest, twoDNoSensorsLifecycleTest)
{
	CommonRobotModelDescendantMock model(true);

	SignalsTester protocolTester(SignalsTester::inOrder);

	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::connected, "connected");
	protocolTester.expectSignal(&model, &CommonRobotModelDescendantMock::allDevicesConfigured, "allDevicesConfigured");

	model.applyConfiguration();

	model.connectToRobot();

	protocolTester.wait(1);

	ASSERT_TRUE(protocolTester.isSignalEmitted("connected"));
	ASSERT_TRUE(protocolTester.isSignalEmitted("allDevicesConfigured"));
}

CommonRobotModelTest::CommonRobotModelDescendantMock::CommonRobotModelDescendantMock(bool immediateConnection)
	: CommonRobotModel("test", "testRobot")
	, mImmediateConnection(immediateConnection)
{
	addAllowedConnection(PortInfo("1", input)
			, { DeviceInfo::create<kitBase::robotModel::robotParts::TouchSensor>()
					, DeviceInfo::create<kitBase::robotModel::robotParts::RangeSensor>()});

	if (!immediateConnection) {
		mConnectionTimer.setInterval(100);
		mConnectionTimer.setSingleShot(true);
		QObject::connect(&mConnectionTimer, &QTimer::timeout, [&] () {
			emit connected(true, "");
		});
	}
}

void CommonRobotModelTest::CommonRobotModelDescendantMock::connectToRobot()
{
	if (!mImmediateConnection) {
		mConnectionTimer.start();
	} else {
		emit connected(true, "");
	}
}

robotParts::Device *CommonRobotModelTest::CommonRobotModelDescendantMock::createDevice(PortInfo const &port
		, DeviceInfo const &deviceInfo)
{
	Q_UNUSED(deviceInfo)

	return new DummyDevice(port);
}
<|endoftext|>


<commit_before>#include "Halide.h"
#include <stdio.h>
#include <stdlib.h>

using namespace Halide;

int test_per_channel_select() {

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    gpu(x, y, c) = cast<uint8_t>(select(c == 0, 128,
                                        c == 1, x,
                                        c == 2, y,
                                        x*y));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected;
                switch (c) {
                    case 0: expected = 128; break;
                    case 1: expected = x; break;
                    case 2: expected = y; break;
                    default: expected = x*y; break;
                }
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int test_flag_scalar_select() {

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    int flag_value = 0;

    Param<int> flag("flag");
    flag.set(flag_value);

    gpu(x, y, c) = cast<uint8_t>(select(flag != 0, 128,
                                        255));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    // This should trigger a copy_to_host operation
    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected = !flag_value ? 255 : 128;
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int test_flag_pixel_select() {

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    int flag_value = 0;

    Param<int> flag("flag");
    flag.set(flag_value);

    Buffer<uint8_t> image(10, 10, 4);
    for (int y=0; y<image.height(); y++) {
        for (int x=0; x<image.width(); x++) {
            for (int c=0; c<image.channels(); c++) {
                image(x, y, c) = 128;
            }
        }
    }

    gpu(x, y, c) = cast<uint8_t>(select(flag != 0, image(x,y,c),
                                        255));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    // This should trigger a copy_to_host operation
    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected = !flag_value ? 255 : 128;
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int main() {

    int err = 0;

    err |= test_per_channel_select();
    err |= test_flag_scalar_select();
    err |= test_flag_pixel_select();

    if (err) {
        printf("FAILED\n");
        return 1;
    }

    printf("Success!\n");
    return 0;
}
<commit_msg>Added failing test cases for issue #1781: Internal assertion failures when compiling certain select expressions for OpenGL target.<commit_after>#include "Halide.h"
#include <stdio.h>
#include <stdlib.h>

using namespace Halide;

int test_per_channel_select() {

    printf("Testing select of channel.\n");

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    gpu(x, y, c) = cast<uint8_t>(select(c == 0, 128,
                                        c == 1, x,
                                        c == 2, y,
                                        x*y));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected;
                switch (c) {
                    case 0: expected = 128; break;
                    case 1: expected = x; break;
                    case 2: expected = y; break;
                    default: expected = x*y; break;
                }
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int test_flag_scalar_select() {

    printf("Testing select of scalar value with flag.\n");

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    int flag_value = 0;

    Param<int> flag("flag");
    flag.set(flag_value);

    gpu(x, y, c) = cast<uint8_t>(select(flag != 0, 128,
                                        255));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    // This should trigger a copy_to_host operation
    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected = !flag_value ? 255 : 128;
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int test_flag_pixel_select() {

    printf("Testing select of pixel value with flag.\n");

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    Func gpu("gpu"), cpu("cpu");
    Var x("x"), y("y"), c("c");

    int flag_value = 0;

    Param<int> flag("flag");
    flag.set(flag_value);

    Buffer<uint8_t> image(10, 10, 4);
    for (int y=0; y<image.height(); y++) {
        for (int x=0; x<image.width(); x++) {
            for (int c=0; c<image.channels(); c++) {
                image(x, y, c) = 128;
            }
        }
    }

    gpu(x, y, c) = cast<uint8_t>(select(flag != 0, image(x,y,c),
                                        255));
    gpu.bound(c, 0, 4);
    gpu.glsl(x, y, c);
    gpu.compute_root();

    // This should trigger a copy_to_host operation
    cpu(x, y, c) = gpu(x, y, c);

    Buffer<uint8_t> out(10, 10, 4);
    cpu.realize(out, target);

    // Verify the result
    for (int y=0; y!=out.height(); ++y) {
        for (int x=0; x!=out.width(); ++x) {
            for (int c=0; c!=out.channels(); ++c) {
                uint8_t expected = !flag_value ? 255 : 128;
                uint8_t actual  = out(x,y,c);

                if (expected != actual) {
                    fprintf(stderr, "Incorrect pixel (%d, %d, %d, %d) at x=%d y=%d.\n",
                            out(x, y, 0), out(x, y, 1), out(x, y, 2), out(x, y, 3),
                            x, y);
                    return 1;
                }
            }
        }
    }

    return 0;
}

int test_nested_select() {

    printf("Testing nested select.\n");

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    // Define the algorithm.
    Var x("x"), y("y"), c("c");
    Func f("f");
    Expr temp = cast<uint8_t>(select(x == 0, 1, 2));
    f(x, y, c) = select(y == 0, temp, 255 - temp);

    // Schedule f to run on the GPU.
    const int channels = 3;
    f.bound(c, 0, channels).glsl(x, y, c);

    // Generate the result.
    const int width = 10, height = 10;
    Buffer<uint8_t> out = f.realize(width, height, channels, target);

    // Check the result.
    int errors = 0;
    out.for_each_element([&](int x, int y, int c) {
        uint8_t temp = x == 0 ? 1 : 2;
        uint8_t expected = y == 0 ? temp : 255 - temp;
        uint8_t actual = out(x, y, c);
        if (expected != actual && ++errors == 1) {
            fprintf(stderr, "out(%d, %d, %d) = %d instead of %d\n",
                    x, y, c, actual, expected);
        }
    });

    return errors;
}

int test_nested_select_varying() {

    printf("Testing nested select with varying condition.\n");

    // This test must be run with an OpenGL target.
    const Target target = get_jit_target_from_environment().with_feature(Target::OpenGL);

    // Define the algorithm.
    Var x("x"), y("y"), c("c");
    Func f("f");
    Expr temp = cast<uint8_t>(select(x - c > 0, 1, 2));
    f(x, y, c) = select(y == 0, temp, 255 - temp);

    // Schedule f to run on the GPU.
    const int channels = 3;
    f.bound(c, 0, channels).glsl(x, y, c);

    // Generate the result.
    const int width = 10, height = 10;
    Buffer<uint8_t> out = f.realize(width, height, channels, target);

    // Check the result.
    int errors = 0;
    out.for_each_element([&](int x, int y, int c) {
        uint8_t temp = x - c > 0 ? 1 : 2;
        uint8_t expected = y == 0 ? temp : 255 - temp;
        uint8_t actual = out(x, y, c);
        if (expected != actual && ++errors == 1) {
            fprintf(stderr, "out(%d, %d, %d) = %d instead of %d\n",
                    x, y, c, actual, expected);
        }
    });

    return errors;
}

int main() {

    int err = 0;

    err |= test_per_channel_select();
    err |= test_flag_scalar_select();
    err |= test_flag_pixel_select();
    err |= test_nested_select();
    err |= test_nested_select_varying();

    if (err) {
        printf("FAILED\n");
        return 1;
    }

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>//===-- ExternalMethods.cpp - Implement External Methods ------------------===//
//
//  This file contains both code to deal with invoking "external" methods, but
//  also contains code that implements "exported" external methods.
//
//  External methods in LLI are implemented by dlopen'ing the lli executable and
//  using dlsym to look op the methods that we want to invoke.  If a method is
//  found, then the arguments are mangled and passed in to the function call.
//
//===----------------------------------------------------------------------===//

#include "Interpreter.h"
#include "llvm/DerivedTypes.h"
#include <map>
#include <dlfcn.h>
#include <link.h>
#include <math.h>

typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
static map<const Method *, ExFunc> Functions;
static map<string, ExFunc> FuncNames;

static Interpreter *TheInterpreter;

// getCurrentExecutablePath() - Return the directory that the lli executable
// lives in.
//
string Interpreter::getCurrentExecutablePath() const {
  Dl_info Info;
  if (dladdr(&TheInterpreter, &Info) == 0) return "";

  string LinkAddr(Info.dli_fname);
  unsigned SlashPos = LinkAddr.rfind('/');
  if (SlashPos != string::npos)
    LinkAddr.resize(SlashPos);    // Trim the executable name off...

  return LinkAddr;
}

static char getTypeID(const Type *Ty) {
  switch (Ty->getPrimitiveID()) {
  case Type::VoidTyID:    return 'V';
  case Type::BoolTyID:    return 'o';
  case Type::UByteTyID:   return 'B';
  case Type::SByteTyID:   return 'b';
  case Type::UShortTyID:  return 'S';
  case Type::ShortTyID:   return 's';
  case Type::UIntTyID:    return 'I';
  case Type::IntTyID:     return 'i';
  case Type::ULongTyID:   return 'L';
  case Type::LongTyID:    return 'l';
  case Type::FloatTyID:   return 'F';
  case Type::DoubleTyID:  return 'D';
  case Type::PointerTyID: return 'P';
  case Type::MethodTyID:  return 'M';
  case Type::StructTyID:  return 'T';
  case Type::ArrayTyID:   return 'A';
  case Type::OpaqueTyID:  return 'O';
  default: return 'U';
  }
}

static ExFunc lookupMethod(const Method *M) {
  // Function not found, look it up... start by figuring out what the
  // composite function name should be.
  string ExtName = "lle_";
  const MethodType *MT = M->getMethodType();
  for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
    ExtName += getTypeID(Ty);
  ExtName += "_" + M->getName();

  //cout << "Tried: '" << ExtName << "'\n";
  ExFunc FnPtr = FuncNames[ExtName];
  if (FnPtr == 0)
    FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
  if (FnPtr == 0)
    FnPtr = FuncNames["lle_X_"+M->getName()];
  if (FnPtr == 0)  // Try calling a generic function... if it exists...
    FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
  if (FnPtr != 0)
    Functions.insert(make_pair(M, FnPtr));  // Cache for later
  return FnPtr;
}

GenericValue Interpreter::callExternalMethod(Method *M,
                                         const vector<GenericValue> &ArgVals) {
  TheInterpreter = this;

  // Do a lookup to see if the method is in our cache... this should just be a
  // defered annotation!
  map<const Method *, ExFunc>::iterator FI = Functions.find(M);
  ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
  if (Fn == 0) {
    cout << "Tried to execute an unknown external method: "
	 << M->getType()->getDescription() << " " << M->getName() << endl;
    return GenericValue();
  }

  // TODO: FIXME when types are not const!
  GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
  return Result;
}

//===----------------------------------------------------------------------===//
//  Methods "exported" to the running application...
//
extern "C" {  // Don't add C++ manglings to llvm mangling :)

// Implement void printstr([ubyte {x N}] *)
GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
  assert(ArgVal.size() == 1 && "printstr only takes one argument!");
  cout << (char*)ArgVal[0].PointerVal;
  return GenericValue();
}

// Implement 'void print(X)' for every type...
GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
  assert(ArgVals.size() == 1 && "generic print only takes one argument!");

  Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
  return GenericValue();
}

// Implement 'void printVal(X)' for every type...
GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
  assert(ArgVal.size() == 1 && "generic print only takes one argument!");

  // Specialize print([ubyte {x N} ] *) and print(sbyte *)
  if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
    if (PTy->getValueType() == Type::SByteTy ||
        isa<ArrayType>(PTy->getValueType())) {
      return lle_VP_printstr(M, ArgVal);
    }

  Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
  return GenericValue();
}

// Implement 'void printString(X)'
// Argument must be [ubyte {x N} ] * or sbyte *
GenericValue lle_X_printString(MethodType *M, const vector<GenericValue> &ArgVal) {
  assert(ArgVal.size() == 1 && "generic print only takes one argument!");
  return lle_VP_printstr(M, ArgVal);
}

// Implement 'void print<TYPE>(X)' for each primitive type or pointer type
#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
  GenericValue lle_X_print##TYPENAME(MethodType *M,\
                                     const vector<GenericValue> &ArgVal) {\
    assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
    assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
    Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
    return GenericValue();\
  }

PRINT_TYPE_FUNC(SByte,   SByteTyID)
PRINT_TYPE_FUNC(UByte,   UByteTyID)
PRINT_TYPE_FUNC(Short,   ShortTyID)
PRINT_TYPE_FUNC(UShort,  UShortTyID)
PRINT_TYPE_FUNC(Int,     IntTyID)
PRINT_TYPE_FUNC(UInt,    UIntTyID)
PRINT_TYPE_FUNC(Long,    LongTyID)
PRINT_TYPE_FUNC(ULong,   ULongTyID)
PRINT_TYPE_FUNC(Float,   FloatTyID)
PRINT_TYPE_FUNC(Double,  DoubleTyID)
PRINT_TYPE_FUNC(Pointer, PointerTyID)

// void "putchar"(sbyte)
GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << Args[0].SByteVal;
  return GenericValue();
}

// int "putchar"(int)
GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << ((char)Args[0].IntVal) << flush;
  return Args[0];
}

// void "putchar"(ubyte)
GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << Args[0].SByteVal << flush;
  return Args[0];
}

// void "__main"()
GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
  return GenericValue();
}

// void "exit"(int)
GenericValue lle_X_exit(MethodType *M, const vector<GenericValue> &Args) {
  TheInterpreter->exitCalled(Args[0]);
  return GenericValue();
}

// void *malloc(uint)
GenericValue lle_X_malloc(MethodType *M, const vector<GenericValue> &Args) {
  assert(Args.size() == 1 && "Malloc expects one argument!");
  GenericValue GV;
  GV.PointerVal = (uint64_t)malloc(Args[0].UIntVal);
  return GV;
}

// void free(void *)
GenericValue lle_X_free(MethodType *M, const vector<GenericValue> &Args) {
  free((void*)Args[0].PointerVal);
  return GenericValue();
}

// double pow(double, double)
GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
  GenericValue GV;
  GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
  return GV;
}

// int printf(sbyte *, ...) - a very rough implementation to make output useful.
GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
  const char *FmtStr = (const char *)Args[0].PointerVal;
  unsigned ArgNo = 1;

  // printf should return # chars printed.  This is completely incorrect, but
  // close enough for now.
  GenericValue GV; GV.IntVal = strlen(FmtStr);
  while (1) {
    switch (*FmtStr) {
    case 0: return GV;             // Null terminator...
    default:                       // Normal nonspecial character
      cout << *FmtStr++;
      break;
    case '\\': {                   // Handle escape codes
      char Buffer[3];
      Buffer[0] = *FmtStr++;
      Buffer[1] = *FmtStr++;
      Buffer[2] = 0;
      cout << Buffer;
      break;
    }
    case '%': {                    // Handle format specifiers
      bool isLong = false;
      ++FmtStr;
      if (*FmtStr == 'l') {
        isLong = true;
        FmtStr++;
      }

      switch (*FmtStr) {
      case '%': cout << *FmtStr; break;                             // %%
      case 'd':                                                     // %d %i
      case 'i': cout << Args[ArgNo++].IntVal; break;
      case 'u': cout << Args[ArgNo++].UIntVal; break;               // %u
      case 'o': cout << oct << Args[ArgNo++].UIntVal << dec; break; // %o
      case 'x':
      case 'X': cout << hex << Args[ArgNo++].UIntVal << dec; break; // %x %X
      case 'e': case 'E': case 'g': case 'G':                       // %[eEgG]
        cout /*<< std::scientific*/ << Args[ArgNo++].DoubleVal
             /*<< std::fixed*/; break;
      case 'f': cout << Args[ArgNo++].DoubleVal; break;             // %f
      case 'c': cout << Args[ArgNo++].UByteVal; break;              // %c
      case 's': cout << (char*)Args[ArgNo++].PointerVal; break;     // %s
      default:  cout << "<unknown printf code '" << *FmtStr << "'!>";
                ArgNo++; break;
      }
      ++FmtStr;
      break;
    }
    }
  }
}

} // End extern "C"

void Interpreter::initializeExternalMethods() {
  FuncNames["lle_VP_printstr"] = lle_VP_printstr;
  FuncNames["lle_X_print"] = lle_X_print;
  FuncNames["lle_X_printVal"] = lle_X_printVal;
  FuncNames["lle_X_printString"] = lle_X_printString;
  FuncNames["lle_X_printUByte"] = lle_X_printUByte;
  FuncNames["lle_X_printSByte"] = lle_X_printSByte;
  FuncNames["lle_X_printUShort"] = lle_X_printUShort;
  FuncNames["lle_X_printShort"] = lle_X_printShort;
  FuncNames["lle_X_printInt"] = lle_X_printInt;
  FuncNames["lle_X_printUInt"] = lle_X_printUInt;
  FuncNames["lle_X_printLong"] = lle_X_printLong;
  FuncNames["lle_X_printULong"] = lle_X_printULong;
  FuncNames["lle_X_printFloat"] = lle_X_printFloat;
  FuncNames["lle_X_printDouble"] = lle_X_printDouble;
  FuncNames["lle_X_printPointer"] = lle_X_printPointer;
  FuncNames["lle_Vb_putchar"]     = lle_Vb_putchar;
  FuncNames["lle_ii_putchar"]     = lle_ii_putchar;
  FuncNames["lle_VB_putchar"]     = lle_VB_putchar;
  FuncNames["lle_V___main"]       = lle_V___main;
  FuncNames["lle_X_exit"]         = lle_X_exit;
  FuncNames["lle_X_malloc"]       = lle_X_malloc;
  FuncNames["lle_X_free"]         = lle_X_free;
  FuncNames["lle_X_pow"]          = lle_X_pow;
  FuncNames["lle_X_printf"]       = lle_X_printf;
}
<commit_msg>Implement sqrt, implement printf better, simpler.<commit_after>//===-- ExternalMethods.cpp - Implement External Methods ------------------===//
//
//  This file contains both code to deal with invoking "external" methods, but
//  also contains code that implements "exported" external methods.
//
//  External methods in LLI are implemented by dlopen'ing the lli executable and
//  using dlsym to look op the methods that we want to invoke.  If a method is
//  found, then the arguments are mangled and passed in to the function call.
//
//===----------------------------------------------------------------------===//

#include "Interpreter.h"
#include "llvm/DerivedTypes.h"
#include <map>
#include <dlfcn.h>
#include <link.h>
#include <math.h>
#include <stdio.h>

typedef GenericValue (*ExFunc)(MethodType *, const vector<GenericValue> &);
static map<const Method *, ExFunc> Functions;
static map<string, ExFunc> FuncNames;

static Interpreter *TheInterpreter;

// getCurrentExecutablePath() - Return the directory that the lli executable
// lives in.
//
string Interpreter::getCurrentExecutablePath() const {
  Dl_info Info;
  if (dladdr(&TheInterpreter, &Info) == 0) return "";

  string LinkAddr(Info.dli_fname);
  unsigned SlashPos = LinkAddr.rfind('/');
  if (SlashPos != string::npos)
    LinkAddr.resize(SlashPos);    // Trim the executable name off...

  return LinkAddr;
}

static char getTypeID(const Type *Ty) {
  switch (Ty->getPrimitiveID()) {
  case Type::VoidTyID:    return 'V';
  case Type::BoolTyID:    return 'o';
  case Type::UByteTyID:   return 'B';
  case Type::SByteTyID:   return 'b';
  case Type::UShortTyID:  return 'S';
  case Type::ShortTyID:   return 's';
  case Type::UIntTyID:    return 'I';
  case Type::IntTyID:     return 'i';
  case Type::ULongTyID:   return 'L';
  case Type::LongTyID:    return 'l';
  case Type::FloatTyID:   return 'F';
  case Type::DoubleTyID:  return 'D';
  case Type::PointerTyID: return 'P';
  case Type::MethodTyID:  return 'M';
  case Type::StructTyID:  return 'T';
  case Type::ArrayTyID:   return 'A';
  case Type::OpaqueTyID:  return 'O';
  default: return 'U';
  }
}

static ExFunc lookupMethod(const Method *M) {
  // Function not found, look it up... start by figuring out what the
  // composite function name should be.
  string ExtName = "lle_";
  const MethodType *MT = M->getMethodType();
  for (unsigned i = 0; const Type *Ty = MT->getContainedType(i); ++i)
    ExtName += getTypeID(Ty);
  ExtName += "_" + M->getName();

  //cout << "Tried: '" << ExtName << "'\n";
  ExFunc FnPtr = FuncNames[ExtName];
  if (FnPtr == 0)
    FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ExtName.c_str());
  if (FnPtr == 0)
    FnPtr = FuncNames["lle_X_"+M->getName()];
  if (FnPtr == 0)  // Try calling a generic function... if it exists...
    FnPtr = (ExFunc)dlsym(RTLD_DEFAULT, ("lle_X_"+M->getName()).c_str());
  if (FnPtr != 0)
    Functions.insert(make_pair(M, FnPtr));  // Cache for later
  return FnPtr;
}

GenericValue Interpreter::callExternalMethod(Method *M,
                                         const vector<GenericValue> &ArgVals) {
  TheInterpreter = this;

  // Do a lookup to see if the method is in our cache... this should just be a
  // defered annotation!
  map<const Method *, ExFunc>::iterator FI = Functions.find(M);
  ExFunc Fn = (FI == Functions.end()) ? lookupMethod(M) : FI->second;
  if (Fn == 0) {
    cout << "Tried to execute an unknown external method: "
	 << M->getType()->getDescription() << " " << M->getName() << endl;
    return GenericValue();
  }

  // TODO: FIXME when types are not const!
  GenericValue Result = Fn(const_cast<MethodType*>(M->getMethodType()),ArgVals);
  return Result;
}

//===----------------------------------------------------------------------===//
//  Methods "exported" to the running application...
//
extern "C" {  // Don't add C++ manglings to llvm mangling :)

// Implement void printstr([ubyte {x N}] *)
GenericValue lle_VP_printstr(MethodType *M, const vector<GenericValue> &ArgVal){
  assert(ArgVal.size() == 1 && "printstr only takes one argument!");
  cout << (char*)ArgVal[0].PointerVal;
  return GenericValue();
}

// Implement 'void print(X)' for every type...
GenericValue lle_X_print(MethodType *M, const vector<GenericValue> &ArgVals) {
  assert(ArgVals.size() == 1 && "generic print only takes one argument!");

  Interpreter::print(M->getParamTypes()[0], ArgVals[0]);
  return GenericValue();
}

// Implement 'void printVal(X)' for every type...
GenericValue lle_X_printVal(MethodType *M, const vector<GenericValue> &ArgVal) {
  assert(ArgVal.size() == 1 && "generic print only takes one argument!");

  // Specialize print([ubyte {x N} ] *) and print(sbyte *)
  if (PointerType *PTy = dyn_cast<PointerType>(M->getParamTypes()[0].get()))
    if (PTy->getValueType() == Type::SByteTy ||
        isa<ArrayType>(PTy->getValueType())) {
      return lle_VP_printstr(M, ArgVal);
    }

  Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);
  return GenericValue();
}

// Implement 'void printString(X)'
// Argument must be [ubyte {x N} ] * or sbyte *
GenericValue lle_X_printString(MethodType *M, const vector<GenericValue> &ArgVal) {
  assert(ArgVal.size() == 1 && "generic print only takes one argument!");
  return lle_VP_printstr(M, ArgVal);
}

// Implement 'void print<TYPE>(X)' for each primitive type or pointer type
#define PRINT_TYPE_FUNC(TYPENAME,TYPEID) \
  GenericValue lle_X_print##TYPENAME(MethodType *M,\
                                     const vector<GenericValue> &ArgVal) {\
    assert(ArgVal.size() == 1 && "generic print only takes one argument!");\
    assert(M->getParamTypes()[0].get()->getPrimitiveID() == Type::##TYPEID);\
    Interpreter::printValue(M->getParamTypes()[0], ArgVal[0]);\
    return GenericValue();\
  }

PRINT_TYPE_FUNC(SByte,   SByteTyID)
PRINT_TYPE_FUNC(UByte,   UByteTyID)
PRINT_TYPE_FUNC(Short,   ShortTyID)
PRINT_TYPE_FUNC(UShort,  UShortTyID)
PRINT_TYPE_FUNC(Int,     IntTyID)
PRINT_TYPE_FUNC(UInt,    UIntTyID)
PRINT_TYPE_FUNC(Long,    LongTyID)
PRINT_TYPE_FUNC(ULong,   ULongTyID)
PRINT_TYPE_FUNC(Float,   FloatTyID)
PRINT_TYPE_FUNC(Double,  DoubleTyID)
PRINT_TYPE_FUNC(Pointer, PointerTyID)

// void "putchar"(sbyte)
GenericValue lle_Vb_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << Args[0].SByteVal;
  return GenericValue();
}

// int "putchar"(int)
GenericValue lle_ii_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << ((char)Args[0].IntVal) << flush;
  return Args[0];
}

// void "putchar"(ubyte)
GenericValue lle_VB_putchar(MethodType *M, const vector<GenericValue> &Args) {
  cout << Args[0].SByteVal << flush;
  return Args[0];
}

// void "__main"()
GenericValue lle_V___main(MethodType *M, const vector<GenericValue> &Args) {
  return GenericValue();
}

// void "exit"(int)
GenericValue lle_X_exit(MethodType *M, const vector<GenericValue> &Args) {
  TheInterpreter->exitCalled(Args[0]);
  return GenericValue();
}

// void *malloc(uint)
GenericValue lle_X_malloc(MethodType *M, const vector<GenericValue> &Args) {
  assert(Args.size() == 1 && "Malloc expects one argument!");
  GenericValue GV;
  GV.PointerVal = (uint64_t)malloc(Args[0].UIntVal);
  return GV;
}

// void free(void *)
GenericValue lle_X_free(MethodType *M, const vector<GenericValue> &Args) {
  assert(Args.size() == 1);
  free((void*)Args[0].PointerVal);
  return GenericValue();
}

// double pow(double, double)
GenericValue lle_X_pow(MethodType *M, const vector<GenericValue> &Args) {
  assert(Args.size() == 2);
  GenericValue GV;
  GV.DoubleVal = pow(Args[0].DoubleVal, Args[1].DoubleVal);
  return GV;
}

// double sqrt(double)
GenericValue lle_X_sqrt(MethodType *M, const vector<GenericValue> &Args) {
  assert(Args.size() == 1);
  GenericValue GV;
  GV.DoubleVal = sqrt(Args[0].DoubleVal);
  return GV;
}

// int printf(sbyte *, ...) - a very rough implementation to make output useful.
GenericValue lle_X_printf(MethodType *M, const vector<GenericValue> &Args) {
  const char *FmtStr = (const char *)Args[0].PointerVal;
  unsigned ArgNo = 1;

  // printf should return # chars printed.  This is completely incorrect, but
  // close enough for now.
  GenericValue GV; GV.IntVal = strlen(FmtStr);
  while (1) {
    switch (*FmtStr) {
    case 0: return GV;             // Null terminator...
    default:                       // Normal nonspecial character
      cout << *FmtStr++;
      break;
    case '\\': {                   // Handle escape codes
      char Buffer[3];
      Buffer[0] = *FmtStr++;
      Buffer[1] = *FmtStr++;
      Buffer[2] = 0;
      cout << Buffer;
      break;
    }
    case '%': {                    // Handle format specifiers
      bool isLong = false;
      ++FmtStr;
      if (*FmtStr == 'l') {
        isLong = true;
        FmtStr++;
      }

      if (*FmtStr == '%')
        cout << *FmtStr;                  // %%
      else {
        char Fmt[] = "%d", Buffer[1000] = "";
        Fmt[1] = *FmtStr;

        switch (*FmtStr) {
        case 'c':
          sprintf(Buffer, Fmt, Args[ArgNo++].SByteVal); break;
        case 'd': case 'i':
        case 'u': case 'o':
        case 'x': case 'X':
          sprintf(Buffer, Fmt, Args[ArgNo++].IntVal); break;
        case 'e': case 'E': case 'g': case 'G': case 'f':
          sprintf(Buffer, Fmt, Args[ArgNo++].DoubleVal); break;
        case 's': cout << (char*)Args[ArgNo++].PointerVal; break;     // %s
        default:  cout << "<unknown printf code '" << *FmtStr << "'!>";
          ArgNo++; break;
        }
        cout << Buffer;
      }
      ++FmtStr;
      break;
    }
    }
  }
}

} // End extern "C"

void Interpreter::initializeExternalMethods() {
  FuncNames["lle_VP_printstr"] = lle_VP_printstr;
  FuncNames["lle_X_print"] = lle_X_print;
  FuncNames["lle_X_printVal"] = lle_X_printVal;
  FuncNames["lle_X_printString"] = lle_X_printString;
  FuncNames["lle_X_printUByte"] = lle_X_printUByte;
  FuncNames["lle_X_printSByte"] = lle_X_printSByte;
  FuncNames["lle_X_printUShort"] = lle_X_printUShort;
  FuncNames["lle_X_printShort"] = lle_X_printShort;
  FuncNames["lle_X_printInt"] = lle_X_printInt;
  FuncNames["lle_X_printUInt"] = lle_X_printUInt;
  FuncNames["lle_X_printLong"] = lle_X_printLong;
  FuncNames["lle_X_printULong"] = lle_X_printULong;
  FuncNames["lle_X_printFloat"] = lle_X_printFloat;
  FuncNames["lle_X_printDouble"] = lle_X_printDouble;
  FuncNames["lle_X_printPointer"] = lle_X_printPointer;
  FuncNames["lle_Vb_putchar"]     = lle_Vb_putchar;
  FuncNames["lle_ii_putchar"]     = lle_ii_putchar;
  FuncNames["lle_VB_putchar"]     = lle_VB_putchar;
  FuncNames["lle_V___main"]       = lle_V___main;
  FuncNames["lle_X_exit"]         = lle_X_exit;
  FuncNames["lle_X_malloc"]       = lle_X_malloc;
  FuncNames["lle_X_free"]         = lle_X_free;
  FuncNames["lle_X_pow"]          = lle_X_pow;
  FuncNames["lle_X_sqrt"]         = lle_X_sqrt;
  FuncNames["lle_X_printf"]       = lle_X_printf;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkbridge.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <plugins/gtk/atkbridge.hxx>
#include <plugins/gtk/gtkframe.hxx>

#include "atkfactory.hxx"
#include "atkutil.hxx"
#include "atkwindow.hxx"

#include <stdio.h>

#if ! ( defined AIX || defined HPUX ) // these have no dl* functions
#include <dlfcn.h>
#endif

bool InitAtkBridge(void)
{
    const char* pVersion = atk_get_toolkit_version();
    if( ! pVersion )
    {
        g_warning( "unable to get gail version number" );
        return false;
    }

    unsigned int major, minor, micro;

    /* check gail minimum version requirements */
    if( sscanf( pVersion, "%u.%u.%u", &major, &minor, &micro) < 3 )
    {
        g_warning( "unable to parse gail version number" );
        return false;
    }

    if( ( (major << 16) | (minor << 8) | micro ) < ( (1 << 16) | 8 << 8 | 6 ) )
    {
        g_warning( "libgail >= 1.8.6 required for accessibility support" );
        return false;
    }

    /* Initialize the AtkUtilityWrapper class */
    g_type_class_unref( g_type_class_ref( OOO_TYPE_ATK_UTIL ) );

    /* Initialize the GailWindow wrapper class */
    g_type_class_unref( g_type_class_ref( OOO_TYPE_WINDOW_WRAPPER ) );

    /* Register AtkObject wrapper factory */
    AtkRegistry * registry = atk_get_default_registry();
    if( registry )
        atk_registry_set_factory_type( registry, OOO_TYPE_FIXED, OOO_TYPE_WRAPPER_FACTORY );

    return true;
}

void DeInitAtkBridge()
{
    restore_gail_window_vtable();

    /* shutdown atk-bridge Gtk+ module here, otherwise it is done in an atexit handler
     * where the VCL Gtk+ plugin might already be unloaded
     */

#if ! ( defined AIX || defined HPUX ) // these have no dl* functions
#if defined __SUNPRO_CC // disable warning: Cannot cast from void* to void(*)()
#pragma disable_warn
#endif
    void (* shutdown) ( void ) =  (void (*) (void)) dlsym( RTLD_DEFAULT, "gnome_accessibility_module_shutdown");
#if defined __SUNPRO_CC
#pragma enable_warn
#endif

    if( shutdown )
        shutdown();
#endif // ! ( defined AIX || defined HPUX )
}

<commit_msg>INTEGRATION: CWS aqua11y02 (1.8.34); FILE MERGED 2008/06/19 11:30:45 obr 1.8.34.2: linux build fixes 2008/06/06 10:19:20 obr 1.8.34.1: #i85292# wrapper now cache the name, suppress unload of gtk plugin when atk-bridge module gets loaded as the shutdown symbol is no longer in global address space<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkbridge.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <plugins/gtk/atkbridge.hxx>
#include <plugins/gtk/gtkframe.hxx>

#include "atkfactory.hxx"
#include "atkutil.hxx"
#include "atkwindow.hxx"
#include <stdio.h>

bool InitAtkBridge(void)
{
    const char* pVersion = atk_get_toolkit_version();
    if( ! pVersion )
    {
        g_warning( "unable to get gail version number" );
        return false;
    }

    unsigned int major, minor, micro;

    /* check gail minimum version requirements */
    if( sscanf( pVersion, "%u.%u.%u", &major, &minor, &micro) < 3 )
    {
        g_warning( "unable to parse gail version number" );
        return false;
    }

    if( ( (major << 16) | (minor << 8) | micro ) < ( (1 << 16) | 8 << 8 | 6 ) )
    {
        g_warning( "libgail >= 1.8.6 required for accessibility support" );
        return false;
    }

    /* Initialize the AtkUtilityWrapper class */
    g_type_class_unref( g_type_class_ref( OOO_TYPE_ATK_UTIL ) );

    /* Initialize the GailWindow wrapper class */
    g_type_class_unref( g_type_class_ref( OOO_TYPE_WINDOW_WRAPPER ) );

    /* Register AtkObject wrapper factory */
    AtkRegistry * registry = atk_get_default_registry();
    if( registry )
        atk_registry_set_factory_type( registry, OOO_TYPE_FIXED, OOO_TYPE_WRAPPER_FACTORY );

    return true;
}

void DeInitAtkBridge()
{
    restore_gail_window_vtable();
}

<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Core/Algorithms/Legacy/Fields/FieldData/SwapFieldDataWithMatrixEntriesAlgo.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
//#include <Core/Datatypes/Matrix.h>
//#include <Core/Datatypes/SparseRowMatrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Dataflow/Network/ModuleStateInterface.h>
#include <Core/Datatypes/Legacy/Base/PropertyManager.h>
//#include <Core/Datatypes/Legacy/Matrix/MatrixTypeConverter.h>

#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Algorithms::Fields::Parameters;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun;

ALGORITHM_PARAMETER_DEF(Fields, PreserveScalar)

SwapFieldDataWithMatrixEntriesAlgo::SwapFieldDataWithMatrixEntriesAlgo()
{
  addParameter(PreserveScalar, false);
}

bool
SwapFieldDataWithMatrixEntriesAlgo::runImpl(FieldHandle input_field, DenseMatrixHandle input_matrix, FieldHandle& output_field, DenseMatrixHandle& output_matrix) const
{
  ScopedAlgorithmStatusReporter r(this, "SwapFieldDataWithMatrixEntriesAlgo");

  if (!input_field)
  {
    error("No input field");
    return (false);
  }

  FieldInformation fi(input_field);

  const bool preserve_scalar = get(Parameters::PreserveScalar).toBool();
	if( output_matrix )
    {
      MatrixHandle matrix_output_handle;
      if(!(get_algo_.run(input_field)))
			{
					matrix_output_handle = get_algo_.run(input_field);
					return false;
			}
			else
			{
					output_matrix = matrix_output_handle;
					return true;
			}

      //send_output_handle("Output Matrix", matrix_output_handle);  correct?
    }

    // Set the data.
    if( output_field )
    {
      FieldHandle field_output_handle;

      if (input_matrix)
      {
					if (preserve_scalar)
						{
								//set_algo_.set_option(keepTypeCheckBox, true);
						}
        if(!(set_algo_.run(input_field, input_matrix))) return false;

				CopyProperties(*input_field, *output_field);
      }
      else
      {
        warning("No input matrix passing the field through");
        output_field = input_field;
      }

      AlgorithmOutput output;
			output[Variables::OutputField] = output_field;
    }
  return true;
}

bool
SwapFieldDataWithMatrixEntriesAlgo::runImpl(FieldHandle input, DenseMatrixHandle input_matrix, FieldHandle& output) const
{
  DenseMatrixHandle dummy;
  return runImpl(input, input_matrix, output, dummy);
}

AlgorithmInputName SwapFieldDataWithMatrixEntriesAlgo::SwapMatrix("SwapMatrix");

AlgorithmOutput SwapFieldDataWithMatrixEntriesAlgo::run_generic(const AlgorithmInput& input) const
{
  auto field = input.get<Field>(Variables::InputField);
	auto inputmatrix = input.get<DenseMatrix>(Variables::InputMatrix);

  FieldHandle output_field;
  if (!runImpl(field, inputmatrix, output_field))
    THROW_ALGORITHM_PROCESSING_ERROR("False returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_field;
  return output;
}
<commit_msg>didn't save last commit<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Core/Algorithms/Legacy/Fields/FieldData/SwapFieldDataWithMatrixEntriesAlgo.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
//#include <Core/Datatypes/Matrix.h>
//#include <Core/Datatypes/SparseRowMatrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Dataflow/Network/ModuleStateInterface.h>
#include <Core/Datatypes/Legacy/Base/PropertyManager.h>
//#include <Core/Datatypes/Legacy/Matrix/MatrixTypeConverter.h>

#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Algorithms::Fields::Parameters;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun;

ALGORITHM_PARAMETER_DEF(Fields, PreserveScalar)

SwapFieldDataWithMatrixEntriesAlgo::SwapFieldDataWithMatrixEntriesAlgo()
{
  addParameter(PreserveScalar, false);
}

bool
SwapFieldDataWithMatrixEntriesAlgo::runImpl(FieldHandle input_field, DenseMatrixHandle input_matrix, FieldHandle& output_field, DenseMatrixHandle& output_matrix) const
{
  ScopedAlgorithmStatusReporter r(this, "SwapFieldDataWithMatrixEntriesAlgo");

  if (!input_field)
  {
    error("No input field");
    return (false);
  }

  FieldInformation fi(input_field);

  const bool preserve_scalar = get(Parameters::PreserveScalar).toBool();
	if( output_matrix )
    {
      MatrixHandle matrix_output_handle;
      if(!(get_algo_.run(input_field)))
			{
					matrix_output_handle = get_algo_.run(input_field);
					return false;
			}
			else
			{
					output_matrix = matrix_output_handle;
					return true;
			}

      //send_output_handle("Output Matrix", matrix_output_handle);  correct?
    }

    // Set the data.
    if( output_field )
    {
      FieldHandle field_output_handle;

      if (input_matrix)
      {
					if (preserve_scalar)
						{
								//set_algo_.set_option("scalardatatype",field_input_handle->vfield()->get_data_type());
								set_algo_.set_option(keepTypeCheckBox, fi.get_data_type());
						}
        if(!(set_algo_.run(input_field, input_matrix))) return false;

				CopyProperties(*input_field, *output_field);
      }
      else
      {
        warning("No input matrix passing the field through");
        output_field = input_field;
      }

      AlgorithmOutput output;
			output[Variables::OutputField] = output_field;
    }
  return true;
}

bool
SwapFieldDataWithMatrixEntriesAlgo::runImpl(FieldHandle input, DenseMatrixHandle input_matrix, FieldHandle& output) const
{
  DenseMatrixHandle dummy;
  return runImpl(input, input_matrix, output, dummy);
}

AlgorithmInputName SwapFieldDataWithMatrixEntriesAlgo::SwapMatrix("SwapMatrix");

AlgorithmOutput SwapFieldDataWithMatrixEntriesAlgo::run_generic(const AlgorithmInput& input) const
{
  auto field = input.get<Field>(Variables::InputField);
	auto inputmatrix = input.get<DenseMatrix>(Variables::InputMatrix);

  FieldHandle output_field;
  if (!runImpl(field, inputmatrix, output_field))
    THROW_ALGORITHM_PROCESSING_ERROR("False returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_field;
  return output;
}
<|endoftext|>