<commit_before>/*
 *  gravity_compensation.cpp
 *
 *  Created on: Nov 11, 2013
 *  Authors:   Francisco Viña
 *            fevb <at> kth.se
 */

/* Copyright (c) 2013, Francisco Viña, CVAP, KTH
   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 KTH 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 KTH BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <ros/ros.h>
#include <gravity_compensation/gravity_compensation.h>
#include <geometry_msgs/PoseStamped.h>
#include <tf_conversions/tf_eigen.h>
#include <eigen3/Eigen/Core>
#include <eigen_conversions/eigen_msg.h>

GravityCompensation::GravityCompensation(GravityCompensationParams *g_comp_params)
{
    m_g_comp_params = g_comp_params;
    m_tf_listener = new tf::TransformListener();
}

GravityCompensation::~GravityCompensation()
{
    delete m_tf_listener;
}

void GravityCompensation::Zero(const geometry_msgs::WrenchStamped &ft_raw,
                          geometry_msgs::WrenchStamped &ft_zeroed)
{
    std::vector<double> bias = m_g_comp_params->getBias();

    ft_zeroed = ft_raw;
    ft_zeroed.wrench.force.x = ft_raw.wrench.force.x-bias[0];
    ft_zeroed.wrench.force.y = ft_raw.wrench.force.y-bias[1];
    ft_zeroed.wrench.force.z = ft_raw.wrench.force.z-bias[2];
    ft_zeroed.wrench.torque.x = ft_raw.wrench.torque.x-bias[3];
    ft_zeroed.wrench.torque.y = ft_raw.wrench.torque.y-bias[4];
    ft_zeroed.wrench.torque.z = ft_raw.wrench.torque.z-bias[5];

    return ft_zeroed;
}

bool GravityCompensation::Compensate(const geometry_msgs::WrenchStamped &ft_zeroed,
                                     const sensor_msgs::Imu &gravity,
                                     geometry_msgs::WrenchStamped &ft_compensated)
{

    geometry_msgs::Vector3Stamped g;
    g.vector = gravity.linear_acceleration;
    g.header = gravity.header;
    g.header.stamp = ros::Time();

    // convert the accelerometer reading to the F/T sensor frame
    geometry_msgs::Vector3Stamped g_ft_frame;
    try
    {
        m_tf_listener->transformVector(ft_zeroed.header.frame_id, g, g_ft_frame);
    }

    catch(tf::TransformException &ex)
    {
        ROS_ERROR("Error transforming gravity vector to ft sensor frame...");
        ROS_ERROR("%s.", ex.what());
        return false;
    }

    geometry_msgs::WrenchStamped gripper_wrench;
    gripper_wrench.header.frame_id = ft_zeroed.header.frame_id;
    double gripper_mass = m_g_comp_params->getGripperMass();

    gripper_wrench.wrench.force.x = g_ft_frame.vector.x * gripper_mass;
    gripper_wrench.wrench.force.y = g_ft_frame.vector.y * gripper_mass;
    gripper_wrench.wrench.force.z = g_ft_frame.vector.z * gripper_mass;

    tf::StampedTransform gripper_com = m_g_comp_params->getGripperCOM();
    geometry_msgs::PoseStamped gripper_com_pose;
    tf::poseTFToMsg(gripper_com, gripper_com_pose.pose);
    gripper_com_pose.header.frame_id = gripper_com.child_frame_id_;
    gripper_com_pose.header.stamp = ros::Time();

    // make sure the gripper COM is expressed with respect to the F/T sensor frame
    geometry_msgs::PoseStamped ft_gripper_com_pose;

    try
    {
        m_tf_listener->transformPose(ft_zeroed.header.frame_id,
                                     gripper_com_pose,
                                     ft_gripper_com_pose);
    }

    catch(tf::TransformException &ex)
    {
        ROS_ERROR("Error looking up transform between the gripper COM and the ft sensor frame");
        ROS_ERROR("%s.", ex.what());
        return false;
    }

    // convert the geometry_msgs::PoseStamped to tf::Transform
    tf::Transform T_ft_gripper_com;
    tf::poseMsgToTF(ft_gripper_com_pose.pose, T_ft_gripper_com);

    // convert to Eigen to do cross product to compute the torque
    Eigen::Vector3d r;
    tf::pointMsgToEigen(ft_gripper_com_pose.pose.position, r);

    Eigen::Vector3d gripper_weight_eigen;
    tf::vectorMsgToEigen(gripper_wrench.wrench.force, gripper_weight_eigen);

    // compute torque generated by weight of the gripper
    Eigen::Vector3d gripper_torque_eigen = r.cross(gripper_weight_eigen);
    tf::vectorEigenToMsg(gripper_torque_eigen, gripper_wrench.wrench.torque);

    // compensate force+torque
    Eigen::Matrix<double, 6, 1> ft_zeroed_eigen;
    Eigen::Matrix<double, 6, 1> ft_compensated_eigen;

    tf::wrenchMsgToEigen(ft_zeroed.wrench, ft_zeroed_eigen);

    ft_compensated_eigen =

    // compensated FT in FT sensor frame
    geometry_msgs::Vector3Stamped FT_Fvec_comp;
    geometry_msgs::Vector3Stamped FT_Tvec_comp;
    FT_Fvec_comp.header.frame_id = EndEffector_Weight.header.frame_id;
    FT_Tvec_comp.header.frame_id = EndEffector_Weight.header.frame_id;
    FT_Fvec_comp.header.stamp = ros::Time();
    FT_Tvec_comp.header.stamp = ros::Time();

    FT_Fvec_comp.vector.x = FT_raw.wrench.force.x - EndEffector_Weight.wrench.force.x;
    FT_Fvec_comp.vector.y = FT_raw.wrench.force.y - EndEffector_Weight.wrench.force.y;
    FT_Fvec_comp.vector.z = FT_raw.wrench.force.z - EndEffector_Weight.wrench.force.z;

    FT_Tvec_comp.vector.x = FT_raw.wrench.torque.x - EndEffector_Weight.wrench.torque.x;
    FT_Tvec_comp.vector.y = FT_raw.wrench.torque.y - EndEffector_Weight.wrench.torque.y;
    FT_Tvec_comp.vector.z = FT_raw.wrench.torque.z - EndEffector_Weight.wrench.torque.z;

    // now expressed in the FT frame
    FT_comp.wrench.force = FT_Fvec_comp.vector;
    FT_comp.wrench.torque = FT_Tvec_comp.vector;
    FT_comp.header.stamp = FT_raw.header.stamp;
    FT_comp.header.frame_id = FT_raw.header.frame_id;

    return true;

    return ft_compensated;
}
<commit_msg>finished Compensate() function<commit_after>/*
 *  gravity_compensation.cpp
 *
 *  Created on: Nov 11, 2013
 *  Authors:   Francisco Viña
 *            fevb <at> kth.se
 */

