<commit_before>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// 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 <limits>
// ospray
#include "ospray/volume/DataDistributedBlockedVolume.h"
#include "ospray/volume/GhostBlockBrickedVolume.h"
#include "ospray/common/Core.h"
#include "ospray/transferFunction/TransferFunction.h"
#include "ospray/volume/GhostBlockBrickedVolume.h"
#if EXP_DATA_PARALLEL
#include "ospray/mpi/MPICommon.h"
#endif
// ispc exports:
#include "DataDistributedBlockedVolume_ispc.h"

namespace ospray {

#if EXP_DATA_PARALLEL

  //! Allocate storage and populate the volume, called through the OSPRay API.
  void DataDistributedBlockedVolume::commit()
  {
    // IW: do NOT call parent commit here - this would try to build
    // the parent acceleration strucutre, which doesn't make sense on
    // blocks that do not exist!!!!

    updateEditableParameters();//

    StructuredVolume::commit();

    for (int i=0;i<numDDBlocks;i++) {
      DDBlock *block = ddBlock+i;
      if (!block->isMine) {
        continue;
      }
      block->cppVolume->commit();
    }
  }

  DataDistributedBlockedVolume::DataDistributedBlockedVolume() :
    numDDBlocks(0),
    ddBlock(NULL)
  {
    PING;
  }

  void DataDistributedBlockedVolume::updateEditableParameters()
  {
    StructuredVolume::updateEditableParameters();
    for (int i=0;i<numDDBlocks;i++) {
      DDBlock *block = ddBlock+i;

      if (!block->isMine) {
        continue;
      }

      Ref<TransferFunction> transferFunction
        = (TransferFunction *)getParamObject("transferFunction", NULL);

      auto &cppVolume = block->cppVolume;
      cppVolume->findParam("transferFunction",1)->set(transferFunction.ptr);

      cppVolume->findParam("samplingRate",1)->set(getParam1f("samplingRate",
                                                             1.f));
      cppVolume->findParam("gradientShadingEnabled",
                           1)->set(getParam1i("gradientShadingEnabled", 0));

      cppVolume.ptr->updateEditableParameters();
    }
  }

  bool DataDistributedBlockedVolume::isDataDistributed() const
  {
    return true;
  }

  void DataDistributedBlockedVolume::buildAccelerator()
  {
    std::cout << "intentionally SKIP building an accelerator for data parallel "
              << "volume (this'll be done on the brick level)" << std::endl;
  }

  std::string DataDistributedBlockedVolume::toString() const
  {
    return("ospray::DataDistributedBlockedVolume<" + voxelType + ">");
  }

  //! Copy voxels into the volume at the given index (non-zero return value
  //! indicates success).
  int DataDistributedBlockedVolume::setRegion(
      /* points to the first voxel to be copies. The
         voxels at 'soruce' MUST have dimensions
         'regionSize', must be organized in 3D-array
         order, and must have the same voxel type as the
         volume.*/
      const void *source,
      /*! coordinates of the lower,
        left, front corner of the target
        region.*/
      const vec3i &regionCoords,
      /*! size of the region that we're writing to; MUST
        be the same as the dimensions of source[][][] */
      const vec3i &regionSize)
  {
    // Create the equivalent ISPC volume container and allocate memory for voxel
    // data.
    if (ispcEquivalent == NULL) createEquivalentISPC();

    // The block domains are in terms of the scaled regions so we must check
    // if the data is for the block in the scaled volume
    const vec3i scaledRegionCoords(vec3f(regionCoords) * scaleFactor);
    const vec3i scaledRegionSize(vec3f(regionSize) * scaleFactor);

    for (int i=0;i<numDDBlocks;i++) {
      // that block isn't mine, I shouldn't care ...
      if (!ddBlock[i].isMine) continue;

      // first, do some culling to make sure we only do setrgion
      // calls on blocks that actually map to this block
      if (ddBlock[i].domain.lower.x >= scaledRegionCoords.x+scaledRegionSize.x) continue;
      if (ddBlock[i].domain.lower.y >= scaledRegionCoords.y+scaledRegionSize.y) continue;
      if (ddBlock[i].domain.lower.z >= scaledRegionCoords.z+scaledRegionSize.z) continue;

      if (ddBlock[i].domain.upper.x+scaledRegionSize.x < scaledRegionCoords.x) continue;
      if (ddBlock[i].domain.upper.y+scaledRegionSize.y < scaledRegionCoords.y) continue;
      if (ddBlock[i].domain.upper.z+scaledRegionSize.z < scaledRegionCoords.z) continue;

      ddBlock[i].cppVolume->setRegion(source,
                                      vec3i(vec3f(scaledRegionCoords-ddBlock[i].domain.lower) / scaleFactor),
                                      regionSize);

      ddBlock[i].ispcVolume = ddBlock[i].cppVolume->getIE();

#ifndef OSPRAY_VOLUME_VOXELRANGE_IN_APP
      ManagedObject::Param *param = ddBlock[i].cppVolume->findParam("voxelRange");
      if (param != NULL && param->type == OSP_FLOAT2){
        vec2f blockRange = ((vec2f*)param->f)[0];
        voxelRange.x = std::min(voxelRange.x, blockRange.x);
        voxelRange.y = std::max(voxelRange.y, blockRange.y);
      }
#endif
    }

#ifndef OSPRAY_VOLUME_VOXELRANGE_IN_APP
    // Do a reduction here to worker 0 since it will be queried for the voxel range by the display node
    vec2f globalVoxelRange = voxelRange;
    MPI_CALL(Reduce(&voxelRange.x, &globalVoxelRange.x, 1, MPI_FLOAT, MPI_MIN, 0, mpi::worker.comm));
    MPI_CALL(Reduce(&voxelRange.y, &globalVoxelRange.y, 1, MPI_FLOAT, MPI_MAX, 0, mpi::worker.comm));
    set("voxelRange", globalVoxelRange);
#endif
    return 0;
  }

  void DataDistributedBlockedVolume::createEquivalentISPC()
  {
    if (ispcEquivalent != NULL) return;

    // Get the voxel type.
    voxelType = getParamString("voxelType", "unspecified");
    exitOnCondition(getVoxelType() == OSP_UNKNOWN,
                    "unrecognized voxel type (must be set before calling "
                    "ospSetRegion())");

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions (must be set before calling "
                    "ospSetRegion())");

    ddBlocks    = getParam3i("num_dp_blocks",vec3i(4,4,4));
    blockSize   = divRoundUp(dimensions,ddBlocks);
    std::cout << "#osp:dp: using data parallel volume of " << ddBlocks
              << " blocks, blockSize is " << blockSize << std::endl;

    // Set the grid origin, default to (0,0,0).
    this->gridOrigin = getParam3f("gridOrigin", vec3f(0.f));

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions");

    // Set the grid spacing, default to (1,1,1).
    this->gridSpacing = getParam3f("gridSpacing", vec3f(1.f));

    this->scaleFactor = getParam3f("scaleFactor", vec3f(1.f));

    numDDBlocks = ospcommon::reduce_mul(ddBlocks);
    ddBlock     = new DDBlock[numDDBlocks];

    printf("=======================================================\n");
    printf("created %ix%ix%i data distributed volume blocks\n",
           ddBlocks.x,ddBlocks.y,ddBlocks.z);
    printf("=======================================================\n");

    if (!ospray::core::isMpiParallel()) {
      throw std::runtime_error("data parallel volume, but not in mpi parallel "
                               "mode...");
    }
    int64 numWorkers = ospray::core::getWorkerCount();
    // PRINT(numDDBlocks);
    // PRINT(numWorkers);

    voxelType = getParamString("voxelType", "unspecified");

    // if (numDDBlocks >= numWorkers) {
    // we have more workers than blocks - use one owner per block,
    // meaning we'll end up with multiple blocks per worker
    int blockID = 0;
    for (int iz=0;iz<ddBlocks.z;iz++)
      for (int iy=0;iy<ddBlocks.y;iy++)
        for (int ix=0;ix<ddBlocks.x;ix++, blockID++) {
          DDBlock *block = &ddBlock[blockID];
          if (numDDBlocks >= numWorkers) {
            block->firstOwner = blockID % numWorkers;
            block->numOwners = 1;
          } else {
            block->firstOwner = (blockID * numWorkers) / numDDBlocks;
            int nextBlockFirstOwner = ((blockID+1)*numWorkers) / numDDBlocks;
            block->numOwners = nextBlockFirstOwner - block->firstOwner; // + 1;
          }
          block->isMine
            = (ospray::core::getWorkerRank() >= block->firstOwner)
            && (ospray::core::getWorkerRank() <
                (block->firstOwner + block->numOwners));
          block->domain.lower = vec3i(ix,iy,iz) * blockSize;
          block->domain.upper = min(block->domain.lower+blockSize,dimensions);
          block->bounds.lower = gridOrigin +
            (gridSpacing * vec3f(block->domain.lower));
          block->bounds.upper = gridOrigin +
            (gridSpacing * vec3f(block->domain.upper));

          // iw: add one voxel overlap, so we can properly interpolate
          // even across block boundaries (we need the full *cell* on
          // the right side, not just the last *voxel*!)
          block->domain.upper = min(block->domain.upper+vec3i(1),dimensions);

          if (block->isMine) {
#ifdef EXP_NEW_BB_VOLUME_KERNELS
            Ref<Volume> volume = new GhostBlockBrickedVolume;
#else
            Ref<Volume> volume = new BlockBrickedVolume;
#endif
            vec3i blockDims = block->domain.upper - block->domain.lower;
            volume->findParam("dimensions",1)->set(blockDims);
            volume->findParam("gridOrigin",1)->set(block->bounds.lower);
            volume->findParam("gridSpacing",1)->set(gridSpacing);
            volume->findParam("voxelType",1)->set(voxelType.c_str());
            volume->findParam("scaleFactor",1)->set(scaleFactor);

            printf("rank %li owns block %i,%i,%i (ID %i), dims %i %i %i\n",
                   (size_t)core::getWorkerRank(),ix,iy,iz,
                   blockID,blockDims.x,blockDims.y,blockDims.z);
            block->cppVolume = volume;
            block->ispcVolume = NULL; //volume->getIE();
          } else {
            block->ispcVolume = NULL;
            block->cppVolume = NULL;
          }
        }

    // Create an ISPC BlockBrickedVolume object and assign type-specific
    // function pointers.
    ispcEquivalent = ispc::DDBVolume_create(this,
                                            (int)getVoxelType(),
                                            (const ispc::vec3i&)dimensions,
                                            (const ispc::vec3i&)ddBlocks,
                                            (const ispc::vec3i&)blockSize,
                                            ddBlock);
    if (!ispcEquivalent) {
      throw std::runtime_error("could not create create data distributed "
                               "volume");
    }
  }

