<commit_before>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <Graph.hpp>

#include <backendsCommon/CpuTensorHandle.hpp>
#include <backendsCommon/WorkloadData.hpp>

#include <cl/ClWorkloadFactory.hpp>

#include <boost/cast.hpp>
#include <boost/test/unit_test.hpp>

#include <utility>

using namespace armnn;
using namespace std;

// connects two layers
void Connect(Layer* from, Layer* to, const TensorInfo& tensorInfo, unsigned int fromIndex = 0, unsigned int toIndex = 0)
{
    from->GetOutputSlot(fromIndex).Connect(to->GetInputSlot(toIndex));
    from->GetOutputHandler(fromIndex).SetTensorInfo(tensorInfo);
}

/////////////////////////////////////////////////////////////////////////////////////////////
// The following test are created specifically to test ReleaseConstantData() method in the Layer
// They build very simple graphs including the layer will be checked.
// Checks weights and biases before the method called and after.
/////////////////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE(LayerReleaseConstantDataTest)

BOOST_AUTO_TEST_CASE(ReleaseBatchNormalizationLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    BatchNormalizationDescriptor layerDesc;
    layerDesc.m_Eps = 0.05f;
    BatchNormalizationLayer* const layer = graph.AddLayer<BatchNormalizationLayer>(layerDesc, "layer");

    armnn::TensorInfo weightInfo({3}, armnn::DataType::Float32);
    layer->m_Mean     = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Beta     = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Gamma    = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Mean->Allocate();
    layer->m_Variance->Allocate();
    layer->m_Beta->Allocate();
    layer->m_Gamma->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    armnn::TensorInfo tensorInfo({2, 3, 1, 1}, armnn::DataType::Float32);
    Connect(input, layer, tensorInfo);
    Connect(layer, output, tensorInfo);

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Mean != nullptr);
    BOOST_CHECK(layer->m_Variance != nullptr);
    BOOST_CHECK(layer->m_Beta != nullptr);
    BOOST_CHECK(layer->m_Gamma != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Mean == nullptr);
    BOOST_CHECK(layer->m_Variance == nullptr);
    BOOST_CHECK(layer->m_Beta == nullptr);
    BOOST_CHECK(layer->m_Gamma == nullptr);

 }

 BOOST_AUTO_TEST_CASE(ReleaseConvolution2dLayerConstantDataTest)
 {
     Graph graph;

     // create the layer we're testing
     Convolution2dDescriptor layerDesc;
     layerDesc.m_PadLeft = 3;
     layerDesc.m_PadRight = 3;
     layerDesc.m_PadTop = 1;
     layerDesc.m_PadBottom = 1;
     layerDesc.m_StrideX = 2;
     layerDesc.m_StrideY = 4;
     layerDesc.m_BiasEnabled = true;

     Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");

     layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({2, 3, 5, 3},
                                                                          armnn::DataType::Float32));
     layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>
             (TensorInfo({2}, GetBiasDataType(armnn::DataType::Float32)));

     layer->m_Weight->Allocate();
     layer->m_Bias->Allocate();

     // create extra layers
     Layer* const input = graph.AddLayer<InputLayer>(0, "input");
     Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

     // connect up
     Connect(input, layer, TensorInfo({2, 3, 8, 16}, armnn::DataType::Float32));
     Connect(layer, output, TensorInfo({2, 2, 2, 10}, armnn::DataType::Float32));

     // check the constants that they are not NULL
     BOOST_CHECK(layer->m_Weight != nullptr);
     BOOST_CHECK(layer->m_Bias != nullptr);

     // free up the constants..
     layer->ReleaseConstantData();

     // check the constants that they are NULL now
     BOOST_CHECK(layer->m_Weight == nullptr);
     BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_CASE(ReleaseDepthwiseConvolution2dLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    DepthwiseConvolution2dDescriptor layerDesc;
    layerDesc.m_PadLeft         = 3;
    layerDesc.m_PadRight        = 3;
    layerDesc.m_PadTop          = 1;
    layerDesc.m_PadBottom       = 1;
    layerDesc.m_StrideX         = 2;
    layerDesc.m_StrideY         = 4;
    layerDesc.m_BiasEnabled     = true;

    DepthwiseConvolution2dLayer* const layer = graph.AddLayer<DepthwiseConvolution2dLayer>(layerDesc, "layer");

    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({3, 3, 5, 3}, DataType::Float32));
    layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({9}, DataType::Float32));
    layer->m_Weight->Allocate();
    layer->m_Bias->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    Connect(input, layer, TensorInfo({2, 3, 8, 16}, armnn::DataType::Float32));
    Connect(layer, output, TensorInfo({2, 9, 2, 10}, armnn::DataType::Float32));

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Weight != nullptr);
    BOOST_CHECK(layer->m_Bias != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Weight == nullptr);
    BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_CASE(ReleaseFullyConnectedLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    FullyConnectedDescriptor layerDesc;
    layerDesc.m_BiasEnabled = true;
    layerDesc.m_TransposeWeightMatrix = true;

    FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");

    float inputsQScale = 1.0f;
    float outputQScale = 2.0f;

    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7, 20},
                                                          DataType::QuantisedAsymm8, inputsQScale, 0));
    layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7},
                                                          GetBiasDataType(DataType::QuantisedAsymm8), inputsQScale));
    layer->m_Weight->Allocate();
    layer->m_Bias->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType::QuantisedAsymm8, inputsQScale));
    Connect(layer, output, TensorInfo({3, 7}, DataType::QuantisedAsymm8, outputQScale));

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Weight != nullptr);
    BOOST_CHECK(layer->m_Bias != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Weight == nullptr);
    BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>Remove leftover header from backendsCommon test<commit_after>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <Graph.hpp>

#include <backendsCommon/CpuTensorHandle.hpp>
#include <backendsCommon/WorkloadData.hpp>

#include <boost/cast.hpp>
#include <boost/test/unit_test.hpp>

#include <utility>

using namespace armnn;
using namespace std;

// connects two layers
void Connect(Layer* from, Layer* to, const TensorInfo& tensorInfo, unsigned int fromIndex = 0, unsigned int toIndex = 0)
{
    from->GetOutputSlot(fromIndex).Connect(to->GetInputSlot(toIndex));
    from->GetOutputHandler(fromIndex).SetTensorInfo(tensorInfo);
}

/////////////////////////////////////////////////////////////////////////////////////////////
// The following test are created specifically to test ReleaseConstantData() method in the Layer
// They build very simple graphs including the layer will be checked.
// Checks weights and biases before the method called and after.
/////////////////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE(LayerReleaseConstantDataTest)

BOOST_AUTO_TEST_CASE(ReleaseBatchNormalizationLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    BatchNormalizationDescriptor layerDesc;
    layerDesc.m_Eps = 0.05f;
    BatchNormalizationLayer* const layer = graph.AddLayer<BatchNormalizationLayer>(layerDesc, "layer");

    armnn::TensorInfo weightInfo({3}, armnn::DataType::Float32);
    layer->m_Mean     = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Beta     = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Gamma    = std::make_unique<ScopedCpuTensorHandle>(weightInfo);
    layer->m_Mean->Allocate();
    layer->m_Variance->Allocate();
    layer->m_Beta->Allocate();
    layer->m_Gamma->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    armnn::TensorInfo tensorInfo({2, 3, 1, 1}, armnn::DataType::Float32);
    Connect(input, layer, tensorInfo);
    Connect(layer, output, tensorInfo);

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Mean != nullptr);
    BOOST_CHECK(layer->m_Variance != nullptr);
    BOOST_CHECK(layer->m_Beta != nullptr);
    BOOST_CHECK(layer->m_Gamma != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Mean == nullptr);
    BOOST_CHECK(layer->m_Variance == nullptr);
    BOOST_CHECK(layer->m_Beta == nullptr);
    BOOST_CHECK(layer->m_Gamma == nullptr);

 }

 BOOST_AUTO_TEST_CASE(ReleaseConvolution2dLayerConstantDataTest)
 {
     Graph graph;

     // create the layer we're testing
     Convolution2dDescriptor layerDesc;
     layerDesc.m_PadLeft = 3;
     layerDesc.m_PadRight = 3;
     layerDesc.m_PadTop = 1;
     layerDesc.m_PadBottom = 1;
     layerDesc.m_StrideX = 2;
     layerDesc.m_StrideY = 4;
     layerDesc.m_BiasEnabled = true;

     Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");

     layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({2, 3, 5, 3},
                                                                          armnn::DataType::Float32));
     layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>
             (TensorInfo({2}, GetBiasDataType(armnn::DataType::Float32)));

     layer->m_Weight->Allocate();
     layer->m_Bias->Allocate();

     // create extra layers
     Layer* const input = graph.AddLayer<InputLayer>(0, "input");
     Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

     // connect up
     Connect(input, layer, TensorInfo({2, 3, 8, 16}, armnn::DataType::Float32));
     Connect(layer, output, TensorInfo({2, 2, 2, 10}, armnn::DataType::Float32));

     // check the constants that they are not NULL
     BOOST_CHECK(layer->m_Weight != nullptr);
     BOOST_CHECK(layer->m_Bias != nullptr);

     // free up the constants..
     layer->ReleaseConstantData();

     // check the constants that they are NULL now
     BOOST_CHECK(layer->m_Weight == nullptr);
     BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_CASE(ReleaseDepthwiseConvolution2dLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    DepthwiseConvolution2dDescriptor layerDesc;
    layerDesc.m_PadLeft         = 3;
    layerDesc.m_PadRight        = 3;
    layerDesc.m_PadTop          = 1;
    layerDesc.m_PadBottom       = 1;
    layerDesc.m_StrideX         = 2;
    layerDesc.m_StrideY         = 4;
    layerDesc.m_BiasEnabled     = true;

    DepthwiseConvolution2dLayer* const layer = graph.AddLayer<DepthwiseConvolution2dLayer>(layerDesc, "layer");

    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({3, 3, 5, 3}, DataType::Float32));
    layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({9}, DataType::Float32));
    layer->m_Weight->Allocate();
    layer->m_Bias->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    Connect(input, layer, TensorInfo({2, 3, 8, 16}, armnn::DataType::Float32));
    Connect(layer, output, TensorInfo({2, 9, 2, 10}, armnn::DataType::Float32));

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Weight != nullptr);
    BOOST_CHECK(layer->m_Bias != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Weight == nullptr);
    BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_CASE(ReleaseFullyConnectedLayerConstantDataTest)
{
    Graph graph;

    // create the layer we're testing
    FullyConnectedDescriptor layerDesc;
    layerDesc.m_BiasEnabled = true;
    layerDesc.m_TransposeWeightMatrix = true;

    FullyConnectedLayer* const layer = graph.AddLayer<FullyConnectedLayer>(layerDesc, "layer");

    float inputsQScale = 1.0f;
    float outputQScale = 2.0f;

    layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7, 20},
                                                          DataType::QuantisedAsymm8, inputsQScale, 0));
    layer->m_Bias   = std::make_unique<ScopedCpuTensorHandle>(TensorInfo({7},
                                                          GetBiasDataType(DataType::QuantisedAsymm8), inputsQScale));
    layer->m_Weight->Allocate();
    layer->m_Bias->Allocate();

    // create extra layers
    Layer* const input = graph.AddLayer<InputLayer>(0, "input");
    Layer* const output = graph.AddLayer<OutputLayer>(0, "output");

    // connect up
    Connect(input, layer, TensorInfo({3, 1, 4, 5}, DataType::QuantisedAsymm8, inputsQScale));
    Connect(layer, output, TensorInfo({3, 7}, DataType::QuantisedAsymm8, outputQScale));

    // check the constants that they are not NULL
    BOOST_CHECK(layer->m_Weight != nullptr);
    BOOST_CHECK(layer->m_Bias != nullptr);

    // free up the constants..
    layer->ReleaseConstantData();

    // check the constants that they are NULL now
    BOOST_CHECK(layer->m_Weight == nullptr);
    BOOST_CHECK(layer->m_Bias == nullptr);
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>#include "dataaccess.h"
#include "performer.h"
//#include <ofstream>
#include <fstream>
#include <iostream>
#include <vector>