/* Copyright (c) 2013, Francisco Viña, CVAP, KTH
   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 KTH 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 KTH BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <ros/ros.h>
#include <gravity_compensation/gravity_compensation.h>
#include <geometry_msgs/PoseStamped.h>
#include <tf_conversions/tf_eigen.h>
#include <eigen3/Eigen/Core>
#include <eigen_conversions/eigen_msg.h>

GravityCompensation::GravityCompensation(GravityCompensationParams *g_comp_params)
{
    m_g_comp_params = g_comp_params;
    m_tf_listener = new tf::TransformListener();
}

GravityCompensation::~GravityCompensation()
{
    delete m_tf_listener;
}

void GravityCompensation::Zero(const geometry_msgs::WrenchStamped &ft_raw,
                          geometry_msgs::WrenchStamped &ft_zeroed)
{
    std::vector<double> bias = m_g_comp_params->getBias();

    ft_zeroed = ft_raw;
    ft_zeroed.wrench.force.x = ft_raw.wrench.force.x-bias[0];
    ft_zeroed.wrench.force.y = ft_raw.wrench.force.y-bias[1];
    ft_zeroed.wrench.force.z = ft_raw.wrench.force.z-bias[2];
    ft_zeroed.wrench.torque.x = ft_raw.wrench.torque.x-bias[3];
    ft_zeroed.wrench.torque.y = ft_raw.wrench.torque.y-bias[4];
    ft_zeroed.wrench.torque.z = ft_raw.wrench.torque.z-bias[5];

}

bool GravityCompensation::Compensate(const geometry_msgs::WrenchStamped &ft_zeroed,
                                     const sensor_msgs::Imu &gravity,
                                     geometry_msgs::WrenchStamped &ft_compensated)
{

    geometry_msgs::Vector3Stamped g;
    g.vector = gravity.linear_acceleration;
    g.header = gravity.header;
    g.header.stamp = ros::Time();

    // convert the accelerometer reading to the F/T sensor frame
    geometry_msgs::Vector3Stamped g_ft_frame;
    try
    {
        m_tf_listener->transformVector(ft_zeroed.header.frame_id, g, g_ft_frame);
    }

    catch(tf::TransformException &ex)
    {
        ROS_ERROR("Error transforming gravity vector to ft sensor frame...");
        ROS_ERROR("%s.", ex.what());
        return false;
    }

    double gripper_mass = m_g_comp_params->getGripperMass();
    Eigen::Vector3d g_ft_frame_eigen;
    tf::vectorMsgToEigen(g_ft_frame.vector, g_ft_frame_eigen);

    Eigen::Matrix<double, 6, 1> gripper_wrench_eigen;
    gripper_wrench_eigen.topRows(3) = g_ft_frame_eigen*gripper_mass;

    tf::StampedTransform gripper_com = m_g_comp_params->getGripperCOM();
    geometry_msgs::PoseStamped gripper_com_pose;
    tf::poseTFToMsg(gripper_com, gripper_com_pose.pose);
    gripper_com_pose.header.frame_id = gripper_com.child_frame_id_;
    gripper_com_pose.header.stamp = ros::Time();

    // make sure the gripper COM is expressed with respect to the F/T sensor frame
    geometry_msgs::PoseStamped ft_gripper_com_pose;

    try
    {
        m_tf_listener->transformPose(ft_zeroed.header.frame_id,
                                     gripper_com_pose,
                                     ft_gripper_com_pose);
    }

    catch(tf::TransformException &ex)
    {
        ROS_ERROR("Error looking up transform between the gripper COM and the ft sensor frame");
        ROS_ERROR("%s.", ex.what());
        return false;
    }

    // convert to Eigen to do cross product to compute the torque
    Eigen::Vector3d r;
    tf::pointMsgToEigen(ft_gripper_com_pose.pose.position, r);

    // compute torque generated by weight of the gripper
    Eigen::Vector3d gripper_torque_eigen = r.cross(gripper_wrench_eigen.topRows(3));
    gripper_wrench_eigen.bottomRows(3) = gripper_torque_eigen;

    // compensate force & torque
    Eigen::Matrix<double, 6, 1> ft_zeroed_eigen;
    tf::wrenchMsgToEigen(ft_zeroed.wrench, ft_zeroed_eigen);
    Eigen::Matrix<double, 6, 1> ft_compensated_eigen;

    ft_compensated_eigen = ft_zeroed_eigen - gripper_wrench_eigen;

    tf::wrenchEigenToMsg(ft_compensated_eigen, ft_compensated.wrench);
    ft_compensated.header = ft_zeroed.header;

    return true;
}
<|endoftext|>


<commit_before>#include "inputdevice.h"
#include "inputcontext.h"
namespace {
    const bool IS_DOWN_UNDEFINED = false;
    const bool IS_UP_UNDEFINED = true;
    const bool IS_RELEASED_UNDEFINED = false;
    const bool IS_PRESSED_UNDEFINED = false;
    const float RANGE_UNDEFINED = 0.0f;
}
namespace sdli {

bool isPressed(const LogicDigitalData& d)
{
    return d.currentStatus
            && d.previousStatus != d.currentStatus;
}

bool isReleased(const LogicDigitalData& d)
{
    return !d.currentStatus
            && d.previousStatus != d.currentStatus;
}

void InputDevice::handleKeyboard(const InputDevice::RawInputData& raw)
{
    auto& ctx = this->contextStack_.top();

    auto inputAction = ctx->keyAction(static_cast<SDL_Scancode>(raw.rawInput));
    auto& logic = logicDigitalData[inputAction];

    logic.previousStatus = logic.currentStatus;
    logic.currentStatus = raw.pollResult;

    if(::sdli::isPressed(logic))
    {
        ctx->fireCallbacks(inputAction, sdli::CallType::OnPress);
        return;
    }
    if(::sdli::isReleased(logic))
    {
        ctx->fireCallbacks(inputAction, sdli::CallType::OnRelease);
        return;
    }
}

InputDevice::InputDevice()
{
}

void InputDevice::poll()
{
    if(this->contextStack_.empty())
    {
        return;
    }

    auto sdl_keystate = SDL_GetKeyboardState(NULL);
//    for(auto& i : keyboardKeys)
//    {
//        auto state = sdl_keystate[i.first];
//        logicDigitalData[i.second].previousStatus = logicDigitalData[i.second].currentStatus;
//        logicDigitalData[i.second].currentStatus = state;
//    }

}

void InputDevice::push(InputType type, unsigned int rawInput, int value)
{
    perFrameCaptures.emplace_back(RawInputData{type, rawInput, value});
}

//TODO: evaluate isPressed correctly - detect changes over multiple samples
void InputDevice::dispatch()
{
    if(this->contextStack_.empty())
    {
        return;
    }

    for(auto& i : logicDigitalData)
    {
        i.second.previousStatus = i.second.currentStatus;
        i.second.currentStatus = false;
    }

    for(auto& d : perFrameCaptures)
    {
        switch(d.type)
        {
        case InputType::Keyboard:
            handleKeyboard(d);
            break;
        default:
            break;
//        case InputType::Keyboard:
//            logicDigitalData[keyboardKeys[static_cast<SDL_Scancode>(d.rawInput)]].currentStatus |= d.pollResult;
//            break;

//        case InputType::GamecontrollerButton:
//            logicDigitalData[gameControllerButtons[static_cast<SDL_GameControllerButton>(d.rawInput)]].currentStatus |= d.pollResult;
//            break;

//        case InputType::GamecontrollerAxis:
//            logicAnalogData[gameControllerAxes[static_cast<SDL_GameControllerAxis>(d.rawInput)].axis].currentStatus = static_cast<float>(d.pollResult);
//            // / gameControllerAxes[static_cast<SDL_GameControllerAxis>(d.rawInput)].normalizeValue;
//            break;
//        case InputType::MouseButton:
//            // TBA - Req for public ?
//            break;
//        case InputType::MouseAxis:
//            // TBA - Req for public ?
//            break;
        }
    }

    perFrameCaptures.clear();
}

float InputDevice::getRange(InputAxis axis)
{
    if(contextStack_.empty()
            || logicAnalogData.find(axis) == logicAnalogData.end())
    {
        return RANGE_UNDEFINED;
    }

    return logicAnalogData[axis].currentStatus;
}

bool InputDevice::isPressed(InputAction action)
{
    if(contextStack_.empty()
            || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_PRESSED_UNDEFINED;
    }

    return logicDigitalData[action].currentStatus
            && logicDigitalData[action].previousStatus != logicDigitalData[action].currentStatus;
}

bool InputDevice::isReleased(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_RELEASED_UNDEFINED;
    }

    return !logicDigitalData[action].currentStatus
            && logicDigitalData[action].previousStatus != logicDigitalData[action].currentStatus;;
}

bool InputDevice::isDown(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_DOWN_UNDEFINED;
    }
    std::function<void()> test;
    return logicDigitalData[action].currentStatus;
}

bool InputDevice::isUp(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_UP_UNDEFINED;
    }

    return logicDigitalData[action].currentStatus;
}

void InputDevice::pushContext(InputContext* newContext)
{
    contextStack_.push(newContext);
}

}
<commit_msg>Fixed Release bug in event dispatching<commit_after>#include "inputdevice.h"
#include "inputcontext.h"
namespace {
    const bool IS_DOWN_UNDEFINED = false;
    const bool IS_UP_UNDEFINED = true;
    const bool IS_RELEASED_UNDEFINED = false;
    const bool IS_PRESSED_UNDEFINED = false;
    const float RANGE_UNDEFINED = 0.0f;
}
namespace sdli {

bool isPressed(const LogicDigitalData& d)
{
    return d.currentStatus
            && d.previousStatus != d.currentStatus;
}

bool isReleased(const LogicDigitalData& d)
{
    return !d.currentStatus
            && d.previousStatus != d.currentStatus;
}

void InputDevice::handleKeyboard(const InputDevice::RawInputData& raw)
{
    auto& ctx = this->contextStack_.top();

    auto inputAction = ctx->keyAction(static_cast<SDL_Scancode>(raw.rawInput));
    auto& logic = logicDigitalData[inputAction];

//    logic.previousStatus = logic.currentStatus;
    logic.currentStatus = raw.pollResult;

    if(::sdli::isPressed(logic))
    {
        ctx->fireCallbacks(inputAction, sdli::CallType::OnPress);
        return;
    }
    if(::sdli::isReleased(logic))
    {
        ctx->fireCallbacks(inputAction, sdli::CallType::OnRelease);
        return;
    }
}

InputDevice::InputDevice()
{
}

void InputDevice::poll()
{
    if(this->contextStack_.empty())
    {
        return;
    }

    auto sdl_keystate = SDL_GetKeyboardState(NULL);
//    for(auto& i : keyboardKeys)
//    {
//        auto state = sdl_keystate[i.first];
//        logicDigitalData[i.second].previousStatus = logicDigitalData[i.second].currentStatus;
//        logicDigitalData[i.second].currentStatus = state;
//    }

}

void InputDevice::push(InputType type, unsigned int rawInput, int value)
{
    perFrameCaptures.emplace_back(RawInputData{type, rawInput, value});
}

//TODO: evaluate isPressed correctly - detect changes over multiple samples
void InputDevice::dispatch()
{
    if(this->contextStack_.empty())
    {
        return;
    }

    for(auto& i : logicDigitalData)
    {
        i.second.previousStatus = i.second.currentStatus;
    }

    for(auto& d : perFrameCaptures)
    {
        switch(d.type)
        {
        case InputType::Keyboard:
            handleKeyboard(d);
            break;
        default:
            break;
//        case InputType::Keyboard:
//            logicDigitalData[keyboardKeys[static_cast<SDL_Scancode>(d.rawInput)]].currentStatus |= d.pollResult;
//            break;

//        case InputType::GamecontrollerButton:
//            logicDigitalData[gameControllerButtons[static_cast<SDL_GameControllerButton>(d.rawInput)]].currentStatus |= d.pollResult;
//            break;

//        case InputType::GamecontrollerAxis:
//            logicAnalogData[gameControllerAxes[static_cast<SDL_GameControllerAxis>(d.rawInput)].axis].currentStatus = static_cast<float>(d.pollResult);
//            // / gameControllerAxes[static_cast<SDL_GameControllerAxis>(d.rawInput)].normalizeValue;
//            break;
//        case InputType::MouseButton:
//            // TBA - Req for public ?
//            break;
//        case InputType::MouseAxis:
//            // TBA - Req for public ?
//            break;
        }
    }

    perFrameCaptures.clear();
}

float InputDevice::getRange(InputAxis axis)
{
    if(contextStack_.empty()
            || logicAnalogData.find(axis) == logicAnalogData.end())
    {
        return RANGE_UNDEFINED;
    }

    return logicAnalogData[axis].currentStatus;
}

bool InputDevice::isPressed(InputAction action)
{
    if(contextStack_.empty()
            || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_PRESSED_UNDEFINED;
    }

    return logicDigitalData[action].currentStatus
            && logicDigitalData[action].previousStatus != logicDigitalData[action].currentStatus;
}

bool InputDevice::isReleased(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_RELEASED_UNDEFINED;
    }

    return !logicDigitalData[action].currentStatus
            && logicDigitalData[action].previousStatus != logicDigitalData[action].currentStatus;;
}

bool InputDevice::isDown(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_DOWN_UNDEFINED;
    }
    std::function<void()> test;
    return logicDigitalData[action].currentStatus;
}

bool InputDevice::isUp(InputAction action)
{
    if(contextStack_.empty() || logicDigitalData.find(action) == logicDigitalData.end())
    {
        return ::IS_UP_UNDEFINED;
    }

    return logicDigitalData[action].currentStatus;
}

void InputDevice::pushContext(InputContext* newContext)
{
    contextStack_.push(newContext);
}

}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

#include "fmu_hopsan.h"
#include "HopsanCore.h"
#include "HopsanEssentials.h"
#include "HopsanTypes.h"
#include <string>
#include "model.hpp"
#include <cassert>
#include "ComponentUtilities/num2string.hpp"
#include <map>

namespace {

static double fmu_time=0;
static hopsan::ComponentSystem *spCoreComponentSystem = 0;
static std::vector<std::string> sComponentNames;
hopsan::HopsanEssentials gHopsanCore;

double *dataPtrs[<<<nports>>>];

std::map<int,hopsan::HString> realParametersMap;
std::map<int,hopsan::HString> intParametersMap;
std::map<int,hopsan::HString> boolParametersMap;
std::map<int,hopsan::HString> stringParametersMap;

std::string parseResourceLocation(std::string uri)
{
    // The resource location is an URI according to rfc3986 on the following format
    // schema://authority/path or schema:/path
    // authority is expected to be empty if included
    // only the 'file' schema is supported by Hopsan
    std::string::size_type se = uri.find_first_of(':');
    std::string schema = uri.substr(0,se);
    // If the next two chars are // then authority is included (may be empty)
    std::string::size_type pb;
    if (uri.substr(se+1,2) == "//") {
        pb = uri.find_first_of('/', se+3);
    } else {
        pb = uri.find_first_of('/', se);
    }
    // Now we know were the path begins (pb), but is it a unix or windows path
    // Check windows
    if (uri.substr(pb+2,2) == ":/") {
        // Skip first /
        pb++;
    }
    std::string path = uri.substr(pb);
#ifdef _WIN32
    std::string::size_type i = path.find_first_of('/');
    while (i != std::string::npos) {
        path.replace(i, 1, 1, '\\');
        i = path.find_first_of('/');
    }
#endif
    return path;
}
}

extern "C" {

int hopsan_instantiate(const char *resourceLocation)
{
    double startT, stopT;      // Dummy variables
    spCoreComponentSystem = gHopsanCore.loadHMFModel(getModelString().c_str(), startT, stopT);
    if (spCoreComponentSystem)
    {
        std::string rl = parseResourceLocation(resourceLocation);
        spCoreComponentSystem->addSearchPath(rl.c_str());

        // Get pointers to I/O data variables
<<<setdataptrs>>>

        //Populate parameter name maps
<<<addparameterstomap>>>

        // Initialize system
        spCoreComponentSystem->setDesiredTimestep(<<<timestep>>>);
        spCoreComponentSystem->setNumLogSamples(0);
        //! @todo disableLog does not work without setNumLogsamples0
        spCoreComponentSystem->disableLog();
        if (spCoreComponentSystem->checkModelBeforeSimulation())
        {
            return 1; // C true
        }
    }
    return 0;  // C false
}

int hopsan_initialize(double startT, double stopT)
{
    return spCoreComponentSystem->initialize(startT, stopT) ? 1 : 0;
}

void hopsan_simulate(double stopTime)
{
    spCoreComponentSystem->simulate(stopTime);
}

void hopsan_finalize()
{
    spCoreComponentSystem->finalize();
}

int hopsan_has_message()
{
    return (gHopsanCore.checkMessage() > 0) ? 1 : 0;
}

void hopsan_get_message(hopsan_message_callback_t message_callback, void* userState)
{
    hopsan::HString message, type, tag;
    gHopsanCore.getMessage(message, type, tag);

    // Replace any # with ## (# is reserved by FMI for value references)
    // # is used as escape character in this case
    message.replace("#", "##");

    // Replace any single % since we do not use printf format strings inside Hopsan
    // The FMI standard assuems that message is a printf format string
    // Use %% to print %
    message.replace("%", "%%");

    message_callback(message.c_str(), type.c_str(), userState);
}

double hopsan_get_real(int vr)
{
    if(vr < <<<nports>>>) {
        return (*dataPtrs[vr]);
    }
    if(realParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(realParametersMap[vr],value);
        bool ok;
        return value.toDouble(&ok);
    }
    return -1;
}

int hopsan_get_integer(int vr)
{
    if(intParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(intParametersMap[vr],value);
        bool ok;
        return value.toLongInt(&ok);
    }
    return -1;
}

int hopsan_get_boolean(int vr)
{
    if(boolParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(boolParametersMap[vr],value);
        bool ok;
        return value.toBool(&ok);
    }
    return false;
}

const char* hopsan_get_string(int vr)
{
    if(stringParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(stringParametersMap[vr],value);
        bool ok;
        return value.c_str();
    }
    return "";
}

void hopsan_set_real(int vr, double value)
{
    if(vr < <<<nports>>>) {
        (*dataPtrs[vr]) = value;
    }
    else if(realParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(realParametersMap[vr], to_hstring(value));
    }
}

void hopsan_set_integer(int vr, int value)
{
    if(intParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(intParametersMap[vr], to_hstring(value));
    }
}

void hopsan_set_boolean(int vr, int value)
{
    if(boolParametersMap.count(vr)) {
        hopsan::HString hvalue = "true";
        if(value != 0) {
            hvalue = "false";
        }
        spCoreComponentSystem->setParameterValue(boolParametersMap[vr], hvalue);
    }
}

void hopsan_set_string(int vr, const char* value)
{
    if(stringParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(stringParametersMap[vr], value);
    }
}

}
<commit_msg>Avoid returning reference to temporary in exported FMI code<commit_after>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

#include "fmu_hopsan.h"
#include "HopsanCore.h"
#include "HopsanEssentials.h"
#include "HopsanTypes.h"
#include <string>
#include "model.hpp"
#include <cassert>
#include "ComponentUtilities/num2string.hpp"
#include <map>

namespace {

static double fmu_time=0;
static hopsan::ComponentSystem *spCoreComponentSystem = 0;
static std::vector<std::string> sComponentNames;
hopsan::HopsanEssentials gHopsanCore;

double *dataPtrs[<<<nports>>>];

std::map<int,hopsan::HString> realParametersMap;
std::map<int,hopsan::HString> intParametersMap;
std::map<int,hopsan::HString> boolParametersMap;
std::map<int,hopsan::HString> stringParametersMap;

static hopsan::HString get_string_retval;

std::string parseResourceLocation(std::string uri)
{
    // The resource location is an URI according to rfc3986 on the following format
    // schema://authority/path or schema:/path
    // authority is expected to be empty if included
    // only the 'file' schema is supported by Hopsan
    std::string::size_type se = uri.find_first_of(':');
    std::string schema = uri.substr(0,se);
    // If the next two chars are // then authority is included (may be empty)
    std::string::size_type pb;
    if (uri.substr(se+1,2) == "//") {
        pb = uri.find_first_of('/', se+3);
    } else {
        pb = uri.find_first_of('/', se);
    }
    // Now we know were the path begins (pb), but is it a unix or windows path
    // Check windows
    if (uri.substr(pb+2,2) == ":/") {
        // Skip first /
        pb++;
    }
    std::string path = uri.substr(pb);
#ifdef _WIN32
    std::string::size_type i = path.find_first_of('/');
    while (i != std::string::npos) {
        path.replace(i, 1, 1, '\\');
        i = path.find_first_of('/');
    }
#endif
    return path;
}
}

extern "C" {

int hopsan_instantiate(const char *resourceLocation)
{
    double startT, stopT;      // Dummy variables
    spCoreComponentSystem = gHopsanCore.loadHMFModel(getModelString().c_str(), startT, stopT);
    if (spCoreComponentSystem)
    {
        std::string rl = parseResourceLocation(resourceLocation);
        spCoreComponentSystem->addSearchPath(rl.c_str());

        // Get pointers to I/O data variables
<<<setdataptrs>>>

        //Populate parameter name maps
<<<addparameterstomap>>>

        // Initialize system
        spCoreComponentSystem->setDesiredTimestep(<<<timestep>>>);
        spCoreComponentSystem->setNumLogSamples(0);
        //! @todo disableLog does not work without setNumLogsamples0
        spCoreComponentSystem->disableLog();
        if (spCoreComponentSystem->checkModelBeforeSimulation())
        {
            return 1; // C true
        }
    }
    return 0;  // C false
}

int hopsan_initialize(double startT, double stopT)
{
    return spCoreComponentSystem->initialize(startT, stopT) ? 1 : 0;
}

void hopsan_simulate(double stopTime)
{
    spCoreComponentSystem->simulate(stopTime);
}

void hopsan_finalize()
{
    spCoreComponentSystem->finalize();
}

int hopsan_has_message()
{
    return (gHopsanCore.checkMessage() > 0) ? 1 : 0;
}

void hopsan_get_message(hopsan_message_callback_t message_callback, void* userState)
{
    hopsan::HString message, type, tag;
    gHopsanCore.getMessage(message, type, tag);

    // Replace any # with ## (# is reserved by FMI for value references)
    // # is used as escape character in this case
    message.replace("#", "##");

    // Replace any single % since we do not use printf format strings inside Hopsan
    // The FMI standard assuems that message is a printf format string
    // Use %% to print %
    message.replace("%", "%%");

    message_callback(message.c_str(), type.c_str(), userState);
}

double hopsan_get_real(int vr)
{
    if(vr < <<<nports>>>) {
        return (*dataPtrs[vr]);
    }
    if(realParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(realParametersMap[vr],value);
        bool ok;
        return value.toDouble(&ok);
    }
    return -1;
}

int hopsan_get_integer(int vr)
{
    if(intParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(intParametersMap[vr],value);
        bool ok;
        return value.toLongInt(&ok);
    }
    return -1;
}

int hopsan_get_boolean(int vr)
{
    if(boolParametersMap.count(vr)) {
        hopsan::HString value;
        spCoreComponentSystem->getParameterValue(boolParametersMap[vr],value);
        bool ok;
        return value.toBool(&ok);
    }
    return false;
}

const char* hopsan_get_string(int vr)
{
    if(stringParametersMap.count(vr)) {
        spCoreComponentSystem->getParameterValue(stringParametersMap[vr],get_string_retval);
        return get_string_retval.c_str();
    }
    return "";
}

void hopsan_set_real(int vr, double value)
{
    if(vr < <<<nports>>>) {
        (*dataPtrs[vr]) = value;
    }
    else if(realParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(realParametersMap[vr], to_hstring(value));
    }
}

void hopsan_set_integer(int vr, int value)
{
    if(intParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(intParametersMap[vr], to_hstring(value));
    }
}

void hopsan_set_boolean(int vr, int value)
{
    if(boolParametersMap.count(vr)) {
        hopsan::HString hvalue = "true";
        if(value != 0) {
            hvalue = "false";
        }
        spCoreComponentSystem->setParameterValue(boolParametersMap[vr], hvalue);
    }
}

void hopsan_set_string(int vr, const char* value)
{
    if(stringParametersMap.count(vr)) {
        spCoreComponentSystem->setParameterValue(stringParametersMap[vr], value);
    }
}

}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                         *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TString.h>

#include "AliITSresponseSDD.h"

//___________________________________________
ClassImp(AliITSresponseSDD)

AliITSresponseSDD::AliITSresponseSDD()
{
  // constructor
   SetMaxAdc();
   SetDiffCoeff();
   SetDriftSpeed();
   SetNSigmaIntegration();
   SetNLookUp();
   // SetClock();
   SetNoiseParam();
   SetNoiseAfterElectronics();
   SetElectronics();
   SetDynamicRange();
   SetChargeLoss();
   SetMinVal();
   SetParamOptions();
   SetZeroSupp();
   SetDataType();
   SetFilenames();
   SetOutputOption();
   SetDo10to8();
}
AliITSresponseSDD::~AliITSresponseSDD() {

  if(fGaus) delete fGaus;

}

void AliITSresponseSDD::SetCompressParam(Int_t  cp[8])
{
  // set compression param

    Int_t i;
    for (i=0; i<8; i++) {
	fCPar[i]=cp[i];
	//printf("\n CompressPar %d %d \n",i,fCPar[i]);

    }
}
void AliITSresponseSDD::GiveCompressParam(Int_t  cp[8])
{
  // give compression param

    Int_t i;
    for (i=0; i<8; i++) {
	cp[i]=fCPar[i];
    }
}

void AliITSresponseSDD::Print()
{
  // Print SDD response Parameters

   cout << "**************************************************" << endl;
   cout << "   Silicon Drift Detector Response Parameters    " << endl;
   cout << "**************************************************" << endl;
   cout << "Diffusion Coefficients: " << fDiffCoeff << ", " << fDiffCoeff1 << endl;

   cout << "Hardware compression parameters: " << endl;
   for(Int_t i=0; i<8; i++) cout << "fCPar[" << i << "] = " << fCPar[i] << endl;
   cout << "Noise before electronics (arbitrary units): " << fNoise << endl;
   cout << "Baseline (ADC units): " << fBaseline << endl;
   cout << "Noise after electronics (ADC units): " << fNoiseAfterEl << endl;

   cout << "Dynamic Range: " << fDynamicRange << endl;
   cout << "Charge Loss: " << fChargeLoss << endl;
   cout << "Temperature: " << fTemperature << endl;
   cout << "Drift Speed: " << fDriftSpeed << endl;
   cout << "Electronics (1=PASCAL, 2=OLA): " << fElectronics << endl;

   cout << "N. of Sigma for signal integration: " << fNsigmas << endl;
   cout << "N. of bins in lookup table: " << fNcomps << endl;

   cout << "Max. ADC Value: " << fMaxAdc << endl;
   cout << "Min. Value: " << fMinVal << endl;

   cout << "**************************************************" << endl;

}

<commit_msg>Set the default for the compression parameters<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                         *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include <TString.h>

#include "AliITSresponseSDD.h"

//___________________________________________
ClassImp(AliITSresponseSDD)

AliITSresponseSDD::AliITSresponseSDD()
{
  // constructor
   SetMaxAdc();
   SetDiffCoeff();
   SetDriftSpeed();
   SetNSigmaIntegration();
   SetNLookUp();
   // SetClock();
   SetNoiseParam();
   SetNoiseAfterElectronics();
   SetElectronics();
   SetDynamicRange();
   SetChargeLoss();
   SetMinVal();
   SetParamOptions();
   SetZeroSupp();
   SetDataType();
   SetFilenames();
   SetOutputOption();
   SetDo10to8();
   // set the default zero suppression parameters
   fCPar[0]=0;
   fCPar[1]=0;
   fCPar[2]=(Int_t)(fBaseline + 2.*fNoiseAfterEl);
   fCPar[3]=(Int_t)(fBaseline + 2.*fNoiseAfterEl);
   fCPar[4]=0;
   fCPar[5]=0;
   fCPar[6]=0;
   fCPar[7]=0;
}

AliITSresponseSDD::~AliITSresponseSDD() {

  if(fGaus) delete fGaus;

}

void AliITSresponseSDD::SetCompressParam(Int_t  cp[8])
{
  // set compression param

    Int_t i;
    for (i=0; i<8; i++) {
	fCPar[i]=cp[i];
	//printf("\n CompressPar %d %d \n",i,fCPar[i]);

    }
}
void AliITSresponseSDD::GiveCompressParam(Int_t  cp[8])
{
  // give compression param

    Int_t i;
    for (i=0; i<8; i++) {
	cp[i]=fCPar[i];
    }
}

void AliITSresponseSDD::Print()
{
  // Print SDD response Parameters

   cout << "**************************************************" << endl;
   cout << "   Silicon Drift Detector Response Parameters    " << endl;
   cout << "**************************************************" << endl;
   cout << "Diffusion Coefficients: " << fDiffCoeff << ", " << fDiffCoeff1 << endl;

   cout << "Hardware compression parameters: " << endl;
   for(Int_t i=0; i<8; i++) cout << "fCPar[" << i << "] = " << fCPar[i] << endl;
   cout << "Noise before electronics (arbitrary units): " << fNoise << endl;
   cout << "Baseline (ADC units): " << fBaseline << endl;
   cout << "Noise after electronics (ADC units): " << fNoiseAfterEl << endl;

   cout << "Dynamic Range: " << fDynamicRange << endl;
   cout << "Charge Loss: " << fChargeLoss << endl;
   cout << "Temperature: " << fTemperature << endl;
   cout << "Drift Speed: " << fDriftSpeed << endl;
   cout << "Electronics (1=PASCAL, 2=OLA): " << fElectronics << endl;

   cout << "N. of Sigma for signal integration: " << fNsigmas << endl;
   cout << "N. of bins in lookup table: " << fNcomps << endl;

   cout << "Max. ADC Value: " << fMaxAdc << endl;
   cout << "Min. Value: " << fMinVal << endl;

   cout << "**************************************************" << endl;

}

<|endoftext|>


<commit_before><commit_msg>Initialise more fields, especially mfFakeDPIScale<commit_after><|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_OS_WINDOWS_REALPATH_HPP__
#define __STOUT_OS_WINDOWS_REALPATH_HPP__

#include <stout/error.hpp>
#include <stout/result.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>

#include <stout/internal/windows/longpath.hpp>

namespace os {

inline Result<std::string> realpath(const std::string& path)
{
  // TODO(andschwa): Test the existence of `path` to be consistent with POSIX
  // `::realpath`.

  std::wstring longpath = ::internal::windows::longpath(path);

  // First query for the buffer size required.
  DWORD length = GetFullPathNameW(longpath.data(), 0, nullptr, nullptr);
  if (length == 0) {
    return WindowsError("Failed to retrieve realpath buffer size");
  }

  std::vector<wchar_t> buffer;
  buffer.reserve(static_cast<size_t>(length));

  DWORD result =
    GetFullPathNameW(longpath.data(), length, buffer.data(), nullptr);

  if (result == 0) {
    return WindowsError("Failed to determine realpath");
  }

  return strings::remove(
      stringify(std::wstring(buffer.data())),
      os::LONGPATH_PREFIX,
      strings::Mode::PREFIX);
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_REALPATH_HPP__
<commit_msg>Windows: Fixed `os::realpath` to behave like POSIX version.<commit_after>// 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.

#ifndef __STOUT_OS_WINDOWS_REALPATH_HPP__
#define __STOUT_OS_WINDOWS_REALPATH_HPP__

#include <stout/error.hpp>
#include <stout/result.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>
#include <stout/windows.hpp>

#include <stout/internal/windows/longpath.hpp>
#include <stout/internal/windows/reparsepoint.hpp>

namespace os {

// This should behave like the POSIX `realpath` API: specifically it should
// resolve symlinks in the path, and succeed only if the target file exists.
// This requires that the user has permissions to resolve each component of the
// path.
inline Result<std::string> realpath(const std::string& path)
{
  const Try<SharedHandle> handle = ::internal::windows::get_handle_follow(path);
  if (handle.isError()) {
    return Error(handle.error());
  }

  // First query for the buffer size required.
  DWORD length = ::GetFinalPathNameByHandleW(
      handle.get().get_handle(), nullptr, 0, FILE_NAME_NORMALIZED);
  if (length == 0) {
    return WindowsError("Failed to retrieve realpath buffer size");
  }

  std::vector<wchar_t> buffer;
  buffer.reserve(static_cast<size_t>(length));

  DWORD result = ::GetFinalPathNameByHandleW(
      handle.get().get_handle(), buffer.data(), length, FILE_NAME_NORMALIZED);

  if (result == 0) {
    return WindowsError("Failed to determine realpath");
  }

  return strings::remove(
      stringify(std::wstring(buffer.data())),
      os::LONGPATH_PREFIX,
      strings::Mode::PREFIX);
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_REALPATH_HPP__
<|endoftext|>


<commit_before>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

// Hades
#include <HadesMemory/Detail/Error.hpp>
#include <HadesMemory/Detail/Process.hpp>

// C++ Standard Library
#include <memory>
#include <string>
#include <vector>
#include <utility>
#include <type_traits>

// Windows API
#include <Windows.h>

namespace HadesMem
{
  // Memory managing class
  class MemoryMgr
  {
  public:
    // Memory exception type
    class Error : public virtual HadesMemError
    { };

    // Open process from process ID
    explicit MemoryMgr(DWORD ProcID);

    // MemoryMgr::Call return data
    class RemoteFunctionRet
    {
    public:
      RemoteFunctionRet();

      RemoteFunctionRet(DWORD_PTR ReturnValue, DWORD64 ReturnValue64,
        DWORD LastError);

      DWORD_PTR GetReturnValue() const;

      DWORD64 GetReturnValue64() const;

      DWORD GetLastError() const;

    private:
      DWORD_PTR m_ReturnValue;
      DWORD64 m_ReturnValue64;
      DWORD m_LastError;
    };

    // Calling conventions
    enum CallConv
    {
      CallConv_Default,
      CallConv_CDECL,
      CallConv_STDCALL,
      CallConv_THISCALL,
      CallConv_FASTCALL,
      CallConv_X64
    };

    // Call remote function
    RemoteFunctionRet Call(LPCVOID Address, CallConv MyCallConv,
      std::vector<PVOID> const& Args) const;

    // Read memory (POD types)
    template <typename T>
    T Read(PVOID Address, typename std::enable_if<std::is_pod<T>::value,
      T>::type* Dummy = 0) const;

    // Read memory (string types)
    template <typename T>
    T ReadString(PVOID Address, typename std::enable_if<std::is_same<T, std::
      basic_string<typename T::value_type>>::value, T>::type* Dummy = 0)
      const;

    // Read memory (vector types)
    template <typename T>
    T ReadList(PVOID Address, std::size_t Size, typename std::enable_if<std::
      is_same<T, std::vector<typename T::value_type>>::value, T>::type*
      Dummy = 0) const;

    // Write memory (POD types)
    template <typename T>
    void Write(PVOID Address, T const& Data, typename std::enable_if<std::
      is_pod<T>::value, T>::type* Dummy = 0) const;

    // Write memory (string types)
    template <typename T>
    void WriteString(PVOID Address, T const& Data, typename std::enable_if<
      std::is_same<T, std::basic_string<typename T::value_type>>::value, T>::
      type* Dummy = 0) const;

    // Write memory (vector types)
    template <typename T>
    void WriteList(PVOID Address, T const& Data, typename std::enable_if<std::
      is_same<T, std::vector<typename T::value_type>>::value, T>::type*
      Dummy = 0) const;

    // Whether an address is currently readable
    bool CanRead(LPCVOID Address) const;

    // Whether an address is currently writable
    bool CanWrite(LPCVOID Address) const;

    // Whether an address is currently executable
    bool CanExecute(LPCVOID Address) const;

    // Whether an address is contained within a guard page
    bool IsGuard(LPCVOID Address) const;

    // Protect a memory region
    DWORD ProtectRegion(LPVOID Address, DWORD Protect) const;

    // Allocate memory
    PVOID Alloc(SIZE_T Size) const;

    // Free memory
    void Free(PVOID Address) const;

    // Get address of export in remote process (by name)
    FARPROC GetRemoteProcAddress(HMODULE RemoteMod,
      std::wstring const& Module, std::string const& Function) const;

    // Get address of export in remote process (by ordinal)
    FARPROC GetRemoteProcAddress(HMODULE RemoteMod,
      std::wstring const& Module, WORD Function) const;

    // Flush instruction cache
    void FlushCache(LPCVOID Address, SIZE_T Size) const;

    // Get process handle of target
    HANDLE GetProcessHandle() const;

    // Get process ID of target
    DWORD GetProcessId() const;

    // Get process path
    std::wstring GetProcessPath() const;

    // Is WoW64 process
    bool IsWoW64Process() const;

  private:
    // Read memory
    void ReadImpl(PVOID Address, PVOID Out, std::size_t OutSize) const;

    // Write memory
    void WriteImpl(PVOID Address, LPCVOID In, std::size_t InSize) const;

    // Target process
    Detail::Process m_Process;
  };

  // RAII class for remote memory allocation and freeing
  class AllocAndFree
  {
  public:
    AllocAndFree(MemoryMgr const& MyMemoryMgr, SIZE_T Size);

    ~AllocAndFree();

    void Free() const;

    PVOID GetBase() const;

    SIZE_T GetSize() const;

  protected:
    AllocAndFree(AllocAndFree const&);
    AllocAndFree& operator=(AllocAndFree const&);

  private:
    MemoryMgr m_Memory;
    SIZE_T m_Size;
    mutable PVOID m_Address;
  };

  // Read memory (POD types)
  template <typename T>
  T MemoryMgr::Read(PVOID Address, typename std::enable_if<std::is_pod<T>::
    value, T>::type* /*Dummy*/) const
  {
    // Read data
    T Data;
    ReadImpl(Address, &Data, sizeof(Data));
    return Data;
  }

  // Read memory (string types)
  template <typename T>
  T MemoryMgr::ReadString(PVOID Address, typename std::enable_if<std::is_same<
    T, std::basic_string<typename T::value_type>>::value, T>::type* /*Dummy*/)
    const
  {
    // Character type
    typedef typename T::value_type CharT;

    // Ensure chracter type is POD
    static_assert(std::is_pod<CharT>::value, "Character type of string must "
      "be POD.");

    // Create buffer to store results
    T Buffer;

    // Loop until a null terminator is found
    for (CharT* AddressReal = static_cast<CharT*>(Address);; ++AddressReal)
    {
      // Read current character
      CharT const Current = this->Read<CharT>(AddressReal);

      // Return generated string on null terminator
      if (Current == CharT())
      {
        return Buffer;
      }

      // Add chaaracter to buffer
      Buffer += Current;
    }
  }

  // Read memory (vector types)
  template <typename T>
  T MemoryMgr::ReadList(PVOID Address, std::size_t Size, typename
    std::enable_if<std::is_same<T, std::vector<typename T::value_type>>::
    value, T>::type* /*Dummy*/) const
  {
    // Value type
    typedef typename T::value_type ValT;

    // Ensure value type is POD
    static_assert(std::is_pod<ValT>::value, "Value type of vector must be "
      "POD.");

    // Read data
    T Data(Size);
    this->ReadImpl(Address, Data.data(), sizeof(ValT) * Size);
    return Data;
  }

  // Write memory (POD types)
  template <typename T>
  void MemoryMgr::Write(PVOID Address, T const& Data, typename std::
    enable_if<std::is_pod<T>::value, T>::type* /*Dummy*/) const
  {
    // Write memory
    WriteImpl(Address, &Data, sizeof(Data));
  }

  // Write memory (string types)
  template <typename T>
  void MemoryMgr::WriteString(PVOID Address, T const& Data,
    typename std::enable_if<std::is_same<T, std::basic_string<typename T::
    value_type>>::value, T>::type* /*Dummy*/) const
  {
    // Character type
    typedef typename T::value_type CharT;

    // Ensure chracter type is POD
    static_assert(std::is_pod<CharT>::value, "Character type of string must "
      "be POD.");

    // Write memory
    std::size_t const RawSize = (Data.size() * sizeof(CharT)) + 1;
    WriteImpl(Address, Data.data(), RawSize);
  }

  // Write memory (vector types)
  template <typename T>
  void MemoryMgr::WriteList(PVOID Address, T const& Data, typename std::
    enable_if<std::is_same<T, std::vector<typename T::value_type>>::value,
    T>::type* /*Dummy*/) const
  {
    // Value type
    typedef typename T::value_type ValT;

    // Ensure value type is POD
    static_assert(std::is_pod<ValT>::value, "Value type of vector must be "
      "POD.");

    // Write memory
    std::size_t const RawSize = Data.size() * sizeof(ValT);
    WriteImpl(Address, Data.data(), RawSize);
  }
}
<commit_msg>* [MemoryMgr] Simplify ReadString implementation.<commit_after>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