  // A volume type with internal data-distribution. needs a renderer
  // that is capable of data-parallel rendering!
  OSP_REGISTER_VOLUME(DataDistributedBlockedVolume, data_distributed_volume);

#endif

} // ::ospray
<commit_msg>Cleaner fix for the scale factor use in data-distributed volumes<commit_after>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// 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 <limits>
// ospray
#include "ospray/volume/DataDistributedBlockedVolume.h"
#include "ospray/volume/GhostBlockBrickedVolume.h"
#include "ospray/common/Core.h"
#include "ospray/transferFunction/TransferFunction.h"
#include "ospray/volume/GhostBlockBrickedVolume.h"
#if EXP_DATA_PARALLEL
#include "ospray/mpi/MPICommon.h"
#endif
// ispc exports:
#include "DataDistributedBlockedVolume_ispc.h"

namespace ospray {

#if EXP_DATA_PARALLEL

  //! Allocate storage and populate the volume, called through the OSPRay API.
  void DataDistributedBlockedVolume::commit()
  {
    // IW: do NOT call parent commit here - this would try to build
    // the parent acceleration strucutre, which doesn't make sense on
    // blocks that do not exist!!!!

    updateEditableParameters();//

    StructuredVolume::commit();

    for (int i=0;i<numDDBlocks;i++) {
      DDBlock *block = ddBlock+i;
      if (!block->isMine) {
        continue;
      }
      block->cppVolume->commit();
    }
  }

  DataDistributedBlockedVolume::DataDistributedBlockedVolume() :
    numDDBlocks(0),
    ddBlock(NULL)
  {
    PING;
  }

  void DataDistributedBlockedVolume::updateEditableParameters()
  {
    StructuredVolume::updateEditableParameters();
    for (int i=0;i<numDDBlocks;i++) {
      DDBlock *block = ddBlock+i;

      if (!block->isMine) {
        continue;
      }

      Ref<TransferFunction> transferFunction
        = (TransferFunction *)getParamObject("transferFunction", NULL);

      auto &cppVolume = block->cppVolume;
      cppVolume->findParam("transferFunction",1)->set(transferFunction.ptr);

      cppVolume->findParam("samplingRate",1)->set(getParam1f("samplingRate",
                                                             1.f));
      cppVolume->findParam("gradientShadingEnabled",
                           1)->set(getParam1i("gradientShadingEnabled", 0));

      cppVolume.ptr->updateEditableParameters();
    }
  }

  bool DataDistributedBlockedVolume::isDataDistributed() const
  {
    return true;
  }

  void DataDistributedBlockedVolume::buildAccelerator()
  {
    std::cout << "intentionally SKIP building an accelerator for data parallel "
              << "volume (this'll be done on the brick level)" << std::endl;
  }

  std::string DataDistributedBlockedVolume::toString() const
  {
    return("ospray::DataDistributedBlockedVolume<" + voxelType + ">");
  }

  //! Copy voxels into the volume at the given index (non-zero return value
  //! indicates success).
  int DataDistributedBlockedVolume::setRegion(
      /* points to the first voxel to be copies. The
         voxels at 'soruce' MUST have dimensions
         'regionSize', must be organized in 3D-array
         order, and must have the same voxel type as the
         volume.*/
      const void *source,
      /*! coordinates of the lower,
        left, front corner of the target
        region.*/
      const vec3i &regionCoords,
      /*! size of the region that we're writing to; MUST
        be the same as the dimensions of source[][][] */
      const vec3i &regionSize)
  {
    // Create the equivalent ISPC volume container and allocate memory for voxel
    // data.
    if (ispcEquivalent == NULL) createEquivalentISPC();

    // The block domains are in terms of the scaled regions so we must check
    // if the data is for the block in the scaled volume
    vec3i finalRegionCoords(vec3f(regionCoords) * scaleFactor);
    vec3i finalRegionSize(vec3f(regionSize) * scaleFactor);
    if (scaleFactor != vec3f(-1.f)) {
      finalRegionCoords = vec3i(vec3f(regionCoords) * scaleFactor);
      finalRegionSize = vec3i(vec3f(regionSize) * scaleFactor);
    } else {
      finalRegionCoords = regionCoords;
      finalRegionSize = regionSize;
    }

    for (int i=0;i<numDDBlocks;i++) {
      // that block isn't mine, I shouldn't care ...
      if (!ddBlock[i].isMine) continue;

      // first, do some culling to make sure we only do setrgion
      // calls on blocks that actually map to this block
      if (ddBlock[i].domain.lower.x >= finalRegionCoords.x+finalRegionSize.x) continue;
      if (ddBlock[i].domain.lower.y >= finalRegionCoords.y+finalRegionSize.y) continue;
      if (ddBlock[i].domain.lower.z >= finalRegionCoords.z+finalRegionSize.z) continue;

      if (ddBlock[i].domain.upper.x+finalRegionSize.x < finalRegionCoords.x) continue;
      if (ddBlock[i].domain.upper.y+finalRegionSize.y < finalRegionCoords.y) continue;
      if (ddBlock[i].domain.upper.z+finalRegionSize.z < finalRegionCoords.z) continue;

      vec3i setRegionCoords = finalRegionCoords - ddBlock[i].domain.lower;
      if (scaleFactor != vec3f(-1.f)) {
        setRegionCoords = vec3i(vec3f(setRegionCoords) / scaleFactor);
      }

      ddBlock[i].cppVolume->setRegion(source, setRegionCoords, regionSize);

      ddBlock[i].ispcVolume = ddBlock[i].cppVolume->getIE();

#ifndef OSPRAY_VOLUME_VOXELRANGE_IN_APP
      ManagedObject::Param *param = ddBlock[i].cppVolume->findParam("voxelRange");
      if (param != NULL && param->type == OSP_FLOAT2){
        vec2f blockRange = ((vec2f*)param->f)[0];
        voxelRange.x = std::min(voxelRange.x, blockRange.x);
        voxelRange.y = std::max(voxelRange.y, blockRange.y);
      }
#endif
    }

#ifndef OSPRAY_VOLUME_VOXELRANGE_IN_APP
    // Do a reduction here to worker 0 since it will be queried for the voxel range by the display node
    vec2f globalVoxelRange = voxelRange;
    MPI_CALL(Reduce(&voxelRange.x, &globalVoxelRange.x, 1, MPI_FLOAT, MPI_MIN, 0, mpi::worker.comm));
    MPI_CALL(Reduce(&voxelRange.y, &globalVoxelRange.y, 1, MPI_FLOAT, MPI_MAX, 0, mpi::worker.comm));
    set("voxelRange", globalVoxelRange);
#endif
    return 0;
  }