DataAccess::DataAccess()
{

}

vector<Performer> DataAccess::readData()
{
    vector<Performer> logs;
    Performer logs2;
    string name;
    string gender;
    string bYear;
    string dYear;

    ifstream myfile ("InfoTestFile.txt");
    if ( myfile.is_open() )
    {
        while ( ! myfile.eof() )
        {
            getline(myfile, name, ',');
            getline(myfile, gender, ',');
            getline(myfile, bYear, ',');
            getline(myfile, dYear, ',');

            Performer P(name, gender, bYear, dYear);

            logs.push_back(P);
        }
        myfile.close();
    }
    else
    {
        cout << "Unable to open file." << endl;
    }

    return logs;
}

void DataAccess::writeData ()
{
    ofstream outputFile;
    outputFile.open("InfoTestFile.txt", fstream::app);

    string name;
    string sex;
    int birth;
    string death;
    cin.ignore();
    cout << "Enter name of a Computer Scientist: ";
    getline(cin,name);
    outputFile << name << ", ";
    cout << "Enter sex: ";
    getline(cin,sex);
    outputFile << sex << ", ";
    cout << "Enter year of birth: ";
    cin >> birth;
    outputFile << birth << ", ";
    cout << "Enter year of death or -- if alive: ";
    cin.ignore();
    getline(cin,death);
    outputFile << death << ", " << endl;

    outputFile.close();
    cout << "Done!\n";
}

<commit_msg>ehv vesen<commit_after>#include "dataaccess.h"
#include "performer.h"
//#include <ofstream>
#include <fstream>
#include <iostream>
#include <vector>

DataAccess::DataAccess()
{

}

vector<Performer> DataAccess::readData()
{
    vector<Performer> logs;
    Performer logs2;
    string name;
    string gender;
    string bYear;
    string dYear;

    ifstream myfile ("InfoTestFile.txt");
    if ( myfile.is_open() )
    {
        while ( ! myfile.eof() )
        {
            getline(myfile, name, ',');
            getline(myfile, gender, ',');
            getline(myfile, bYear, ',');
            getline(myfile, dYear, ',');

            Performer P(name, gender, bYear, dYear);

            logs.push_back(P);
        }
        myfile.close();
    }

    return logs;
}

void DataAccess::writeData ()
{
    ofstream outputFile;
    outputFile.open("InfoTestFile.txt", fstream::app);

    string name;
    string sex;
    int birth;
    string death;
    cin.ignore();
    cout << "Enter name of a Computer Scientist: ";
    getline(cin,name);
    outputFile << name << ", ";
    cout << "Enter sex: ";
    getline(cin,sex);
    outputFile << sex << ", ";
    cout << "Enter year of birth: ";
    cin >> birth;
    outputFile << birth << ", ";
    cout << "Enter year of death or -- if alive: ";
    cin.ignore();
    getline(cin,death);
    outputFile << death << ", " << endl;

    outputFile.close();
    cout << "Done!\n";
}

<|endoftext|>


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

#include "kitBase/blocksBase/common/waitForLightSensorBlock.h"

#include "kitBase/robotModel/robotParts/lightSensor.h"

using namespace kitBase;
using namespace blocksBase::common;
using namespace robotModel;

WaitForLightSensorBlock::WaitForLightSensorBlock(kitBase::robotModel::RobotModelInterface &robotModel)
	: WaitForSensorBlock(robotModel)
{
}

void WaitForLightSensorBlock::responseSlot(int reading)
{
	const int result = eval<int>("Percents");
	if (errorsOccured()) {
		processResponce(reading, result);
	}
}

kitBase::robotModel::DeviceInfo WaitForLightSensorBlock::device() const
{
	return DeviceInfo::create<robotParts::LightSensor>();
}
<commit_msg>Fixed wait for light block work [ci skip]<commit_after>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "kitBase/blocksBase/common/waitForLightSensorBlock.h"

#include "kitBase/robotModel/robotParts/lightSensor.h"

using namespace kitBase;
using namespace blocksBase::common;
using namespace robotModel;

WaitForLightSensorBlock::WaitForLightSensorBlock(kitBase::robotModel::RobotModelInterface &robotModel)
	: WaitForSensorBlock(robotModel)
{
}

void WaitForLightSensorBlock::responseSlot(int reading)
{
	const int result = eval<int>("Percents");
	if (!errorsOccured()) {
		processResponce(reading, result);
	}
}

kitBase::robotModel::DeviceInfo WaitForLightSensorBlock::device() const
{
	return DeviceInfo::create<robotParts::LightSensor>();
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2012, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is 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.
*/

/**
 * @file tgBoxAnchorDebugModel.cpp
 * @brief Contains the implementation of class tgBoxAnchorDebugModel.
 * $Id$
 */

// This module
#include "tgBoxAnchorDebugModel.h"
// This library
#include "core/tgBasicActuator.h"
#include "core/tgRod.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgBasicActuatorInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBasicActuator and tgRod for a descripton of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double rodLength;
        double stiffness;
        double damping;
        double friction;
        double rollFriction;
        double restitution;
        double pretension;
        bool   hist;
        double maxTens;
        double targetVelocity;
        bool moveCablePointAToEdge;
        bool moveCablePointBToEdge;
    } c =
   {
     0.688,    // density (kg / length^3)
     3.0,     // radius (length)
     2.0,      // rodLength (length)
     613.0,   // stiffness (kg / sec^2) was 1500
     200.0,    // damping (kg / sec)
     0.99,      // friction (unitless)
     0.01,     // rollFriction (unitless)
     0.0,      // restitution (?)
     200.0,        // pretension -> set to 4 * 613, the previous value of the rest length controller
     0,			// History logging (boolean)
     100000,   // maxTens
     10000,    // targetVelocity
     false,    // moveCablePointAToEdge
     false,     // moveCablePointBToEdge

     // Use the below values for earlier versions of simulation.
     // 1.006,
     // 0.31,
     // 300000.0,
     // 3000.0,
     // 15.0,
     // 7.5,
  };
} // namespace

// Constructor does nothing. Everything happens in setup.
tgBoxAnchorDebugModel::tgBoxAnchorDebugModel() : tgModel()
{
}

// Destructor does nothing. Everythign happens in teardown.
tgBoxAnchorDebugModel::~tgBoxAnchorDebugModel()
{
}

void tgBoxAnchorDebugModel::addNodes(tgStructure& s)
{
  s.addNode(0, 0, 0);            // 0
  s.addNode(0, c.rodLength, 0);            // 1
  s.addNode(0, 2 * c.rodLength, 0);            // 2
  s.addNode(0, 3 * c.rodLength, 0);            // 3
}

void tgBoxAnchorDebugModel::addRods(tgStructure& s)
{
    s.addPair( 0,  1, "rod");
    s.addPair( 2,  3, "rod");
}

//void tgBoxAnchorDebugModel::addActuators(tgStructure& s)
//{
//    s.addPair(1, 2,  "muscle");
//}

void tgBoxAnchorDebugModel::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction,
				c.rollFriction, c.restitution);

    /// @todo acceleration constraint was removed on 12/10/14 Replace with tgKinematicActuator as appropreate
    //tgBasicActuator::Config muscleConfig(c.stiffness, c.damping, c.pretension, remove act
					// c.hist, c.maxTens, c.targetVelocity); remove act
    // Since the boolean flags for moving the anchor attachment points
    // are not next in line in the Config constructor, assign them explicitly
    // after the config struct has been constructed:
    //muscleConfig.moveCablePointAToEdge = c.moveCablePointAToEdge; remove act
   // muscleConfig.moveCablePointBToEdge = c.moveCablePointBToEdge; remove act

    // Start creating the structure
    tgStructure s;
    addNodes(s);

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after addNodes: " <<
      s.getNodes() << std::endl;
    */

    addRods(s);
    //addActuators(s); remove actuators

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after addPairs: " <<
      s.getNodes() << std::endl;
    // Check: did the pairs move?
    std::cout << "Pairs in the structure after addPairs: " << std::endl;
    // need to iterate through the std::vector of tgPair objects
    std::vector<tgPair> pairsAfterAdd = s.getPairs().getPairs();
    for( size_t i = 0; i < pairsAfterAdd.size(); i++ ) {
      // Print the pair.
      std::cout << pairsAfterAdd[i] << ", from and to: " <<
	pairsAfterAdd[i].getFrom() << " , " << pairsAfterAdd[i].getTo() << std::endl;
    }
    */

    // Move the whole structure up a bit.
    s.move(btVector3(0, 5, 0));

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after move: " <<
      s.getNodes() << std::endl;
    // Check: did the pairs move?
    std::cout << "Pairs in the structure after move: " << std::endl;
    // need to iterate through the std::vector of tgPair objects
    std::vector<tgPair> pairsAfterMove = s.getPairs().getPairs();
    for( size_t i = 0; i < pairsAfterMove.size(); i++ ) {
      // Print the pair.
      std::cout << pairsAfterMove[i] << ", from and to: " <<
	pairsAfterMove[i].getFrom() << " , " << pairsAfterMove[i].getTo() <<
	std::endl;
    }
    */

    // Add a rotation. This is needed if the ground slopes too much,
    // otherwise  glitches put a rod below the ground.
    /*btVector3 rotationPoint = btVector3(0, 0, 0); // origin
    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
    double rotationAngle = M_PI/2;
    s.addRotation(rotationPoint, rotationAxis, rotationAngle);
    */

    // Create the build spec that uses tags to turn the structure into a real model
    tgBuildSpec spec;
    spec.addBuilder("rod", new tgRodInfo(rodConfig));
    //spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    //allActuators = tgCast::filter<tgModel, tgBasicActuator> (getDescendants()); remove act

    // call the onSetup methods of all observed things e.g. controllers
    //notifySetup();

    // Actually setup the children
    tgModel::setup(world);
}