// Hades
#include <HadesMemory/Detail/Error.hpp>
#include <HadesMemory/Detail/Process.hpp>

// C++ Standard Library
#include <memory>
#include <string>
#include <vector>
#include <utility>
#include <type_traits>

// Windows API
#include <Windows.h>

namespace HadesMem
{
  // Memory managing class
  class MemoryMgr
  {
  public:
    // Memory exception type
    class Error : public virtual HadesMemError
    { };

    // Open process from process ID
    explicit MemoryMgr(DWORD ProcID);

    // MemoryMgr::Call return data
    class RemoteFunctionRet
    {
    public:
      RemoteFunctionRet();

      RemoteFunctionRet(DWORD_PTR ReturnValue, DWORD64 ReturnValue64,
        DWORD LastError);

      DWORD_PTR GetReturnValue() const;

      DWORD64 GetReturnValue64() const;

      DWORD GetLastError() const;

    private:
      DWORD_PTR m_ReturnValue;
      DWORD64 m_ReturnValue64;
      DWORD m_LastError;
    };

    // Calling conventions
    enum CallConv
    {
      CallConv_Default,
      CallConv_CDECL,
      CallConv_STDCALL,
      CallConv_THISCALL,
      CallConv_FASTCALL,
      CallConv_X64
    };