  void DataDistributedBlockedVolume::createEquivalentISPC()
  {
    if (ispcEquivalent != NULL) return;

    // Get the voxel type.
    voxelType = getParamString("voxelType", "unspecified");
    exitOnCondition(getVoxelType() == OSP_UNKNOWN,
                    "unrecognized voxel type (must be set before calling "
                    "ospSetRegion())");

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions (must be set before calling "
                    "ospSetRegion())");

    ddBlocks    = getParam3i("num_dp_blocks",vec3i(4,4,4));
    blockSize   = divRoundUp(dimensions,ddBlocks);
    std::cout << "#osp:dp: using data parallel volume of " << ddBlocks
              << " blocks, blockSize is " << blockSize << std::endl;

    // Set the grid origin, default to (0,0,0).
    this->gridOrigin = getParam3f("gridOrigin", vec3f(0.f));

    // Get the volume dimensions.
    this->dimensions = getParam3i("dimensions", vec3i(0));
    exitOnCondition(reduce_min(this->dimensions) <= 0,
                    "invalid volume dimensions");

    // Set the grid spacing, default to (1,1,1).
    this->gridSpacing = getParam3f("gridSpacing", vec3f(1.f));

    this->scaleFactor = getParam3f("scaleFactor", vec3f(-1.f));

    numDDBlocks = ospcommon::reduce_mul(ddBlocks);
    ddBlock     = new DDBlock[numDDBlocks];

    printf("=======================================================\n");
    printf("created %ix%ix%i data distributed volume blocks\n",
           ddBlocks.x,ddBlocks.y,ddBlocks.z);
    printf("=======================================================\n");

    if (!ospray::core::isMpiParallel()) {
      throw std::runtime_error("data parallel volume, but not in mpi parallel "
                               "mode...");
    }
    int64 numWorkers = ospray::core::getWorkerCount();
    // PRINT(numDDBlocks);
    // PRINT(numWorkers);

    voxelType = getParamString("voxelType", "unspecified");

    // if (numDDBlocks >= numWorkers) {
    // we have more workers than blocks - use one owner per block,
    // meaning we'll end up with multiple blocks per worker
    int blockID = 0;
    for (int iz=0;iz<ddBlocks.z;iz++)
      for (int iy=0;iy<ddBlocks.y;iy++)
        for (int ix=0;ix<ddBlocks.x;ix++, blockID++) {
          DDBlock *block = &ddBlock[blockID];
          if (numDDBlocks >= numWorkers) {
            block->firstOwner = blockID % numWorkers;
            block->numOwners = 1;
          } else {
            block->firstOwner = (blockID * numWorkers) / numDDBlocks;
            int nextBlockFirstOwner = ((blockID+1)*numWorkers) / numDDBlocks;
            block->numOwners = nextBlockFirstOwner - block->firstOwner; // + 1;
          }
          block->isMine
            = (ospray::core::getWorkerRank() >= block->firstOwner)
            && (ospray::core::getWorkerRank() <
                (block->firstOwner + block->numOwners));
          block->domain.lower = vec3i(ix,iy,iz) * blockSize;
          block->domain.upper = min(block->domain.lower+blockSize,dimensions);
          block->bounds.lower = gridOrigin +
            (gridSpacing * vec3f(block->domain.lower));
          block->bounds.upper = gridOrigin +
            (gridSpacing * vec3f(block->domain.upper));

          // iw: add one voxel overlap, so we can properly interpolate
          // even across block boundaries (we need the full *cell* on
          // the right side, not just the last *voxel*!)
          block->domain.upper = min(block->domain.upper+vec3i(1),dimensions);

          if (block->isMine) {
#ifdef EXP_NEW_BB_VOLUME_KERNELS
            Ref<Volume> volume = new GhostBlockBrickedVolume;
#else
            Ref<Volume> volume = new BlockBrickedVolume;
#endif
            vec3i blockDims = block->domain.upper - block->domain.lower;
            volume->findParam("dimensions",1)->set(blockDims);
            volume->findParam("gridOrigin",1)->set(block->bounds.lower);
            volume->findParam("gridSpacing",1)->set(gridSpacing);
            volume->findParam("voxelType",1)->set(voxelType.c_str());
            if (scaleFactor != vec3f(-1.f)) {
              volume->findParam("scaleFactor",1)->set(scaleFactor);
            }

            printf("rank %li owns block %i,%i,%i (ID %i), dims %i %i %i\n",
                   (size_t)core::getWorkerRank(),ix,iy,iz,
                   blockID,blockDims.x,blockDims.y,blockDims.z);
            block->cppVolume = volume;
            block->ispcVolume = NULL; //volume->getIE();
          } else {
            block->ispcVolume = NULL;
            block->cppVolume = NULL;
          }
        }

    // Create an ISPC BlockBrickedVolume object and assign type-specific
    // function pointers.
    ispcEquivalent = ispc::DDBVolume_create(this,
                                            (int)getVoxelType(),
                                            (const ispc::vec3i&)dimensions,
                                            (const ispc::vec3i&)ddBlocks,
                                            (const ispc::vec3i&)blockSize,
                                            ddBlock);
    if (!ispcEquivalent) {
      throw std::runtime_error("could not create create data distributed "
                               "volume");
    }
  }

  // A volume type with internal data-distribution. needs a renderer
  // that is capable of data-parallel rendering!
  OSP_REGISTER_VOLUME(DataDistributedBlockedVolume, data_distributed_volume);

#endif

} // ::ospray
<|endoftext|>


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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt 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 notices for more information.

 =========================================================================*/
#include <QApplication>
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperQtWidgetView.h"
#include "itksys/SystemTools.hxx"

using otb::Wrapper::Application;
using otb::Wrapper::ApplicationRegistry;
using otb::Wrapper::QtWidgetView;

int main(int argc, char* argv[])
{
  QApplication qtApp(argc, argv);

  if (argc < 2)
    {
    std::cerr << "Usage : " << argv[0] << " module_name [module_path]" << std::endl;
    return EXIT_FAILURE;
    }

  std::string moduleName = argv[1];

  // Get the module path list
  std::list<std::string> modulePathList;
  if (argc > 2)
    {
    std::copy(argv + 2, argv + argc, std::back_inserter(modulePathList));

    // Load the path in the environment
    std::string specificEnv("ITK_AUTOLOAD_PATH=");
    std::list<std::string>::const_iterator it = modulePathList.begin();
    while( it != modulePathList.end() )
      {
      std::string modulePath = *it;

      specificEnv += *it;
      ++it;
      if (it != modulePathList.end())
        specificEnv += ":";
      }

    // do NOT use putenv() directly, since the string memory must be managed carefully
    itksys::SystemTools::PutEnv(specificEnv.c_str());
    }

  // Reload factories to take into account new path
  itk::ObjectFactoryBase::ReHash();

  // Create module
  Application::Pointer app = ApplicationRegistry::CreateApplication(moduleName);
  if (app.IsNull())

    {
    std::cerr << "Could not find application " << moduleName << std::endl;

    const char* modulePath = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
    std::cout << "Module search path : " << (modulePath ? modulePath : "") << std::endl;

    std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();

    std::cout << "Available applications : " << (list.empty() ? "None" : "") << std::endl;
    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
      {
      std::cout << "  " << *it << std::endl;
      }
    return EXIT_FAILURE;
    }

  // Create GUI based on module
  QtWidgetView* gui = new QtWidgetView(app);
  gui->CreateGui();
  //gui->GetMainWindow()->show();

  // Start event processing loop
  return qtApp.exec();
}
<commit_msg>ENH : Improve the launcher to include previous modifications       - The global widget is a QMainWindow that includes :         * the QtWidgetView         * the ProgressReport Widget as a dockable widget         * add some connections to be able to close correctly the main           application<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt 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 notices for more information.

 =========================================================================*/
#include <QApplication>
#include <QObject>
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperQtWidgetView.h"
#include "otbWrapperQtWidgetProgressReport.h"
#include "itksys/SystemTools.hxx"

using otb::Wrapper::Application;
using otb::Wrapper::ApplicationRegistry;
using otb::Wrapper::QtWidgetView;
using otb::Wrapper::QtWidgetProgressReport;
int main(int argc, char* argv[])
{
  QApplication qtApp(argc, argv);

  if (argc < 2)
    {
    std::cerr << "Usage : " << argv[0] << " module_name [module_path]" << std::endl;
    return EXIT_FAILURE;
    }

  std::string moduleName = argv[1];

  // Get the module path list
  std::list<std::string> modulePathList;
  if (argc > 2)
    {
    std::copy(argv + 2, argv + argc, std::back_inserter(modulePathList));

    // Load the path in the environment
    std::string specificEnv("ITK_AUTOLOAD_PATH=");
    std::list<std::string>::const_iterator it = modulePathList.begin();
    while( it != modulePathList.end() )
      {
      std::string modulePath = *it;

      specificEnv += *it;
      ++it;
      if (it != modulePathList.end())
        specificEnv += ":";
      }

    // do NOT use putenv() directly, since the string memory must be managed carefully
    itksys::SystemTools::PutEnv(specificEnv.c_str());
    }

  // Reload factories to take into account new path
  itk::ObjectFactoryBase::ReHash();

  // Create module
  Application::Pointer app = ApplicationRegistry::CreateApplication(moduleName);
  if (app.IsNull())

    {
    std::cerr << "Could not find application " << moduleName << std::endl;

    const char* modulePath = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
    std::cout << "Module search path : " << (modulePath ? modulePath : "") << std::endl;
    std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();

    std::cout << "Available applications : " << (list.empty() ? "None" : "") << std::endl;
    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
      {
      std::cout << "  " << *it << std::endl;
      }
    return EXIT_FAILURE;
    }

  // MainWidget : that contains the view and any other widget
  // (progress, logs...)
  QMainWindow* mainWindow =  new QMainWindow();

  // Create GUI based on module
  QtWidgetView* gui = new QtWidgetView(app);

  // Connect the View "Quit" signal, to the mainWindow close slot
  QObject::connect(gui, SIGNAL(QuitSignal()), mainWindow, SLOT(close()));

  // Create a progressReport object
  QtWidgetProgressReport* progressReport =  new QtWidgetProgressReport(gui->GetModel());
  progressReport->SetApplication(app);

  // Create a dock widget containg the progress widget
  QDockWidget* qdock = new QDockWidget("Progress Reporting ...", mainWindow);
  qdock->setWidget(progressReport);

  // build the main window, central widget is the plugin view, other
  // are docked widget (progress, logs...)
  mainWindow->setCentralWidget(gui);
  mainWindow->addDockWidget(Qt::BottomDockWidgetArea, qdock);

  gui->CreateGui();
  mainWindow->show();

  // Start event processing loop
  return qtApp.exec();
}
<|endoftext|>


<commit_before>#include <exotica/Exotica.h>
#undef NDEBUG
#include <pybind11/eigen.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <task_map/CoM.h>
#include <task_map/Distance.h>
#include <task_map/EffFrame.h>
#include <task_map/EffOrientation.h>
#include <task_map/EffPosition.h>
#include <task_map/IMesh.h>
#include <task_map/Identity.h>
#include <task_map/JointLimit.h>
#include <task_map/SphereCollision.h>

using namespace exotica;
namespace py = pybind11;