void tgBoxAnchorDebugModel::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        // Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void tgBoxAnchorDebugModel::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

//const std::vector<tgBasicActuator*>& tgBoxAnchorDebugModel::getAllActuators() const remove act
//{ remove act
//    return allActuators; remove act
//} remove act

void tgBoxAnchorDebugModel::teardown()
{
    notifyTeardown();
    tgModel::teardown();
}
<commit_msg>Developed box in tg trying to bring it to life in tgWorld<commit_after>/*
 * Copyright © 2012, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is 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.
*/

/**
 * @file tgBoxAnchorDebugModel.cpp
 * @brief Contains the implementation of class tgBoxAnchorDebugModel.
 * $Id$
 */

// This module
#include "tgBoxAnchorDebugModel.h"
// This library
#include "core/tgBasicActuator.h"
#include "core/tgRod.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgBasicActuatorInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBasicActuator and tgRod for a descripton of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double rodLength;
        double stiffness;
        double damping;
        double friction;
        double rollFriction;
        double restitution;
        double pretension;
        bool   hist;
        double maxTens;
        double targetVelocity;
        bool moveCablePointAToEdge;
        bool moveCablePointBToEdge;
    } c =
   {
     0.688,    // density (kg / length^3)
     3.0,     // radius (length)
     2.0,      // rodLength (length)
     613.0,   // stiffness (kg / sec^2) was 1500
     200.0,    // damping (kg / sec)
     0.99,      // friction (unitless)
     0.01,     // rollFriction (unitless)
     0.0,      // restitution (?)
     200.0,        // pretension -> set to 4 * 613, the previous value of the rest length controller
     0,			// History logging (boolean)
     100000,   // maxTens
     10000,    // targetVelocity
     false,    // moveCablePointAToEdge
     false,     // moveCablePointBToEdge

     // Use the below values for earlier versions of simulation.
     // 1.006,
     // 0.31,
     // 300000.0,
     // 3000.0,
     // 15.0,
     // 7.5,
  };
} // namespace

// Constructor does nothing. Everything happens in setup.
tgBoxAnchorDebugModel::tgBoxAnchorDebugModel() : tgModel()
{
}

// Destructor does nothing. Everythign happens in teardown.
tgBoxAnchorDebugModel::~tgBoxAnchorDebugModel()
{
}

void tgBoxAnchorDebugModel::addNodes(tgStructure& s)
{
  s.addNode(0, 0, 0);            // 0
  s.addNode(0, c.rodLength, 0);            // 1
  s.addNode(0, 2 * c.rodLength, 0);            // 2
  s.addNode(0, 3 * c.rodLength, 0);            // 3
}

void tgBoxAnchorDebugModel::addRods(tgStructure& s)
{
    s.addPair( 0,  1, "rod");
    s.addPair( 2,  3, "rod");
}

//void tgBoxAnchorDebugModel::addActuators(tgStructure& s)
//{
//    s.addPair(1, 2,  "muscle");
//}

void tgBoxAnchorDebugModel::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction,
				c.rollFriction, c.restitution);

    /// @todo acceleration constraint was removed on 12/10/14 Replace with tgKinematicActuator as appropreate
    //tgBasicActuator::Config muscleConfig(c.stiffness, c.damping, c.pretension, remove act
					// c.hist, c.maxTens, c.targetVelocity); remove act
    // Since the boolean flags for moving the anchor attachment points
    // are not next in line in the Config constructor, assign them explicitly
    // after the config struct has been constructed:
    //muscleConfig.moveCablePointAToEdge = c.moveCablePointAToEdge; remove act
   // muscleConfig.moveCablePointBToEdge = c.moveCablePointBToEdge; remove act

    // Start creating the structure
    tgStructure s;
    addNodes(s);

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after addNodes: " <<
      s.getNodes() << std::endl;
    */

    addRods(s);
    //addActuators(s); remove actuators

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after addPairs: " <<
      s.getNodes() << std::endl;
    // Check: did the pairs move?
    std::cout << "Pairs in the structure after addPairs: " << std::endl;
    // need to iterate through the std::vector of tgPair objects
    std::vector<tgPair> pairsAfterAdd = s.getPairs().getPairs();
    for( size_t i = 0; i < pairsAfterAdd.size(); i++ ) {
      // Print the pair.
      std::cout << pairsAfterAdd[i] << ", from and to: " <<
	pairsAfterAdd[i].getFrom() << " , " << pairsAfterAdd[i].getTo() << std::endl;
    }
    */

    // Move the whole structure up a bit.
    s.move(btVector3(0, 5, 0));

    /*
    // DEBUGGING
    // Check: did the nodes move?
    std::cout << "Nodes in the structure after move: " <<
      s.getNodes() << std::endl;
    // Check: did the pairs move?
    std::cout << "Pairs in the structure after move: " << std::endl;
    // need to iterate through the std::vector of tgPair objects
    std::vector<tgPair> pairsAfterMove = s.getPairs().getPairs();
    for( size_t i = 0; i < pairsAfterMove.size(); i++ ) {
      // Print the pair.
      std::cout << pairsAfterMove[i] << ", from and to: " <<
	pairsAfterMove[i].getFrom() << " , " << pairsAfterMove[i].getTo() <<
	std::endl;
    }
    */
    btVector3 positions[2] = {
		btVector3(0.8,-2,2),
		btVector3(0.8,2,2)
	};

	   tgBuildSpec spec;
   // spec.addBuilder("rod", new tgRodInfo(rodConfig));

    for( int currentIndex = 0; currentIndex < 1; currentIndex++ )
    {
    btScalar yaw = 1.0;
    btScalar roll = 1.0;
    btScalar pitch = 1.0;

    btBoxShape* box = new btBoxShape( btVector3(yaw, roll, pitch) );

    box->setMargin(0.01);

    btCompoundShape* compound = new btCompoundShape();
    compound->addChildShape(btTransform::getIdentity(),box);

    btVector3 localInertia;
    box->calculateLocalInertia(1, localInertia);

    btRigidBody* body = new btRigidBody(1,0,compound,localInertia);

    btTransform tr;
    tr.setIdentity();
    tr.setOrigin(positions[currentIndex]);
    body->setCenterOfMassTransform(tr);

    body->setAngularVelocity(btVector3(0,0,10));
    body->setLinearVelocity(btVector3(0,.2,0));
    body->setFriction(btSqrt(1));

	tgTags tgObject;

	tgRod* tgRodObject = new tgRod( body, tgObject, 1.0 );

	//spec.addBuilder("rod", new tgRodInfo(  tgRodObject ) );
    }

    // Add a rotation. This is needed if the ground slopes too much,
    // otherwise  glitches put a rod below the ground.
    /*btVector3 rotationPoint = btVector3(0, 0, 0); // origin
    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
    double rotationAngle = M_PI/2;
    s.addRotation(rotationPoint, rotationAxis, rotationAngle);
    */

    // Create the build spec that uses tags to turn the structure into a real model
   // tgBuildSpec spec; WE COMMENT ThIS OUT
    // spec.addBuilder("rod", new tgRodInfo(rodConfig)); THIS TOO
    //spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    //allActuators = tgCast::filter<tgModel, tgBasicActuator> (getDescendants()); remove act

    // call the onSetup methods of all observed things e.g. controllers
    //notifySetup();

    // Actually setup the children
    tgModel::setup(world);
}

void tgBoxAnchorDebugModel::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        // Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void tgBoxAnchorDebugModel::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

//const std::vector<tgBasicActuator*>& tgBoxAnchorDebugModel::getAllActuators() const remove act
//{ remove act
//    return allActuators; remove act
//} remove act

void tgBoxAnchorDebugModel::teardown()
{
    notifyTeardown();
    tgModel::teardown();
}
<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once

#include <boost/filesystem.hpp>
#include <fstream>
#include <stdint.h>

#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/types.hpp>
#include <fc/log/logger.hpp>

namespace eosio {

/*
 *   *.log:
 *   +---------+----------------+-----------+------------------+-----+---------+----------------+
 *   | Entry i | Pos of Entry i | Entry i+1 | Pos of Entry i+1 | ... | Entry z | Pos of Entry z |
 *   +---------+----------------+-----------+------------------+-----+---------+----------------+
 *
 *   *.index:
 *   +-----------+-------------+-----+-----------+
 *   | Summary i | Summary i+1 | ... | Summary z |
 *   +-----------+-------------+-----+-----------+
 *
 * each entry:
 *    uint32_t       block_num
 *    block_id_type  block_id
 *    uint64_t       size of payload
 *    uint8_t        version
 *                   payload
 *
 * each summary:
 *    uint64_t       position of entry in *.log
 *
 * state payload:
 *    uint32_t    size of deltas
 *    char[]      deltas
 */

struct history_log_header {
   uint32_t             block_num = 0;
   chain::block_id_type block_id;
   uint64_t             payload_size = 0;
   uint8_t              version      = 0;
};

struct history_summary {
   uint64_t pos = 0;
};

class history_log {
 private:
   const char* const    name = "";
   std::string          log_filename;
   std::string          index_filename;
   std::fstream         log;
   std::fstream         index;
   uint32_t             _begin_block = 0;
   uint32_t             _end_block   = 0;
   chain::block_id_type last_block_id;

 public:
   history_log(const char* const name, std::string log_filename, std::string index_filename)
       : name(name)
       , log_filename(std::move(log_filename))
       , index_filename(std::move(index_filename)) {
      open_log();
      open_index();
   }

   uint32_t begin_block() const { return _begin_block; }
   uint32_t end_block() const { return _end_block; }

