<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Asher Elmquist, Rainer Gericke
// =============================================================================
//
// Sample test program for sequential lmtv 2.5 ton simulation. It demonstrates
// chassis torsion due to random wheel excitation.
//
// The vehicle reference frame has Z up, X towards the front of the vehicle, and
// Y pointing to the left.
// All units SI.
//
// =============================================================================

#define USE_IRRLICHT

#include "chrono_vehicle/ChConfigVehicle.h"
#include "chrono_vehicle/ChVehicleModelData.h"
#include "chrono_vehicle/terrain/RigidTerrain.h"
#ifdef USE_IRRLICHT
#include "chrono_vehicle/driver/ChIrrGuiDriver.h"
#include "chrono_vehicle/wheeled_vehicle/utils/ChWheeledVehicleIrrApp.h"
#endif
#include "chrono_vehicle/driver/ChPathFollowerDriver.h"
#include "chrono/utils/ChUtilsInputOutput.h"

#include "chrono_models/vehicle/mtv/LMTV.h"

#include "chrono_thirdparty/filesystem/path.h"

#include <chrono>
#include <thread>
#include <math.h>

using namespace chrono;
using namespace chrono::vehicle;
using namespace chrono::vehicle::mtv;

// =============================================================================

// Initial vehicle location and orientation
ChVector<> initLoc(0, 0, 1.0);
ChQuaternion<> initRot(1, 0, 0, 0);

// Visualization type for vehicle parts (PRIMITIVES, MESH, or NONE)
VisualizationType chassis_vis_type = VisualizationType::MESH;
VisualizationType suspension_vis_type = VisualizationType::PRIMITIVES;
VisualizationType steering_vis_type = VisualizationType::PRIMITIVES;
VisualizationType wheel_vis_type = VisualizationType::MESH;
VisualizationType tire_vis_type = VisualizationType::MESH;

// Type of tire model (RIGID, TMEASY)
TireModelType tire_model = TireModelType::TMEASY;

// Point on chassis tracked by the camera
ChVector<> trackPoint(0.0, 0.0, 1.75);

ChVector<> vehCOM(-1.933, 0.014, 0.495);

// Simulation step sizes
double step_size = 1e-3;
double tire_step_size = step_size;

// Simulation end time
double tend = 60;

// Time interval between two render frames
double render_step_size = 1.0 / 50;  // FPS = 50
double output_step_size = 1e-2;

// vehicle driver inputs
// Desired vehicle speed (m/s)
double mph_to_ms = 0.44704;
double target_speed = 5 * mph_to_ms;

// output directory
const std::string out_dir = "../LMTV_QUALITY";
const std::string pov_dir = out_dir + "/POVRAY";
bool povray_output = false;
bool data_output = true;

std::string path_file("paths/straightOrigin.txt");
std::string steering_controller_file("mtv/SteeringController.json");
std::string speed_controller_file("mtv/SpeedController.json");

std::string rnd_1("terrain/meshes/uneven_300m_6m_10mm.obj");
std::string rnd_2("terrain/meshes/uneven_300m_6m_20mm.obj");
std::string rnd_3("terrain/meshes/uneven_300m_6m_30mm.obj");
std::string rnd_4("terrain/meshes/uneven_300m_6m_40mm.obj");

std::string output_file_name("quality");

std::string terrainFile = rnd_1;

// =============================================================================