PYBIND11_MODULE(task_map_py, module)
{
    module.doc() = "Exotica task map definitions";

    py::module::import("pyexotica");

    py::class_<EffFrame, std::shared_ptr<EffFrame>, TaskMap> effFrame(module, "EffFrame");
    effFrame.def_readonly("rotationType", &EffFrame::rotationType);

    py::class_<EffPosition, std::shared_ptr<EffPosition>, TaskMap> effPosition(module, "EffPosition");

    py::class_<EffOrientation, std::shared_ptr<EffOrientation>, TaskMap> effOrientation(module, "EffOrientation");
    effOrientation.def_readonly("rotationType", &EffOrientation::rotationType);

    py::class_<CoM, std::shared_ptr<CoM>, TaskMap> com(module, "CoM");

    py::class_<Distance, std::shared_ptr<Distance>, TaskMap> distance(module, "Distance");

    py::class_<Identity, std::shared_ptr<Identity>, TaskMap> identity(module, "Identity");
    identity.def_readonly("N", &Identity::N);
    identity.def_readonly("jointMap", &Identity::jointMap);
    identity.def_readwrite("jointRef", &Identity::jointRef);

    py::class_<IMesh, std::shared_ptr<IMesh>, TaskMap> iMesh(module, "IMesh");
    iMesh.def_property("W", &IMesh::getWeights, &IMesh::setWeights);
    iMesh.def("setWeight", &IMesh::setWeight);
    iMesh.def_static("computeLaplace", [](Eigen::VectorXdRefConst EffPhi, Eigen::MatrixXdRefConst Weights) { return IMesh::computeLaplace(EffPhi, Weights); });

    py::class_<JointLimit, std::shared_ptr<JointLimit>, TaskMap> jointLimit(module, "JointLimit");

    py::class_<SphereCollision, std::shared_ptr<SphereCollision>, TaskMap> sphereCollision(module, "SphereCollision");
}
<commit_msg>task_map_py: Expose EffAxisAlignment<commit_after>#include <exotica/Exotica.h>
#undef NDEBUG
#include <pybind11/eigen.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <task_map/CoM.h>
#include <task_map/Distance.h>
#include <task_map/EffAxisAlignment.h>
#include <task_map/EffFrame.h>
#include <task_map/EffOrientation.h>
#include <task_map/EffPosition.h>
#include <task_map/IMesh.h>
#include <task_map/Identity.h>
#include <task_map/JointLimit.h>
#include <task_map/SphereCollision.h>

using namespace exotica;
namespace py = pybind11;

PYBIND11_MODULE(task_map_py, module)
{
    module.doc() = "Exotica task map definitions";

    py::module::import("pyexotica");

    py::class_<EffFrame, std::shared_ptr<EffFrame>, TaskMap> effFrame(module, "EffFrame");
    effFrame.def_readonly("rotationType", &EffFrame::rotationType);

    py::class_<EffPosition, std::shared_ptr<EffPosition>, TaskMap> effPosition(module, "EffPosition");

    py::class_<EffOrientation, std::shared_ptr<EffOrientation>, TaskMap> effOrientation(module, "EffOrientation");
    effOrientation.def_readonly("rotationType", &EffOrientation::rotationType);

    py::class_<EffAxisAlignment, std::shared_ptr<EffAxisAlignment>, TaskMap> effAxisAlignment(module, "EffAxisAlignment");
    effAxisAlignment.def("getAxis", &EffAxisAlignment::getAxis);
    effAxisAlignment.def("setAxis", &EffAxisAlignment::setAxis);
    effAxisAlignment.def("getDirection", &EffAxisAlignment::getDirection);
    effAxisAlignment.def("setDirection", &EffAxisAlignment::setDirection);

    py::class_<CoM, std::shared_ptr<CoM>, TaskMap> com(module, "CoM");

    py::class_<Distance, std::shared_ptr<Distance>, TaskMap> distance(module, "Distance");

    py::class_<Identity, std::shared_ptr<Identity>, TaskMap> identity(module, "Identity");
    identity.def_readonly("N", &Identity::N);
    identity.def_readonly("jointMap", &Identity::jointMap);
    identity.def_readwrite("jointRef", &Identity::jointRef);

    py::class_<IMesh, std::shared_ptr<IMesh>, TaskMap> iMesh(module, "IMesh");
    iMesh.def_property("W", &IMesh::getWeights, &IMesh::setWeights);
    iMesh.def("setWeight", &IMesh::setWeight);
    iMesh.def_static("computeLaplace", [](Eigen::VectorXdRefConst EffPhi, Eigen::MatrixXdRefConst Weights) { return IMesh::computeLaplace(EffPhi, Weights); });

    py::class_<JointLimit, std::shared_ptr<JointLimit>, TaskMap> jointLimit(module, "JointLimit");

    py::class_<SphereCollision, std::shared_ptr<SphereCollision>, TaskMap> sphereCollision(module, "SphereCollision");
}
<|endoftext|>


<commit_before>#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots (const Matrix& rkA, Roots& adRoot)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar msInv3 = 1.0/3.0;
  const Scalar msRoot3 = ei_sqrt(Scalar(3.0));

  Scalar dA00 = rkA(0,0);
  Scalar dA01 = rkA(0,1);
  Scalar dA02 = rkA(0,2);
  Scalar dA11 = rkA(1,1);
  Scalar dA12 = rkA(1,2);
  Scalar dA22 = rkA(2,2);

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar dC0 = dA00*dA11*dA22 + Scalar(2)*dA01*dA02*dA12 - dA00*dA12*dA12 - dA11*dA02*dA02 - dA22*dA01*dA01;
  Scalar dC1 = dA00*dA11 - dA01*dA01 + dA00*dA22 - dA02*dA02 + dA11*dA22 - dA12*dA12;
  Scalar dC2 = dA00 + dA11 + dA22;

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar dC2Div3 = dC2*msInv3;
  Scalar dADiv3 = (dC1 - dC2*dC2Div3)*msInv3;
  if (dADiv3 > Scalar(0))
    dADiv3 = Scalar(0);

  Scalar dMBDiv2 = Scalar(0.5)*(dC0 + dC2Div3*(Scalar(2)*dC2Div3*dC2Div3 - dC1));

  Scalar dQ = dMBDiv2*dMBDiv2 + dADiv3*dADiv3*dADiv3;
  if (dQ > Scalar(0))
    dQ = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar dMagnitude = ei_sqrt(-dADiv3);
  Scalar dAngle = std::atan2(ei_sqrt(-dQ),dMBDiv2)*msInv3;
  Scalar dCos = ei_cos(dAngle);
  Scalar dSin = ei_sin(dAngle);
  adRoot(0) = dC2Div3 + 2.f*dMagnitude*dCos;
  adRoot(1) = dC2Div3 - dMagnitude*(dCos + msRoot3*dSin);
  adRoot(2) = dC2Div3 - dMagnitude*(dCos - msRoot3*dSin);

  // Sort in increasing order.
  if (adRoot(0) >= adRoot(1))
    std::swap(adRoot(0),adRoot(1));
  if (adRoot(1) >= adRoot(2))
  {
    std::swap(adRoot(1),adRoot(2));
    if (adRoot(0) >= adRoot(1))
      std::swap(adRoot(0),adRoot(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
    // Scale the matrix so its entries are in [-1,1].  The scaling is applied
    // only when at least one matrix entry has magnitude larger than 1.

    Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
    scale = std::max(scale,Scalar(1));
    Matrix scaledMat = mat / scale;

    // Compute the eigenvalues
//     scaledMat.setZero();
    computeRoots(scaledMat,evals);

    // compute the eigen vectors
    // here we assume 3 differents eigenvalues

    // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

    // naive version
    Matrix tmp;
    tmp = scaledMat;
    tmp.diagonal().array() -= evals(0);
    evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();

    tmp = scaledMat;
    tmp.diagonal().array() -= evals(1);
    evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();

    tmp = scaledMat;
    tmp.diagonal().array() -= evals(2);
    evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

    // Rescale back to the original size.
    evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<commit_msg>add missing copyrights<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

// The computeRoots function included in this is based on materials
// covered by the following copyright and license:
//
// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <Eigen/Geometry>
#include <bench/BenchTimer.h>

using namespace Eigen;
using namespace std;

template<typename Matrix, typename Roots>
inline void computeRoots(const Matrix& m, Roots& roots)
{
  typedef typename Matrix::Scalar Scalar;
  const Scalar s_inv3 = 1.0/3.0;
  const Scalar s_sqrt3 = ei_sqrt(Scalar(3.0));

  // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
  // eigenvalues are the roots to this equation, all guaranteed to be
  // real-valued, because the matrix is symmetric.
  Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(0,1)*m(0,2)*m(1,2) - m(0,0)*m(1,2)*m(1,2) - m(1,1)*m(0,2)*m(0,2) - m(2,2)*m(0,1)*m(0,1);
  Scalar c1 = m(0,0)*m(1,1) - m(0,1)*m(0,1) + m(0,0)*m(2,2) - m(0,2)*m(0,2) + m(1,1)*m(2,2) - m(1,2)*m(1,2);
  Scalar c2 = m(0,0) + m(1,1) + m(2,2);

  // Construct the parameters used in classifying the roots of the equation
  // and in solving the equation for the roots in closed form.
  Scalar c2_over_3 = c2*s_inv3;
  Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
  if (a_over_3 > Scalar(0))
    a_over_3 = Scalar(0);

  Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));

  Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
  if (q > Scalar(0))
    q = Scalar(0);

  // Compute the eigenvalues by solving for the roots of the polynomial.
  Scalar rho = ei_sqrt(-a_over_3);
  Scalar theta = std::atan2(ei_sqrt(-q),half_b)*s_inv3;
  Scalar cos_theta = ei_cos(theta);
  Scalar sin_theta = ei_sin(theta);
  roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
  roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
  roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);

  // Sort in increasing order.
  if (roots(0) >= roots(1))
    std::swap(roots(0),roots(1));
  if (roots(1) >= roots(2))
  {
    std::swap(roots(1),roots(2));
    if (roots(0) >= roots(1))
      std::swap(roots(0),roots(1));
  }
}