   template <typename F>
   void write_entry(history_log_header header, const chain::block_id_type& prev_id, F write_payload) {
      EOS_ASSERT(_begin_block == _end_block || header.block_num <= _end_block, chain::plugin_exception,
                 "missed a block in ${name}.log", ("name", name));

      if (_begin_block != _end_block && header.block_num > _begin_block) {
         if (header.block_num == _end_block) {
            EOS_ASSERT(prev_id == last_block_id, chain::plugin_exception, "missed a fork change in ${name}.log",
                       ("name", name));
         } else {
            history_log_header prev;
            get_entry(header.block_num - 1, prev);
            EOS_ASSERT(prev_id == prev.block_id, chain::plugin_exception, "missed a fork change in ${name}.log",
                       ("name", name));
         }
      }

      if (header.block_num < _end_block)
         truncate(header.block_num);
      log.seekg(0, std::ios_base::end);
      uint64_t pos = log.tellg();
      log.write((char*)&header, sizeof(header));
      write_payload(log);
      uint64_t end = log.tellg();
      EOS_ASSERT(end == pos + sizeof(header) + header.payload_size, chain::plugin_exception,
                 "wrote payload with incorrect size to ${name}.log", ("name", name));
      log.write((char*)&pos, sizeof(pos));

      index.seekg(0, std::ios_base::end);
      history_summary summary{.pos = pos};
      index.write((char*)&summary, sizeof(summary));
      if (_begin_block == _end_block)
         _begin_block = header.block_num;
      _end_block    = header.block_num + 1;
      last_block_id = header.block_id;
   }

   // returns stream positioned at payload
   std::fstream& get_entry(uint32_t block_num, history_log_header& header) {
      EOS_ASSERT(block_num >= _begin_block && block_num < _end_block, chain::plugin_exception,
                 "read non-existing block in ${name}.log", ("name", name));
      log.seekg(get_pos(block_num));
      log.read((char*)&header, sizeof(header));
      return log;
   }

   chain::block_id_type get_block_id(uint32_t block_num) {
      history_log_header header;
      get_entry(block_num, header);
      return header.block_id;
   }

 private:
   bool get_last_block(uint64_t size) {
      history_log_header header;
      uint64_t           suffix;
      log.seekg(size - sizeof(suffix));
      log.read((char*)&suffix, sizeof(suffix));
      if (suffix > size || suffix + sizeof(header) > size) {
         elog("corrupt ${name}.log (2)", ("name", name));
         return false;
      }
      log.seekg(suffix);
      log.read((char*)&header, sizeof(header));
      if (suffix + sizeof(header) + header.payload_size + sizeof(suffix) != size) {
         elog("corrupt ${name}.log (3)", ("name", name));
         return false;
      }
      _end_block    = header.block_num + 1;
      last_block_id = header.block_id;
      if (_begin_block >= _end_block) {
         elog("corrupt ${name}.log (4)", ("name", name));
         return false;
      }
      return true;
   }

   void recover_blocks(uint64_t size) {
      ilog("recover ${name}.log", ("name", name));
      uint64_t pos       = 0;
      uint32_t num_found = 0;
      while (true) {
         history_log_header header;
         if (pos + sizeof(header) > size)
            break;
         log.seekg(pos);
         log.read((char*)&header, sizeof(header));
         uint64_t suffix;
         if (header.payload_size > size || pos + sizeof(header) + header.payload_size + sizeof(suffix) > size)
            break;
         log.seekg(pos + sizeof(header) + header.payload_size);
         log.read((char*)&suffix, sizeof(suffix));
         if (suffix != pos)
            break;
         pos = pos + sizeof(header) + header.payload_size + sizeof(suffix);
         if (!(++num_found % 10000)) {
            printf("%10u blocks found, log pos=%12llu\r", (unsigned)num_found, (unsigned long long)pos);
            fflush(stdout);
         }
      }
      log.flush();
      boost::filesystem::resize_file(log_filename, pos);
      log.sync();
      EOS_ASSERT(get_last_block(pos), chain::plugin_exception, "recover ${name}.log failed", ("name", name));
   }

   void open_log() {
      log.open(log_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app);
      uint64_t size = log.tellg();
      if (size >= sizeof(history_log_header)) {
         history_log_header header;
         log.seekg(0);
         log.read((char*)&header, sizeof(header));
         EOS_ASSERT(header.version == 0 && sizeof(header) + header.payload_size + sizeof(uint64_t) <= size,
                    chain::plugin_exception, "corrupt ${name}.log (1)", ("name", name));
         _begin_block  = header.block_num;
         last_block_id = header.block_id;
         if (!get_last_block(size))
            recover_blocks(size);
         ilog("${name}.log has blocks ${b}-${e}", ("name", name)("b", _begin_block)("e", _end_block - 1));
      } else {
         EOS_ASSERT(!size, chain::plugin_exception, "corrupt ${name}.log (5)", ("name", name));
         ilog("${name}.log is empty", ("name", name));
      }
   }

   void open_index() {
      index.open(index_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app);
      if (index.tellg() == (_end_block - _begin_block) * sizeof(history_summary))
         return;
      ilog("Regenerate ${name}.index", ("name", name));
      index.close();
      index.open(index_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc);

      log.seekg(0, std::ios_base::end);
      uint64_t size      = log.tellg();
      uint64_t pos       = 0;
      uint32_t num_found = 0;
      while (pos < size) {
         history_log_header header;
         EOS_ASSERT(pos + sizeof(header) <= size, chain::plugin_exception, "corrupt ${name}.log (6)", ("name", name));
         log.seekg(pos);
         log.read((char*)&header, sizeof(header));
         uint64_t suffix_pos = pos + sizeof(header) + header.payload_size;
         uint64_t suffix;
         EOS_ASSERT(suffix_pos + sizeof(suffix) <= size, chain::plugin_exception, "corrupt ${name}.log (7)",
                    ("name", name));
         log.seekg(suffix_pos);
         log.read((char*)&suffix, sizeof(suffix));
         // ilog("block ${b} at ${pos}-${end} suffix=${suffix} file_size=${fs}",
         //      ("b", header.block_num)("pos", pos)("end", suffix_pos + sizeof(suffix))("suffix", suffix)("fs", size));
         EOS_ASSERT(suffix == pos, chain::plugin_exception, "corrupt ${name}.log (8)", ("name", name));

         history_summary summary{.pos = pos};
         index.write((char*)&summary, sizeof(summary));
         pos = suffix_pos + sizeof(suffix);
         if (!(++num_found % 10000)) {
            printf("%10u blocks found, log pos=%12llu\r", (unsigned)num_found, (unsigned long long)pos);
            fflush(stdout);
         }
      }
   }

   uint64_t get_pos(uint32_t block_num) {
      history_summary summary;
      index.seekg((block_num - _begin_block) * sizeof(summary));
      index.read((char*)&summary, sizeof(summary));
      return summary.pos;
   }

   void truncate(uint32_t block_num) {
      log.flush();
      index.flush();
      uint64_t num_removed = 0;
      if (block_num <= _begin_block) {
         num_removed = _end_block - _begin_block;
         log.seekg(0);
         index.seekg(0);
         boost::filesystem::resize_file(log_filename, 0);
         boost::filesystem::resize_file(index_filename, 0);
         _begin_block = _end_block = 0;
      } else {
         num_removed  = _end_block - block_num;
         uint64_t pos = get_pos(block_num);
         log.seekg(0);
         index.seekg(0);
         boost::filesystem::resize_file(log_filename, pos);
         boost::filesystem::resize_file(index_filename, (block_num - _begin_block) * sizeof(history_summary));
         _end_block = block_num;
      }
      log.sync();
      index.sync();
      ilog("fork or replay: removed ${n} blocks from ${name}.log", ("n", num_removed)("name", name));
   }
}; // history_log

} // namespace eosio
<commit_msg>state_history_plugin: ubuntu fixes<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once

#include <boost/filesystem.hpp>
#include <fstream>
#include <stdint.h>

#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/types.hpp>
#include <fc/log/logger.hpp>

namespace eosio {

/*
 *   *.log:
 *   +---------+----------------+-----------+------------------+-----+---------+----------------+
 *   | Entry i | Pos of Entry i | Entry i+1 | Pos of Entry i+1 | ... | Entry z | Pos of Entry z |
 *   +---------+----------------+-----------+------------------+-----+---------+----------------+
 *
 *   *.index:
 *   +-----------+-------------+-----+-----------+
 *   | Summary i | Summary i+1 | ... | Summary z |
 *   +-----------+-------------+-----+-----------+
 *
 * each entry:
 *    uint32_t       block_num
 *    block_id_type  block_id
 *    uint64_t       size of payload
 *    uint8_t        version
 *                   payload
 *
 * each summary:
 *    uint64_t       position of entry in *.log
 *
 * state payload:
 *    uint32_t    size of deltas
 *    char[]      deltas
 */

struct history_log_header {
   uint32_t             block_num = 0;
   chain::block_id_type block_id;
   uint64_t             payload_size = 0;
   uint8_t              version      = 0;
};

struct history_summary {
   uint64_t pos = 0;
};

class history_log {
 private:
   const char* const    name = "";
   std::string          log_filename;
   std::string          index_filename;
   std::fstream         log;
   std::fstream         index;
   uint32_t             _begin_block = 0;
   uint32_t             _end_block   = 0;
   chain::block_id_type last_block_id;

 public:
   history_log(const char* const name, std::string log_filename, std::string index_filename)
       : name(name)
       , log_filename(std::move(log_filename))
       , index_filename(std::move(index_filename)) {
      open_log();
      open_index();
   }

   uint32_t begin_block() const { return _begin_block; }
   uint32_t end_block() const { return _end_block; }

   template <typename F>
   void write_entry(history_log_header header, const chain::block_id_type& prev_id, F write_payload) {
      EOS_ASSERT(_begin_block == _end_block || header.block_num <= _end_block, chain::plugin_exception,
                 "missed a block in ${name}.log", ("name", name));

      if (_begin_block != _end_block && header.block_num > _begin_block) {
         if (header.block_num == _end_block) {
            EOS_ASSERT(prev_id == last_block_id, chain::plugin_exception, "missed a fork change in ${name}.log",
                       ("name", name));
         } else {
            history_log_header prev;
            get_entry(header.block_num - 1, prev);
            EOS_ASSERT(prev_id == prev.block_id, chain::plugin_exception, "missed a fork change in ${name}.log",
                       ("name", name));
         }
      }

      if (header.block_num < _end_block)
         truncate(header.block_num);
      log.seekg(0, std::ios_base::end);
      uint64_t pos = log.tellg();
      log.write((char*)&header, sizeof(header));
      write_payload(log);
      uint64_t end = log.tellg();
      EOS_ASSERT(end == pos + sizeof(header) + header.payload_size, chain::plugin_exception,
                 "wrote payload with incorrect size to ${name}.log", ("name", name));
      log.write((char*)&pos, sizeof(pos));

      index.seekg(0, std::ios_base::end);
      history_summary summary{.pos = pos};
      index.write((char*)&summary, sizeof(summary));
      if (_begin_block == _end_block)
         _begin_block = header.block_num;
      _end_block    = header.block_num + 1;
      last_block_id = header.block_id;
   }