int main(int argc, char* argv[]) {
    int terrainCode = 1;
    // read in argument as simulation duration
    switch (argc) {
        default:
        case 1:
            target_speed = 5;
            break;
        case 2:
            target_speed = atof(argv[1]);
            break;
        case 3:
            target_speed = atof(argv[1]);
            terrainCode = atoi(argv[2]);
            break;
    }
    switch (terrainCode) {
        case 1:
            terrainFile = rnd_1;
            break;
        case 2:
            terrainFile = rnd_2;
            break;
        case 3:
            terrainFile = rnd_3;
            break;
        case 4:
            terrainFile = rnd_4;
            break;
        default:
            std::cout << "Invalid Terrain Code - (1-4)";
    }

    output_file_name += "_" + std::to_string((int)target_speed);
    output_file_name += "_" + std::to_string((int)terrainCode);
    target_speed = target_speed * mph_to_ms;

    // --------------
    // Create systems
    // --------------

    // Create the vehicle, set parameters, and initialize
    LMTV lmtv;
    lmtv.SetContactMethod(ChContactMethod::NSC);
    lmtv.SetChassisFixed(false);
    lmtv.SetInitPosition(ChCoordsys<>(initLoc, initRot));
    lmtv.SetTireType(tire_model);
    lmtv.SetTireStepSize(tire_step_size);
    lmtv.Initialize();

    lmtv.SetChassisVisualizationType(chassis_vis_type);
    lmtv.SetSuspensionVisualizationType(suspension_vis_type);
    lmtv.SetSteeringVisualizationType(steering_vis_type);
    lmtv.SetWheelVisualizationType(wheel_vis_type);
    lmtv.SetTireVisualizationType(tire_vis_type);

    std::cout << "Vehicle mass:               " << lmtv.GetVehicle().GetVehicleMass() << std::endl;
    std::cout << "Vehicle mass (with tires):  " << lmtv.GetTotalMass() << std::endl;

    // ------------------
    // Create the terrain
    // ------------------
    double swept_radius = 0.01;

    auto patch_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
    patch_mat->SetFriction(0.9f);
    patch_mat->SetRestitution(0.01f);
    RigidTerrain terrain(lmtv.GetSystem());
    auto patch = terrain.AddPatch(patch_mat, CSYSNORM, vehicle::GetDataFile(terrainFile), "test_mesh", swept_radius);
    patch->SetColor(ChColor(0.8f, 0.8f, 0.5f));
    patch->SetTexture(vehicle::GetDataFile("terrain/textures/dirt.jpg"), 12, 12);
    terrain.Initialize();

    // create the driver
    auto path = ChBezierCurve::read(vehicle::GetDataFile(path_file));
    ChPathFollowerDriver driver(lmtv.GetVehicle(), vehicle::GetDataFile(steering_controller_file),
                                vehicle::GetDataFile(speed_controller_file), path, "my_path", target_speed, false);
    driver.Initialize();

    // -------------------------------------
    // Create the vehicle Irrlicht interface
    // Create the driver system
    // -------------------------------------

#ifdef USE_IRRLICHT
    ChWheeledVehicleIrrApp app(&lmtv.GetVehicle(), L"LMTV ride & twist test");
    app.SetSkyBox();
    app.AddTypicalLights(irr::core::vector3df(30.f, -30.f, 100.f), irr::core::vector3df(30.f, 50.f, 100.f), 250, 130);
    app.SetChaseCamera(trackPoint, 6.0, 0.5);
    /*app.SetTimestep(step_size);*/
    app.AssetBindAll();
    app.AssetUpdateAll();

    // Visualization of controller points (sentinel & target)
    irr::scene::IMeshSceneNode* ballS = app.GetSceneManager()->addSphereSceneNode(0.1f);
    irr::scene::IMeshSceneNode* ballT = app.GetSceneManager()->addSphereSceneNode(0.1f);
    ballS->getMaterial(0).EmissiveColor = irr::video::SColor(0, 255, 0, 0);
    ballT->getMaterial(0).EmissiveColor = irr::video::SColor(0, 0, 255, 0);

#endif

    // -------------
    // Prepare output
    // -------------

    if (data_output || povray_output) {
        if (!filesystem::create_directory(filesystem::path(out_dir))) {
            std::cout << "Error creating directory " << out_dir << std::endl;
            return 1;
        }
    }
    if (povray_output) {
        if (!filesystem::create_directory(filesystem::path(pov_dir))) {
            std::cout << "Error creating directory " << pov_dir << std::endl;
            return 1;
        }
        driver.ExportPathPovray(out_dir);
    }

    utils::CSV_writer csv("\t");
    csv.stream().setf(std::ios::scientific | std::ios::showpos);
    csv.stream().precision(6);

    // Number of simulation steps between two 3D view render frames
    int render_steps = (int)std::ceil(render_step_size / step_size);

    // Number of simulation steps between two output frames
    int output_steps = (int)std::ceil(output_step_size / step_size);

    csv << "time";
    csv << "throttle";
    csv << "MotorSpeed";
    csv << "CurrentTransmissionGear";
    for (int i = 0; i < 4; i++) {
        csv << "WheelTorque";
    }
    for (int i = 0; i < 4; i++) {
        csv << "WheelAngVelX";
        csv << "WheelAngVelY";
        csv << "WheelAngVelZ";
    }
    csv << "VehicleSpeed";
    csv << "VehicleDriverAccelerationX";
    csv << "VehicleDriverAccelerationY";
    csv << "VehicleDriverAccelerationZ";

    csv << "VehicleCOMAccelerationX";
    csv << "VehicleCOMAccelerationY";
    csv << "VehicleCOMAccelerationZ";

    for (int i = 0; i < 4; i++) {
        csv << "TireForce";
    }
    csv << "EngineTorque";

    csv << "W0 Pos x"
        << "W0 Pos Y"
        << "W0 Pos Z"
        << "W1 Pos x"
        << "W1 Pos Y"
        << "W1 Pos Z";
    csv << "W2 Pos x"
        << "W2 Pos Y"
        << "W2 Pos Z"
        << "W3 Pos x"
        << "W3 Pos Y"
        << "W3 Pos Z";

    for (auto& axle : lmtv.GetVehicle().GetAxles()) {
        for (auto& wheel : axle->GetWheels()) {
            csv << wheel->GetPos();
        }
    }

    csv << std::endl;

    // ---------------
    // Simulation loop
    // ---------------

    std::cout << "data at: " << vehicle::GetDataFile(steering_controller_file) << std::endl;
    std::cout << "data at: " << vehicle::GetDataFile(speed_controller_file) << std::endl;
    std::cout << "data at: " << vehicle::GetDataFile(path_file) << std::endl;

    int step_number = 0;
    int render_frame = 0;

    double time = 0;

#ifdef USE_IRRLICHT
    while (app.GetDevice()->run() && (time < tend)) {
#else
    while (time < tend) {
#endif
        time = lmtv.GetSystem()->GetChTime();

#ifdef USE_IRRLICHT
        // path visualization
        const ChVector<>& pS = driver.GetSteeringController().GetSentinelLocation();
        const ChVector<>& pT = driver.GetSteeringController().GetTargetLocation();
        ballS->setPosition(irr::core::vector3df((irr::f32)pS.x(), (irr::f32)pS.y(), (irr::f32)pS.z()));
        ballT->setPosition(irr::core::vector3df((irr::f32)pT.x(), (irr::f32)pT.y(), (irr::f32)pT.z()));

        // std::cout<<"Target:\t"<<(irr::f32)pT.x()<<",\t "<<(irr::f32)pT.y()<<",\t "<<(irr::f32)pT.z()<<std::endl;
        // std::cout<<"Vehicle:\t"<<lmtv.GetVehicle().GetChassisBody()->GetPos().x()
        //   <<",\t "<<lmtv.GetVehicle().GetChassisBody()->GetPos().y()<<",\t "
        //   <<lmtv.GetVehicle().GetChassisBody()->GetPos().z()<<std::endl;

        // Render scene
        if (step_number % render_steps == 0) {
            app.BeginScene(true, true, irr::video::SColor(255, 140, 161, 192));
            app.DrawAll();
            app.EndScene();
        }

#endif

        if (povray_output && step_number % render_steps == 0) {
            char filename[100];
            sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
            utils::WriteShapesPovray(lmtv.GetSystem(), filename);
            render_frame++;
        }

        // Driver inputs
        ChDriver::Inputs driver_inputs = driver.GetInputs();

        // Update modules (process inputs from other modules)
        driver.Synchronize(time);
        terrain.Synchronize(time);
        lmtv.Synchronize(time, driver_inputs, terrain);

#ifdef USE_IRRLICHT
        app.Synchronize("Follower driver", driver_inputs);
#endif

        // Advance simulation for one timestep for all modules

        driver.Advance(step_size);
        terrain.Advance(step_size);
        lmtv.Advance(step_size);

#ifdef USE_IRRLICHT
        app.Advance(step_size);
#endif

        if (data_output && step_number % output_steps == 0) {
            // std::cout << time << std::endl;
            csv << time;
            csv << driver_inputs.m_throttle;
            csv << lmtv.GetVehicle().GetPowertrain()->GetMotorSpeed();
            csv << lmtv.GetVehicle().GetPowertrain()->GetCurrentTransmissionGear();
            for (int axle = 0; axle < 2; axle++) {
                csv << lmtv.GetVehicle().GetDriveline()->GetSpindleTorque(axle, LEFT);
                csv << lmtv.GetVehicle().GetDriveline()->GetSpindleTorque(axle, RIGHT);
            }
            for (int axle = 0; axle < 2; axle++) {
                csv << lmtv.GetVehicle().GetSpindleAngVel(axle, LEFT);
                csv << lmtv.GetVehicle().GetSpindleAngVel(axle, RIGHT);
            }
            csv << lmtv.GetVehicle().GetVehicleSpeed();
            csv << lmtv.GetVehicle().GetVehicleAcceleration(
                lmtv.GetVehicle().GetChassis()->GetLocalDriverCoordsys().pos);

            csv << lmtv.GetVehicle().GetVehicleAcceleration(vehCOM);

            for (auto& axle : lmtv.GetVehicle().GetAxles()) {
                for (auto& wheel : axle->GetWheels()) {
                    csv << wheel->GetTire()->ReportTireForce(&terrain).force;
                }
            }

            csv << lmtv.GetVehicle().GetPowertrain()->GetMotorTorque();

            csv << std::endl;
        }

        // Increment frame number
        step_number++;
    }

    if (data_output) {
        csv.write_to_file(out_dir + "/" + output_file_name + ".dat");
    }

    return 0;
}
<commit_msg>Fix output path for LMTV vehicle demo<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Asher Elmquist, Rainer Gericke
// =============================================================================
//
// Sample test program for sequential lmtv 2.5 ton simulation. It demonstrates
// chassis torsion due to random wheel excitation.
//
// The vehicle reference frame has Z up, X towards the front of the vehicle, and
// Y pointing to the left.
// All units SI.
//
// =============================================================================

#define USE_IRRLICHT

#include "chrono_vehicle/ChConfigVehicle.h"
#include "chrono_vehicle/ChVehicleModelData.h"
#include "chrono_vehicle/terrain/RigidTerrain.h"
#ifdef USE_IRRLICHT
#include "chrono_vehicle/driver/ChIrrGuiDriver.h"
#include "chrono_vehicle/wheeled_vehicle/utils/ChWheeledVehicleIrrApp.h"
#endif
#include "chrono_vehicle/driver/ChPathFollowerDriver.h"
#include "chrono/utils/ChUtilsInputOutput.h"

#include "chrono_models/vehicle/mtv/LMTV.h"

#include "chrono_thirdparty/filesystem/path.h"

#include <chrono>
#include <thread>
#include <math.h>

using namespace chrono;
using namespace chrono::vehicle;
using namespace chrono::vehicle::mtv;

// =============================================================================

// Initial vehicle location and orientation
ChVector<> initLoc(0, 0, 1.0);
ChQuaternion<> initRot(1, 0, 0, 0);

// Visualization type for vehicle parts (PRIMITIVES, MESH, or NONE)
VisualizationType chassis_vis_type = VisualizationType::MESH;
VisualizationType suspension_vis_type = VisualizationType::PRIMITIVES;
VisualizationType steering_vis_type = VisualizationType::PRIMITIVES;
VisualizationType wheel_vis_type = VisualizationType::MESH;
VisualizationType tire_vis_type = VisualizationType::MESH;

// Type of tire model (RIGID, TMEASY)
TireModelType tire_model = TireModelType::TMEASY;

// Point on chassis tracked by the camera
ChVector<> trackPoint(0.0, 0.0, 1.75);

ChVector<> vehCOM(-1.933, 0.014, 0.495);

// Simulation step sizes
double step_size = 1e-3;
double tire_step_size = step_size;

// Simulation end time
double tend = 60;

// Time interval between two render frames
double render_step_size = 1.0 / 50;  // FPS = 50
double output_step_size = 1e-2;

// vehicle driver inputs
// Desired vehicle speed (m/s)
double mph_to_ms = 0.44704;
double target_speed = 5 * mph_to_ms;

// output directory
const std::string out_dir = GetChronoOutputPath() + "LMTV_QUALITY";
const std::string pov_dir = out_dir + "/POVRAY";
bool povray_output = false;
bool data_output = true;

std::string path_file("paths/straightOrigin.txt");
std::string steering_controller_file("mtv/SteeringController.json");
std::string speed_controller_file("mtv/SpeedController.json");

std::string rnd_1("terrain/meshes/uneven_300m_6m_10mm.obj");
std::string rnd_2("terrain/meshes/uneven_300m_6m_20mm.obj");
std::string rnd_3("terrain/meshes/uneven_300m_6m_30mm.obj");
std::string rnd_4("terrain/meshes/uneven_300m_6m_40mm.obj");

std::string output_file_name("quality");

std::string terrainFile = rnd_1;

// =============================================================================

int main(int argc, char* argv[]) {
    int terrainCode = 1;
    // read in argument as simulation duration
    switch (argc) {
        default:
        case 1:
            target_speed = 5;
            break;
        case 2:
            target_speed = atof(argv[1]);
            break;
        case 3:
            target_speed = atof(argv[1]);
            terrainCode = atoi(argv[2]);
            break;
    }
    switch (terrainCode) {
        case 1:
            terrainFile = rnd_1;
            break;
        case 2:
            terrainFile = rnd_2;
            break;
        case 3:
            terrainFile = rnd_3;
            break;
        case 4:
            terrainFile = rnd_4;
            break;
        default:
            std::cout << "Invalid Terrain Code - (1-4)";
    }

    output_file_name += "_" + std::to_string((int)target_speed);
    output_file_name += "_" + std::to_string((int)terrainCode);
    target_speed = target_speed * mph_to_ms;

    // --------------
    // Create systems
    // --------------

    // Create the vehicle, set parameters, and initialize
    LMTV lmtv;
    lmtv.SetContactMethod(ChContactMethod::NSC);
    lmtv.SetChassisFixed(false);
    lmtv.SetInitPosition(ChCoordsys<>(initLoc, initRot));
    lmtv.SetTireType(tire_model);
    lmtv.SetTireStepSize(tire_step_size);
    lmtv.Initialize();

    lmtv.SetChassisVisualizationType(chassis_vis_type);
    lmtv.SetSuspensionVisualizationType(suspension_vis_type);
    lmtv.SetSteeringVisualizationType(steering_vis_type);
    lmtv.SetWheelVisualizationType(wheel_vis_type);
    lmtv.SetTireVisualizationType(tire_vis_type);

    std::cout << "Vehicle mass:               " << lmtv.GetVehicle().GetVehicleMass() << std::endl;
    std::cout << "Vehicle mass (with tires):  " << lmtv.GetTotalMass() << std::endl;

    // ------------------
    // Create the terrain
    // ------------------
    double swept_radius = 0.01;

    auto patch_mat = chrono_types::make_shared<ChMaterialSurfaceNSC>();
    patch_mat->SetFriction(0.9f);
    patch_mat->SetRestitution(0.01f);
    RigidTerrain terrain(lmtv.GetSystem());
    auto patch = terrain.AddPatch(patch_mat, CSYSNORM, vehicle::GetDataFile(terrainFile), "test_mesh", swept_radius);
    patch->SetColor(ChColor(0.8f, 0.8f, 0.5f));
    patch->SetTexture(vehicle::GetDataFile("terrain/textures/dirt.jpg"), 12, 12);
    terrain.Initialize();

    // create the driver
    auto path = ChBezierCurve::read(vehicle::GetDataFile(path_file));
    ChPathFollowerDriver driver(lmtv.GetVehicle(), vehicle::GetDataFile(steering_controller_file),
                                vehicle::GetDataFile(speed_controller_file), path, "my_path", target_speed, false);
    driver.Initialize();

    // -------------------------------------
    // Create the vehicle Irrlicht interface
    // Create the driver system
    // -------------------------------------

#ifdef USE_IRRLICHT
    ChWheeledVehicleIrrApp app(&lmtv.GetVehicle(), L"LMTV ride & twist test");
    app.SetSkyBox();
    app.AddTypicalLights(irr::core::vector3df(30.f, -30.f, 100.f), irr::core::vector3df(30.f, 50.f, 100.f), 250, 130);
    app.SetChaseCamera(trackPoint, 6.0, 0.5);
    /*app.SetTimestep(step_size);*/
    app.AssetBindAll();
    app.AssetUpdateAll();

    // Visualization of controller points (sentinel & target)
    irr::scene::IMeshSceneNode* ballS = app.GetSceneManager()->addSphereSceneNode(0.1f);
    irr::scene::IMeshSceneNode* ballT = app.GetSceneManager()->addSphereSceneNode(0.1f);
    ballS->getMaterial(0).EmissiveColor = irr::video::SColor(0, 255, 0, 0);
    ballT->getMaterial(0).EmissiveColor = irr::video::SColor(0, 0, 255, 0);

#endif

    // -------------
    // Prepare output
    // -------------

    if (data_output || povray_output) {
        if (!filesystem::create_directory(filesystem::path(out_dir))) {
            std::cout << "Error creating directory " << out_dir << std::endl;
            return 1;
        }
    }
    if (povray_output) {
        if (!filesystem::create_directory(filesystem::path(pov_dir))) {
            std::cout << "Error creating directory " << pov_dir << std::endl;
            return 1;
        }
        driver.ExportPathPovray(out_dir);
    }

    utils::CSV_writer csv("\t");
    csv.stream().setf(std::ios::scientific | std::ios::showpos);
    csv.stream().precision(6);

    // Number of simulation steps between two 3D view render frames
    int render_steps = (int)std::ceil(render_step_size / step_size);

    // Number of simulation steps between two output frames
    int output_steps = (int)std::ceil(output_step_size / step_size);

    csv << "time";
    csv << "throttle";
    csv << "MotorSpeed";
    csv << "CurrentTransmissionGear";
    for (int i = 0; i < 4; i++) {
        csv << "WheelTorque";
    }
    for (int i = 0; i < 4; i++) {
        csv << "WheelAngVelX";
        csv << "WheelAngVelY";
        csv << "WheelAngVelZ";
    }
    csv << "VehicleSpeed";
    csv << "VehicleDriverAccelerationX";
    csv << "VehicleDriverAccelerationY";
    csv << "VehicleDriverAccelerationZ";

    csv << "VehicleCOMAccelerationX";
    csv << "VehicleCOMAccelerationY";
    csv << "VehicleCOMAccelerationZ";

    for (int i = 0; i < 4; i++) {
        csv << "TireForce";
    }
    csv << "EngineTorque";

    csv << "W0 Pos x"
        << "W0 Pos Y"
        << "W0 Pos Z"
        << "W1 Pos x"
        << "W1 Pos Y"
        << "W1 Pos Z";
    csv << "W2 Pos x"
        << "W2 Pos Y"
        << "W2 Pos Z"
        << "W3 Pos x"
        << "W3 Pos Y"
        << "W3 Pos Z";

    for (auto& axle : lmtv.GetVehicle().GetAxles()) {
        for (auto& wheel : axle->GetWheels()) {
            csv << wheel->GetPos();
        }
    }

    csv << std::endl;

    // ---------------
    // Simulation loop
    // ---------------

    std::cout << "data at: " << vehicle::GetDataFile(steering_controller_file) << std::endl;
    std::cout << "data at: " << vehicle::GetDataFile(speed_controller_file) << std::endl;
    std::cout << "data at: " << vehicle::GetDataFile(path_file) << std::endl;

    int step_number = 0;
    int render_frame = 0;

    double time = 0;

#ifdef USE_IRRLICHT
    while (app.GetDevice()->run() && (time < tend)) {
#else
    while (time < tend) {
#endif
        time = lmtv.GetSystem()->GetChTime();

#ifdef USE_IRRLICHT
        // path visualization
        const ChVector<>& pS = driver.GetSteeringController().GetSentinelLocation();
        const ChVector<>& pT = driver.GetSteeringController().GetTargetLocation();
        ballS->setPosition(irr::core::vector3df((irr::f32)pS.x(), (irr::f32)pS.y(), (irr::f32)pS.z()));
        ballT->setPosition(irr::core::vector3df((irr::f32)pT.x(), (irr::f32)pT.y(), (irr::f32)pT.z()));

        // std::cout<<"Target:\t"<<(irr::f32)pT.x()<<",\t "<<(irr::f32)pT.y()<<",\t "<<(irr::f32)pT.z()<<std::endl;
        // std::cout<<"Vehicle:\t"<<lmtv.GetVehicle().GetChassisBody()->GetPos().x()
        //   <<",\t "<<lmtv.GetVehicle().GetChassisBody()->GetPos().y()<<",\t "
        //   <<lmtv.GetVehicle().GetChassisBody()->GetPos().z()<<std::endl;

        // Render scene
        if (step_number % render_steps == 0) {
            app.BeginScene(true, true, irr::video::SColor(255, 140, 161, 192));
            app.DrawAll();
            app.EndScene();
        }

#endif

        if (povray_output && step_number % render_steps == 0) {
            char filename[100];
            sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
            utils::WriteShapesPovray(lmtv.GetSystem(), filename);
            render_frame++;
        }

        // Driver inputs
        ChDriver::Inputs driver_inputs = driver.GetInputs();

        // Update modules (process inputs from other modules)
        driver.Synchronize(time);
        terrain.Synchronize(time);
        lmtv.Synchronize(time, driver_inputs, terrain);

#ifdef USE_IRRLICHT
        app.Synchronize("Follower driver", driver_inputs);
#endif

        // Advance simulation for one timestep for all modules

        driver.Advance(step_size);
        terrain.Advance(step_size);
        lmtv.Advance(step_size);

#ifdef USE_IRRLICHT
        app.Advance(step_size);
#endif

        if (data_output && step_number % output_steps == 0) {
            // std::cout << time << std::endl;
            csv << time;
            csv << driver_inputs.m_throttle;
            csv << lmtv.GetVehicle().GetPowertrain()->GetMotorSpeed();
            csv << lmtv.GetVehicle().GetPowertrain()->GetCurrentTransmissionGear();
            for (int axle = 0; axle < 2; axle++) {
                csv << lmtv.GetVehicle().GetDriveline()->GetSpindleTorque(axle, LEFT);
                csv << lmtv.GetVehicle().GetDriveline()->GetSpindleTorque(axle, RIGHT);
            }
            for (int axle = 0; axle < 2; axle++) {
                csv << lmtv.GetVehicle().GetSpindleAngVel(axle, LEFT);
                csv << lmtv.GetVehicle().GetSpindleAngVel(axle, RIGHT);
            }
            csv << lmtv.GetVehicle().GetVehicleSpeed();
            csv << lmtv.GetVehicle().GetVehicleAcceleration(
                lmtv.GetVehicle().GetChassis()->GetLocalDriverCoordsys().pos);

            csv << lmtv.GetVehicle().GetVehicleAcceleration(vehCOM);

            for (auto& axle : lmtv.GetVehicle().GetAxles()) {
                for (auto& wheel : axle->GetWheels()) {
                    csv << wheel->GetTire()->ReportTireForce(&terrain).force;
                }
            }

            csv << lmtv.GetVehicle().GetPowertrain()->GetMotorTorque();

            csv << std::endl;
        }

        // Increment frame number
        step_number++;
    }

    if (data_output) {
        csv.write_to_file(out_dir + "/" + output_file_name + ".dat");
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef MEMORY_ARENA_HPP
#define MEMORY_ARENA_HPP

#include <cstdint>
#include <cstdlib>
#include <utility>
#include <vector>
#include "slice.hpp"

/**
 * A memory arena.
 */
template <size_t MIN_CHUNK_SIZE=4096>
class MemoryArena
{
	struct Chunk {
		size_t size = 0;
		size_t used = 0;
		char* data = nullptr;
	};

	std::vector<Chunk> chunks;

	void add_chunk(size_t size) {
		Chunk c;
		c.size = size;
		if (size > 0) {
			c.data = new char[size];
		}
		chunks.push_back(c);
	}

	void clear_chunks() {
		for (auto& c: chunks) {
			if (c.data != nullptr)
				delete[] c.data;
		}
		chunks.clear();
	}

	/**
	 * Allocates enough contiguous space for count items of type T, and
	 * returns a pointer to the front of that space.
	 */
	template <typename T>
	T* _alloc(size_t count) {
		// Figure out how much padding we need between elements for proper
		// memory alignment if we put them in an array.
		const auto array_pad = (alignof(T) - (sizeof(T) % alignof(T))) % alignof(T);

		// Total needed bytes for the requested array of data
		const auto needed_bytes = (sizeof(T) * count) + (array_pad * (count - 1));

		// Figure out how much padding we need at the beginning to put the
		// first element in the right place for memory alignment.
		const auto mem_addr = (uintptr_t)(chunks.back().data + chunks.back().used);
		const auto begin_pad = (alignof(T) - (mem_addr % alignof(T))) % alignof(T);

		// Get the number of bytes left in the current chunk
		const auto available_bytes = chunks.back().size - chunks.back().used;

		// If we don't have enough space in this chunk, then we need to create
		// a new chunk.
		if ((begin_pad + needed_bytes) > available_bytes) {
			// Calculate the minimum needed bytes to guarantee that we can
			// accommodate properlyaligned data.
			const auto min_needed_bytes = needed_bytes + alignof(T);

			// Make sure we don't get a chunk smaller than MIN_CHUNK_SIZE
			const size_t new_chunk_size = min_needed_bytes > MIN_CHUNK_SIZE ? min_needed_bytes : MIN_CHUNK_SIZE;

			// Create the new chunk, and then recurse for DRY purposes.
			// TODO: if we break things up differently, we could perhaps
			// avoid the redundant work caused by recursing while still
			// being DRY.  Super low priority, though, unless this somehow
			// turns out to be a performance bottleneck.
			add_chunk(new_chunk_size);
			return _alloc<T>(count);
		}

		// Otherwise, proceed in getting the pointer and recording how much
		// of the chunk we used.
		T* ptr = reinterpret_cast<T*>(chunks.back().data + chunks.back().used + begin_pad);
		for (int i=0; i < count; ++i) {
			new(ptr+i) T();
		}
		chunks.back().used += begin_pad + needed_bytes;

		// Ta da!
		return ptr;
	}

public:
	MemoryArena() {
		// Start with a single chunk of size zero,
		// to simplify the logic in _alloc()
		add_chunk(0);
	}
	~MemoryArena() {
		clear_chunks();
	}

	// No copying, only moving, but...
	// HACK: MSVC is stupid, so we're making
	// the copy-constructors behave like
	// move constructors.
#ifdef _MSC_VER
	MemoryArena(MemoryArena& other) {
		chunks = std::move(other.chunks);
	}
	MemoryArena& operator=(MemoryArena& other) {
		chunks = std::move(other.chunks);
		return *this;
	}
#else
	MemoryArena(MemoryArena& other) = delete;
	MemoryArena& operator=(MemoryArena& other) = delete;
#endif
	MemoryArena(MemoryArena&& other) {
		chunks = std::move(other.chunks);
	}
	MemoryArena& operator=(MemoryArena&& other) {
		chunks = std::move(other.chunks);
		return *this;
	}

	/**
	 * Allocates space for a single element of type T and returns a
	 * raw pointer to that space.
	 */
	template <typename T>
	T* alloc() {
		return _alloc<T>(1);
	}

	/**
	 * Allocates space for a single element of type T, initializes it with
	 * init, and returns a raw pointer to that space.
	 */
	template <typename T>
	T* alloc(const T& init) {
		auto ptr = _alloc<T>(1);
		*ptr = init;
		return ptr;
	}

	/**
	 * Allocates enough space for count elements of type T, and returns
	 * a Slice to that space.
	 */
	template <typename T>
	Slice<T> alloc_array(size_t count) {
		if (count <= 0)
			return Slice<T>();

		return Slice<T>(_alloc<T>(count), count);
	}

	/**
	 * Allocates space to hold the contents of the iters, and copys the
	 * iter's contents over.  Returns a Slice to that memory.
	 */
	template <typename ITER, typename T=typename ITER::value_type>
	Slice<T> alloc_from_iters(ITER begin, ITER end) {
		const size_t size = std::distance(begin, end);
		if (size <= 0)
			return Slice<T>();

		auto ptr = _alloc<T>(size);

		for (size_t i = 0; i < size; ++i) {
			ptr[i] = *begin;
			++begin;
		}

		return Slice<T>(ptr, size);
	}
};

#endif // MEMORY_ARENA_HPP<commit_msg>MSVC: Adding defines for alignof and alignas<commit_after>#ifndef MEMORY_ARENA_HPP
#define MEMORY_ARENA_HPP

#include <cstdint>
#include <cstdlib>
#include <utility>
#include <vector>
#include "slice.hpp"

#ifdef _MSC_VER
#define alignof(T) __alignof(T)
#define alignas(T) __declspec(align(T))
#endif

/**
 * A memory arena.
 */
template <size_t MIN_CHUNK_SIZE=4096>
class MemoryArena
{
	struct Chunk {
		size_t size = 0;
		size_t used = 0;
		char* data = nullptr;
	};

	std::vector<Chunk> chunks;

	void add_chunk(size_t size) {
		Chunk c;
		c.size = size;
		if (size > 0) {
			c.data = new char[size];
		}
		chunks.push_back(c);
	}

	void clear_chunks() {
		for (auto& c: chunks) {
			if (c.data != nullptr)
				delete[] c.data;
		}
		chunks.clear();
	}

	/**
	 * Allocates enough contiguous space for count items of type T, and
	 * returns a pointer to the front of that space.
	 */
	template <typename T>
	T* _alloc(size_t count) {
		// Figure out how much padding we need between elements for proper
		// memory alignment if we put them in an array.
		const auto array_pad = (alignof(T) - (sizeof(T) % alignof(T))) % alignof(T);

		// Total needed bytes for the requested array of data
		const auto needed_bytes = (sizeof(T) * count) + (array_pad * (count - 1));

		// Figure out how much padding we need at the beginning to put the
		// first element in the right place for memory alignment.
		const auto mem_addr = (uintptr_t)(chunks.back().data + chunks.back().used);
		const auto begin_pad = (alignof(T) - (mem_addr % alignof(T))) % alignof(T);

		// Get the number of bytes left in the current chunk
		const auto available_bytes = chunks.back().size - chunks.back().used;

		// If we don't have enough space in this chunk, then we need to create
		// a new chunk.
		if ((begin_pad + needed_bytes) > available_bytes) {
			// Calculate the minimum needed bytes to guarantee that we can
			// accommodate properlyaligned data.
			const auto min_needed_bytes = needed_bytes + alignof(T);

			// Make sure we don't get a chunk smaller than MIN_CHUNK_SIZE
			const size_t new_chunk_size = min_needed_bytes > MIN_CHUNK_SIZE ? min_needed_bytes : MIN_CHUNK_SIZE;

			// Create the new chunk, and then recurse for DRY purposes.
			// TODO: if we break things up differently, we could perhaps
			// avoid the redundant work caused by recursing while still
			// being DRY.  Super low priority, though, unless this somehow
			// turns out to be a performance bottleneck.
			add_chunk(new_chunk_size);
			return _alloc<T>(count);
		}

		// Otherwise, proceed in getting the pointer and recording how much
		// of the chunk we used.
		T* ptr = reinterpret_cast<T*>(chunks.back().data + chunks.back().used + begin_pad);
		for (int i=0; i < count; ++i) {
			new(ptr+i) T();
		}
		chunks.back().used += begin_pad + needed_bytes;

		// Ta da!
		return ptr;
	}

public:
	MemoryArena() {
		// Start with a single chunk of size zero,
		// to simplify the logic in _alloc()
		add_chunk(0);
	}
	~MemoryArena() {
		clear_chunks();
	}

	// No copying, only moving, but...
	// HACK: MSVC is stupid, so we're making
	// the copy-constructors behave like
	// move constructors.
#ifdef _MSC_VER
	MemoryArena(MemoryArena& other) {
		chunks = std::move(other.chunks);
	}
	MemoryArena& operator=(MemoryArena& other) {
		chunks = std::move(other.chunks);
		return *this;
	}
#else
	MemoryArena(MemoryArena& other) = delete;
	MemoryArena& operator=(MemoryArena& other) = delete;
#endif
	MemoryArena(MemoryArena&& other) {
		chunks = std::move(other.chunks);
	}
	MemoryArena& operator=(MemoryArena&& other) {
		chunks = std::move(other.chunks);
		return *this;
	}

	/**
	 * Allocates space for a single element of type T and returns a
	 * raw pointer to that space.
	 */
	template <typename T>
	T* alloc() {
		return _alloc<T>(1);
	}

	/**
	 * Allocates space for a single element of type T, initializes it with
	 * init, and returns a raw pointer to that space.
	 */
	template <typename T>
	T* alloc(const T& init) {
		auto ptr = _alloc<T>(1);
		*ptr = init;
		return ptr;
	}

	/**
	 * Allocates enough space for count elements of type T, and returns
	 * a Slice to that space.
	 */
	template <typename T>
	Slice<T> alloc_array(size_t count) {
		if (count <= 0)
			return Slice<T>();

		return Slice<T>(_alloc<T>(count), count);
	}

	/**
	 * Allocates space to hold the contents of the iters, and copys the
	 * iter's contents over.  Returns a Slice to that memory.
	 */
	template <typename ITER, typename T=typename ITER::value_type>
	Slice<T> alloc_from_iters(ITER begin, ITER end) {
		const size_t size = std::distance(begin, end);
		if (size <= 0)
			return Slice<T>();

		auto ptr = _alloc<T>(size);

		for (size_t i = 0; i < size; ++i) {
			ptr[i] = *begin;
			++begin;
		}

		return Slice<T>(ptr, size);
	}
};

#endif // MEMORY_ARENA_HPP<|endoftext|>


<commit_before>#ifndef STRAGGLER_EVENT_HPP
#define STRAGGLER_EVENT_HPP

namespace warped {

// This is a Straggler event class
class StragglerEvent : public Event {
public:
    StragglerEvent() = default;
    StragglerEvent( const std::string& receiver_name,
                    const std::string& sender_name,
                    unsigned int timestamp )
        :   receiver_name_(receiver_name),
            sender_name_(sender_name),
            timestamp_(timestamp)
    {}

    const std::string& receiverName() const { return receiver_name_; }
    const std::string& senderName() const { return sender_name_; }
    unsigned int timestamp() const { return timestamp_; }

    std::string receiver_name_;
    std::string sender_name_;
    unsigned int timestamp_;
    const std::vector<const std::unique_ptr<Event>> events_to_cancel_;
};

} // namespace warped

#endif
<commit_msg>removed unused StragglerEvent file<commit_after><|endoftext|>


<commit_before>#include "Riostream.h"

#include "Coefficient.h"
#include "RooAbsReal.h"
#include <math.h>
#include "TMath.h"

ClassImp(doofit::roofit::functions::bdecay::Coefficient)

namespace doofit {
namespace roofit {
namespace functions {
namespace bdecay {

Coefficient::Coefficient(const std::string& name,
                       RooAbsReal& _cp_coeff_,
                       CoeffType   _coeff_type_,
                       RooAbsReal& _tag_,
                       RooAbsReal& _mistag_b_,
                       RooAbsReal& _mistag_bbar_,
                       RooAbsReal& _production_asym_
                       ) :
  RooAbsReal(name.c_str(),name.c_str()),
  cp_coeff_("cp_coeff_","cp_coeff_",this,_cp_coeff_),
  coeff_type_(_coeff_type_),
  tag_("tag_","tag_",this,_tag_),
  mistag_b_("mistag_b_","mistag_b_",this,_mistag_b_),
  mistag_bbar_("mistag_bbar_","mistag_bbar_",this,_mistag_bbar_),
  production_asym_("production_asym_","production_asym_",this,_production_asym_)
{
}

Coefficient::Coefficient(const Coefficient& other, const char* name) :
  RooAbsReal(other,name),
  cp_coeff_("cp_coeff_",this,other.cp_coeff_),
  coeff_type_(other.coeff_type_),
  tag_("tag_",this,other.tag_),
  mistag_b_("mistag_b_",this,other.mistag_b_),
  mistag_bbar_("mistag_bbar_",this,other.mistag_bbar_),
  production_asym_("production_asym_",this,other.production_asym_)
{
}

inline Double_t Coefficient::evaluate() const
{
  if (coeff_type_ == kSin){
    return -1.0 * cp_coeff_ * ( tag_ - production_asym_ * ( 1.0 - tag_ * mistag_b_ + tag_ * mistag_bbar_ ) - tag_ * ( mistag_b_ + mistag_bbar_ ) );
  }
  else if (coeff_type_ == kCos){
    return +1.0 * cp_coeff_ * ( tag_ - production_asym_ * ( 1.0 - tag_ * mistag_b_ + tag_ * mistag_bbar_ ) - tag_ * ( mistag_b_ + mistag_bbar_ ) );
  }
  else if (coeff_type_ == kSinh){
    // TODO: Implement Sinh coefficient if necessary!
    return cp_coeff_;
  }
  else if (coeff_type_ == kCosh){
    return cp_coeff_ * ( 1.0 + tag_ * production_asym_ * ( 1.0 - mistag_b_ - mistag_bbar_ ) + tag_ * ( mistag_b_ - mistag_bbar_ ) );
  }
  else{
    std::cout << "ERROR\t" << "Coefficient::evaluate(): No valid coefficient type!" << std::endl;
    abort();
  }
}

Int_t Coefficient::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars/**, const char* rangeName**/) const{

  // WARNING: works only if untagged events hold a tag state of ±1

  // return 1: integration over one tag state
  // return 2: integration over two tag states

  // Now we have to handle the different possibilities:
  // 1.) a uncalibrated + uncombined tag is used (single RooRealVar)
  // 2.) a calibrated + uncombined tag ist used (single RooAbsReal)
  // 3.) a calibrated + combined tag is used (two RooAbsReals)
  // since we cannot access the observables, we have to trust that only
  // two possible integrals are requested, namely the integral over
  // a single tag state or the integral over two tag states.
  // For all other cases this implementation fails.

  if (allVars.getSize() == 0){
    std::printf("ERROR: In %s line %u (%s): allVars = ", __func__, __LINE__, __FILE__);
    allVars.Print();
    return 0;
  }
  else if (allVars.getSize() == 1){
    // case 1. and 2.: only one tag
    return 1;
  }
  else if (allVars.getSize() == 2){
    // case 3.: integration over two tag states
    return 2;
  }
  else{
    std::printf("ERROR: In %s line %u (%s): allVars = ", __func__, __LINE__, __FILE__);
    allVars.Print();
    return 0;
  }
}

Double_t Coefficient::analyticalIntegral(Int_t code/**, const char* rangeName**/) const{
  if (code != 1 || code != 2){
    std::printf("ERROR: In %s line %u (%s)", __func__, __LINE__, __FILE__);
    return 0;
    abort();
  }
  if (coeff_type_ == kSin){
    return +2.0 * production_asym_ * cp_coeff_ * code;
  }
  else if (coeff_type_ == kCos){
    return -2.0 * production_asym_ * cp_coeff_ * code;
  }
  else if (coeff_type_ == kSinh){
    return 2.0 * cp_coeff_ * code;
  }
  else if (coeff_type_ == kCosh){
    return 2.0 * cp_coeff_ * code;
  }
  else{
    std::printf("ERROR: In %s line %u (%s)", __func__, __LINE__, __FILE__);
    return 0;
    abort();
  }
}

} // namespace bdecay
} // namespace functions
} // namespace roofit
} // namespace doofit
<commit_msg>doofit::roofit::functions::pdfs::bdecay::Coefficient: corrected wrong sign in osh coefficient<commit_after>#include "Riostream.h"

#include "Coefficient.h"
#include "RooAbsReal.h"
#include <math.h>
#include "TMath.h"

ClassImp(doofit::roofit::functions::bdecay::Coefficient)

namespace doofit {
namespace roofit {
namespace functions {
namespace bdecay {

Coefficient::Coefficient(const std::string& name,
                       RooAbsReal& _cp_coeff_,
                       CoeffType   _coeff_type_,
                       RooAbsReal& _tag_,
                       RooAbsReal& _mistag_b_,
                       RooAbsReal& _mistag_bbar_,
                       RooAbsReal& _production_asym_
                       ) :
  RooAbsReal(name.c_str(),name.c_str()),
  cp_coeff_("cp_coeff_","cp_coeff_",this,_cp_coeff_),
  coeff_type_(_coeff_type_),
  tag_("tag_","tag_",this,_tag_),
  mistag_b_("mistag_b_","mistag_b_",this,_mistag_b_),
  mistag_bbar_("mistag_bbar_","mistag_bbar_",this,_mistag_bbar_),
  production_asym_("production_asym_","production_asym_",this,_production_asym_)
{
}

Coefficient::Coefficient(const Coefficient& other, const char* name) :
  RooAbsReal(other,name),
  cp_coeff_("cp_coeff_",this,other.cp_coeff_),
  coeff_type_(other.coeff_type_),
  tag_("tag_",this,other.tag_),
  mistag_b_("mistag_b_",this,other.mistag_b_),
  mistag_bbar_("mistag_bbar_",this,other.mistag_bbar_),
  production_asym_("production_asym_",this,other.production_asym_)
{
}

inline Double_t Coefficient::evaluate() const
{
  if (coeff_type_ == kSin){
    return -1.0 * cp_coeff_ * ( tag_ - production_asym_ * ( 1.0 - tag_ * mistag_b_ + tag_ * mistag_bbar_ ) - tag_ * ( mistag_b_ + mistag_bbar_ ) );
  }
  else if (coeff_type_ == kCos){
    return +1.0 * cp_coeff_ * ( tag_ - production_asym_ * ( 1.0 - tag_ * mistag_b_ + tag_ * mistag_bbar_ ) - tag_ * ( mistag_b_ + mistag_bbar_ ) );
  }
  else if (coeff_type_ == kSinh){
    // TODO: Implement Sinh coefficient
    return cp_coeff_;
  }
  else if (coeff_type_ == kCosh){
    return cp_coeff_ * ( 1.0 - tag_ * production_asym_ * ( 1.0 - mistag_b_ - mistag_bbar_ ) - tag_ * ( mistag_b_ - mistag_bbar_ ) );
  }
  else{
    std::cout << "ERROR\t" << "Coefficient::evaluate(): No valid coefficient type!" << std::endl;
    abort();
  }
}

Int_t Coefficient::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars/**, const char* rangeName**/) const{

  // WARNING: works only if untagged events hold a tag state of ±1

  // return 1: integration over one tag state
  // return 2: integration over two tag states

  // Now we have to handle the different possibilities:
  // 1.) a uncalibrated + uncombined tag is used (single RooRealVar)
  // 2.) a calibrated + uncombined tag ist used (single RooAbsReal)
  // 3.) a calibrated + combined tag is used (two RooAbsReals)
  // since we cannot access the observables, we have to trust that only
  // two possible integrals are requested, namely the integral over
  // a single tag state or the integral over two tag states.
  // For all other cases this implementation fails.

  if (allVars.getSize() == 0){
    std::printf("ERROR: In %s line %u (%s): allVars = ", __func__, __LINE__, __FILE__);
    allVars.Print();
    return 0;
  }
  else if (allVars.getSize() == 1){
    // case 1. and 2.: only one tag
    return 1;
  }
  else if (allVars.getSize() == 2){
    // case 3.: integration over two tag states
    return 2;
  }
  else{
    std::printf("ERROR: In %s line %u (%s): allVars = ", __func__, __LINE__, __FILE__);
    allVars.Print();
    return 0;
  }
}

Double_t Coefficient::analyticalIntegral(Int_t code/**, const char* rangeName**/) const{
  if (code != 1 || code != 2){
    std::printf("ERROR: In %s line %u (%s)", __func__, __LINE__, __FILE__);
    return 0;
    abort();
  }
  if (coeff_type_ == kSin){
    return +2.0 * production_asym_ * cp_coeff_ * code;
  }
  else if (coeff_type_ == kCos){
    return -2.0 * production_asym_ * cp_coeff_ * code;
  }
  else if (coeff_type_ == kSinh){
    return 2.0 * cp_coeff_ * code;
  }
  else if (coeff_type_ == kCosh){
    return 2.0 * cp_coeff_ * code;
  }
  else{
    std::printf("ERROR: In %s line %u (%s)", __func__, __LINE__, __FILE__);
    return 0;
    abort();
  }
}

} // namespace bdecay
} // namespace functions
} // namespace roofit
} // namespace doofit
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: macropg.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-21 14:55:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _MACROPG_HXX
#define _MACROPG_HXX

#include <sfx2/basedlgs.hxx>
#include <sfx2/tabdlg.hxx>

#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/uno/Reference.hxx>

#ifndef _SFXMACITEM_HXX //autogen
#include <svtools/macitem.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#include <rtl/ustring.hxx>

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

#include <hash_map>

typedef ::std::hash_map< ::rtl::OUString, ::std::pair< ::rtl::OUString, ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > EventsHash;
typedef ::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > UIEventsStringHash;

class _SvxMacroTabPage;
class SvStringsDtor;
class SvTabListBox;
class Edit;
class String;

class _HeaderTabListBox;
class _SvxMacroTabPage_Impl;

class _SvxMacroTabPage : public SfxTabPage
{
#if _SOLAR__PRIVATE
    DECL_STATIC_LINK( _SvxMacroTabPage, SelectEvent_Impl, SvTabListBox * );
    DECL_STATIC_LINK( _SvxMacroTabPage, AssignDeleteHdl_Impl, PushButton * );
#endif
protected:
    _SvxMacroTabPage_Impl*      mpImpl;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > m_xAppEvents;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > m_xDocEvents;
    ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifiable > m_xModifiable;
    EventsHash m_appEventsHash;
    EventsHash m_docEventsHash;
    bool bReadOnly, bDocModified, bAppEvents, bInitialized;
    UIEventsStringHash aUIStrings;

                                _SvxMacroTabPage( Window* pParent, const ResId& rId, const SfxItemSet& rItemSet );

    void                        EnableButtons( const String& rLanguage );
    ::com::sun::star::uno::Any  GetPropsByName( const ::rtl::OUString& eventName, const EventsHash& eventsHash );
    ::std::pair< ::rtl::OUString, ::rtl::OUString > GetPairFromAny( ::com::sun::star::uno::Any aAny );

public:

    virtual                     ~_SvxMacroTabPage();
    void                        InitResources();

    void                        InitAndSetHandler( ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xAppEvents, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xDocEvents, ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifiable > xModifiable );
    virtual BOOL                FillItemSet( SfxItemSet& rSet );
    virtual void                Reset();

    void                        DisplayAppEvents( bool appEvents);
    void                        SetReadOnly( BOOL bSet );
    BOOL                        IsReadOnly() const;
};

class SvxMacroTabPage : public _SvxMacroTabPage
{
public:
    SvxMacroTabPage( Window* pParent, const ResId& rId,
                    const SfxItemSet& rSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
    virtual ~SvxMacroTabPage();

    static SfxTabPage* Create( Window* pParent, const SfxItemSet& rAttrSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
};

class SVX_DLLPUBLIC SvxMacroAssignDlg : public SfxSingleTabDialog
{
public:
    SvxMacroAssignDlg( Window* pParent, SfxItemSet& rSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
    virtual ~SvxMacroAssignDlg();
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.430); FILE MERGED 2005/09/05 14:15:46 rt 1.5.430.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: macropg.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:02:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _MACROPG_HXX
#define _MACROPG_HXX

#include <sfx2/basedlgs.hxx>
#include <sfx2/tabdlg.hxx>

#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/uno/Reference.hxx>

#ifndef _SFXMACITEM_HXX //autogen
#include <svtools/macitem.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#include <rtl/ustring.hxx>

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

#include <hash_map>

typedef ::std::hash_map< ::rtl::OUString, ::std::pair< ::rtl::OUString, ::rtl::OUString >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > EventsHash;
typedef ::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > UIEventsStringHash;

class _SvxMacroTabPage;
class SvStringsDtor;
class SvTabListBox;
class Edit;
class String;

class _HeaderTabListBox;
class _SvxMacroTabPage_Impl;

class _SvxMacroTabPage : public SfxTabPage
{
#if _SOLAR__PRIVATE
    DECL_STATIC_LINK( _SvxMacroTabPage, SelectEvent_Impl, SvTabListBox * );
    DECL_STATIC_LINK( _SvxMacroTabPage, AssignDeleteHdl_Impl, PushButton * );
#endif
protected:
    _SvxMacroTabPage_Impl*      mpImpl;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > m_xAppEvents;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > m_xDocEvents;
    ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifiable > m_xModifiable;
    EventsHash m_appEventsHash;
    EventsHash m_docEventsHash;
    bool bReadOnly, bDocModified, bAppEvents, bInitialized;
    UIEventsStringHash aUIStrings;

                                _SvxMacroTabPage( Window* pParent, const ResId& rId, const SfxItemSet& rItemSet );

    void                        EnableButtons( const String& rLanguage );
    ::com::sun::star::uno::Any  GetPropsByName( const ::rtl::OUString& eventName, const EventsHash& eventsHash );
    ::std::pair< ::rtl::OUString, ::rtl::OUString > GetPairFromAny( ::com::sun::star::uno::Any aAny );

public:

    virtual                     ~_SvxMacroTabPage();
    void                        InitResources();

    void                        InitAndSetHandler( ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xAppEvents, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xDocEvents, ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifiable > xModifiable );
    virtual BOOL                FillItemSet( SfxItemSet& rSet );
    virtual void                Reset();

    void                        DisplayAppEvents( bool appEvents);
    void                        SetReadOnly( BOOL bSet );
    BOOL                        IsReadOnly() const;
};

class SvxMacroTabPage : public _SvxMacroTabPage
{
public:
    SvxMacroTabPage( Window* pParent, const ResId& rId,
                    const SfxItemSet& rSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
    virtual ~SvxMacroTabPage();

    static SfxTabPage* Create( Window* pParent, const SfxItemSet& rAttrSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
};

class SVX_DLLPUBLIC SvxMacroAssignDlg : public SfxSingleTabDialog
{
public:
    SvxMacroAssignDlg( Window* pParent, SfxItemSet& rSet, ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > xNameReplace, sal_uInt16 nSelectedIndex=0 );
    virtual ~SvxMacroAssignDlg();
};

#endif
<|endoftext|>


<commit_before>#include "dg/llvm/analysis/PointsTo/PointerSubgraph.h"
#include "llvm/llvm-utils.h"

namespace dg {
namespace analysis {
namespace pta {

PSNode *LLVMPointerSubgraphBuilder::createAlloc(const llvm::Instruction *Inst)
{
    PSNodeAlloc *node = PSNodeAlloc::get(PS.create(PSNodeType::ALLOC));
    addNode(Inst, node);

    const llvm::AllocaInst *AI = llvm::dyn_cast<llvm::AllocaInst>(Inst);
    if (AI)
        node->setSize(getAllocatedSize(AI, DL));

    return node;
}

PSNode * LLVMPointerSubgraphBuilder::createLifetimeEnd(const llvm::Instruction *Inst)
{
    PSNode *op1 = getOperand(Inst->getOperand(1));
    PSNode *node = PS.create(PSNodeType::INVALIDATE_OBJECT, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createStore(const llvm::Instruction *Inst)
{
    const llvm::Value *valOp = Inst->getOperand(0);

    PSNode *op1 = getOperand(valOp);
    PSNode *op2 = getOperand(Inst->getOperand(1));

    PSNode *node = PS.create(PSNodeType::STORE, op1, op2);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createLoad(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);

    PSNode *op1 = getOperand(op);
    PSNode *node = PS.create(PSNodeType::LOAD, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createGEP(const llvm::Instruction *Inst)
{
    using namespace llvm;

    const GetElementPtrInst *GEP = cast<GetElementPtrInst>(Inst);
    const Value *ptrOp = GEP->getPointerOperand();
    unsigned bitwidth = getPointerBitwidth(DL, ptrOp);
    APInt offset(bitwidth, 0);

    PSNode *node = nullptr;
    PSNode *op = getOperand(ptrOp);

    if (*_options.fieldSensitivity > 0
        && GEP->accumulateConstantOffset(*DL, offset)) {
        // is offset in given bitwidth?
        if (offset.isIntN(bitwidth)) {
            // is 0 < offset < field_sensitivity ?
            uint64_t off = offset.getLimitedValue(*_options.fieldSensitivity);
            if (off == 0 || off < *_options.fieldSensitivity)
                node = PS.create(PSNodeType::GEP, op, offset.getZExtValue());
        } else
            errs() << "WARN: GEP offset greater than " << bitwidth << "-bit";
            // fall-through to Offset::UNKNOWN in this case
    }

    // we didn't create the node with concrete offset,
    // in which case we are supposed to create a node
    // with Offset::UNKNOWN
    if (!node)
        node = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createSelect(const llvm::Instruction *Inst)
{
    // with ptrtoint/inttoptr it may not be a pointer
    // assert(Inst->getType()->isPointerTy() && "BUG: This select is not a pointer");

    // select <cond> <op1> <op2>
    PSNode *op1 = getOperand(Inst->getOperand(1));
    PSNode *op2 = getOperand(Inst->getOperand(2));

    // select works as a PHI in points-to analysis
    PSNode *node = PS.create(PSNodeType::PHI, op1, op2, nullptr);
    addNode(Inst, node);

    assert(node);
    return node;
}

Offset accumulateEVOffsets(const llvm::ExtractValueInst *EV,
                           const llvm::DataLayout& DL) {
    Offset off{0};
    llvm::CompositeType *type
        = llvm::dyn_cast<llvm::CompositeType>(EV->getAggregateOperand()->getType());
    assert(type && "Don't have composite type in extractvalue");

    for (unsigned idx : EV->indices()) {
        assert(type->indexValid(idx) && "Invalid index");
        if (llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(type)) {
            const llvm::StructLayout *SL = DL.getStructLayout(STy);
            off += SL->getElementOffset(idx);
        } else {
            // array or vector, so just move in the array
            auto seqTy = llvm::cast<llvm::SequentialType>(type);
            off += idx + DL.getTypeAllocSize(seqTy->getElementType());
        }

        type = llvm::dyn_cast<llvm::CompositeType>(type->getTypeAtIndex(idx));
        if (!type)
            break; // we're done
    }

    return off;
}

PSNodesSeq
LLVMPointerSubgraphBuilder::createExtract(const llvm::Instruction *Inst)
{
    using namespace llvm;

    const ExtractValueInst *EI = cast<ExtractValueInst>(Inst);

    // extract <agg> <idx> {<idx>, ...}
    PSNode *op1 = getOperand(EI->getAggregateOperand());
    PSNode *G = PS.create(PSNodeType::GEP, op1, accumulateEVOffsets(EI, *DL));
    PSNode *L = PS.create(PSNodeType::LOAD, G);

    G->addSuccessor(L);

    PSNodesSeq ret = PSNodesSeq(G, L);
    addNode(Inst, ret);

    return ret;
}

PSNode *LLVMPointerSubgraphBuilder::createPHI(const llvm::Instruction *Inst)
{
    PSNode *node = PS.create(PSNodeType::PHI, nullptr);
    addNode(Inst, node);

    // NOTE: we didn't add operands to PHI node here, but after building
    // the whole function, because some blocks may not have been built
    // when we were creating the phi node

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createCast(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);
    PSNode *op1 = getOperand(op);
    PSNode *node = PS.create(PSNodeType::CAST, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

// ptrToInt work just as a bitcast
PSNode *LLVMPointerSubgraphBuilder::createPtrToInt(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);

    PSNode *op1 = getOperand(op);
    // NOTE: we don't support arithmetic operations, so instead of
    // just casting the value do gep with unknown offset -
    // this way we cover any shift of the pointer due to arithmetic
    // operations
    // PSNode *node = PS.create(PSNodeType::CAST, op1);
    PSNode *node = PS.create(PSNodeType::GEP, op1, 0);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createIntToPtr(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);
    PSNode *op1;

    if (llvm::isa<llvm::Constant>(op)) {
        llvm::errs() << "PTA warning: IntToPtr with constant: "
                     << *Inst << "\n";
        // if this is inttoptr with constant, just make the pointer
        // unknown
        op1 = UNKNOWN_MEMORY;
    } else
        op1 = getOperand(op);

    PSNode *node = PS.create(PSNodeType::CAST, op1);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createAdd(const llvm::Instruction *Inst)
{
    using namespace llvm;

    PSNode *node;
    PSNode *op;
    const Value *val = nullptr;
    uint64_t off = Offset::UNKNOWN;

    if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(1));
        val = Inst->getOperand(0);
    } else if (isa<ConstantInt>(Inst->getOperand(1))) {
        op = getOperand(Inst->getOperand(0));
        val = Inst->getOperand(1);
    } else {
        // the operands are both non-constant. Check if we
        // can get an operand as one of them and if not,
        // fall-back to unknown memory, because we
        // would need to track down both operads...
        op = tryGetOperand(Inst->getOperand(0));
        if (!op)
            op = tryGetOperand(Inst->getOperand(1));

        if (!op)
            return createUnknown(Inst);
    }

    assert(op && "Don't have operand for add");
    if (val)
        off = getConstantValue(val);

    node = PS.create(PSNodeType::GEP, op, off);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createArithmetic(const llvm::Instruction *Inst)
{
    using namespace llvm;

    PSNode *node;
    PSNode *op;

    // we don't know if the operand is the first or
    // the other operand
    if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(1));
    } else if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(0));
    } else {
        // the operands are both non-constant. Check if we
        // can get an operand as one of them and if not,
        // fall-back to unknown memory, because we
        // would need to track down both operads...
        op = tryGetOperand(Inst->getOperand(0));
        if (!op)
            op = tryGetOperand(Inst->getOperand(1));

        if (!op)
            return createUnknown(Inst);
    }

    // we don't know what the operation does,
    // so set unknown offset
    node = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createReturn(const llvm::Instruction *Inst)
{
    PSNode *op1 = nullptr;
    // is nullptr if this is 'ret void'
    llvm::Value *retVal = llvm::cast<llvm::ReturnInst>(Inst)->getReturnValue();

    // we create even void and non-pointer return nodes,
    // since these modify CFG (they won't bear any
    // points-to information though)
    // XXX is that needed?

    // DONT: if(retVal->getType()->isPointerTy())
    // we have ptrtoint which break the types...
    if (retVal) {
        // A struct is being returned. In this case,
        // return the address of the local variable
        // that holds the return value, so that
        // we can then do a load on this object
        if (retVal->getType()->isAggregateType()) {
            if (llvm::LoadInst *LI = llvm::dyn_cast<llvm::LoadInst>(retVal)) {
                op1 = getOperand(LI->getPointerOperand());
            }

            if (!op1) {
                llvm::errs() << "WARN: Unsupported return of an aggregate type\n";
                llvm::errs() << *Inst << "\n";

                op1 = UNKNOWN_MEMORY;
            }
        }

        if (llvm::isa<llvm::ConstantPointerNull>(retVal)
            || isConstantZero(retVal))
            op1 = NULLPTR;
        else if (typeCanBePointer(DL, retVal->getType()) &&
                  (!isInvalid(retVal->stripPointerCasts(), invalidate_nodes) ||
                   llvm::isa<llvm::ConstantExpr>(retVal) ||
                   llvm::isa<llvm::UndefValue>(retVal)))
            op1 = getOperand(retVal);
    }

    assert((op1 || !retVal || !retVal->getType()->isPointerTy())
           && "Don't have an operand for ReturnInst with pointer");

    PSNode *node = PS.create(PSNodeType::RETURN, op1, nullptr);
    addNode(Inst, node);

    return node;
}

} // namespace pta
} // namespace analysis
} // namespace dg

<commit_msg>PTA: fix compatibility with LLVM < 3.7<commit_after>#include "dg/llvm/analysis/PointsTo/PointerSubgraph.h"
#include "llvm/llvm-utils.h"

namespace dg {
namespace analysis {
namespace pta {

PSNode *LLVMPointerSubgraphBuilder::createAlloc(const llvm::Instruction *Inst)
{
    PSNodeAlloc *node = PSNodeAlloc::get(PS.create(PSNodeType::ALLOC));
    addNode(Inst, node);

    const llvm::AllocaInst *AI = llvm::dyn_cast<llvm::AllocaInst>(Inst);
    if (AI)
        node->setSize(getAllocatedSize(AI, DL));

    return node;
}

PSNode * LLVMPointerSubgraphBuilder::createLifetimeEnd(const llvm::Instruction *Inst)
{
    PSNode *op1 = getOperand(Inst->getOperand(1));
    PSNode *node = PS.create(PSNodeType::INVALIDATE_OBJECT, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createStore(const llvm::Instruction *Inst)
{
    const llvm::Value *valOp = Inst->getOperand(0);

    PSNode *op1 = getOperand(valOp);
    PSNode *op2 = getOperand(Inst->getOperand(1));

    PSNode *node = PS.create(PSNodeType::STORE, op1, op2);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createLoad(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);

    PSNode *op1 = getOperand(op);
    PSNode *node = PS.create(PSNodeType::LOAD, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createGEP(const llvm::Instruction *Inst)
{
    using namespace llvm;

    const GetElementPtrInst *GEP = cast<GetElementPtrInst>(Inst);
    const Value *ptrOp = GEP->getPointerOperand();
    unsigned bitwidth = getPointerBitwidth(DL, ptrOp);
    APInt offset(bitwidth, 0);

    PSNode *node = nullptr;
    PSNode *op = getOperand(ptrOp);

    if (*_options.fieldSensitivity > 0
        && GEP->accumulateConstantOffset(*DL, offset)) {
        // is offset in given bitwidth?
        if (offset.isIntN(bitwidth)) {
            // is 0 < offset < field_sensitivity ?
            uint64_t off = offset.getLimitedValue(*_options.fieldSensitivity);
            if (off == 0 || off < *_options.fieldSensitivity)
                node = PS.create(PSNodeType::GEP, op, offset.getZExtValue());
        } else
            errs() << "WARN: GEP offset greater than " << bitwidth << "-bit";
            // fall-through to Offset::UNKNOWN in this case
    }

    // we didn't create the node with concrete offset,
    // in which case we are supposed to create a node
    // with Offset::UNKNOWN
    if (!node)
        node = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN);

    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createSelect(const llvm::Instruction *Inst)
{
    // with ptrtoint/inttoptr it may not be a pointer
    // assert(Inst->getType()->isPointerTy() && "BUG: This select is not a pointer");

    // select <cond> <op1> <op2>
    PSNode *op1 = getOperand(Inst->getOperand(1));
    PSNode *op2 = getOperand(Inst->getOperand(2));

    // select works as a PHI in points-to analysis
    PSNode *node = PS.create(PSNodeType::PHI, op1, op2, nullptr);
    addNode(Inst, node);

    assert(node);
    return node;
}

Offset accumulateEVOffsets(const llvm::ExtractValueInst *EV,
                           const llvm::DataLayout& DL) {
    Offset off{0};
    llvm::CompositeType *type
        = llvm::dyn_cast<llvm::CompositeType>(EV->getAggregateOperand()->getType());
    assert(type && "Don't have composite type in extractvalue");

    for (unsigned idx : EV->getIndices()) {
        assert(type->indexValid(idx) && "Invalid index");
        if (llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(type)) {
            const llvm::StructLayout *SL = DL.getStructLayout(STy);
            off += SL->getElementOffset(idx);
        } else {
            // array or vector, so just move in the array
            auto seqTy = llvm::cast<llvm::SequentialType>(type);
            off += idx + DL.getTypeAllocSize(seqTy->getElementType());
        }

        type = llvm::dyn_cast<llvm::CompositeType>(type->getTypeAtIndex(idx));
        if (!type)
            break; // we're done
    }

    return off;
}

PSNodesSeq
LLVMPointerSubgraphBuilder::createExtract(const llvm::Instruction *Inst)
{
    using namespace llvm;

    const ExtractValueInst *EI = cast<ExtractValueInst>(Inst);

    // extract <agg> <idx> {<idx>, ...}
    PSNode *op1 = getOperand(EI->getAggregateOperand());
    PSNode *G = PS.create(PSNodeType::GEP, op1, accumulateEVOffsets(EI, *DL));
    PSNode *L = PS.create(PSNodeType::LOAD, G);

    G->addSuccessor(L);

    PSNodesSeq ret = PSNodesSeq(G, L);
    addNode(Inst, ret);

    return ret;
}

PSNode *LLVMPointerSubgraphBuilder::createPHI(const llvm::Instruction *Inst)
{
    PSNode *node = PS.create(PSNodeType::PHI, nullptr);
    addNode(Inst, node);

    // NOTE: we didn't add operands to PHI node here, but after building
    // the whole function, because some blocks may not have been built
    // when we were creating the phi node

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createCast(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);
    PSNode *op1 = getOperand(op);
    PSNode *node = PS.create(PSNodeType::CAST, op1);

    addNode(Inst, node);

    assert(node);
    return node;
}

// ptrToInt work just as a bitcast
PSNode *LLVMPointerSubgraphBuilder::createPtrToInt(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);

    PSNode *op1 = getOperand(op);
    // NOTE: we don't support arithmetic operations, so instead of
    // just casting the value do gep with unknown offset -
    // this way we cover any shift of the pointer due to arithmetic
    // operations
    // PSNode *node = PS.create(PSNodeType::CAST, op1);
    PSNode *node = PS.create(PSNodeType::GEP, op1, 0);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createIntToPtr(const llvm::Instruction *Inst)
{
    const llvm::Value *op = Inst->getOperand(0);
    PSNode *op1;

    if (llvm::isa<llvm::Constant>(op)) {
        llvm::errs() << "PTA warning: IntToPtr with constant: "
                     << *Inst << "\n";
        // if this is inttoptr with constant, just make the pointer
        // unknown
        op1 = UNKNOWN_MEMORY;
    } else
        op1 = getOperand(op);

    PSNode *node = PS.create(PSNodeType::CAST, op1);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createAdd(const llvm::Instruction *Inst)
{
    using namespace llvm;

    PSNode *node;
    PSNode *op;
    const Value *val = nullptr;
    uint64_t off = Offset::UNKNOWN;

    if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(1));
        val = Inst->getOperand(0);
    } else if (isa<ConstantInt>(Inst->getOperand(1))) {
        op = getOperand(Inst->getOperand(0));
        val = Inst->getOperand(1);
    } else {
        // the operands are both non-constant. Check if we
        // can get an operand as one of them and if not,
        // fall-back to unknown memory, because we
        // would need to track down both operads...
        op = tryGetOperand(Inst->getOperand(0));
        if (!op)
            op = tryGetOperand(Inst->getOperand(1));

        if (!op)
            return createUnknown(Inst);
    }

    assert(op && "Don't have operand for add");
    if (val)
        off = getConstantValue(val);

    node = PS.create(PSNodeType::GEP, op, off);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createArithmetic(const llvm::Instruction *Inst)
{
    using namespace llvm;

    PSNode *node;
    PSNode *op;

    // we don't know if the operand is the first or
    // the other operand
    if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(1));
    } else if (isa<ConstantInt>(Inst->getOperand(0))) {
        op = getOperand(Inst->getOperand(0));
    } else {
        // the operands are both non-constant. Check if we
        // can get an operand as one of them and if not,
        // fall-back to unknown memory, because we
        // would need to track down both operads...
        op = tryGetOperand(Inst->getOperand(0));
        if (!op)
            op = tryGetOperand(Inst->getOperand(1));

        if (!op)
            return createUnknown(Inst);
    }

    // we don't know what the operation does,
    // so set unknown offset
    node = PS.create(PSNodeType::GEP, op, Offset::UNKNOWN);
    addNode(Inst, node);

    assert(node);
    return node;
}

PSNode *LLVMPointerSubgraphBuilder::createReturn(const llvm::Instruction *Inst)
{
    PSNode *op1 = nullptr;
    // is nullptr if this is 'ret void'
    llvm::Value *retVal = llvm::cast<llvm::ReturnInst>(Inst)->getReturnValue();

    // we create even void and non-pointer return nodes,
    // since these modify CFG (they won't bear any
    // points-to information though)
    // XXX is that needed?

    // DONT: if(retVal->getType()->isPointerTy())
    // we have ptrtoint which break the types...
    if (retVal) {
        // A struct is being returned. In this case,
        // return the address of the local variable
        // that holds the return value, so that
        // we can then do a load on this object
        if (retVal->getType()->isAggregateType()) {
            if (llvm::LoadInst *LI = llvm::dyn_cast<llvm::LoadInst>(retVal)) {
                op1 = getOperand(LI->getPointerOperand());
            }

            if (!op1) {
                llvm::errs() << "WARN: Unsupported return of an aggregate type\n";
                llvm::errs() << *Inst << "\n";

                op1 = UNKNOWN_MEMORY;
            }
        }

        if (llvm::isa<llvm::ConstantPointerNull>(retVal)
            || isConstantZero(retVal))
            op1 = NULLPTR;
        else if (typeCanBePointer(DL, retVal->getType()) &&
                  (!isInvalid(retVal->stripPointerCasts(), invalidate_nodes) ||
                   llvm::isa<llvm::ConstantExpr>(retVal) ||
                   llvm::isa<llvm::UndefValue>(retVal)))
            op1 = getOperand(retVal);
    }

    assert((op1 || !retVal || !retVal->getType()->isPointerTy())
           && "Don't have an operand for ReturnInst with pointer");

    PSNode *node = PS.create(PSNodeType::RETURN, op1, nullptr);
    addNode(Inst, node);

    return node;
}

} // namespace pta
} // namespace analysis
} // namespace dg

<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date( time_t date )
{
    static char buf[ 12 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date_year( time_t date )
{
    static char buf[ 15 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%02d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/
char    *
format_time( int tot_secs )
{
    int     days;
    int     hours;
    int     min;
    int     secs;
    static char answer[25];

	if ( tot_secs < 0 ) {
		sprintf(answer,"[?????]");
		return answer;
	}

    days = tot_secs / DAY;
    tot_secs %= DAY;
    hours = tot_secs / HOUR;
    tot_secs %= HOUR;
    min = tot_secs / MINUTE;
    secs = tot_secs % MINUTE;

    (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
    return answer;
}

<commit_msg>Changed the format_time from MM/DD/YY to MM/DD/YYYY.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date( time_t date )
{
    static char buf[ 12 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date_year( time_t date )
{
    static char buf[ 15 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%02d/%-4d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, (tm->tm_year + 1900), tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/
char    *
format_time( int tot_secs )
{
    int     days;
    int     hours;
    int     min;
    int     secs;
    static char answer[25];

	if ( tot_secs < 0 ) {
		sprintf(answer,"[?????]");
		return answer;
	}

    days = tot_secs / DAY;
    tot_secs %= DAY;
    hours = tot_secs / HOUR;
    tot_secs %= HOUR;
    min = tot_secs / MINUTE;
    secs = tot_secs % MINUTE;

    (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
    return answer;
}

<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"

#ifndef WIN32
#include "types.h"
#endif

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date( time_t date )
{
    static char buf[ 12 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date_year( time_t date )
{
    static char buf[ 15 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%02d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/
char    *
format_time( int tot_secs )
{
    int     days;
    int     hours;
    int     min;
    int     secs;
    static char answer[25];

    days = tot_secs / DAY;
    tot_secs %= DAY;
    hours = tot_secs / HOUR;
    tot_secs %= HOUR;
    min = tot_secs / MINUTE;
    secs = tot_secs % MINUTE;

    (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
    return answer;
}

<commit_msg>file types.h has gone away, so we shouldn't include it!<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date( time_t date )
{
    static char buf[ 12 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a date expressed in "UNIX time" into "month/day hour:minute".
*/
char *
format_date_year( time_t date )
{
    static char buf[ 15 ];
    struct tm   *tm;

	if (date<0) {
		strcpy(buf,"    ???    ");
		return buf;
	}

    tm = localtime( &date );
    sprintf( buf, "%2d/%02d/%-2d %02d:%02d",
        (tm->tm_mon)+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min
    );
    return buf;
}

/*
  Format a time value which is encoded as seconds since the UNIX
  "epoch".  We return a string in the format dd+hh:mm:ss, indicating
  days, hours, minutes, and seconds.  The string is in static data
  space, and will be overwritten by the next call to this function.
*/
char    *
format_time( int tot_secs )
{
    int     days;
    int     hours;
    int     min;
    int     secs;
    static char answer[25];

    days = tot_secs / DAY;
    tot_secs %= DAY;
    hours = tot_secs / HOUR;
    tot_secs %= HOUR;
    min = tot_secs / MINUTE;
    secs = tot_secs % MINUTE;

    (void)sprintf( answer, "%3d+%02d:%02d:%02d", days, hours, min, secs );
    return answer;
}

<|endoftext|>


<commit_before>#include "env.hpp"

namespace Vole {
  Env::Env(Env* par)
  : parent(par) { }

  Value Env::lookup(Symbol name) {
    for (auto current = this; current; current = current->parent) {
      if (current->bindings.count(name)) {
        return current->bindings[name];
      }
    }
    throw "unbound variable";
  }

  void Env::bind(Symbol name, Value value) {
    bindings[name] = value;
  }

  void Env::assign(Symbol name, Value value) {
    for (auto current = this; current; current = current->parent) {
      if (current->bindings.count(name)) {
        current->bindings[name] = value;
        return;
      }
    }
    throw "assignment to unbound variable";
  }

}<commit_msg>whitespace tweak<commit_after>#include "env.hpp"

namespace Vole {

  Env::Env(Env* par)
  : parent(par) { }

  Value Env::lookup(Symbol name) {
    for (auto current = this; current; current = current->parent) {
      if (current->bindings.count(name)) {
        return current->bindings[name];
      }
    }
    throw "unbound variable";
  }

  void Env::bind(Symbol name, Value value) {
    bindings[name] = value;
  }

  void Env::assign(Symbol name, Value value) {
    for (auto current = this; current; current = current->parent) {
      if (current->bindings.count(name)) {
        current->bindings[name] = value;
        return;
      }
    }
    throw "assignment to unbound variable";
  }

}<|endoftext|>


<commit_before>/*=============================================================================
	Copyright (c) 2012-2013 Richard Otis

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

// N-Dimensional uniform grid

#ifndef INCLUDED_NDGRID
#define INCLUDED_NDGRID

#include <vector>

struct NDGrid {
	template <typename Func> static void sample(
			const double min_extent,
			const double max_extent,
			const std::size_t dimension,
			const double grid_points_per_major_axis,
			const Func &func,
			std::vector<double>& address) {
		if (address.size() == dimension) {
			// terminating condition; address is complete
			func(address);
		}
		else {
			double step = (max_extent - min_extent) / grid_points_per_major_axis;
			for (auto j = 0; j <= grid_points_per_major_axis; ++j) {
				double location = step*j + min_extent;
				address.push_back(location);
				// recursive step
				NDGrid::sample(min_extent, max_extent, dimension, grid_points_per_major_axis, func, address);
				address.pop_back(); // remove the element we just added (this way avoids copying)
			}
		}
	}
	template <typename Func> static inline void sample(
			const double min_extent,
			const double max_extent,
			const std::size_t dimension,
			const double grid_points_per_major_axis,
			const Func &func) {
		std::vector<double> address;
		NDGrid::sample(min_extent, max_extent, dimension, grid_points_per_major_axis, func, address);
	}
};

#endif
<commit_msg>Dimension-dependent bounds for NDGrid<commit_after>/*=============================================================================
	Copyright (c) 2012-2013 Richard Otis

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

// N-Dimensional uniform grid

#ifndef INCLUDED_NDGRID
#define INCLUDED_NDGRID

#include <vector>
#include <utility>

struct NDGrid {
	template <typename Func> static void sample(
			const std::vector<std::pair<double,double> > &extents,
			const double grid_points_per_major_axis,
			const Func &func,
			std::vector<double>& address) {
		if (address.size() == extents.size()) {
			// terminating condition; address is complete
			func(address);
		}
		else {
			const double max_extent = extents[address.size()].second;
			const double min_extent = extents[address.size()].first;
			double step = (max_extent - min_extent) / grid_points_per_major_axis;
			for (auto j = 0; j <= grid_points_per_major_axis; ++j) {
				double location = step*j + min_extent;
				address.push_back(location);
				// recursive step
				NDGrid::sample(extents, grid_points_per_major_axis, func, address);
				address.pop_back(); // remove the element we just added (this way avoids copying)
			}
		}
	}
	template <typename Func> static inline void sample(
			const std::vector<std::pair<double,double> > &extents,
			const double grid_points_per_major_axis,
			const Func &func) {
		std::vector<double> address;
		NDGrid::sample(extents, grid_points_per_major_axis, func, address);
	}
	template <typename Func> static void sample(
			const double min_extent,
			const double max_extent,
			const std::size_t dimension,
			const double grid_points_per_major_axis,
			const Func &func,
			std::vector<double>& address) {
		if (address.size() == dimension) {
			// terminating condition; address is complete
			func(address);
		}
		else {
			double step = (max_extent - min_extent) / grid_points_per_major_axis;
			for (auto j = 0; j <= grid_points_per_major_axis; ++j) {
				double location = step*j + min_extent;
				address.push_back(location);
				// recursive step
				NDGrid::sample(min_extent, max_extent, dimension, grid_points_per_major_axis, func, address);
				address.pop_back(); // remove the element we just added (this way avoids copying)
			}
		}
	}
	template <typename Func> static inline void sample(
			const double min_extent,
			const double max_extent,
			const std::size_t dimension,
			const double grid_points_per_major_axis,
			const Func &func) {
		std::vector<double> address;
		NDGrid::sample(min_extent, max_extent, dimension, grid_points_per_major_axis, func, address);
	}
};

#endif
<|endoftext|>