template<typename Matrix, typename Vector>
void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals)
{
  typedef typename Matrix::Scalar Scalar;
  // Scale the matrix so its entries are in [-1,1].  The scaling is applied
  // only when at least one matrix entry has magnitude larger than 1.

  Scalar scale = mat.cwiseAbs()/*.template triangularView<Lower>()*/.maxCoeff();
  scale = std::max(scale,Scalar(1));
  Matrix scaledMat = mat / scale;

  // Compute the eigenvalues
//   scaledMat.setZero();
  computeRoots(scaledMat,evals);

  // compute the eigen vectors
  // **here we assume 3 differents eigenvalues**

  // "optimized version" which appears to be slower with gcc!
//     Vector base;
//     Scalar alpha, beta;
//     base <<   scaledMat(1,0) * scaledMat(2,1),
//               scaledMat(1,0) * scaledMat(2,0),
//              -scaledMat(1,0) * scaledMat(1,0);
//     for(int k=0; k<2; ++k)
//     {
//       alpha = scaledMat(0,0) - evals(k);
//       beta  = scaledMat(1,1) - evals(k);
//       evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized();
//     }
//     evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized();

  // naive version
  Matrix tmp;
  tmp = scaledMat;
  tmp.diagonal().array() -= evals(0);
  evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(1);
  evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized();

  tmp = scaledMat;
  tmp.diagonal().array() -= evals(2);
  evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized();

  // Rescale back to the original size.
  evals *= scale;
}

int main()
{
  BenchTimer t;
  int tries = 10;
  int rep = 400000;
  typedef Matrix3f Mat;
  typedef Vector3f Vec;
  Mat A = Mat::Random(3,3);
  A = A.adjoint() * A;

  SelfAdjointEigenSolver<Mat> eig(A);
  BENCH(t, tries, rep, eig.compute(A));
  std::cout << "Eigen:  " << t.best() << "s\n";

  Mat evecs;
  Vec evals;
  BENCH(t, tries, rep, eigen33(A,evecs,evals));
  std::cout << "Direct: " << t.best() << "s\n\n";

  std::cerr << "Eigenvalue/eigenvector diffs:\n";
  std::cerr << (evals - eig.eigenvalues()).transpose() << "\n";
  for(int k=0;k<3;++k)
    if(evecs.col(k).dot(eig.eigenvectors().col(k))<0)
      evecs.col(k) = -evecs.col(k);
  std::cerr << evecs - eig.eigenvectors() << "\n\n";
}
<|endoftext|>


<commit_before>/**
 *  Argument.cpp
 *
 *  Implementation for the Argument class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  type        Argument type
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument
 */
Argument::Argument(const char *name, Type type, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)(type == Type::Array || type == Type::Callable ? type : Type::Null);
#else
    _info->array_type_hint = type == Type::Array;
    _info->return_reference = false;
    _info->required_num_args = 0;   // @todo is this correct?
#endif
    _info->class_name = NULL;
    _info->class_name_len = 0;
    _info->allow_null = false;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  classname   Name of the class
 *  @param  nullable    Can it be null?
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument?
 */
Argument::Argument(const char *name, const char *classname, bool nullable, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)Type::Object;
#endif
    _info->class_name = classname;
    _info->class_name_len = strlen(classname);
    _info->allow_null = nullable;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Copy constructor
 *  @param  argument
 */
Argument::Argument(const Argument &argument)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    *_info = *argument._info;

    // store if required
    _required = argument._required;
}

/**
 *  Move constructor
 *  @param  argument
 */
Argument::Argument(Argument &&argument)
{
    // copy memory pointer
    _info = argument._info;

    // forget in other object
    argument._info = nullptr;
}

/**
 *  Destructor
 */
Argument::~Argument()
{
    if (_info) delete _info;
}

/**
 *  Fill an arg_info structure with data
 *  @param  info
 *  @internal
 */
void Argument::fill(struct _zend_arg_info *info) const
{
    // copy all data
    *info = *_info;
}

/**
 *  End of namespace
 */
}
<commit_msg>Fixed initialization of _required variable in Argument move constructor<commit_after>/**
 *  Argument.cpp
 *
 *  Implementation for the Argument class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace Php {

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  type        Argument type
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument
 */
Argument::Argument(const char *name, Type type, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)(type == Type::Array || type == Type::Callable ? type : Type::Null);
#else
    _info->array_type_hint = type == Type::Array;
    _info->return_reference = false;
    _info->required_num_args = 0;   // @todo is this correct?
#endif
    _info->class_name = NULL;
    _info->class_name_len = 0;
    _info->allow_null = false;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Constructor
 *  @param  name        Name of the argument
 *  @param  classname   Name of the class
 *  @param  nullable    Can it be null?
 *  @param  required    Is this argument required?
 *  @param  byref       Is this a reference argument?
 */
Argument::Argument(const char *name, const char *classname, bool nullable, bool required, bool byref)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    _info->name = name;
    _info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
    _info->type_hint = (unsigned char)Type::Object;
#endif
    _info->class_name = classname;
    _info->class_name_len = strlen(classname);
    _info->allow_null = nullable;
    _info->pass_by_reference = byref;

    // store if required
    _required = required;
}

/**
 *  Copy constructor
 *  @param  argument
 */
Argument::Argument(const Argument &argument)
{
    // construct object
    _info = new zend_arg_info;

    // fill members
    *_info = *argument._info;

    // store if required
    _required = argument._required;
}

/**
 *  Move constructor
 *  @param  argument
 */
Argument::Argument(Argument &&argument)
{
    // copy memory pointer
    _info = argument._info;

    // forget in other object
    argument._info = nullptr;

    // store if required
    _required = argument._required;
}

/**
 *  Destructor
 */
Argument::~Argument()
{
    if (_info) delete _info;
}

/**
 *  Fill an arg_info structure with data
 *  @param  info
 *  @internal
 */
void Argument::fill(struct _zend_arg_info *info) const
{
    // copy all data
    *info = *_info;
}

/**
 *  End of namespace
 */
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// oxygenargbhelper.h
// handle oxygen ARGB (translucent windows) support
// -------------------
//
// Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
//
// Loosely inspired (and largely rewritten) from BeSpin style
// Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
//
// 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 "oxygenargbhelper.h"
#include "oxygenargbhelper.moc"

#include <QtGui/QDialog>
#include <QtGui/QIcon>

namespace Oxygen
{

    //______________________________________________________________
    ArgbHelper::ArgbHelper( QObject* parent, StyleHelper& helper ):
        QObject( parent ),
        _helper( helper ),
        _applicationType( AppUnknown ),
        _enabled( false ),
        _opacity( 0xff )
    {}

    //______________________________________________________________
    void ArgbHelper::registerApplication( QApplication* app )
    {

        // get application full path
        if( app->argc() < 1 ) return;

        QString appName( app->argv()[0] );
        int position( appName.lastIndexOf( '/' ) );
        if( position >= 0 ) appName.remove( 0, position+1 );

        if( appName == "plasma" || appName.startsWith( "plasma-" ) )
        {

            /*
            HACK: need to detect if application is of type Plasma
            because applying translucency to some of its widgets creates
            painting issues which could not be identified with a 'generic'
            criteria.
            */
            _applicationType = AppPlasma;

        } else if( _blackList.contains( appName ) ) {

            // black-list application
            _applicationType = AppBlackListed;

        }

    }

    //______________________________________________________________
    bool ArgbHelper::registerWidget( QWidget *widget )
    {

        // check blacklisted applications
        if( _applicationType == AppBlackListed ) return false;

        // adjust flags for windows and dialogs
        switch( widget->windowFlags() & Qt::WindowType_Mask )
        {

            case Qt::Window:
            case Qt::Dialog:
            {

                // do not handle all kind of 'special background' widgets
                if( widget->windowType() == Qt::Desktop ||
                    widget->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop) ||
                    widget->testAttribute(Qt::WA_NoSystemBackground) ||
                    widget->testAttribute(Qt::WA_PaintOnScreen)
                    ) break;

                // disable kde screensaver windows
                /*
                the kscreensaver widgets get a WA_PaintOnScreen flag set,
                which should have been covered by the above, but somehow the flag is set too late,
                and notably after polish is called. Or so it seems.
                */
                if( widget->inherits( "KScreenSaver" ) ) break;

                // Hack: stop here if application is of type Plasma
                /*
                Right now we need to reject window candidates if the application is of type plasma
                because it conflicts with some widgets embedded into the SysTray. Ideally one would
                rather find a "generic" reason, not to handle them
                */
                if( _applicationType == AppPlasma && !qobject_cast<QDialog*>(widget) ) break;

                // stop here if no translucent background selected/supported
                if( !( _helper.compositingActive() && enabled() ) ) break;

                // more tests
                if( !widget->isWindow() ) break;
                if(
                    widget->inherits( "QTipLabel") ||
                    widget->inherits( "QSplashScreen") ) break;

                if( widget->windowFlags().testFlag( Qt::FramelessWindowHint ) ) break;

                if( widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )
                { setupTransparency( widget ); }

                return true;
            }

            default: break;

        }