   // returns stream positioned at payload
   std::fstream& get_entry(uint32_t block_num, history_log_header& header) {
      EOS_ASSERT(block_num >= _begin_block && block_num < _end_block, chain::plugin_exception,
                 "read non-existing block in ${name}.log", ("name", name));
      log.seekg(get_pos(block_num));
      log.read((char*)&header, sizeof(header));
      return log;
   }

   chain::block_id_type get_block_id(uint32_t block_num) {
      history_log_header header;
      get_entry(block_num, header);
      return header.block_id;
   }

 private:
   bool get_last_block(uint64_t size) {
      history_log_header header;
      uint64_t           suffix;
      log.seekg(size - sizeof(suffix));
      log.read((char*)&suffix, sizeof(suffix));
      if (suffix > size || suffix + sizeof(header) > size) {
         elog("corrupt ${name}.log (2)", ("name", name));
         return false;
      }
      log.seekg(suffix);
      log.read((char*)&header, sizeof(header));
      if (suffix + sizeof(header) + header.payload_size + sizeof(suffix) != size) {
         elog("corrupt ${name}.log (3)", ("name", name));
         return false;
      }
      _end_block    = header.block_num + 1;
      last_block_id = header.block_id;
      if (_begin_block >= _end_block) {
         elog("corrupt ${name}.log (4)", ("name", name));
         return false;
      }
      return true;
   }

   void recover_blocks(uint64_t size) {
      ilog("recover ${name}.log", ("name", name));
      uint64_t pos       = 0;
      uint32_t num_found = 0;
      while (true) {
         history_log_header header;
         if (pos + sizeof(header) > size)
            break;
         log.seekg(pos);
         log.read((char*)&header, sizeof(header));
         uint64_t suffix;
         if (header.payload_size > size || pos + sizeof(header) + header.payload_size + sizeof(suffix) > size)
            break;
         log.seekg(pos + sizeof(header) + header.payload_size);
         log.read((char*)&suffix, sizeof(suffix));
         if (suffix != pos)
            break;
         pos = pos + sizeof(header) + header.payload_size + sizeof(suffix);
         if (!(++num_found % 10000)) {
            printf("%10u blocks found, log pos=%12llu\r", (unsigned)num_found, (unsigned long long)pos);
            fflush(stdout);
         }
      }
      log.flush();
      boost::filesystem::resize_file(log_filename, pos);
      log.sync();
      EOS_ASSERT(get_last_block(pos), chain::plugin_exception, "recover ${name}.log failed", ("name", name));
   }

   void open_log() {
      log.open(log_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app);
      log.seekg(0, std::ios_base::end);
      uint64_t size = log.tellg();
      if (size >= sizeof(history_log_header)) {
         history_log_header header;
         log.seekg(0);
         log.read((char*)&header, sizeof(header));
         EOS_ASSERT(header.version == 0 && sizeof(header) + header.payload_size + sizeof(uint64_t) <= size,
                    chain::plugin_exception, "corrupt ${name}.log (1)", ("name", name));
         _begin_block  = header.block_num;
         last_block_id = header.block_id;
         if (!get_last_block(size))
            recover_blocks(size);
         ilog("${name}.log has blocks ${b}-${e}", ("name", name)("b", _begin_block)("e", _end_block - 1));
      } else {
         EOS_ASSERT(!size, chain::plugin_exception, "corrupt ${name}.log (5)", ("name", name));
         ilog("${name}.log is empty", ("name", name));
      }
   }

   void open_index() {
      index.open(index_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app);
      index.seekg(0, std::ios_base::end);
      if (index.tellg() == (_end_block - _begin_block) * sizeof(history_summary))
         return;
      ilog("Regenerate ${name}.index", ("name", name));
      index.close();
      index.open(index_filename, std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc);

      log.seekg(0, std::ios_base::end);
      uint64_t size      = log.tellg();
      uint64_t pos       = 0;
      uint32_t num_found = 0;
      while (pos < size) {
         history_log_header header;
         EOS_ASSERT(pos + sizeof(header) <= size, chain::plugin_exception, "corrupt ${name}.log (6)", ("name", name));
         log.seekg(pos);
         log.read((char*)&header, sizeof(header));
         uint64_t suffix_pos = pos + sizeof(header) + header.payload_size;
         uint64_t suffix;
         EOS_ASSERT(suffix_pos + sizeof(suffix) <= size, chain::plugin_exception, "corrupt ${name}.log (7)",
                    ("name", name));
         log.seekg(suffix_pos);
         log.read((char*)&suffix, sizeof(suffix));
         // ilog("block ${b} at ${pos}-${end} suffix=${suffix} file_size=${fs}",
         //      ("b", header.block_num)("pos", pos)("end", suffix_pos + sizeof(suffix))("suffix", suffix)("fs", size));
         EOS_ASSERT(suffix == pos, chain::plugin_exception, "corrupt ${name}.log (8)", ("name", name));

         history_summary summary{.pos = pos};
         index.write((char*)&summary, sizeof(summary));
         pos = suffix_pos + sizeof(suffix);
         if (!(++num_found % 10000)) {
            printf("%10u blocks found, log pos=%12llu\r", (unsigned)num_found, (unsigned long long)pos);
            fflush(stdout);
         }
      }
   }

   uint64_t get_pos(uint32_t block_num) {
      history_summary summary;
      index.seekg((block_num - _begin_block) * sizeof(summary));
      index.read((char*)&summary, sizeof(summary));
      return summary.pos;
   }

   void truncate(uint32_t block_num) {
      log.flush();
      index.flush();
      uint64_t num_removed = 0;
      if (block_num <= _begin_block) {
         num_removed = _end_block - _begin_block;
         log.seekg(0);
         index.seekg(0);
         boost::filesystem::resize_file(log_filename, 0);
         boost::filesystem::resize_file(index_filename, 0);
         _begin_block = _end_block = 0;
      } else {
         num_removed  = _end_block - block_num;
         uint64_t pos = get_pos(block_num);
         log.seekg(0);
         index.seekg(0);
         boost::filesystem::resize_file(log_filename, pos);
         boost::filesystem::resize_file(index_filename, (block_num - _begin_block) * sizeof(history_summary));
         _end_block = block_num;
      }
      log.sync();
      index.sync();
      ilog("fork or replay: removed ${n} blocks from ${name}.log", ("n", num_removed)("name", name));
   }
}; // history_log

} // namespace eosio
<|endoftext|>


<commit_before>/*
 * copyright: (c) RDO-Team, 2011
 * filename : update_i.inl
 * author   :
 * date     : 24.01.2011
 * bref     :
 * indent   : 4T
 */

// ====================================================================== INCLUDES
// ====================================================================== SYNOPSIS
// ===============================================================================

OPEN_RDO_CONVERTER_NAMESPACE

// ----------------------------------------------------------------------------
// ---------- IDocUpdate::Position
// ----------------------------------------------------------------------------
inline IDocUpdate::Position::Position(ruint pos)
	: m_position(pos)
{}

inline IDocUpdate::Position::Position(CREF(Position) pos)
	: m_position(pos.m_position)
{}

inline ruint IDocUpdate::Position::get() const
{
	return m_position;
}

inline rbool IDocUpdate::Position::begin() const
{
	return m_position == POSITION_BEGIN;
}

inline rbool IDocUpdate::Position::end() const
{
	return m_position == POSITION_END;
}

inline rbool IDocUpdate::Position::real() const
{
	return m_position != POSITION_BEGIN && m_position != POSITION_END;
}

inline void IDocUpdate::Position::operator+= (CREF(Position) pos)
{
	if (real() && pos.real())
	{
		m_position += pos.m_position;
	}
}

inline void IDocUpdate::Position::operator-= (CREF(Position) pos)
{
	if (real() && pos.real())
	{
		m_position -= pos.m_position;
	}
}

inline IDocUpdate::Position IDocUpdate::Position::operator+ (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return Position(m_position + pos.m_position);
	}

	NEVER_REACH_HERE;
	return Position(0);
}

inline IDocUpdate::Position IDocUpdate::Position::operator- (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return Position(m_position - pos.m_position);
	}

	NEVER_REACH_HERE;
	return Position(0);
}

inline rbool IDocUpdate::Position::operator<= (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return m_position <= pos.m_position;
	}

	if (begin())
	{
		return true;
	}
	else if (end())
	{
		return pos.end() ? true : false;
	}

	NEVER_REACH_HERE;
	return false;
}

inline rbool IDocUpdate::Position::operator>= (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return m_position >= pos.m_position;
	}

	if (begin())
	{
		return pos.begin() ? true : false;
	}
	else if (end())
	{
		return true;
	}

	NEVER_REACH_HERE;
	return false;
}

inline rbool IDocUpdate::Position::operator< (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return m_position < pos.m_position;
	}

	if (begin())
	{
		return pos.begin() ? false : true;
	}
	else if (end())
	{
		return false;
	}

	NEVER_REACH_HERE;
	return false;
}

inline rbool IDocUpdate::Position::operator> (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return m_position > pos.m_position;
	}

	if (begin())
	{
		return false;
	}
	else if (end())
	{
		return pos.end() ? false : true;
	}

	NEVER_REACH_HERE;
	return false;
}

inline rbool IDocUpdate::Position::operator== (CREF(Position) pos) const
{
	return m_position == pos.m_position;
}

inline rbool IDocUpdate::Position::operator!= (CREF(Position) pos) const
{
	return !operator==(pos);
}

CLOSE_RDO_CONVERTER_NAMESPACE
<commit_msg> - обработаны состояния при сравнении<commit_after>/*
 * copyright: (c) RDO-Team, 2011
 * filename : update_i.inl
 * author   :
 * date     : 24.01.2011
 * bref     :
 * indent   : 4T
 */

// ====================================================================== INCLUDES
// ====================================================================== SYNOPSIS
// ===============================================================================

OPEN_RDO_CONVERTER_NAMESPACE

// ----------------------------------------------------------------------------
// ---------- IDocUpdate::Position
// ----------------------------------------------------------------------------
inline IDocUpdate::Position::Position(ruint pos)
	: m_position(pos)
{}

inline IDocUpdate::Position::Position(CREF(Position) pos)
	: m_position(pos.m_position)
{}

inline ruint IDocUpdate::Position::get() const
{
	return m_position;
}

inline rbool IDocUpdate::Position::begin() const
{
	return m_position == POSITION_BEGIN;
}

inline rbool IDocUpdate::Position::end() const
{
	return m_position == POSITION_END;
}