    // Call remote function
    RemoteFunctionRet Call(LPCVOID Address, CallConv MyCallConv,
      std::vector<PVOID> const& Args) const;

    // Read memory (POD types)
    template <typename T>
    T Read(PVOID Address, typename std::enable_if<std::is_pod<T>::value,
      T>::type* Dummy = 0) const;

    // Read memory (string types)
    template <typename T>
    T ReadString(PVOID Address, typename std::enable_if<std::is_same<T, std::
      basic_string<typename T::value_type>>::value, T>::type* Dummy = 0)
      const;

    // Read memory (vector types)
    template <typename T>
    T ReadList(PVOID Address, std::size_t Size, typename std::enable_if<std::
      is_same<T, std::vector<typename T::value_type>>::value, T>::type*
      Dummy = 0) const;

    // Write memory (POD types)
    template <typename T>
    void Write(PVOID Address, T const& Data, typename std::enable_if<std::
      is_pod<T>::value, T>::type* Dummy = 0) const;

    // Write memory (string types)
    template <typename T>
    void WriteString(PVOID Address, T const& Data, typename std::enable_if<
      std::is_same<T, std::basic_string<typename T::value_type>>::value, T>::
      type* Dummy = 0) const;

    // Write memory (vector types)
    template <typename T>
    void WriteList(PVOID Address, T const& Data, typename std::enable_if<std::
      is_same<T, std::vector<typename T::value_type>>::value, T>::type*
      Dummy = 0) const;