        return false;

    }

    //______________________________________________________________
    bool ArgbHelper::unregisterWidget( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) )
        {
            widget->setAttribute(Qt::WA_NoSystemBackground, false);
            widget->setAttribute(Qt::WA_TranslucentBackground, false);
            return true;
        }

        return false;

    }

    //_______________________________________________________
    bool ArgbHelper::eventFilter( QObject* object, QEvent* event )
    {

        // check event type
        if( event->type() != QEvent::WinIdChange ) return false;

        // cast widget
        if( QWidget* widget = static_cast<QWidget*>( object ) )
        { setupTransparency( widget ); }

        return false;

    }

    //______________________________________________________________
    void ArgbHelper::setupTransparency( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) ) return;

        // some extra protection
        if( !(widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )) return;

        // translucent background already set. Do nothing.
        if( widget->testAttribute(Qt::WA_TranslucentBackground) )
        {
            // set Argb xproperty
            _helper.setHasArgb( widget->winId(), true );
            return;
        }

        /*
        whenever you set the translucency flag, Qt will create a new widget under the hood, replacing the old
        Unfortunately some properties are lost, among them the window icon. We save it and restore it manually
        */

        // store icon
        QIcon icon(widget->windowIcon());

        // store position
        QPoint position( widget->x(), widget->y() );

        // set translucent flag
        widget->setAttribute( Qt::WA_TranslucentBackground );

        // re-install icon
        widget->setWindowIcon(icon);
        if( !widget->isVisible() ) widget->move( position );

        // add to set of transparent widgets and connect destruction signal
        _transparentWidgets.insert( widget );
        connect( widget, SIGNAL( destroyed( QObject* ) ), SLOT( unregisterTransparentWidget( QObject* ) ) );

        // set Argb xproperty
        _helper.setHasArgb( widget->winId(), true );

        return;
    }

}
<commit_msg>Hide widgets before setting WA_TranslucentBackground flag on toplevels. This fixes, I think, the long lasting window positionning issue. CCBUG: 274285<commit_after>//////////////////////////////////////////////////////////////////////////////
// oxygenargbhelper.h
// handle oxygen ARGB (translucent windows) support
// -------------------
//
// Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
//
// Loosely inspired (and largely rewritten) from BeSpin style
// Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
//
// 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 "oxygenargbhelper.h"
#include "oxygenargbhelper.moc"

#include <QtGui/QDialog>
#include <QtGui/QIcon>

namespace Oxygen
{

    //______________________________________________________________
    ArgbHelper::ArgbHelper( QObject* parent, StyleHelper& helper ):
        QObject( parent ),
        _helper( helper ),
        _applicationType( AppUnknown ),
        _enabled( false ),
        _opacity( 0xff )
    {}

    //______________________________________________________________
    void ArgbHelper::registerApplication( QApplication* app )
    {

        // get application full path
        if( app->argc() < 1 ) return;

        QString appName( app->argv()[0] );
        int position( appName.lastIndexOf( '/' ) );
        if( position >= 0 ) appName.remove( 0, position+1 );

        if( appName == "plasma" || appName.startsWith( "plasma-" ) )
        {

            /*
            HACK: need to detect if application is of type Plasma
            because applying translucency to some of its widgets creates
            painting issues which could not be identified with a 'generic'
            criteria.
            */
            _applicationType = AppPlasma;

        } else if( _blackList.contains( appName ) ) {

            // black-list application
            _applicationType = AppBlackListed;

        }

    }

    //______________________________________________________________
    bool ArgbHelper::registerWidget( QWidget *widget )
    {

        // check blacklisted applications
        if( _applicationType == AppBlackListed ) return false;

        // adjust flags for windows and dialogs
        switch( widget->windowFlags() & Qt::WindowType_Mask )
        {

            case Qt::Window:
            case Qt::Dialog:
            {

                // do not handle all kind of 'special background' widgets
                if( widget->windowType() == Qt::Desktop ||
                    widget->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop) ||
                    widget->testAttribute(Qt::WA_NoSystemBackground) ||
                    widget->testAttribute(Qt::WA_PaintOnScreen)
                    ) break;

                // disable kde screensaver windows
                /*
                the kscreensaver widgets get a WA_PaintOnScreen flag set,
                which should have been covered by the above, but somehow the flag is set too late,
                and notably after polish is called. Or so it seems.
                */
                if( widget->inherits( "KScreenSaver" ) ) break;

                // Hack: stop here if application is of type Plasma
                /*
                Right now we need to reject window candidates if the application is of type plasma
                because it conflicts with some widgets embedded into the SysTray. Ideally one would
                rather find a "generic" reason, not to handle them
                */
                if( _applicationType == AppPlasma && !qobject_cast<QDialog*>(widget) ) break;

                // stop here if no translucent background selected/supported
                if( !( _helper.compositingActive() && enabled() ) ) break;

                // more tests
                if( !widget->isWindow() ) break;
                if(
                    widget->inherits( "QTipLabel") ||
                    widget->inherits( "QSplashScreen") ) break;

                if( widget->windowFlags().testFlag( Qt::FramelessWindowHint ) ) break;

                if( widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )
                { setupTransparency( widget ); }

                return true;
            }

            default: break;

        }

        return false;

    }

    //______________________________________________________________
    bool ArgbHelper::unregisterWidget( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) )
        {
            widget->setAttribute(Qt::WA_NoSystemBackground, false);
            widget->setAttribute(Qt::WA_TranslucentBackground, false);
            return true;
        }

        return false;

    }

    //_______________________________________________________
    bool ArgbHelper::eventFilter( QObject* object, QEvent* event )
    {

        // check event type
        if( event->type() != QEvent::WinIdChange ) return false;

        // cast widget
        if( QWidget* widget = static_cast<QWidget*>( object ) )
        { setupTransparency( widget ); }

        return false;

    }

    //______________________________________________________________
    void ArgbHelper::setupTransparency( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) ) return;

        // some extra protection
        if( !(widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )) return;

        // translucent background already set. Do nothing.
        if( widget->testAttribute(Qt::WA_TranslucentBackground) )
        {
            // set Argb xproperty
            _helper.setHasArgb( widget->winId(), true );
            return;
        }

        /*
        whenever you set the translucency flag, Qt will create a new widget under the hood, replacing the old
        Unfortunately some properties are lost, among them the window icon. We save it and restore it manually
        */

        // store icon
        QIcon icon(widget->windowIcon());

        // keep track on whether the widget is already visible
        const bool wasVisible( widget->isVisible() );

        // set translucent flag
        if( wasVisible ) widget->hide();
        widget->setAttribute( Qt::WA_TranslucentBackground );

        // re-install icon
        widget->setWindowIcon(icon);
        if( wasVisible ) widget->show();

        // add to set of transparent widgets and connect destruction signal
        _transparentWidgets.insert( widget );
        connect( widget, SIGNAL( destroyed( QObject* ) ), SLOT( unregisterTransparentWidget( QObject* ) ) );

        // set Argb xproperty
        _helper.setHasArgb( widget->winId(), true );

        return;
    }

}
<|endoftext|>


<commit_before>/*
 * Load balancer for AddressList.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "balancer.hxx"
#include "cache.hxx"
#include "address_list.hxx"
#include "net/SocketAddress.hxx"
#include "failure.hxx"
#include "bulldog.h"
#include "pool.hxx"

#include <assert.h>
#include <stdbool.h>
#include <time.h>

struct balancer_item {
    struct cache_item item;

    struct pool *pool;

    /** the index of the item that will be returned next */
    unsigned next;

    AddressList addresses;
};

struct balancer {
    struct pool *pool;

    /**
     * This library uses the cache library to store remote host
     * states in a lossy way.
     */
    struct cache *cache;
};

static bool
check_failure(const SocketAddress address, bool allow_fade)
{
    enum failure_status status = failure_get_status(address);
    if (status == FAILURE_FADE && allow_fade)
        status = FAILURE_OK;
    return status == FAILURE_OK;
}

gcc_pure
static bool
check_bulldog(const SocketAddress address, bool allow_fade)
{
    return bulldog_check(address.GetAddress(), address.GetSize()) &&
        (allow_fade ||
         !bulldog_is_fading(address.GetAddress(), address.GetSize()));
}

static bool
CheckAddress(const SocketAddress address, bool allow_fade)
{
    return check_failure(address, allow_fade) &&
        check_bulldog(address, allow_fade);
}

static SocketAddress
next_failover_address(const AddressList &list)
{
    assert(list.GetSize() > 0);

    for (auto i : list)
        if (CheckAddress(i, true))
            return i;

    /* none available - return first node as last resort */
    return list[0];
}

static const SocketAddress &
next_address(struct balancer_item *item)
{
    assert(item->addresses.GetSize() >= 2);
    assert(item->next < item->addresses.GetSize());

    const SocketAddress &address = item->addresses[item->next];

    ++item->next;
    if (item->next >= item->addresses.GetSize())
        item->next = 0;

    return address;
}

static const SocketAddress &
next_address_checked(struct balancer_item *item, bool allow_fade)
{
    const SocketAddress &first = next_address(item);
    const SocketAddress *ret = &first;
    do {
        if (CheckAddress(*ret, allow_fade))
            return *ret;

        ret = &next_address(item);
    } while (ret != &first);

    /* all addresses failed: */
    return first;
}

static const SocketAddress &
next_sticky_address_checked(const AddressList &al, unsigned session)
{
    assert(al.GetSize() >= 2);

    unsigned i = session % al.GetSize();
    bool allow_fade = true;

    const SocketAddress &first = al[i];
    const SocketAddress *ret = &first;
    do {
        if (CheckAddress(*ret, allow_fade))
            return *ret;

        /* only the first iteration is allowed to override
           FAILURE_FADE */
        allow_fade = false;

        ++i;
        if (i >= al.GetSize())
            i = 0;

        ret = &al[i];

    } while (ret != &first);

    /* all addresses failed: */
    return first;
}