inline rbool IDocUpdate::Position::real() const
{
	return m_position != POSITION_BEGIN && m_position != POSITION_END;
}

inline void IDocUpdate::Position::operator+= (CREF(Position) pos)
{
	if (real() && pos.real())
	{
		m_position += pos.m_position;
	}
}

inline void IDocUpdate::Position::operator-= (CREF(Position) pos)
{
	if (real() && pos.real())
	{
		m_position -= pos.m_position;
	}
}

inline IDocUpdate::Position IDocUpdate::Position::operator+ (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return Position(m_position + pos.m_position);
	}

	NEVER_REACH_HERE;
	return Position(0);
}

inline IDocUpdate::Position IDocUpdate::Position::operator- (CREF(Position) pos) const
{
	if (real() && pos.real())
	{
		return Position(m_position - pos.m_position);
	}

	NEVER_REACH_HERE;
	return Position(0);
}

inline rbool IDocUpdate::Position::operator<= (CREF(Position) pos) const
{
	switch(get())
	{
	case POSITION_BEGIN: return true;
	case POSITION_END  : return pos.end() ? true : false;
	default            : switch (pos.get())
	                     {
	                     case POSITION_BEGIN: return false;
	                     case POSITION_END  : return true;
	                     default            : return m_position <= pos.m_position;
	                     }
	}
}

inline rbool IDocUpdate::Position::operator>= (CREF(Position) pos) const
{
	switch(get())
	{
	case POSITION_BEGIN: return pos.begin() ? true : false;
	case POSITION_END  : return true;
	default            : switch (pos.get())
	                     {
	                     case POSITION_BEGIN: return true;
	                     case POSITION_END  : return false;
	                     default            : return m_position >= pos.m_position;
	                     }
	}
}

inline rbool IDocUpdate::Position::operator< (CREF(Position) pos) const
{
	switch(get())
	{
	case POSITION_BEGIN: return pos.begin() ? false : true;
	case POSITION_END  : NEVER_REACH_HERE; return false;
	default            : switch (pos.get())
	                     {
	                     case POSITION_BEGIN: return false;
	                     case POSITION_END  : return true;
	                     default            : return m_position < pos.m_position;
	                     }
	}
}

inline rbool IDocUpdate::Position::operator> (CREF(Position) pos) const
{
	switch(get())
	{
	case POSITION_BEGIN: NEVER_REACH_HERE; return false;
	case POSITION_END  : return pos.end() ? false : true;
	default            : switch (pos.get())
	                     {
	                     case POSITION_BEGIN: return true;
	                     case POSITION_END  : return false;
	                     default            : return m_position > pos.m_position;
	                     }
	}
}

inline rbool IDocUpdate::Position::operator== (CREF(Position) pos) const
{
	return m_position == pos.m_position;
}

inline rbool IDocUpdate::Position::operator!= (CREF(Position) pos) const
{
	return !operator==(pos);
}

CLOSE_RDO_CONVERTER_NAMESPACE
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3DEngine.hpp>
# include <Window/IWindow.hpp>
# include <Siv3D/EngineLog.hpp>
# include "CMouse.hpp"

namespace s3d
{
	CMouse::CMouse()
	{

	}

	CMouse::~CMouse()
	{
		LOG_TRACE(U"CMouse::~CMouse()");
	}

	void CMouse::init()
	{
		LOG_TRACE(U"CMouse::init()");

		m_glfwWindow = static_cast<GLFWwindow*>(Siv3DEngine::Get<ISiv3DWindow>()->getHandle());

		m_buttonsInternal.fill(MouseButtonState::Released);

		::glfwSetScrollCallback(m_glfwWindow, OnScroll);

		::glfwSetMouseButtonCallback(m_glfwWindow, OnMouseButtonUpdated);

		LOG_INFO(U"ℹ CMouse initialized");
	}

	void CMouse::update()
	{
		{
			std::lock_guard<std::mutex> lock(m_buttonMutex);

			for (uint32 i = 0; i < MouseButtonCount; ++i)
			{
				auto& state = m_buttonsInternal[i];

				const bool pressed = (state == MouseButtonState::Pressed) || (state == MouseButtonState::Tapped);

				m_states[i].update(pressed);

				if (state == MouseButtonState::Tapped)
				{
					state = MouseButtonState::Released;
				}
			}
		}

		{
			std::lock_guard<std::mutex> lock(m_scrollMutex);

			m_scroll = m_scrollInternal;

			m_scrollInternal.set(0.0, 0.0);
		}
	}

	bool CMouse::down(const uint32 index) const
	{
		return m_states[index].down;
	}

	bool CMouse::pressed(const uint32 index) const
	{
		return m_states[index].pressed;
	}

	bool CMouse::up(const uint32 index) const
	{
		return m_states[index].up;
	}

	Duration CMouse::pressedDuration(const uint32 index) const
	{
		return m_states[index]._pressedDuration;
	}

	const Vec2& CMouse::wheel() const
	{
		return m_scroll;
	}

	void CMouse::onScroll(const double v, const double h)
	{
		std::lock_guard lock(m_scrollMutex);

		m_scrollInternal.moveBy(h, v);
	}

	void CMouse::onMouseButtonUpdated(const int32 index, const bool pressed)
	{
		std::lock_guard<std::mutex> lock(m_buttonMutex);

		auto& state = m_buttonsInternal[index];

		if(state == MouseButtonState::Released)
		{
			if(pressed)
			{
				state = MouseButtonState::Pressed;
			}
		}
		else if(state == MouseButtonState::Pressed)
		{
			if(!pressed)
			{
				state = MouseButtonState::Tapped;
			}
		}
		else
		{
			if(pressed)
			{
				state = MouseButtonState::Pressed;
			}
		}
	}

	void CMouse::OnScroll(GLFWwindow*, const double h, const double v)
	{
		Siv3DEngine::Get<ISiv3DMouse>()->onScroll(h, -v);
	}

	void CMouse::OnMouseButtonUpdated(GLFWwindow*, const int button, const int action, int)
	{
		Siv3DEngine::Get<ISiv3DMouse>()->onMouseButtonUpdated(button, (action == GLFW_PRESS));
	}
}
<commit_msg>マウスホイール修正 (mac)<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3DEngine.hpp>
# include <Window/IWindow.hpp>
# include <Siv3D/EngineLog.hpp>
# include "CMouse.hpp"

namespace s3d
{
	CMouse::CMouse()
	{

	}

	CMouse::~CMouse()
	{
		LOG_TRACE(U"CMouse::~CMouse()");
	}

	void CMouse::init()
	{
		LOG_TRACE(U"CMouse::init()");

		m_glfwWindow = static_cast<GLFWwindow*>(Siv3DEngine::Get<ISiv3DWindow>()->getHandle());

		m_buttonsInternal.fill(MouseButtonState::Released);

		::glfwSetScrollCallback(m_glfwWindow, OnScroll);

		::glfwSetMouseButtonCallback(m_glfwWindow, OnMouseButtonUpdated);

		LOG_INFO(U"ℹ CMouse initialized");
	}

	void CMouse::update()
	{
		{
			std::lock_guard<std::mutex> lock(m_buttonMutex);

			for (uint32 i = 0; i < MouseButtonCount; ++i)
			{
				auto& state = m_buttonsInternal[i];

				const bool pressed = (state == MouseButtonState::Pressed) || (state == MouseButtonState::Tapped);

				m_states[i].update(pressed);

				if (state == MouseButtonState::Tapped)
				{
					state = MouseButtonState::Released;
				}
			}
		}

		{
			std::lock_guard<std::mutex> lock(m_scrollMutex);

			m_scroll = m_scrollInternal;

			m_scrollInternal.set(0.0, 0.0);
		}
	}

	bool CMouse::down(const uint32 index) const
	{
		return m_states[index].down;
	}

	bool CMouse::pressed(const uint32 index) const
	{
		return m_states[index].pressed;
	}

	bool CMouse::up(const uint32 index) const
	{
		return m_states[index].up;
	}

	Duration CMouse::pressedDuration(const uint32 index) const
	{
		return m_states[index]._pressedDuration;
	}

	const Vec2& CMouse::wheel() const
	{
		return m_scroll;
	}

	void CMouse::onScroll(const double v, const double h)
	{
		std::lock_guard lock(m_scrollMutex);

		m_scrollInternal.moveBy(v, h);
	}

	void CMouse::onMouseButtonUpdated(const int32 index, const bool pressed)
	{
		std::lock_guard<std::mutex> lock(m_buttonMutex);

		auto& state = m_buttonsInternal[index];

		if(state == MouseButtonState::Released)
		{
			if(pressed)
			{
				state = MouseButtonState::Pressed;
			}
		}
		else if(state == MouseButtonState::Pressed)
		{
			if(!pressed)
			{
				state = MouseButtonState::Tapped;
			}
		}
		else
		{
			if(pressed)
			{
				state = MouseButtonState::Pressed;
			}
		}
	}

	void CMouse::OnScroll(GLFWwindow*, const double h, const double v)
	{
		Siv3DEngine::Get<ISiv3DMouse>()->onScroll(h, -v);
	}

	void CMouse::OnMouseButtonUpdated(GLFWwindow*, const int button, const int action, int)
	{
		Siv3DEngine::Get<ISiv3DMouse>()->onMouseButtonUpdated(button, (action == GLFW_PRESS));
	}
}
<|endoftext|>


<commit_before>//===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine tests ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "gtest/gtest.h"
#include <stdlib.h>
#include <string>

using namespace llvm;

namespace {

class TempEnvVar {
 public:
  TempEnvVar(const char *name, const char *value)
      : name(name) {
    const char *old_value = getenv(name);
    EXPECT_EQ(NULL, old_value) << old_value;
#if HAVE_SETENV
    setenv(name, value, true);
#else
#   define SKIP_ENVIRONMENT_TESTS
#endif
  }

  ~TempEnvVar() {
#if HAVE_SETENV
    // Assume setenv and unsetenv come together.
    unsetenv(name);
#endif
  }

 private:
  const char *const name;
};

template <typename T>
class StackOption : public cl::opt<T> {
  using Base = cl::opt<T>;
public:
  // One option...
  template<class M0t>
  explicit StackOption(const M0t &M0) : Base(M0) {}

  // Two options...
  template<class M0t, class M1t>
  StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {}

  // Three options...
  template<class M0t, class M1t, class M2t>
  StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {}

  // Four options...
  template<class M0t, class M1t, class M2t, class M3t>
  StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
    : Base(M0, M1, M2, M3) {}