    // Whether an address is currently readable
    bool CanRead(LPCVOID Address) const;

    // Whether an address is currently writable
    bool CanWrite(LPCVOID Address) const;

    // Whether an address is currently executable
    bool CanExecute(LPCVOID Address) const;

    // Whether an address is contained within a guard page
    bool IsGuard(LPCVOID Address) const;

    // Protect a memory region
    DWORD ProtectRegion(LPVOID Address, DWORD Protect) const;

    // Allocate memory
    PVOID Alloc(SIZE_T Size) const;

    // Free memory
    void Free(PVOID Address) const;

    // Get address of export in remote process (by name)
    FARPROC GetRemoteProcAddress(HMODULE RemoteMod,
      std::wstring const& Module, std::string const& Function) const;

    // Get address of export in remote process (by ordinal)
    FARPROC GetRemoteProcAddress(HMODULE RemoteMod,
      std::wstring const& Module, WORD Function) const;

    // Flush instruction cache
    void FlushCache(LPCVOID Address, SIZE_T Size) const;

    // Get process handle of target
    HANDLE GetProcessHandle() const;

    // Get process ID of target
    DWORD GetProcessId() const;

    // Get process path
    std::wstring GetProcessPath() const;

    // Is WoW64 process
    bool IsWoW64Process() const;

  private:
    // Read memory
    void ReadImpl(PVOID Address, PVOID Out, std::size_t OutSize) const;

    // Write memory
    void WriteImpl(PVOID Address, LPCVOID In, std::size_t InSize) const;