/*
 * cache class
 *
 */

static void
balancer_cache_destroy(struct cache_item *_item)
{
    struct balancer_item *item = (struct balancer_item *)_item;

    pool_unref(item->pool);
}

static const struct cache_class balancer_cache_class = {
    .destroy = balancer_cache_destroy,
};

/*
 * public API
 *
 */

struct balancer *
balancer_new(struct pool &pool)
{
    auto balancer = NewFromPool<struct balancer>(pool);

    balancer->pool = &pool;
    balancer->cache = cache_new(pool, &balancer_cache_class,
                                1021, 2048);
    return balancer;
}

void
balancer_free(struct balancer *balancer)
{
    cache_close(balancer->cache);
}

SocketAddress
balancer_get(struct balancer &balancer, const AddressList &list,
             unsigned session)
{
    struct balancer_item *item;
    struct pool *pool;

    if (list.IsSingle())
        return list[0];

    switch (list.sticky_mode) {
    case STICKY_NONE:
        break;

    case STICKY_FAILOVER:
        return next_failover_address(list);

    case STICKY_SOURCE_IP:
    case STICKY_SESSION_MODULO:
    case STICKY_COOKIE:
    case STICKY_JVM_ROUTE:
        if (session != 0)
            return next_sticky_address_checked(list, session);
        break;
    }

    const char *key = list.GetKey();
    item = (struct balancer_item *)cache_get(balancer.cache, key);

    if (item == nullptr) {
        /* create a new cache item */

        pool = pool_new_linear(balancer.pool, "balancer_item", 1024);
        item = NewFromPool<struct balancer_item>(*pool);
        cache_item_init_relative(&item->item, 1800, 1);
        item->pool = pool;
        item->next = 0;
        item->addresses.CopyFrom(pool, list);

        cache_put(balancer.cache, p_strdup(pool, key), &item->item);
    }

    return next_address_checked(item, list.sticky_mode == STICKY_NONE);
}

void
balancer_event_add(struct balancer &balancer)
{
    cache_event_add(balancer.cache);
}

void
balancer_event_del(struct balancer &balancer)
{
    cache_event_del(balancer.cache);
}
<commit_msg>balancer: work around "non-trivial designated initializers not supported"<commit_after>/*
 * Load balancer for AddressList.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "balancer.hxx"
#include "cache.hxx"
#include "address_list.hxx"
#include "net/SocketAddress.hxx"
#include "failure.hxx"
#include "bulldog.h"
#include "pool.hxx"

#include <assert.h>
#include <stdbool.h>
#include <time.h>

struct balancer_item {
    struct cache_item item;

    struct pool *pool;

    /** the index of the item that will be returned next */
    unsigned next;

    AddressList addresses;
};

struct balancer {
    struct pool *pool;

    /**
     * This library uses the cache library to store remote host
     * states in a lossy way.
     */
    struct cache *cache;
};

static bool
check_failure(const SocketAddress address, bool allow_fade)
{
    enum failure_status status = failure_get_status(address);
    if (status == FAILURE_FADE && allow_fade)
        status = FAILURE_OK;
    return status == FAILURE_OK;
}

gcc_pure
static bool
check_bulldog(const SocketAddress address, bool allow_fade)
{
    return bulldog_check(address.GetAddress(), address.GetSize()) &&
        (allow_fade ||
         !bulldog_is_fading(address.GetAddress(), address.GetSize()));
}

static bool
CheckAddress(const SocketAddress address, bool allow_fade)
{
    return check_failure(address, allow_fade) &&
        check_bulldog(address, allow_fade);
}

static SocketAddress
next_failover_address(const AddressList &list)
{
    assert(list.GetSize() > 0);

    for (auto i : list)
        if (CheckAddress(i, true))
            return i;

    /* none available - return first node as last resort */
    return list[0];
}

static const SocketAddress &
next_address(struct balancer_item *item)
{
    assert(item->addresses.GetSize() >= 2);
    assert(item->next < item->addresses.GetSize());

    const SocketAddress &address = item->addresses[item->next];

    ++item->next;
    if (item->next >= item->addresses.GetSize())
        item->next = 0;

    return address;
}

static const SocketAddress &
next_address_checked(struct balancer_item *item, bool allow_fade)
{
    const SocketAddress &first = next_address(item);
    const SocketAddress *ret = &first;
    do {
        if (CheckAddress(*ret, allow_fade))
            return *ret;

        ret = &next_address(item);
    } while (ret != &first);

    /* all addresses failed: */
    return first;
}

static const SocketAddress &
next_sticky_address_checked(const AddressList &al, unsigned session)
{
    assert(al.GetSize() >= 2);

    unsigned i = session % al.GetSize();
    bool allow_fade = true;

    const SocketAddress &first = al[i];
    const SocketAddress *ret = &first;
    do {
        if (CheckAddress(*ret, allow_fade))
            return *ret;

        /* only the first iteration is allowed to override
           FAILURE_FADE */
        allow_fade = false;

        ++i;
        if (i >= al.GetSize())
            i = 0;

        ret = &al[i];

    } while (ret != &first);

    /* all addresses failed: */
    return first;
}

/*
 * cache class
 *
 */

static void
balancer_cache_destroy(struct cache_item *_item)
{
    struct balancer_item *item = (struct balancer_item *)_item;

    pool_unref(item->pool);
}

static const struct cache_class balancer_cache_class = {
    .validate = nullptr,
    .destroy = balancer_cache_destroy,
};

/*
 * public API
 *
 */

struct balancer *
balancer_new(struct pool &pool)
{
    auto balancer = NewFromPool<struct balancer>(pool);

    balancer->pool = &pool;
    balancer->cache = cache_new(pool, &balancer_cache_class,
                                1021, 2048);
    return balancer;
}

void
balancer_free(struct balancer *balancer)
{
    cache_close(balancer->cache);
}

SocketAddress
balancer_get(struct balancer &balancer, const AddressList &list,
             unsigned session)
{
    struct balancer_item *item;
    struct pool *pool;

    if (list.IsSingle())
        return list[0];

    switch (list.sticky_mode) {
    case STICKY_NONE:
        break;

    case STICKY_FAILOVER:
        return next_failover_address(list);

    case STICKY_SOURCE_IP:
    case STICKY_SESSION_MODULO:
    case STICKY_COOKIE:
    case STICKY_JVM_ROUTE:
        if (session != 0)
            return next_sticky_address_checked(list, session);
        break;
    }

    const char *key = list.GetKey();
    item = (struct balancer_item *)cache_get(balancer.cache, key);

    if (item == nullptr) {
        /* create a new cache item */

        pool = pool_new_linear(balancer.pool, "balancer_item", 1024);
        item = NewFromPool<struct balancer_item>(*pool);
        cache_item_init_relative(&item->item, 1800, 1);
        item->pool = pool;
        item->next = 0;
        item->addresses.CopyFrom(pool, list);

        cache_put(balancer.cache, p_strdup(pool, key), &item->item);
    }

    return next_address_checked(item, list.sticky_mode == STICKY_NONE);
}

void
balancer_event_add(struct balancer &balancer)
{
    cache_event_add(balancer.cache);
}

void
balancer_event_del(struct balancer &balancer)
{
    cache_event_del(balancer.cache);
}
<|endoftext|>


<commit_before>#include "SvApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "ModulesApp.h"

// kernels
#include "SV_Continuity.h"
#include "SV_Momentum.h"
#include "SV_ArtificialViscFlux.h"

// auxkernels
#include "BathymetryAux.h"
#include "PressureAux.h"
#include "EntropyAux.h"
#include "EntropyFluxAux.h"
#include "VelocityAux.h"
#include "NormVectorAux.h"

// ics
#include "StepIC.h"

// bcs
#include "SVSetWaterHeightInletBC.h"
#include "SVSetWaterHeightOutletBC.h"
#include "SVSetWaterVelocityInletBC.h"
#include "SVSetWaterVelocity.h"
#include "SolidWallBC.h"

// userobject: eos
#include "HydrostaticPressure.h"

// materials
#include "ComputeViscCoeff.h"

// bathymetry function
#include "Bathymetry1D_step.h"

template<>
InputParameters validParams<SvApp>()
{
  InputParameters params = validParams<MooseApp>();

  params.set<bool>("use_legacy_uo_initialization") = false;
  params.set<bool>("use_legacy_uo_aux_computation") = false;
  return params;
}

SvApp::SvApp(const std::string & name, InputParameters parameters) :
    MooseApp(name, parameters)
{
  srand(processor_id());

  Moose::registerObjects(_factory);
  ModulesApp::registerObjects(_factory);
  SvApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  ModulesApp::associateSyntax(_syntax, _action_factory);
  SvApp::associateSyntax(_syntax, _action_factory);
}

SvApp::~SvApp()
{
}

void
SvApp::registerApps()
{
  registerApp(SvApp);
}