  ~StackOption() {
    this->removeArgument();
  }
};

cl::OptionCategory TestCategory("Test Options", "Description");
cl::opt<int> TestOption("test-option", cl::desc("old description"));
TEST(CommandLineTest, ModifyExisitingOption) {
  const char Description[] = "New description";
  const char ArgString[] = "new-test-option";
  const char ValueString[] = "Integer";

  StringMap<cl::Option*> Map;
  cl::getRegisteredOptions(Map);

  ASSERT_TRUE(Map.count("test-option") == 1) <<
    "Could not find option in map.";

  cl::Option *Retrieved = Map["test-option"];
  ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";

  ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
    "Incorrect default option category.";

  Retrieved->setCategory(TestCategory);
  ASSERT_EQ(&TestCategory,Retrieved->Category) <<
    "Failed to modify option's option category.";

  Retrieved->setDescription(Description);
  ASSERT_STREQ(Retrieved->HelpStr, Description) <<
    "Changing option description failed.";

  Retrieved->setArgStr(ArgString);
  ASSERT_STREQ(ArgString, Retrieved->ArgStr) <<
    "Failed to modify option's Argument string.";

  Retrieved->setValueStr(ValueString);
  ASSERT_STREQ(Retrieved->ValueStr, ValueString) <<
    "Failed to modify option's Value string.";

  Retrieved->setHiddenFlag(cl::Hidden);
  ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
    "Failed to modify option's hidden flag.";
}
#ifndef SKIP_ENVIRONMENT_TESTS

const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS";

cl::opt<std::string> EnvironmentTestOption("env-test-opt");
TEST(CommandLineTest, ParseEnvironment) {
  TempEnvVar TEV(test_env_var, "-env-test-opt=hello");
  EXPECT_EQ("", EnvironmentTestOption);
  cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  EXPECT_EQ("hello", EnvironmentTestOption);
}

// This test used to make valgrind complain
// ("Conditional jump or move depends on uninitialised value(s)")
//
// Warning: Do not run any tests after this one that try to gain access to
// registered command line options because this will likely result in a
// SEGFAULT. This can occur because the cl::opt in the test below is declared
// on the stack which will be destroyed after the test completes but the
// command line system will still hold a pointer to a deallocated cl::Option.
TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
  // Put cl::opt on stack to check for proper initialization of fields.
  StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
  TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
  EXPECT_EQ("", EnvironmentTestOptionLocal);
  cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  EXPECT_EQ("hello-local", EnvironmentTestOptionLocal);
}

#endif  // SKIP_ENVIRONMENT_TESTS

TEST(CommandLineTest, UseOptionCategory) {
  StackOption<int> TestOption2("test-option", cl::cat(TestCategory));

  ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
                                                  "Category.";
}

class StrDupSaver : public cl::StringSaver {
  const char *SaveString(const char *Str) LLVM_OVERRIDE {
    return strdup(Str);
  }
};

typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver,
                            SmallVectorImpl<const char *> &NewArgv);

void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
                              const char *const Output[], size_t OutputSize) {
  SmallVector<const char *, 0> Actual;
  StrDupSaver Saver;
  parse(Input, Saver, Actual);
  EXPECT_EQ(OutputSize, Actual.size());
  for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
    if (I < OutputSize)
      EXPECT_STREQ(Output[I], Actual[I]);
    free(const_cast<char *>(Actual[I]));
  }
}

TEST(CommandLineTest, TokenizeGNUCommandLine) {
  const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' "
                      "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\"";
  const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar",
                                 "foobarbaz", "C:\\src\\foo.cpp",
                                 "C:\\src\\foo.cpp" };
  testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
                           array_lengthof(Output));
}

TEST(CommandLineTest, TokenizeWindowsCommandLine) {
  const char *Input = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
                      "\"st \\\"u\" \\v";
  const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
                                 "lmn", "o", "pqr", "st \"u", "\\v" };
  testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
                           array_lengthof(Output));
}

TEST(CommandLineTest, AliasesWithArguments) {
  static const size_t ARGC = 3;
  const char *const Inputs[][ARGC] = {
    { "-tool", "-actual=x", "-extra" },
    { "-tool", "-actual", "x" },
    { "-tool", "-alias=x", "-extra" },
    { "-tool", "-alias", "x" }
  };

  for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
    StackOption<std::string> Actual("actual");
    StackOption<bool> Extra("extra");
    StackOption<std::string> Input(cl::Positional);

    cl::alias Alias("alias", llvm::cl::aliasopt(Actual));

    cl::ParseCommandLineOptions(ARGC, Inputs[i]);
    EXPECT_EQ("x", Actual);
    EXPECT_EQ(0, Input.getNumOccurrences());

    Alias.removeArgument();
  }
}

}  // anonymous namespace
<commit_msg>Remove C++11ism from r200407.<commit_after>//===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine tests ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "gtest/gtest.h"
#include <stdlib.h>
#include <string>

using namespace llvm;

namespace {

class TempEnvVar {
 public:
  TempEnvVar(const char *name, const char *value)
      : name(name) {
    const char *old_value = getenv(name);
    EXPECT_EQ(NULL, old_value) << old_value;
#if HAVE_SETENV
    setenv(name, value, true);
#else
#   define SKIP_ENVIRONMENT_TESTS
#endif
  }

  ~TempEnvVar() {
#if HAVE_SETENV
    // Assume setenv and unsetenv come together.
    unsetenv(name);
#endif
  }

 private:
  const char *const name;
};

template <typename T>
class StackOption : public cl::opt<T> {
  typedef cl::opt<T> Base;
public:
  // One option...
  template<class M0t>
  explicit StackOption(const M0t &M0) : Base(M0) {}

  // Two options...
  template<class M0t, class M1t>
  StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {}

  // Three options...
  template<class M0t, class M1t, class M2t>
  StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {}

  // Four options...
  template<class M0t, class M1t, class M2t, class M3t>
  StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
    : Base(M0, M1, M2, M3) {}

  ~StackOption() {
    this->removeArgument();
  }
};

cl::OptionCategory TestCategory("Test Options", "Description");
cl::opt<int> TestOption("test-option", cl::desc("old description"));
TEST(CommandLineTest, ModifyExisitingOption) {
  const char Description[] = "New description";
  const char ArgString[] = "new-test-option";
  const char ValueString[] = "Integer";

  StringMap<cl::Option*> Map;
  cl::getRegisteredOptions(Map);

  ASSERT_TRUE(Map.count("test-option") == 1) <<
    "Could not find option in map.";

  cl::Option *Retrieved = Map["test-option"];
  ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";

  ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
    "Incorrect default option category.";

  Retrieved->setCategory(TestCategory);
  ASSERT_EQ(&TestCategory,Retrieved->Category) <<
    "Failed to modify option's option category.";

  Retrieved->setDescription(Description);
  ASSERT_STREQ(Retrieved->HelpStr, Description) <<
    "Changing option description failed.";

  Retrieved->setArgStr(ArgString);
  ASSERT_STREQ(ArgString, Retrieved->ArgStr) <<
    "Failed to modify option's Argument string.";

  Retrieved->setValueStr(ValueString);
  ASSERT_STREQ(Retrieved->ValueStr, ValueString) <<
    "Failed to modify option's Value string.";

  Retrieved->setHiddenFlag(cl::Hidden);
  ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
    "Failed to modify option's hidden flag.";
}
#ifndef SKIP_ENVIRONMENT_TESTS

const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS";

cl::opt<std::string> EnvironmentTestOption("env-test-opt");
TEST(CommandLineTest, ParseEnvironment) {
  TempEnvVar TEV(test_env_var, "-env-test-opt=hello");
  EXPECT_EQ("", EnvironmentTestOption);
  cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  EXPECT_EQ("hello", EnvironmentTestOption);
}

// This test used to make valgrind complain
// ("Conditional jump or move depends on uninitialised value(s)")
//
// Warning: Do not run any tests after this one that try to gain access to
// registered command line options because this will likely result in a
// SEGFAULT. This can occur because the cl::opt in the test below is declared
// on the stack which will be destroyed after the test completes but the
// command line system will still hold a pointer to a deallocated cl::Option.
TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
  // Put cl::opt on stack to check for proper initialization of fields.
  StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
  TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
  EXPECT_EQ("", EnvironmentTestOptionLocal);
  cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  EXPECT_EQ("hello-local", EnvironmentTestOptionLocal);
}

#endif  // SKIP_ENVIRONMENT_TESTS

TEST(CommandLineTest, UseOptionCategory) {
  StackOption<int> TestOption2("test-option", cl::cat(TestCategory));

  ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
                                                  "Category.";
}

class StrDupSaver : public cl::StringSaver {
  const char *SaveString(const char *Str) LLVM_OVERRIDE {
    return strdup(Str);
  }
};

typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver,
                            SmallVectorImpl<const char *> &NewArgv);

void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
                              const char *const Output[], size_t OutputSize) {
  SmallVector<const char *, 0> Actual;
  StrDupSaver Saver;
  parse(Input, Saver, Actual);
  EXPECT_EQ(OutputSize, Actual.size());
  for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
    if (I < OutputSize)
      EXPECT_STREQ(Output[I], Actual[I]);
    free(const_cast<char *>(Actual[I]));
  }
}

TEST(CommandLineTest, TokenizeGNUCommandLine) {
  const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' "
                      "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\"";
  const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar",
                                 "foobarbaz", "C:\\src\\foo.cpp",
                                 "C:\\src\\foo.cpp" };
  testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
                           array_lengthof(Output));
}

TEST(CommandLineTest, TokenizeWindowsCommandLine) {
  const char *Input = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
                      "\"st \\\"u\" \\v";
  const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
                                 "lmn", "o", "pqr", "st \"u", "\\v" };
  testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
                           array_lengthof(Output));
}

TEST(CommandLineTest, AliasesWithArguments) {
  static const size_t ARGC = 3;
  const char *const Inputs[][ARGC] = {
    { "-tool", "-actual=x", "-extra" },
    { "-tool", "-actual", "x" },
    { "-tool", "-alias=x", "-extra" },
    { "-tool", "-alias", "x" }
  };

  for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
    StackOption<std::string> Actual("actual");
    StackOption<bool> Extra("extra");
    StackOption<std::string> Input(cl::Positional);

    cl::alias Alias("alias", llvm::cl::aliasopt(Actual));

    cl::ParseCommandLineOptions(ARGC, Inputs[i]);
    EXPECT_EQ("x", Actual);
    EXPECT_EQ(0, Input.getNumOccurrences());

    Alias.removeArgument();
  }
}

}  // anonymous namespace
<|endoftext|>


<commit_before><commit_msg>Unit test for https://bugs.webkit.org/show_bug.cgi?id=30262<commit_after><|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <unsupported/Eigen/Polynomials>
#include <iostream>
#include <algorithm>

using namespace std;