    // Target process
    Detail::Process m_Process;
  };

  // RAII class for remote memory allocation and freeing
  class AllocAndFree
  {
  public:
    AllocAndFree(MemoryMgr const& MyMemoryMgr, SIZE_T Size);

    ~AllocAndFree();

    void Free() const;

    PVOID GetBase() const;

    SIZE_T GetSize() const;

  protected:
    AllocAndFree(AllocAndFree const&);
    AllocAndFree& operator=(AllocAndFree const&);

  private:
    MemoryMgr m_Memory;
    SIZE_T m_Size;
    mutable PVOID m_Address;
  };

  // Read memory (POD types)
  template <typename T>
  T MemoryMgr::Read(PVOID Address, typename std::enable_if<std::is_pod<T>::
    value, T>::type* /*Dummy*/) const
  {
    // Read data
    T Data;
    ReadImpl(Address, &Data, sizeof(Data));
    return Data;
  }

  // Read memory (string types)
  template <typename T>
  T MemoryMgr::ReadString(PVOID Address, typename std::enable_if<std::is_same<
    T, std::basic_string<typename T::value_type>>::value, T>::type* /*Dummy*/)
    const
  {
    // Character type
    typedef typename T::value_type CharT;

    // Ensure chracter type is POD
    static_assert(std::is_pod<CharT>::value, "Character type of string must "
      "be POD.");

    // Create buffer to store results
    T Buffer;

    // Read until a null terminator is found
    CharT* AddressReal = static_cast<CharT*>(Address);
    for (CharT Current = this->Read<CharT>(AddressReal); Current != CharT();
      ++AddressReal, Current = this->Read<CharT>(AddressReal))
    {
      Buffer.push_back(Current);
    }

    // Return buffer
    return Buffer;
  }

  // Read memory (vector types)
  template <typename T>
  T MemoryMgr::ReadList(PVOID Address, std::size_t Size, typename
    std::enable_if<std::is_same<T, std::vector<typename T::value_type>>::
    value, T>::type* /*Dummy*/) const
  {
    // Value type
    typedef typename T::value_type ValT;

    // Ensure value type is POD
    static_assert(std::is_pod<ValT>::value, "Value type of vector must be "
      "POD.");

    // Read data
    T Data(Size);
    this->ReadImpl(Address, Data.data(), sizeof(ValT) * Size);
    return Data;
  }

  // Write memory (POD types)
  template <typename T>
  void MemoryMgr::Write(PVOID Address, T const& Data, typename std::
    enable_if<std::is_pod<T>::value, T>::type* /*Dummy*/) const
  {
    // Write memory
    WriteImpl(Address, &Data, sizeof(Data));
  }

  // Write memory (string types)
  template <typename T>
  void MemoryMgr::WriteString(PVOID Address, T const& Data,
    typename std::enable_if<std::is_same<T, std::basic_string<typename T::
    value_type>>::value, T>::type* /*Dummy*/) const
  {
    // Character type
    typedef typename T::value_type CharT;

    // Ensure chracter type is POD
    static_assert(std::is_pod<CharT>::value, "Character type of string must "
      "be POD.");

    // Write memory
    std::size_t const RawSize = (Data.size() * sizeof(CharT)) + 1;
    WriteImpl(Address, Data.data(), RawSize);
  }

  // Write memory (vector types)
  template <typename T>
  void MemoryMgr::WriteList(PVOID Address, T const& Data, typename std::
    enable_if<std::is_same<T, std::vector<typename T::value_type>>::value,
    T>::type* /*Dummy*/) const
  {
    // Value type
    typedef typename T::value_type ValT;

    // Ensure value type is POD
    static_assert(std::is_pod<ValT>::value, "Value type of vector must be "
      "POD.");

    // Write memory
    std::size_t const RawSize = Data.size() * sizeof(ValT);
    WriteImpl(Address, Data.data(), RawSize);
  }
}
<|endoftext|>


<commit_before>#ifndef VEXCL_SPARSE_PRODUCT_HPP
#define VEXCL_SPARSE_PRODUCT_HPP

namespace vex {
namespace sparse {

struct matrix_vector_product_terminal {};

typedef vector_expression<
        typename boost::proto::terminal< matrix_vector_product_terminal >::type
        > matrix_vector_product_expression;

template <class Matrix, class Vector>
struct matrix_vector_product : matrix_vector_product_expression
{
    const Matrix &A;
    typename boost::proto::result_of::as_child<const Vector, vector_domain>::type x;