void
SvApp::registerObjects(Factory & factory)
{
  // kernels
  registerKernel(SV_Continuity);
  registerKernel(SV_Momentum);
  registerKernel(SV_ArtificialViscFlux);

  // auxkernels
  registerAux(BathymetryAux);
  registerAux(PressureAux);
  registerAux(EntropyAux);
  registerAux(EntropyFluxAux);
  registerAux(VelocityAux);
  registerAux(NormVectorAux);

  // ics
  registerInitialCondition(StepIC);

  // bcs
  registerBoundaryCondition(SVSetWaterHeightInletBC);
  registerBoundaryCondition(SVSetWaterHeightOutletBC);
  registerBoundaryCondition(SVSetWaterVelocityInletBC);
  registerBoundaryCondition(SVSetWaterVelocity);
  registerBoundaryCondition(SolidWallBC);

  // userobject: eos
  registerUserObject(HydrostaticPressure);

  // materials
  registerMaterial(ComputeViscCoeff);

  // functions
  registerFunction(Bathymetry1D_step);
}

void
SvApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
}
<commit_msg>adding explicit kernel in App<commit_after>#include "SvApp.h"
#include "Moose.h"
#include "AppFactory.h"
#include "ModulesApp.h"

// kernels
#include "SV_Continuity.h"
#include "SV_Continuity_Explicit.h"
#include "SV_Momentum.h"
#include "SV_Momentum_Explicit.h"
#include "SV_ArtificialViscFlux.h"
#include "SV_ArtificialViscFlux_Explicit.h"

// auxkernels
#include "BathymetryAux.h"
#include "PressureAux.h"
#include "EntropyAux.h"
#include "EntropyFluxAux.h"
#include "VelocityAux.h"
#include "NormVectorAux.h"

// ics
#include "StepIC.h"

// bcs
#include "SVSetWaterHeightInletBC.h"
#include "SVSetWaterHeightOutletBC.h"
#include "SVSetWaterVelocityInletBC.h"
#include "SVSetWaterVelocity.h"
#include "SolidWallBC.h"

// userobject: eos
#include "HydrostaticPressure.h"

// materials
#include "ComputeViscCoeff.h"

// bathymetry function
#include "Bathymetry1D_step.h"

template<>
InputParameters validParams<SvApp>()
{
  InputParameters params = validParams<MooseApp>();

  params.set<bool>("use_legacy_uo_initialization") = false;
  params.set<bool>("use_legacy_uo_aux_computation") = false;
  return params;
}

SvApp::SvApp(const std::string & name, InputParameters parameters) :
    MooseApp(name, parameters)
{
  srand(processor_id());

  Moose::registerObjects(_factory);
  ModulesApp::registerObjects(_factory);
  SvApp::registerObjects(_factory);

  Moose::associateSyntax(_syntax, _action_factory);
  ModulesApp::associateSyntax(_syntax, _action_factory);
  SvApp::associateSyntax(_syntax, _action_factory);
}

SvApp::~SvApp()
{
}

void
SvApp::registerApps()
{
  registerApp(SvApp);
}

void
SvApp::registerObjects(Factory & factory)
{
  // kernels
  registerKernel(SV_Continuity);
  registerKernel(SV_Continuity_Expl);
  registerKernel(SV_Momentum);
  registerKernel(SV_Momentum_Expl);
  registerKernel(SV_ArtificialViscFlux);
  registerKernel(SV_ArtificialViscFlux_Expl);

  // auxkernels
  registerAux(BathymetryAux);
  registerAux(PressureAux);
  registerAux(EntropyAux);
  registerAux(EntropyFluxAux);
  registerAux(VelocityAux);
  registerAux(NormVectorAux);

  // ics
  registerInitialCondition(StepIC);

  // bcs
  registerBoundaryCondition(SVSetWaterHeightInletBC);
  registerBoundaryCondition(SVSetWaterHeightOutletBC);
  registerBoundaryCondition(SVSetWaterVelocityInletBC);
  registerBoundaryCondition(SVSetWaterVelocity);
  registerBoundaryCondition(SolidWallBC);

  // userobject: eos
  registerUserObject(HydrostaticPressure);

  // materials
  registerMaterial(ComputeViscCoeff);

  // functions
  registerFunction(Bathymetry1D_step);
}

void
SvApp::associateSyntax(Syntax & syntax, ActionFactory & action_factory)
{
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Dave Greene
 */

#ifndef __BASE_MISC_HH__
#define __BASE_MISC_HH__

#include "base/compiler.hh"
#include "base/cprintf.hh"
#include "base/varargs.hh"

#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
#endif

// General exit message, these functions will never return and will
// either abort() if code is < 0 or exit with the code if >= 0
void __exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;

void __exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;

inline void
__exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const std::string& format, CPRINTF_DEFINITION)
{
    __exit_message(prefix, code, func, file, line, format.c_str(),
                   VARARGS_ALLARGS);
}

M5_PRAGMA_NORETURN(__exit_message)
#define exit_message(prefix, code, ...)                            \
    __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

//
// This implements a cprintf based panic() function.  panic() should
// be called when something happens that should never ever happen
// regardless of what the user does (i.e., an acutal m5 bug).  panic()
// calls abort which can dump core or enter the debugger.
//
//
#define panic(...) exit_message("panic", -1, __VA_ARGS__)

//
// This implements a cprintf based fatal() function.  fatal() should
// be called when the simulation cannot continue due to some condition
// that is the user's fault (bad configuration, invalid arguments,
// etc.) and not a simulator bug.  fatal() calls exit(1), i.e., a
// "normal" exit with an error code, as opposed to abort() like
// panic() does.
//
#define fatal(...) exit_message("fatal", 1, __VA_ARGS__)

void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
          const char *func, const char *file, int line,
          const char *format, CPRINTF_DECLARATION);

inline void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
          const char *func, const char *file, int line,
          const std::string &format, CPRINTF_DECLARATION)
{
    __base_message(stream, prefix, verbose, func, file, line, format.c_str(),
              VARARGS_ALLARGS);
}

#define base_message(stream, prefix, verbose, ...)                      \
    __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

// Only print the message the first time this expression is
// encountered.  i.e.  This doesn't check the string itself and
// prevent duplicate strings, this prevents the statement from
// happening more than once. So, even if the arguments change and that
// would have resulted in a different message thoes messages would be
// supressed.
#define base_message_once(...) do {                     \
        static bool once = false;                       \
        if (!once) {                                    \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

#define cond_message(cond, ...) do {            \
        if (cond)                               \
            base_message(__VA_ARGS__);          \
    } while (0)

#define cond_message_once(cond, ...) do {               \
        static bool once = false;                       \
        if (!once && cond) {                            \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

extern bool want_warn, warn_verbose;
extern bool want_info, info_verbose;
extern bool want_hack, hack_verbose;

#define warn(...) \
    cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform(...) \
    cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack(...) \
    cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#define warn_once(...) \
    cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform_once(...) \
    cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack_once(...) \
    cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#endif // __BASE_MISC_HH__
<commit_msg>base: calls abort() from fatal Currently fatal() ends the simulation in a normal fashion.  This results in the call stack getting lost when using a debugger and it is not always possible to debug the simulation just from the information provided by the printed error message.  Even though the error is likely due to a user's fault, the information available should not be thrown away.  Hence, this patch to call abort() from fatal(). (transplanted from f60cd60445b7af00658ecd2127a03daddf58270a)<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Dave Greene
 */

#ifndef __BASE_MISC_HH__
#define __BASE_MISC_HH__

#include "base/compiler.hh"
#include "base/cprintf.hh"
#include "base/varargs.hh"

#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
#endif

// General exit message, these functions will never return and will
// either abort() if code is < 0 or exit with the code if >= 0
void __exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;

void __exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;

inline void
__exit_message(const char *prefix, int code,
    const char *func, const char *file, int line,
    const std::string& format, CPRINTF_DEFINITION)
{
    __exit_message(prefix, code, func, file, line, format.c_str(),
                   VARARGS_ALLARGS);
}

M5_PRAGMA_NORETURN(__exit_message)
#define exit_message(prefix, code, ...)                            \
    __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

//
// This implements a cprintf based panic() function.  panic() should
// be called when something happens that should never ever happen
// regardless of what the user does (i.e., an acutal m5 bug).  panic()
// calls abort which can dump core or enter the debugger.
//
//
#define panic(...) exit_message("panic", -1, __VA_ARGS__)

//
// This implements a cprintf based fatal() function.  fatal() should
// be called when the simulation cannot continue due to some condition
// that is the user's fault (bad configuration, invalid arguments,
// etc.) and not a simulator bug.  fatal() calls  abort() like
// panic() does.
//
#define fatal(...) exit_message("fatal", -1, __VA_ARGS__)

void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
          const char *func, const char *file, int line,
          const char *format, CPRINTF_DECLARATION);

inline void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
          const char *func, const char *file, int line,
          const std::string &format, CPRINTF_DECLARATION)
{
    __base_message(stream, prefix, verbose, func, file, line, format.c_str(),
              VARARGS_ALLARGS);
}

#define base_message(stream, prefix, verbose, ...)                      \
    __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

// Only print the message the first time this expression is
// encountered.  i.e.  This doesn't check the string itself and
// prevent duplicate strings, this prevents the statement from
// happening more than once. So, even if the arguments change and that
// would have resulted in a different message thoes messages would be
// supressed.
#define base_message_once(...) do {                     \
        static bool once = false;                       \
        if (!once) {                                    \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

#define cond_message(cond, ...) do {            \
        if (cond)                               \
            base_message(__VA_ARGS__);          \
    } while (0)

#define cond_message_once(cond, ...) do {               \
        static bool once = false;                       \
        if (!once && cond) {                            \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

extern bool want_warn, warn_verbose;
extern bool want_info, info_verbose;
extern bool want_hack, hack_verbose;

#define warn(...) \
    cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform(...) \
    cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack(...) \
    cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#define warn_once(...) \
    cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform_once(...) \
    cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack_once(...) \
    cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#endif // __BASE_MISC_HH__
<|endoftext|>