namespace Eigen {
namespace internal {
template<int Size>
struct increment_if_fixed_size
{
  enum {
    ret = (Size == Dynamic) ? Dynamic : Size+1
  };
};
}
}

template<int Deg, typename POLYNOMIAL, typename SOLVER>
bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
{
  typedef typename POLYNOMIAL::Index Index;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef typename SOLVER::RootsType    RootsType;
  typedef Matrix<Scalar,Deg,1>          EvalRootsType;

  const Index deg = pols.size()-1;

  psolve.compute( pols );
  const RootsType& roots( psolve.roots() );
  EvalRootsType evr( deg );
  for( int i=0; i<roots.size(); ++i ){
    evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }

  bool evalToZero = evr.isZero( test_precision<Scalar>() );
  if( !evalToZero )
  {
    cerr << "WRONG root: " << endl;
    cerr << "Polynomial: " << pols.transpose() << endl;
    cerr << "Roots found: " << roots.transpose() << endl;
    cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
    cerr << endl;
  }

  std::vector<Scalar> rootModuli( roots.size() );
  Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
  aux = roots.array().abs();
  std::sort( rootModuli.begin(), rootModuli.end() );
  bool distinctModuli=true;
  for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
  {
    if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
      distinctModuli = false; }
  }
  VERIFY( evalToZero || !distinctModuli );

  return distinctModuli;
}

template<int Deg, typename POLYNOMIAL>
void evalSolver( const POLYNOMIAL& pols )
{
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
}

template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
{
  using std::sqrt;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
  {
    //It is supposed that
    // 1) the roots found are correct
    // 2) the roots have distinct moduli

    typedef typename POLYNOMIAL::Scalar                 Scalar;
    typedef typename REAL_ROOTS::Scalar                 Real;

    //Test realRoots
    std::vector< Real > calc_realRoots;
    psolve.realRoots( calc_realRoots );
    VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );

    const Scalar psPrec = sqrt( test_precision<Scalar>() );

    for( size_t i=0; i<calc_realRoots.size(); ++i )
    {
      bool found = false;
      for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
      {
        if( internal::isApprox( calc_realRoots[i], real_roots[j], psPrec ) ){
          found = true; }
      }
      VERIFY( found );
    }

    //Test greatestRoot
    VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
          abs( psolve.greatestRoot() ), psPrec ) );

    //Test smallestRoot
    VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
          abs( psolve.smallestRoot() ), psPrec ) );

    bool hasRealRoot;
    //Test absGreatestRealRoot
    Real r = psolve.absGreatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) );  }

    //Test absSmallestRealRoot
    r = psolve.absSmallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }

    //Test greatestRealRoot
    r = psolve.greatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }

    //Test smallestRealRoot
    r = psolve.smallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
    VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
  }
}

template<typename _Scalar, int _Deg>
void polynomialsolver(int deg)
{
  typedef internal::increment_if_fixed_size<_Deg>            Dim;
  typedef Matrix<_Scalar,Dim::ret,1>                  PolynomialType;
  typedef Matrix<_Scalar,_Deg,1>                      EvalRootsType;

  cout << "Standard cases" << endl;
  PolynomialType pols = PolynomialType::Random(deg+1);
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Hard cases" << endl;
  _Scalar multipleRoot = internal::random<_Scalar>();
  EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
  roots_to_monicPolynomial( allRoots, pols );
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Test sugar" << endl;
  EvalRootsType realRoots = EvalRootsType::Random(deg);
  roots_to_monicPolynomial( realRoots, pols );
  evalSolverSugarFunction<_Deg>(
      pols,
      realRoots.template cast <
                    std::complex<
                         typename NumTraits<_Scalar>::Real
                         >
                    >(),
      realRoots );
}

void test_polynomialsolver()
{
  for(int i = 0; i < g_repeat; i++)
  {
    CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
    CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
    CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
    CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
    CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
    CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
    CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
    CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );

    CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_11((polynomialsolver<float,Dynamic>(1)) );
  }
}
<commit_msg>PolynomialSolver: test template constructor in test suite.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <unsupported/Eigen/Polynomials>
#include <iostream>
#include <algorithm>

using namespace std;

namespace Eigen {
namespace internal {
template<int Size>
struct increment_if_fixed_size
{
  enum {
    ret = (Size == Dynamic) ? Dynamic : Size+1
  };
};
}
}

template<int Deg, typename POLYNOMIAL, typename SOLVER>
bool aux_evalSolver( const POLYNOMIAL& pols, SOLVER& psolve )
{
  typedef typename POLYNOMIAL::Index Index;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef typename SOLVER::RootsType    RootsType;
  typedef Matrix<Scalar,Deg,1>          EvalRootsType;

  const Index deg = pols.size()-1;

  // Test template constructor from coefficient vector
  SOLVER solve_constr (pols);

  psolve.compute( pols );
  const RootsType& roots( psolve.roots() );
  EvalRootsType evr( deg );
  for( int i=0; i<roots.size(); ++i ){
    evr[i] = std::abs( poly_eval( pols, roots[i] ) ); }

  bool evalToZero = evr.isZero( test_precision<Scalar>() );
  if( !evalToZero )
  {
    cerr << "WRONG root: " << endl;
    cerr << "Polynomial: " << pols.transpose() << endl;
    cerr << "Roots found: " << roots.transpose() << endl;
    cerr << "Abs value of the polynomial at the roots: " << evr.transpose() << endl;
    cerr << endl;
  }

  std::vector<Scalar> rootModuli( roots.size() );
  Map< EvalRootsType > aux( &rootModuli[0], roots.size() );
  aux = roots.array().abs();
  std::sort( rootModuli.begin(), rootModuli.end() );
  bool distinctModuli=true;
  for( size_t i=1; i<rootModuli.size() && distinctModuli; ++i )
  {
    if( internal::isApprox( rootModuli[i], rootModuli[i-1] ) ){
      distinctModuli = false; }
  }
  VERIFY( evalToZero || !distinctModuli );

  return distinctModuli;
}

template<int Deg, typename POLYNOMIAL>
void evalSolver( const POLYNOMIAL& pols )
{
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve );
}

template< int Deg, typename POLYNOMIAL, typename ROOTS, typename REAL_ROOTS >
void evalSolverSugarFunction( const POLYNOMIAL& pols, const ROOTS& roots, const REAL_ROOTS& real_roots )
{
  using std::sqrt;
  typedef typename POLYNOMIAL::Scalar Scalar;

  typedef PolynomialSolver<Scalar, Deg >              PolynomialSolverType;

  PolynomialSolverType psolve;
  if( aux_evalSolver<Deg, POLYNOMIAL, PolynomialSolverType>( pols, psolve ) )
  {
    //It is supposed that
    // 1) the roots found are correct
    // 2) the roots have distinct moduli

    typedef typename POLYNOMIAL::Scalar                 Scalar;
    typedef typename REAL_ROOTS::Scalar                 Real;

    //Test realRoots
    std::vector< Real > calc_realRoots;
    psolve.realRoots( calc_realRoots );
    VERIFY( calc_realRoots.size() == (size_t)real_roots.size() );

    const Scalar psPrec = sqrt( test_precision<Scalar>() );

    for( size_t i=0; i<calc_realRoots.size(); ++i )
    {
      bool found = false;
      for( size_t j=0; j<calc_realRoots.size()&& !found; ++j )
      {
        if( internal::isApprox( calc_realRoots[i], real_roots[j], psPrec ) ){
          found = true; }
      }
      VERIFY( found );
    }

    //Test greatestRoot
    VERIFY( internal::isApprox( roots.array().abs().maxCoeff(),
          abs( psolve.greatestRoot() ), psPrec ) );

    //Test smallestRoot
    VERIFY( internal::isApprox( roots.array().abs().minCoeff(),
          abs( psolve.smallestRoot() ), psPrec ) );

    bool hasRealRoot;
    //Test absGreatestRealRoot
    Real r = psolve.absGreatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().maxCoeff(), abs(r), psPrec ) );  }

    //Test absSmallestRealRoot
    r = psolve.absSmallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().abs().minCoeff(), abs( r ), psPrec ) ); }

    //Test greatestRealRoot
    r = psolve.greatestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
      VERIFY( internal::isApprox( real_roots.array().maxCoeff(), r, psPrec ) ); }

    //Test smallestRealRoot
    r = psolve.smallestRealRoot( hasRealRoot );
    VERIFY( hasRealRoot == (real_roots.size() > 0 ) );
    if( hasRealRoot ){
    VERIFY( internal::isApprox( real_roots.array().minCoeff(), r, psPrec ) ); }
  }
}

template<typename _Scalar, int _Deg>
void polynomialsolver(int deg)
{
  typedef internal::increment_if_fixed_size<_Deg>            Dim;
  typedef Matrix<_Scalar,Dim::ret,1>                  PolynomialType;
  typedef Matrix<_Scalar,_Deg,1>                      EvalRootsType;

  cout << "Standard cases" << endl;
  PolynomialType pols = PolynomialType::Random(deg+1);
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Hard cases" << endl;
  _Scalar multipleRoot = internal::random<_Scalar>();
  EvalRootsType allRoots = EvalRootsType::Constant(deg,multipleRoot);
  roots_to_monicPolynomial( allRoots, pols );
  evalSolver<_Deg,PolynomialType>( pols );

  cout << "Test sugar" << endl;
  EvalRootsType realRoots = EvalRootsType::Random(deg);
  roots_to_monicPolynomial( realRoots, pols );
  evalSolverSugarFunction<_Deg>(
      pols,
      realRoots.template cast <
                    std::complex<
                         typename NumTraits<_Scalar>::Real
                         >
                    >(),
      realRoots );
}

void test_polynomialsolver()
{
  for(int i = 0; i < g_repeat; i++)
  {
    CALL_SUBTEST_1( (polynomialsolver<float,1>(1)) );
    CALL_SUBTEST_2( (polynomialsolver<double,2>(2)) );
    CALL_SUBTEST_3( (polynomialsolver<double,3>(3)) );
    CALL_SUBTEST_4( (polynomialsolver<float,4>(4)) );
    CALL_SUBTEST_5( (polynomialsolver<double,5>(5)) );
    CALL_SUBTEST_6( (polynomialsolver<float,6>(6)) );
    CALL_SUBTEST_7( (polynomialsolver<float,7>(7)) );
    CALL_SUBTEST_8( (polynomialsolver<double,8>(8)) );

    CALL_SUBTEST_9( (polynomialsolver<float,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_10((polynomialsolver<double,Dynamic>(
            internal::random<int>(9,13)
            )) );
    CALL_SUBTEST_11((polynomialsolver<float,Dynamic>(1)) );
  }
}
<|endoftext|>