    matrix_vector_product(const Matrix &A, const Vector &x)
        : A(A), x(boost::proto::as_child(x)) {}
};

} // namespace sparse

namespace traits {

template <> struct is_vector_expr_terminal< sparse::matrix_vector_product_terminal >
    : std::true_type {};

template <class Matrix, class Vector>
struct terminal_is_value< sparse::matrix_vector_product<Matrix, Vector> >
    : std::true_type {};

template <class Matrix, class Vector>
struct terminal_preamble< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.terminal_preamble(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct local_terminal_init< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.local_terminal_init(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct kernel_param_declaration< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.kernel_param_declaration(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct partial_vector_expr< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.partial_vector_expr(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct kernel_arg_setter< sparse::matrix_vector_product<Matrix, Vector> > {
    static void set(const sparse::matrix_vector_product<Matrix, Vector> &term,
            backend::kernel &kernel, unsigned part, size_t index_offset,
            detail::kernel_generator_state_ptr state)
    {
        term.A.kernel_arg_setter(term.x, kernel, part, index_offset, state);
    }
};

template <class Matrix, class Vector>
struct expression_properties< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(const sparse::matrix_vector_product<Matrix, Vector> &term,
            std::vector<backend::command_queue> &queue_list,
            std::vector<size_t> &partition,
            size_t &size
            )
    {
        term.A.expression_properties(term.x, queue_list, partition, size);
    }
};

} // namespace traits

} // namespace vex

#endif
<commit_msg>Missing preamble<commit_after>#ifndef VEXCL_SPARSE_PRODUCT_HPP
#define VEXCL_SPARSE_PRODUCT_HPP

/*
The MIT License

Copyright (c) 2012-2018 Denis Demidov <dennis.demidov@gmail.com>

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.
*/

/**
 * \file   vexcl/sparse/product.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Sparse matrix-vector product terminal.
 */

#include <vexcl/operations.hpp>

namespace vex {
namespace sparse {

struct matrix_vector_product_terminal {};

typedef vector_expression<
        typename boost::proto::terminal< matrix_vector_product_terminal >::type
        > matrix_vector_product_expression;

template <class Matrix, class Vector>
struct matrix_vector_product : matrix_vector_product_expression
{
    const Matrix &A;
    typename boost::proto::result_of::as_child<const Vector, vector_domain>::type x;

    matrix_vector_product(const Matrix &A, const Vector &x)
        : A(A), x(boost::proto::as_child(x)) {}
};

} // namespace sparse

namespace traits {

template <> struct is_vector_expr_terminal< sparse::matrix_vector_product_terminal >
    : std::true_type {};

template <class Matrix, class Vector>
struct terminal_is_value< sparse::matrix_vector_product<Matrix, Vector> >
    : std::true_type {};

template <class Matrix, class Vector>
struct terminal_preamble< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.terminal_preamble(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct local_terminal_init< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.local_terminal_init(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct kernel_param_declaration< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.kernel_param_declaration(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct partial_vector_expr< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(backend::source_generator &src,
            const sparse::matrix_vector_product<Matrix, Vector> &term,
            const backend::command_queue &q, const std::string &prm_name,
            detail::kernel_generator_state_ptr state)
    {
        term.A.partial_vector_expr(term.x, src, q, prm_name, state);
    }
};

template <class Matrix, class Vector>
struct kernel_arg_setter< sparse::matrix_vector_product<Matrix, Vector> > {
    static void set(const sparse::matrix_vector_product<Matrix, Vector> &term,
            backend::kernel &kernel, unsigned part, size_t index_offset,
            detail::kernel_generator_state_ptr state)
    {
        term.A.kernel_arg_setter(term.x, kernel, part, index_offset, state);
    }
};

template <class Matrix, class Vector>
struct expression_properties< sparse::matrix_vector_product<Matrix, Vector> > {
    static void get(const sparse::matrix_vector_product<Matrix, Vector> &term,
            std::vector<backend::command_queue> &queue_list,
            std::vector<size_t> &partition,
            size_t &size
            )
    {
        term.A.expression_properties(term.x, queue_list, partition, size);
    }
};

} // namespace traits

} // namespace vex

#endif
<|endoftext|>


<commit_before>// Copyright 2019 The Bazel Authors. All rights reserved.
//
// 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 "tools/common/file_system.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>

#ifdef __APPLE__
#include <copyfile.h>
#include <removefile.h>
#else
#include <fcntl.h>
#include <sys/sendfile.h>
#endif

#include "tools/common/path_utils.h"

std::string GetCurrentDirectory() {
  // Passing null,0 causes getcwd to allocate the buffer of the correct size.
  char *buffer = getcwd(nullptr, 0);
  std::string cwd(buffer);
  free(buffer);
  return cwd;
}

bool FileExists(const std::string &path) {
  return access(path.c_str(), 0) == 0;
}

bool RemoveFile(const std::string &path) {
#ifdef __APPLE__
  return removefile(path.c_str(), nullptr, 0);
#elif __unix__
  return remove(path.c_str());
#else
#error Only macOS and Unix are supported at this time.
#endif
}

bool CopyFile(const std::string &src, const std::string &dest) {
#ifdef __APPLE__
  // The `copyfile` function with `COPYFILE_ALL` mode preserves permissions and
  // modification time.
  return copyfile(src.c_str(), dest.c_str(), nullptr,
                  COPYFILE_ALL | COPYFILE_CLONE) == 0;
#elif __unix__
  // On Linux, we can use `sendfile` to copy it more easily than calling
  // `read`/`write` in a loop.
  struct stat stat_buf;
  bool success = false;

  int src_fd = open(src.c_str(), O_RDONLY);
  if (src_fd) {
    fstat(src_fd, &stat_buf);

    int dest_fd = open(dest.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode);
    if (dest_fd) {
      off_t offset = 0;
      if (sendfile(dest_fd, src_fd, &offset, stat_buf.st_size) != -1) {
        struct timespec timespecs[2] = {stat_buf.st_atim, stat_buf.st_mtim};
        futimens(dest_fd, timespecs);
        success = true;
      }
      close(dest_fd);
    }
    close(src_fd);
  }
  return success;
#else
// TODO(allevato): If we want to support Windows in the future, we'll need to
// use something like `CopyFileA`.
#error Only macOS and Unix are supported at this time.
#endif
}

bool MakeDirs(const std::string &path, int mode) {
  // If we got an empty string, we've recursed past the first segment in the
  // path. Assume it exists (if it doesn't, we'll fail when we try to create a
  // directory inside it).
  if (path.empty()) {
    return true;
  }

  struct stat dir_stats;
  if (stat(path.c_str(), &dir_stats) == 0) {
    // Return true if the directory already exists.
    return S_ISDIR(dir_stats.st_mode);
  }

  // Recurse to create the parent directory.
  if (!MakeDirs(Dirname(path).c_str(), mode)) {
    return false;
  }

  // Create the directory that was requested.
  return mkdir(path.c_str(), mode) == 0;
}
<commit_msg>Fix race condition in MakeDirs (#644)<commit_after>// Copyright 2019 The Bazel Authors. All rights reserved.
//
// 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 "tools/common/file_system.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <iostream>
#include <string>
#include <string.h>

#ifdef __APPLE__
#include <copyfile.h>
#include <removefile.h>
#else
#include <fcntl.h>
#include <sys/sendfile.h>
#endif

#include "tools/common/path_utils.h"

std::string GetCurrentDirectory() {
  // Passing null,0 causes getcwd to allocate the buffer of the correct size.
  char *buffer = getcwd(nullptr, 0);
  std::string cwd(buffer);
  free(buffer);
  return cwd;
}

bool FileExists(const std::string &path) {
  return access(path.c_str(), 0) == 0;
}

bool RemoveFile(const std::string &path) {
#ifdef __APPLE__
  return removefile(path.c_str(), nullptr, 0);
#elif __unix__
  return remove(path.c_str());
#else
#error Only macOS and Unix are supported at this time.
#endif
}

bool CopyFile(const std::string &src, const std::string &dest) {
#ifdef __APPLE__
  // The `copyfile` function with `COPYFILE_ALL` mode preserves permissions and
  // modification time.
  return copyfile(src.c_str(), dest.c_str(), nullptr,
                  COPYFILE_ALL | COPYFILE_CLONE) == 0;
#elif __unix__
  // On Linux, we can use `sendfile` to copy it more easily than calling
  // `read`/`write` in a loop.
  struct stat stat_buf;
  bool success = false;

  int src_fd = open(src.c_str(), O_RDONLY);
  if (src_fd) {
    fstat(src_fd, &stat_buf);

    int dest_fd = open(dest.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode);
    if (dest_fd) {
      off_t offset = 0;
      if (sendfile(dest_fd, src_fd, &offset, stat_buf.st_size) != -1) {
        struct timespec timespecs[2] = {stat_buf.st_atim, stat_buf.st_mtim};
        futimens(dest_fd, timespecs);
        success = true;
      }
      close(dest_fd);
    }
    close(src_fd);
  }
  return success;
#else
// TODO(allevato): If we want to support Windows in the future, we'll need to
// use something like `CopyFileA`.
#error Only macOS and Unix are supported at this time.
#endif
}

bool MakeDirs(const std::string &path, int mode) {
  // If we got an empty string, we've recursed past the first segment in the
  // path. Assume it exists (if it doesn't, we'll fail when we try to create a
  // directory inside it).
  if (path.empty()) {
    return true;
  }

  struct stat dir_stats;
  if (stat(path.c_str(), &dir_stats) == 0) {
    // Return true if the directory already exists.
    if (!S_ISDIR(dir_stats.st_mode)) {
      std::cerr << "error: path exists and isn't a directory "
                << strerror(errno) << " (" << path.c_str() << ") \n";
      return false;
    } else {
      return true;
    }
  }

  // Recurse to create the parent directory.
  if (!MakeDirs(Dirname(path).c_str(), mode)) {
    return false;
  }

  // Create the directory that was requested.
  int mkdir_ret = mkdir(path.c_str(), mode);
  if (mkdir_ret == 0) {
    return true;
  }

  // Save the mkdir errno for better reporting.
  int mkdir_errno = errno;

  // Deal with a race condition when 2 `MakeDirs` are running at the same time:
  // one `mkdir` invocation will fail in each recursive call at different
  // points. Don't recurse here to avoid an infinite loop in failure cases.
  if (errno == EEXIST && stat(path.c_str(), &dir_stats) == 0) {
    if (!S_ISDIR(dir_stats.st_mode)) {
      std::cerr << "error: path exists and isn't a directory "
                << strerror(errno) << " (" << path.c_str() << ") \n";
      return false;
    } else {
      // Return true if the directory already exists.
      return true;
    }
  }

  std::cerr << "error:" << strerror(mkdir_errno) << " (" << path.c_str()
            << ") \n";
  return false;
}
<|endoftext|>


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

  Library:   CTK

  Copyright (c) 2010  Kitware Inc.

  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.commontk.org/LICENSE

  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.

=========================================================================*/

/// Qt includes
#include <QColor>
#include <QDebug>
#include <QLinearGradient>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QtGlobal>
#include <QVariant>

/// CTK includes
#include "ctkTransferFunction.h"
#include "ctkTransferFunctionItem.h"
#include "ctkTransferFunctionScene.h"

//-----------------------------------------------------------------------------
class ctkTransferFunctionItemPrivate :
  public ctkPrivate<ctkTransferFunctionItem>
{
public:
  ctkTransferFunctionItemPrivate();
  void init();
  QRectF               Rect;
  ctkTransferFunction* TransferFunction;
};

//-----------------------------------------------------------------------------
ctkTransferFunctionItemPrivate::ctkTransferFunctionItemPrivate()
{
  this->TransferFunction = 0;
  this->Rect = QRectF(0.,0.,1.,1.);
}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItemPrivate::init()
{
  //CTK_P(ctkTransferFunctionItem);
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::ctkTransferFunctionItem(QGraphicsItem* parentGraphicsItem)
  :QGraphicsObject(parentGraphicsItem)
{
  CTK_INIT_PRIVATE(ctkTransferFunctionItem);
  ctk_d()->init();
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::ctkTransferFunctionItem(
  ctkTransferFunction* transferFunction, QGraphicsItem* parentItem)
  :QGraphicsObject(parentItem)
{
  CTK_INIT_PRIVATE(ctkTransferFunctionItem);
  ctk_d()->init();
  this->setTransferFunction(transferFunction);
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::~ctkTransferFunctionItem()
{

}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItem::setTransferFunction(ctkTransferFunction* transferFunction)
{
  CTK_D(ctkTransferFunctionItem);
  d->TransferFunction = transferFunction;
  if (this->scene())
    {
    connect(d->TransferFunction,SIGNAL(changed()),
            this->scene(), SLOT(update()),Qt::UniqueConnection);
    }
}

//-----------------------------------------------------------------------------
ctkTransferFunction* ctkTransferFunctionItem::transferFunction() const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->TransferFunction;
}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItem::setRect(const QRectF& newRect)
{
  CTK_D(ctkTransferFunctionItem);
  if (d->Rect == newRect)
    {
    return;
    }
  d->Rect = newRect;
  this->update();
}

//-----------------------------------------------------------------------------
QRectF ctkTransferFunctionItem::rect() const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->Rect;
}

//-----------------------------------------------------------------------------
QRectF ctkTransferFunctionItem::boundingRect()const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->Rect;
}
/*
//-----------------------------------------------------------------------------
QList<ctkPoint> ctkTransferFunctionItem::bezierParams(
  ctkControlPoint* start, ctkControlPoint* end) const
{
  Q_ASSERT(start);
  Q_ASSERT(end);
  QList<ctkPoint> points;

  ctkBezierControlPoint* bezierCP = dynamic_cast<ctkBezierControlPoint*>(start);
  if (!bezierCP)
    {// just duplicate start and end into p1 and p2
    points << start->P;
    points << start->P;
    points << end->P;
    points << end->P;
    return points;
    }

  points << start->P;
  points << bezierCP->P1;
  points << bezierCP->P2;
  points << end->P;
  return points;
}

//-----------------------------------------------------------------------------
QList<ctkPoint> ctkTransferFunctionItem::nonLinearPoints(
  ctkControlPoint* start, ctkControlPoint* end) const
{
  Q_ASSERT(start);

  ctkNonLinearControlPoint* nonLinearCP =
    dynamic_cast<ctkNonLinearControlPoint*>(start);
  if (!nonLinearCP)
    {
    QList<ctkPoint> points;
    points << start->P;
    points << end->P;
    return points;
    }
  return nonLinearCP->SubPoints;
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::y(const QVariant& v) const
{
  Q_ASSERT(v.canConvert<qreal>() || v.canConvert<QColor>());
  if (v.canConvert<QColor>())
    {
    return v.value<QColor>().alphaF();
    }
  return v.toReal();
}

//-----------------------------------------------------------------------------
QColor ctkTransferFunctionItem::color(const QVariant& v) const
{
  //Q_ASSERT(v.canConvert<QColor>());
  if (v.canConvert<QColor>())
    {
    return v.value<QColor>();
    }
  else
    {
    //black background
    QColor defaultColor(0., 0., 0.);
    return defaultColor;
    }
  return QColor();
}
//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeXDiff()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  qreal rangeX[2];
  d->TransferFunction->range(rangeX);
  return this->rect().width() / (rangeX[1] - rangeX[0]);
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeXOffSet()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  qreal rangeX[2];
  d->TransferFunction->range(rangeX);
  return rangeX[0];
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeYDiff()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  QVariant rangeY[2];
  rangeY[0] = d->TransferFunction->minValue();
  rangeY[1] = d->TransferFunction->maxValue();
  qreal rangeYDiff = this->rect().height();
  if (rangeY[0].canConvert<qreal>())
    {
    if (rangeY[1].toReal() == rangeY[0].toReal())
      {
      rangeYDiff /= rangeY[0].toReal();
      return rangeYDiff;
      }
    else
      {
      rangeYDiff /= rangeY[1].toReal() - rangeY[0].toReal();
      return rangeYDiff;
      }
    }
    else if (rangeY[0].canConvert<QColor>())
      {
      if ( rangeY[1].value<QColor>().alphaF() == rangeY[0].value<QColor>().alphaF())
        {
        rangeYDiff /= rangeY[0].value<QColor>().alphaF();
        return rangeYDiff;
        }
      else
        {
        rangeYDiff /= rangeY[1].value<QColor>().alphaF() - rangeY[0].value<QColor>().alphaF();
        return rangeYDiff;
        }
      }
    else
      {
      Q_ASSERT(rangeY[0].canConvert<qreal>() ||
      rangeY[0].canConvert<QColor>());
      }
  return rangeYDiff;
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeYOffSet()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  QVariant rangeY[2];
  rangeY[0] = d->TransferFunction->minValue();
  rangeY[1] = d->TransferFunction->maxValue();
  if (rangeY[0].canConvert<qreal>())
    {
    if (rangeY[1].toReal() == rangeY[0].toReal())
      {
      return 0.;
      }
    else
      {
      return rangeY[0].toReal();
      }
    }
  else if (rangeY[0].canConvert<QColor>())
    {
    if ( rangeY[1].value<QColor>().alphaF() == rangeY[0].value<QColor>().alphaF())
      {
      return 0.;
      }
    else
      {
      return rangeY[0].value<QColor>().alphaF();
      }
    }
  else
    {
    Q_ASSERT(rangeY[0].canConvert<qreal>() ||
        rangeY[0].canConvert<QColor>());
    }
  return 0;
}

//-----------------------------------------------------------------------------
QPointF ctkTransferFunctionItem::transferFunction2ScreenCoordinates( qreal x, qreal y)
{
  QPointF screenCoordinates((x - this->rangeXOffSet() ) * this->rangeXDiff(),
      this->rect().height() - (y - this->rangeYOffSet() ) * this->rangeYDiff() );
  return screenCoordinates;
}

//-----------------------------------------------------------------------------
QPointF ctkTransferFunctionItem::screen2TransferFunctionCoordinates( qreal x, qreal y)
{
  QPointF transferFunctionCoordinates((x / this->rangeXDiff() ) + this->rangeXOffSet(),
      ( - y + this->rect().height() )/this->rangeYDiff() + this->rangeYOffSet());

  return transferFunctionCoordinates;
}
*/

//-----------------------------------------------------------------------------
QVariant ctkTransferFunctionItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
  QVariant res = this->QGraphicsObject::itemChange(change, value);
  if (change == QGraphicsItem::ItemSceneChange && this->scene())
    {
    connect(this->transferFunction(),SIGNAL(changed()),
            this->scene(), SLOT(update()),Qt::UniqueConnection);
    }
  return res;
}
<commit_msg>BUG: ctkTransferFunctionItem, the event was not the one it was supposed to be<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) 2010  Kitware Inc.

  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.commontk.org/LICENSE

  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.

=========================================================================*/

/// Qt includes
#include <QColor>
#include <QDebug>
#include <QLinearGradient>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QtGlobal>
#include <QVariant>

/// CTK includes
#include "ctkTransferFunction.h"
#include "ctkTransferFunctionItem.h"
#include "ctkTransferFunctionScene.h"

//-----------------------------------------------------------------------------
class ctkTransferFunctionItemPrivate :
  public ctkPrivate<ctkTransferFunctionItem>
{
public:
  ctkTransferFunctionItemPrivate();
  void init();
  QRectF               Rect;
  ctkTransferFunction* TransferFunction;
};

//-----------------------------------------------------------------------------
ctkTransferFunctionItemPrivate::ctkTransferFunctionItemPrivate()
{
  this->TransferFunction = 0;
  this->Rect = QRectF(0.,0.,1.,1.);
}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItemPrivate::init()
{
  //CTK_P(ctkTransferFunctionItem);
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::ctkTransferFunctionItem(QGraphicsItem* parentGraphicsItem)
  :QGraphicsObject(parentGraphicsItem)
{
  CTK_INIT_PRIVATE(ctkTransferFunctionItem);
  ctk_d()->init();
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::ctkTransferFunctionItem(
  ctkTransferFunction* transferFunction, QGraphicsItem* parentItem)
  :QGraphicsObject(parentItem)
{
  CTK_INIT_PRIVATE(ctkTransferFunctionItem);
  ctk_d()->init();
  this->setTransferFunction(transferFunction);
}

//-----------------------------------------------------------------------------
ctkTransferFunctionItem::~ctkTransferFunctionItem()
{

}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItem::setTransferFunction(ctkTransferFunction* transferFunction)
{
  CTK_D(ctkTransferFunctionItem);
  d->TransferFunction = transferFunction;
  if (this->scene())
    {
    connect(d->TransferFunction,SIGNAL(changed()),
            this->scene(), SLOT(update()),Qt::UniqueConnection);
    }
}

//-----------------------------------------------------------------------------
ctkTransferFunction* ctkTransferFunctionItem::transferFunction() const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->TransferFunction;
}

//-----------------------------------------------------------------------------
void ctkTransferFunctionItem::setRect(const QRectF& newRect)
{
  CTK_D(ctkTransferFunctionItem);
  if (d->Rect == newRect)
    {
    return;
    }
  d->Rect = newRect;
  this->update();
}

//-----------------------------------------------------------------------------
QRectF ctkTransferFunctionItem::rect() const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->Rect;
}

//-----------------------------------------------------------------------------
QRectF ctkTransferFunctionItem::boundingRect()const
{
  CTK_D(const ctkTransferFunctionItem);
  return d->Rect;
}
/*
//-----------------------------------------------------------------------------
QList<ctkPoint> ctkTransferFunctionItem::bezierParams(
  ctkControlPoint* start, ctkControlPoint* end) const
{
  Q_ASSERT(start);
  Q_ASSERT(end);
  QList<ctkPoint> points;

  ctkBezierControlPoint* bezierCP = dynamic_cast<ctkBezierControlPoint*>(start);
  if (!bezierCP)
    {// just duplicate start and end into p1 and p2
    points << start->P;
    points << start->P;
    points << end->P;
    points << end->P;
    return points;
    }

  points << start->P;
  points << bezierCP->P1;
  points << bezierCP->P2;
  points << end->P;
  return points;
}

//-----------------------------------------------------------------------------
QList<ctkPoint> ctkTransferFunctionItem::nonLinearPoints(
  ctkControlPoint* start, ctkControlPoint* end) const
{
  Q_ASSERT(start);

  ctkNonLinearControlPoint* nonLinearCP =
    dynamic_cast<ctkNonLinearControlPoint*>(start);
  if (!nonLinearCP)
    {
    QList<ctkPoint> points;
    points << start->P;
    points << end->P;
    return points;
    }
  return nonLinearCP->SubPoints;
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::y(const QVariant& v) const
{
  Q_ASSERT(v.canConvert<qreal>() || v.canConvert<QColor>());
  if (v.canConvert<QColor>())
    {
    return v.value<QColor>().alphaF();
    }
  return v.toReal();
}

//-----------------------------------------------------------------------------
QColor ctkTransferFunctionItem::color(const QVariant& v) const
{
  //Q_ASSERT(v.canConvert<QColor>());
  if (v.canConvert<QColor>())
    {
    return v.value<QColor>();
    }
  else
    {
    //black background
    QColor defaultColor(0., 0., 0.);
    return defaultColor;
    }
  return QColor();
}
//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeXDiff()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  qreal rangeX[2];
  d->TransferFunction->range(rangeX);
  return this->rect().width() / (rangeX[1] - rangeX[0]);
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeXOffSet()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  qreal rangeX[2];
  d->TransferFunction->range(rangeX);
  return rangeX[0];
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeYDiff()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  QVariant rangeY[2];
  rangeY[0] = d->TransferFunction->minValue();
  rangeY[1] = d->TransferFunction->maxValue();
  qreal rangeYDiff = this->rect().height();
  if (rangeY[0].canConvert<qreal>())
    {
    if (rangeY[1].toReal() == rangeY[0].toReal())
      {
      rangeYDiff /= rangeY[0].toReal();
      return rangeYDiff;
      }
    else
      {
      rangeYDiff /= rangeY[1].toReal() - rangeY[0].toReal();
      return rangeYDiff;
      }
    }
    else if (rangeY[0].canConvert<QColor>())
      {
      if ( rangeY[1].value<QColor>().alphaF() == rangeY[0].value<QColor>().alphaF())
        {
        rangeYDiff /= rangeY[0].value<QColor>().alphaF();
        return rangeYDiff;
        }
      else
        {
        rangeYDiff /= rangeY[1].value<QColor>().alphaF() - rangeY[0].value<QColor>().alphaF();
        return rangeYDiff;
        }
      }
    else
      {
      Q_ASSERT(rangeY[0].canConvert<qreal>() ||
      rangeY[0].canConvert<QColor>());
      }
  return rangeYDiff;
}

//-----------------------------------------------------------------------------
qreal ctkTransferFunctionItem::rangeYOffSet()
{
  // pointer to private class
  CTK_D(ctkTransferFunctionItem);

  QVariant rangeY[2];
  rangeY[0] = d->TransferFunction->minValue();
  rangeY[1] = d->TransferFunction->maxValue();
  if (rangeY[0].canConvert<qreal>())
    {
    if (rangeY[1].toReal() == rangeY[0].toReal())
      {
      return 0.;
      }
    else
      {
      return rangeY[0].toReal();
      }
    }
  else if (rangeY[0].canConvert<QColor>())
    {
    if ( rangeY[1].value<QColor>().alphaF() == rangeY[0].value<QColor>().alphaF())
      {
      return 0.;
      }
    else
      {
      return rangeY[0].value<QColor>().alphaF();
      }
    }
  else
    {
    Q_ASSERT(rangeY[0].canConvert<qreal>() ||
        rangeY[0].canConvert<QColor>());
    }
  return 0;
}

//-----------------------------------------------------------------------------
QPointF ctkTransferFunctionItem::transferFunction2ScreenCoordinates( qreal x, qreal y)
{
  QPointF screenCoordinates((x - this->rangeXOffSet() ) * this->rangeXDiff(),
      this->rect().height() - (y - this->rangeYOffSet() ) * this->rangeYDiff() );
  return screenCoordinates;
}

//-----------------------------------------------------------------------------
QPointF ctkTransferFunctionItem::screen2TransferFunctionCoordinates( qreal x, qreal y)
{
  QPointF transferFunctionCoordinates((x / this->rangeXDiff() ) + this->rangeXOffSet(),
      ( - y + this->rect().height() )/this->rangeYDiff() + this->rangeYOffSet());

  return transferFunctionCoordinates;
}
*/

//-----------------------------------------------------------------------------
QVariant ctkTransferFunctionItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
  QVariant res = this->QGraphicsObject::itemChange(change, value);
  if (change == QGraphicsItem::ItemSceneHasChanged && this->scene())
    {
    connect(this->transferFunction(),SIGNAL(changed()),
            this->scene(), SLOT(update()),Qt::UniqueConnection);
    }
  return res;
}
<|endoftext|>