<commit_before>/* -------------------------------------------------------------------------- *
 *                       OpenSim:  ModelVisualizer.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Michael A. Sherman                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

#include "ModelVisualizer.h"
#include "Model.h"
#include <OpenSim/version.h>
#include <OpenSim/Common/ModelDisplayHints.h>
#include <simbody/internal/Visualizer_InputListener.h>
#include <simbody/internal/Visualizer_Reporter.h>

#include <string>
using std::string;
#include <iostream>
using std::cout; using std::cerr; using std::clog; using std::endl;

using namespace OpenSim;
using namespace SimTK;

//==============================================================================
//                       OPENSIM INPUT LISTENER
//==============================================================================

// These constants are used to identify the OpenSim display menu in the
// Visualizer window and particular selections from it.
static const int ShowMenuId = 1;
static const int ToggleWrapGeometry = 0;
static const int ToggleContactGeometry = 1;
static const int ToggleMusclePaths = 2;
static const int TogglePathPoints = 3;
static const int ToggleMarkers = 4;
static const int ToggleFrames = 5;
static const int ToggleDefaultGeometry = 6;

/* This class gets first crack at user input coming in through the Visualizer
window. We use it to intercept anything we want to handle as part of the
standard OpenSim-provided interface, such as turning on and off display of wrap
objects. Anything we don't handle here will just get passed on to the
Visualizer's InputSilo where it will remain until the user's program goes
looking for it. */
class OpenSimInputListener : public Visualizer::InputListener {
public:
    OpenSimInputListener(Model& model) : _model(model) {}

    /* This is the implementation of the InputListener interface. We're going
    to override only the menu-pick method and ignore anything we don't
    recognize. Caution: this is being called from the Visualizer's input thread,
    *not* the main execution thread. Synchronization is required to do anything
    complicated; here we're just setting/clearing visualization flags so no
    synchronization is required. Note that the Visualizer's InputSilo class
    handles synchronization automatically but this one does not. */
    bool menuSelected(int menu, int item) override {
        if (menu != ShowMenuId) return false; // some other menu
        ModelDisplayHints& hints = _model.updDisplayHints();
        switch(item) {
        case ToggleWrapGeometry:
            hints.set_show_wrap_geometry(!hints.get_show_wrap_geometry());
            return true; // absorb this input
        case ToggleContactGeometry:
            hints.set_show_contact_geometry(!hints.get_show_contact_geometry());
            return true;
        case ToggleMusclePaths:
            hints.set_show_path_geometry(!hints.get_show_path_geometry());
            return true;
        case TogglePathPoints:
            hints.set_show_path_points(!hints.get_show_path_points());
            return true;
        case ToggleMarkers:
            hints.set_show_markers(!hints.get_show_markers());
            return true;
        case ToggleDefaultGeometry: {
            SimbodyMatterSubsystem& matter =
                _model.updMatterSubsystem();
            matter.setShowDefaultGeometry(!matter.getShowDefaultGeometry());
            return true;
            }
        };
        return false; // let someone else deal with this input
    }
private:
    Model&  _model;
};

// Draw a path point with a small body-axis-aligned cross centered on
// the point.
void DefaultGeometry::drawPathPoint(const MobilizedBodyIndex&             body,
                          const Vec3&                           pt_B,
                          const Vec3&                           color,
                          Array_<SimTK::DecorativeGeometry>&    geometry)
{
    geometry.push_back(DecorativeSphere(0.005)
                .setTransform(pt_B)
                .setBodyId(body)
                .setColor(color)
                .setOpacity(0.8));
}

void DefaultGeometry::generateDecorations
   (const State&                         state,
    Array_<SimTK::DecorativeGeometry>&   geometry)
{
    // Ask all the ModelComponents to generate dynamic geometry.
    _model.generateDecorations(false, _model.getDisplayHints(),
                               state, geometry);
}

//==============================================================================
//                            MODEL VISUALIZER
//==============================================================================

void ModelVisualizer::show(const SimTK::State& state) const {
    // Make sure we're realized at least through Velocity stage.
    _model.getMultibodySystem().realize(state, SimTK::Stage::Velocity);
    getSimbodyVisualizer().report(state);
}

// See if we can find the given file. The rules are
//  - if it is an absolute pathname, we only get one shot, else:
//  - define "modelDir" to be the absolute pathname of the
//      directory from which we read in the .osim model, if we did,
//      otherwise modelDir="." (current directory).
//  - look for the geometry file in modelDir
//  - look for the geometry file in modelDir/Geometry
//  - search the user added paths in dirToSearch in reverse chronological order
//    i.e. latest path added is searched first.
//  - look for the geometry file in installDir/Geometry
bool ModelVisualizer::
findGeometryFile(const Model& aModel,
                 const std::string&          geoFile,
                 bool&                       geoFileIsAbsolute,
                 SimTK::Array_<std::string>& attempts)
{
    attempts.clear();
    std::string geoDirectory, geoFileName, geoExtension;
    SimTK::Pathname::deconstructPathname(geoFile,
        geoFileIsAbsolute, geoDirectory, geoFileName, geoExtension);

    bool foundIt = false;
    if (geoFileIsAbsolute) {
        attempts.push_back(geoFile);
        foundIt = Pathname::fileExists(attempts.back());
    } else {
        const string geoDir = "Geometry" + Pathname::getPathSeparator();
        string modelDir;
        if (aModel.getInputFileName() == "Unassigned")
            modelDir = Pathname::getCurrentWorkingDirectory();
        else {
            bool isAbsolutePath; string directory, fileName, extension;
            SimTK::Pathname::deconstructPathname(
                aModel.getInputFileName(),
                isAbsolutePath, directory, fileName, extension);
            modelDir = isAbsolutePath
                ? directory
                : Pathname::getCurrentWorkingDirectory() + directory;
        }

        attempts.push_back(modelDir + geoFile);
        foundIt = Pathname::fileExists(attempts.back());

        if (!foundIt) {
            attempts.push_back(modelDir + geoDir + geoFile);
            foundIt = Pathname::fileExists(attempts.back());
        }

        if (!foundIt) {
            for(auto dir = dirsToSearch.crbegin();
                dir != dirsToSearch.crend();
                ++dir) {
                attempts.push_back(*dir + geoFile);
                if(Pathname::fileExists(attempts.back())) {
                    foundIt = true;
                    break;
                }
            }
        }

        if (!foundIt) {
            const string installDir =
                Pathname::getInstallDir("OPENSIM_HOME", "OpenSim");
            attempts.push_back(installDir + geoDir + geoFile);
            foundIt = Pathname::fileExists(attempts.back());
        }
    }

    return foundIt;
}

// Initialize the static variable.
SimTK::Array_<std::string> ModelVisualizer::dirsToSearch{};

void ModelVisualizer::addDirToGeometrySearchPaths(const std::string& dir) {
    // Make sure to add trailing path-separator if one is not present.
    if(dir.back() == Pathname::getPathSeparator().back())
        dirsToSearch.push_back(dir);
    else
        dirsToSearch.push_back(dir + Pathname::getPathSeparator());
}

// Call this on a newly-constructed ModelVisualizer (typically from the Model's
// initSystem() method) to set up the various auxiliary classes used for
// visualization and user interaction. This involves modifications to the
// System that must be done prior to realizeTopology(), and may modify the
// Model also.
void ModelVisualizer::createVisualizer() {
    _model.updMatterSubsystem().setShowDefaultGeometry(false);

    // Allocate a Simbody Visualizer. If environment variable
    // OPENSIM_HOME is set, add its bin subdirectory to the search path
    // for the SimbodyVisualizer executable. The search will go as
    // follows: first look in the same directory as the currently-
    // executing executable; then look in the $OPENSIM_HOME/bin
    // directory, then look at all the paths in the environment
    // variable PATH, then look in various default Simbody places.
    Array_<String> searchPath;
    if (SimTK::Pathname::environmentVariableExists("OPENSIM_HOME")) {
        searchPath.push_back(
            SimTK::Pathname::getEnvironmentVariable("OPENSIM_HOME")
            + "/bin");
    }
    if (SimTK::Pathname::environmentVariableExists("PATH")) {
        const auto& path = SimTK::Pathname::getEnvironmentVariable("PATH");
        std::string buffer{};
        for(const auto ch : path) {
            if(ch == ':' || ch == ';') {
                searchPath.push_back(buffer);
                buffer.clear();
            } else
                buffer.push_back(ch);
        }
    }
    _viz = new SimTK::Visualizer(_model.getMultibodySystem(),
                                 searchPath);

    // Make the Simbody Visualizer (that is, the display window) kill itself
    // when the API-side connection is lost (because the Visualizer object gets
    // destructed). Otherwise it will hang around afterwards.
    _viz->setShutdownWhenDestructed(true);

    _viz->setCameraClippingPlanes(.01,100.);
    _viz->setBackgroundColor(SimTK::Black);
    _viz->setBackgroundType(SimTK::Visualizer::SolidColor);

    // Give it an OpenSim-friendly window heading.
    bool isAbsolutePath; string directory, fileName, extension;
    SimTK::Pathname::deconstructPathname(
        SimTK::Pathname::getThisExecutablePath(),
        isAbsolutePath, directory, fileName, extension);
    _viz->setWindowTitle("OpenSim " + OpenSim::GetVersion()
                            + ": " + fileName + " (" + _model.getName() + ")");

    // Create a menu for choosing what to display.
    SimTK::Array_< std::pair<SimTK::String, int> > selections;
    selections.push_back(std::make_pair("Wrap geometry",
                                        ToggleWrapGeometry));
    selections.push_back(std::make_pair("Contact geometry",
                                        ToggleContactGeometry));
    selections.push_back(std::make_pair("Muscle paths",ToggleMusclePaths));
    selections.push_back(std::make_pair("Path points",TogglePathPoints));
    selections.push_back(std::make_pair("Markers",ToggleMarkers));
    selections.push_back(std::make_pair("Frames",ToggleFrames));
    selections.push_back(std::make_pair("Default geometry",
                                        ToggleDefaultGeometry));
    _viz->addMenu("Show", ShowMenuId, selections);

    // Add a DecorationGenerator to dispatch runtime generateDecorations()
    // calls.
    _decoGen = new DefaultGeometry(_model);
    _viz->addDecorationGenerator(_decoGen);

    // Add an input listener to handle display menu picks.
    _viz->addInputListener(new OpenSimInputListener(_model));

    // Allocate an InputSilo to pick up anything the above listener doesn't.
    _silo = new SimTK::Visualizer::InputSilo();
    _viz->addInputListener(_silo);

    // This is used for regular output of frames during forward dynamics.
    // TODO: allow user control of timing.
    _model.updMultibodySystem().addEventReporter
        (new SimTK::Visualizer::Reporter(*_viz, 1./30));
}

// We also rummage through the model to find fixed geometry that should be part
// of every frame. The supplied State must be realized through Instance stage.
void ModelVisualizer::collectFixedGeometry(const State& state) const {
    // Collect any fixed geometry from the ModelComponents.
    Array_<DecorativeGeometry> fixedGeometry;
    _model.generateDecorations
       (true, _model.getDisplayHints(), state, fixedGeometry);

    for (unsigned i=0; i < fixedGeometry.size(); ++i) {
        const DecorativeGeometry& dgeo = fixedGeometry[i];
        //cout << dgeo.getBodyId() << dgeo.getTransform() << endl;
        _viz->addDecoration(MobilizedBodyIndex(dgeo.getBodyId()),
                            Transform(), dgeo);
    }
}
<commit_msg>Remove default solid black background as the preset value.<commit_after>/* -------------------------------------------------------------------------- *
 *                       OpenSim:  ModelVisualizer.cpp                        *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Michael A. Sherman                                              *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

#include "ModelVisualizer.h"
#include "Model.h"
#include <OpenSim/version.h>
#include <OpenSim/Common/ModelDisplayHints.h>
#include <simbody/internal/Visualizer_InputListener.h>
#include <simbody/internal/Visualizer_Reporter.h>

#include <string>
using std::string;
#include <iostream>
using std::cout; using std::cerr; using std::clog; using std::endl;

using namespace OpenSim;
using namespace SimTK;

//==============================================================================
//                       OPENSIM INPUT LISTENER
//==============================================================================

// These constants are used to identify the OpenSim display menu in the
// Visualizer window and particular selections from it.
static const int ShowMenuId = 1;
static const int ToggleWrapGeometry = 0;
static const int ToggleContactGeometry = 1;
static const int ToggleMusclePaths = 2;
static const int TogglePathPoints = 3;
static const int ToggleMarkers = 4;
static const int ToggleFrames = 5;
static const int ToggleDefaultGeometry = 6;

/* This class gets first crack at user input coming in through the Visualizer
window. We use it to intercept anything we want to handle as part of the
standard OpenSim-provided interface, such as turning on and off display of wrap
objects. Anything we don't handle here will just get passed on to the
Visualizer's InputSilo where it will remain until the user's program goes
looking for it. */
class OpenSimInputListener : public Visualizer::InputListener {
public:
    OpenSimInputListener(Model& model) : _model(model) {}

    /* This is the implementation of the InputListener interface. We're going
    to override only the menu-pick method and ignore anything we don't
    recognize. Caution: this is being called from the Visualizer's input thread,
    *not* the main execution thread. Synchronization is required to do anything
    complicated; here we're just setting/clearing visualization flags so no
    synchronization is required. Note that the Visualizer's InputSilo class
    handles synchronization automatically but this one does not. */
    bool menuSelected(int menu, int item) override {
        if (menu != ShowMenuId) return false; // some other menu
        ModelDisplayHints& hints = _model.updDisplayHints();
        switch(item) {
        case ToggleWrapGeometry:
            hints.set_show_wrap_geometry(!hints.get_show_wrap_geometry());
            return true; // absorb this input
        case ToggleContactGeometry:
            hints.set_show_contact_geometry(!hints.get_show_contact_geometry());
            return true;
        case ToggleMusclePaths:
            hints.set_show_path_geometry(!hints.get_show_path_geometry());
            return true;
        case TogglePathPoints:
            hints.set_show_path_points(!hints.get_show_path_points());
            return true;
        case ToggleMarkers:
            hints.set_show_markers(!hints.get_show_markers());
            return true;
        case ToggleDefaultGeometry: {
            SimbodyMatterSubsystem& matter =
                _model.updMatterSubsystem();
            matter.setShowDefaultGeometry(!matter.getShowDefaultGeometry());
            return true;
            }
        };
        return false; // let someone else deal with this input
    }
private:
    Model&  _model;
};

// Draw a path point with a small body-axis-aligned cross centered on
// the point.
void DefaultGeometry::drawPathPoint(const MobilizedBodyIndex&             body,
                          const Vec3&                           pt_B,
                          const Vec3&                           color,
                          Array_<SimTK::DecorativeGeometry>&    geometry)
{
    geometry.push_back(DecorativeSphere(0.005)
                .setTransform(pt_B)
                .setBodyId(body)
                .setColor(color)
                .setOpacity(0.8));
}

void DefaultGeometry::generateDecorations
   (const State&                         state,
    Array_<SimTK::DecorativeGeometry>&   geometry)
{
    // Ask all the ModelComponents to generate dynamic geometry.
    _model.generateDecorations(false, _model.getDisplayHints(),
                               state, geometry);
}

//==============================================================================
//                            MODEL VISUALIZER
//==============================================================================

void ModelVisualizer::show(const SimTK::State& state) const {
    // Make sure we're realized at least through Velocity stage.
    _model.getMultibodySystem().realize(state, SimTK::Stage::Velocity);
    getSimbodyVisualizer().report(state);
}

// See if we can find the given file. The rules are
//  - if it is an absolute pathname, we only get one shot, else:
//  - define "modelDir" to be the absolute pathname of the
//      directory from which we read in the .osim model, if we did,
//      otherwise modelDir="." (current directory).
//  - look for the geometry file in modelDir
//  - look for the geometry file in modelDir/Geometry
//  - search the user added paths in dirToSearch in reverse chronological order
//    i.e. latest path added is searched first.
//  - look for the geometry file in installDir/Geometry
bool ModelVisualizer::
findGeometryFile(const Model& aModel,
                 const std::string&          geoFile,
                 bool&                       geoFileIsAbsolute,
                 SimTK::Array_<std::string>& attempts)
{
    attempts.clear();
    std::string geoDirectory, geoFileName, geoExtension;
    SimTK::Pathname::deconstructPathname(geoFile,
        geoFileIsAbsolute, geoDirectory, geoFileName, geoExtension);

    bool foundIt = false;
    if (geoFileIsAbsolute) {
        attempts.push_back(geoFile);
        foundIt = Pathname::fileExists(attempts.back());
    } else {
        const string geoDir = "Geometry" + Pathname::getPathSeparator();
        string modelDir;
        if (aModel.getInputFileName() == "Unassigned")
            modelDir = Pathname::getCurrentWorkingDirectory();
        else {
            bool isAbsolutePath; string directory, fileName, extension;
            SimTK::Pathname::deconstructPathname(
                aModel.getInputFileName(),
                isAbsolutePath, directory, fileName, extension);
            modelDir = isAbsolutePath
                ? directory
                : Pathname::getCurrentWorkingDirectory() + directory;
        }

        attempts.push_back(modelDir + geoFile);
        foundIt = Pathname::fileExists(attempts.back());

        if (!foundIt) {
            attempts.push_back(modelDir + geoDir + geoFile);
            foundIt = Pathname::fileExists(attempts.back());
        }

        if (!foundIt) {
            for(auto dir = dirsToSearch.crbegin();
                dir != dirsToSearch.crend();
                ++dir) {
                attempts.push_back(*dir + geoFile);
                if(Pathname::fileExists(attempts.back())) {
                    foundIt = true;
                    break;
                }
            }
        }

        if (!foundIt) {
            const string installDir =
                Pathname::getInstallDir("OPENSIM_HOME", "OpenSim");
            attempts.push_back(installDir + geoDir + geoFile);
            foundIt = Pathname::fileExists(attempts.back());
        }
    }

    return foundIt;
}

// Initialize the static variable.
SimTK::Array_<std::string> ModelVisualizer::dirsToSearch{};

void ModelVisualizer::addDirToGeometrySearchPaths(const std::string& dir) {
    // Make sure to add trailing path-separator if one is not present.
    if(dir.back() == Pathname::getPathSeparator().back())
        dirsToSearch.push_back(dir);
    else
        dirsToSearch.push_back(dir + Pathname::getPathSeparator());
}

// Call this on a newly-constructed ModelVisualizer (typically from the Model's
// initSystem() method) to set up the various auxiliary classes used for
// visualization and user interaction. This involves modifications to the
// System that must be done prior to realizeTopology(), and may modify the
// Model also.
void ModelVisualizer::createVisualizer() {
    _model.updMatterSubsystem().setShowDefaultGeometry(false);

    // Allocate a Simbody Visualizer. If environment variable
    // OPENSIM_HOME is set, add its bin subdirectory to the search path
    // for the SimbodyVisualizer executable. The search will go as
    // follows: first look in the same directory as the currently-
    // executing executable; then look in the $OPENSIM_HOME/bin
    // directory, then look at all the paths in the environment
    // variable PATH, then look in various default Simbody places.
    Array_<String> searchPath;
    if (SimTK::Pathname::environmentVariableExists("OPENSIM_HOME")) {
        searchPath.push_back(
            SimTK::Pathname::getEnvironmentVariable("OPENSIM_HOME")
            + "/bin");
    }
    if (SimTK::Pathname::environmentVariableExists("PATH")) {
        const auto& path = SimTK::Pathname::getEnvironmentVariable("PATH");
        std::string buffer{};
        for(const auto ch : path) {
            if(ch == ':' || ch == ';') {
                searchPath.push_back(buffer);
                buffer.clear();
            } else
                buffer.push_back(ch);
        }
    }
    _viz = new SimTK::Visualizer(_model.getMultibodySystem(),
                                 searchPath);

    // Make the Simbody Visualizer (that is, the display window) kill itself
    // when the API-side connection is lost (because the Visualizer object gets
    // destructed). Otherwise it will hang around afterwards.
    _viz->setShutdownWhenDestructed(true);

    _viz->setCameraClippingPlanes(.01,100.);

    // Give it an OpenSim-friendly window heading.
    bool isAbsolutePath; string directory, fileName, extension;
    SimTK::Pathname::deconstructPathname(
        SimTK::Pathname::getThisExecutablePath(),
        isAbsolutePath, directory, fileName, extension);
    _viz->setWindowTitle("OpenSim " + OpenSim::GetVersion()
                            + ": " + fileName + " (" + _model.getName() + ")");

    // Create a menu for choosing what to display.
    SimTK::Array_< std::pair<SimTK::String, int> > selections;
    selections.push_back(std::make_pair("Wrap geometry",
                                        ToggleWrapGeometry));
    selections.push_back(std::make_pair("Contact geometry",
                                        ToggleContactGeometry));
    selections.push_back(std::make_pair("Muscle paths",ToggleMusclePaths));
    selections.push_back(std::make_pair("Path points",TogglePathPoints));
    selections.push_back(std::make_pair("Markers",ToggleMarkers));
    selections.push_back(std::make_pair("Frames",ToggleFrames));
    selections.push_back(std::make_pair("Default geometry",
                                        ToggleDefaultGeometry));
    _viz->addMenu("Show", ShowMenuId, selections);

    // Add a DecorationGenerator to dispatch runtime generateDecorations()
    // calls.
    _decoGen = new DefaultGeometry(_model);
    _viz->addDecorationGenerator(_decoGen);

    // Add an input listener to handle display menu picks.
    _viz->addInputListener(new OpenSimInputListener(_model));

    // Allocate an InputSilo to pick up anything the above listener doesn't.
    _silo = new SimTK::Visualizer::InputSilo();
    _viz->addInputListener(_silo);

    // This is used for regular output of frames during forward dynamics.
    // TODO: allow user control of timing.
    _model.updMultibodySystem().addEventReporter
        (new SimTK::Visualizer::Reporter(*_viz, 1./30));
}

// We also rummage through the model to find fixed geometry that should be part
// of every frame. The supplied State must be realized through Instance stage.
void ModelVisualizer::collectFixedGeometry(const State& state) const {
    // Collect any fixed geometry from the ModelComponents.
    Array_<DecorativeGeometry> fixedGeometry;
    _model.generateDecorations
       (true, _model.getDisplayHints(), state, fixedGeometry);

    for (unsigned i=0; i < fixedGeometry.size(); ++i) {
        const DecorativeGeometry& dgeo = fixedGeometry[i];
        //cout << dgeo.getBodyId() << dgeo.getTransform() << endl;
        _viz->addDecoration(MobilizedBodyIndex(dgeo.getBodyId()),
                            Transform(), dgeo);
    }
}
<|endoftext|>


<commit_before>//
// Created by Vadim N. on 04/04/2015.
//

#include <ostream>

#include "Model"

using namespace ymir;

/**
 * \brief Main function of a script for generation of pre-selected receptors. It has
 * a strict order of input arguments in console:
 * argv[0] - name of the script (default);
 * argv[1] - path to a model
 * argv[2] - number of immune receptors to generate
 * argv[3] - path to an output file
 */
int main(int argc, char* argv[]) {
    std::string model_path(argv[1]), out_file_path(argv[3]);
    size_t count = std::stoi(argv[2]);

    std::cout << "Model path:\t" << model_path << std::endl;
    std::cout << "Output file:\t" << out_file_path << std::endl;
    std::cout << "Number of clonotypes:\t" << (size_t) count << std::endl;
    std::cout << std::endl;

    ProbabilisticAssemblingModel model(model_path);

    if (model.status()) {
        std::cout << std::endl;

        size_t to_generate, generated = 0;
        size_t block_size = 100000;
        RepertoireWriter writer;
        size_t iter = 0;
        while (generated < count) {
            to_generate = std::min(count - generated, block_size);
            generated += to_generate;
            Cloneset gen_rep = model.generateSequences(to_generate, false);
            if (!writer.write(out_file_path, gen_rep, model.gene_segments(), iter > 0)) {
                std::cout << "Problems in writing the output file. Terminating..." << std::endl;
            }
            std::cout << "Generated " << (size_t) generated << "/" << (size_t) count << std::endl;
            ++iter;
        }
    } else {
        std::cout << "Problems with the model. Terminating..." << std::endl;
    }

    return 0;
}<commit_msg>remove iter<commit_after>//
// Created by Vadim N. on 04/04/2015.
//

#include <ostream>

#include "Model"

using namespace ymir;

/**
 * \brief Main function of a script for generation of pre-selected receptors. It has
 * a strict order of input arguments in console:
 * argv[0] - name of the script (default);
 * argv[1] - path to a model
 * argv[2] - number of immune receptors to generate
 * argv[3] - path to an output file
 */
int main(int argc, char* argv[]) {
    std::string model_path(argv[1]), out_file_path(argv[3]);
    size_t count = std::stoi(argv[2]);

    std::cout << "Model path:\t" << model_path << std::endl;
    std::cout << "Output file:\t" << out_file_path << std::endl;
    std::cout << "Number of clonotypes:\t" << (size_t) count << std::endl;
    std::cout << std::endl;

    ProbabilisticAssemblingModel model(model_path);

    if (model.status()) {
        std::cout << std::endl;

        size_t to_generate, generated = 0;
        size_t block_size = 100000;
        RepertoireWriter writer;
        while (generated < count) {
            to_generate = std::min(count - generated, block_size);
            generated += to_generate;
            Cloneset gen_rep = model.generateSequences(to_generate, false);
            if (!writer.write(out_file_path, gen_rep, model.gene_segments(), generated == to_generate)) {
                std::cout << "Problems in writing the output file. Terminating..." << std::endl;
            }
            std::cout << "Generated " << (size_t) generated << "/" << (size_t) count << std::endl;
        }
    } else {
        std::cout << "Problems with the model. Terminating..." << std::endl;
    }

    return 0;
}<|endoftext|>


<commit_before>#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef long long ll;

class BigNum
{
public:
    BigNum() : size_(1) { d_[0] = 0; }
    BigNum(int x);
    BigNum(const char *s);
    void To(int x);
    void Print() const;
    void MulInt(int x);
    BigNum MulBig(const BigNum &y) const;

private:
    static const int kSize = 60;
    static const int kDigits = 4;
    static const int kBase = 10000;
    static void Check(bool b) { while (!b)puts("error"); }
    int size_;
    int d_[kSize];
};

BigNum::BigNum(int x) : size_(0)
{
    for (; !size_ || x; d_[size_++] = x % kBase, x /= kBase);
}

BigNum::BigNum(const char *s)
{
    while (*s == '0')s++;
    if (!*s){ To(0); return; }
    int l = strlen(s);
    size_ = (l - 1) / kDigits + 1;
    int p = size_ - 1; d_[p] = 0;
    for (int i = 0; i < l; i++)
    {
        if (i == l - p * kDigits)d_[--p] = 0;
        d_[p] = d_[p] * 10 + s[i] - '0';
    }
}

void BigNum::To(int x)
{
    size_ = 1; d_[0] = x;
}

void BigNum::Print() const
{
    printf("%d", d_[size_ - 1]);
    for (int i = size_ - 2; i >= 0; i--)
        printf("%0*d", kDigits, d_[i]);
}

void BigNum::MulInt(int x)
{
    if (x == 0) { To(0); return; }
    int c = 0;
    for (int i = 0; i < size_; i++){ ll t = (ll)d_[i] * x + c; c = static_cast<int>(t / kBase); d_[i] = t % kBase; }
    for (; c; c /= kBase) d_[size_++] = c % kBase;
}

BigNum BigNum::MulBig(const BigNum &y) const
{
    int l = size_ + y.size_;
    Check(l <= kSize);
    BigNum z;
    memset(z.d_, 0, sizeof(z.d_));
    for (int a = 0; a < size_; a++)for (int b = 0; b < y.size_; b++)
    {
        z.d_[a + b] += d_[a] * y.d_[b];
        if (z.d_[a + b] >= kBase) { z.d_[a + b + 1] += z.d_[a + b] / kBase; z.d_[a + b] %= kBase; }
        /* carefully */
    }
    for (z.size_ = l; z.size_ > 1 && !z.d_[z.size_ - 1]; z.size_--);
    return z;
}
<commit_msg>BigNum add size()<commit_after>#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef long long ll;

class BigNum
{
public:
    BigNum() : size_(1) { d_[0] = 0; }
    BigNum(int x);
    BigNum(const char *s);
    int size() const { return size_; }
    void To(int x);
    void Print() const;
    void MulInt(int x);
    BigNum MulBig(const BigNum &y) const;

private:
    static const int kSize = 60;
    static const int kDigits = 4;
    static const int kBase = 10000;
    static void Check(bool b) { while (!b)puts("error"); }
    int size_;
    int d_[kSize];
};

BigNum::BigNum(int x) : size_(0)
{
    for (; !size_ || x; d_[size_++] = x % kBase, x /= kBase);
}

BigNum::BigNum(const char *s)
{
    while (*s == '0')s++;
    if (!*s){ To(0); return; }
    int l = strlen(s);
    size_ = (l - 1) / kDigits + 1;
    int p = size_ - 1; d_[p] = 0;
    for (int i = 0; i < l; i++)
    {
        if (i == l - p * kDigits)d_[--p] = 0;
        d_[p] = d_[p] * 10 + s[i] - '0';
    }
}

void BigNum::To(int x)
{
    size_ = 1; d_[0] = x;
}

void BigNum::Print() const
{
    printf("%d", d_[size_ - 1]);
    for (int i = size_ - 2; i >= 0; i--)
        printf("%0*d", kDigits, d_[i]);
}

void BigNum::MulInt(int x)
{
    if (x == 0) { To(0); return; }
    int c = 0;
    for (int i = 0; i < size_; i++){ ll t = (ll)d_[i] * x + c; c = static_cast<int>(t / kBase); d_[i] = t % kBase; }
    for (; c; c /= kBase) d_[size_++] = c % kBase;
}

BigNum BigNum::MulBig(const BigNum &y) const
{
    int l = size_ + y.size_;
    Check(l <= kSize);
    BigNum z;
    memset(z.d_, 0, sizeof(z.d_));
    for (int a = 0; a < size_; a++)for (int b = 0; b < y.size_; b++)
    {
        z.d_[a + b] += d_[a] * y.d_[b];
        if (z.d_[a + b] >= kBase) { z.d_[a + b + 1] += z.d_[a + b] / kBase; z.d_[a + b] %= kBase; }
        /* carefully */
    }
    for (z.size_ = l; z.size_ > 1 && !z.d_[z.size_ - 1]; z.size_--);
    return z;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll_test.hpp"

#include "dll/neural/conv_same_layer.hpp"
#include "dll/neural/conv_layer.hpp"
#include "dll/neural/dense_layer.hpp"
#include "dll/dbn.hpp"
#include "dll/pooling/mp_layer.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/conv/same/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 28 * 28, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/2", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,
            dll::dense_desc<6 * 14 * 14, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/3", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,

            dll::conv_same_desc<6, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<12, 14, 14, 1, 2, 2>::layer_t,

            dll::dense_desc<12 * 7 * 7, 400, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<400, 10, dll::activation<dll::function::SOFTMAX>>::layer_t
        >, dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.01;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/4", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::conv_same_desc<6, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,

            dll::conv_same_desc<6, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::conv_same_desc<12, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<12, 14, 14, 1, 2, 2>::layer_t,

            dll::dense_desc<12 * 7 * 7, 400, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<400, 10, dll::activation<dll::function::SOFTMAX>>::layer_t
        >, dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.01;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}
<commit_msg>Make the test more stable<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll_test.hpp"

#include "dll/neural/conv_same_layer.hpp"
#include "dll/neural/conv_layer.hpp"
#include "dll/neural/dense_layer.hpp"
#include "dll/dbn.hpp"
#include "dll/pooling/mp_layer.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/conv/same/1", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::dense_desc<6 * 28 * 28, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(600);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    dbn->display();

    FT_CHECK(50, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/2", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::SIGMOID>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,
            dll::dense_desc<6 * 14 * 14, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.05;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/3", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,

            dll::conv_same_desc<6, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<12, 14, 14, 1, 2, 2>::layer_t,

            dll::dense_desc<12 * 7 * 7, 400, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<400, 10, dll::activation<dll::function::SOFTMAX>>::layer_t
        >, dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.01;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}

TEST_CASE("unit/conv/same/4", "[conv][dbn][mnist][sgd]") {
    typedef dll::dbn_desc<
        dll::dbn_layers<
            dll::conv_same_desc<1, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::conv_same_desc<6, 28, 28, 6, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<6, 28, 28, 1, 2, 2>::layer_t,

            dll::conv_same_desc<6, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::conv_same_desc<12, 14, 14, 12, 3, 3, dll::activation<dll::function::RELU>>::layer_t,
            dll::mp_layer_3d_desc<12, 14, 14, 1, 2, 2>::layer_t,

            dll::dense_desc<12 * 7 * 7, 400, dll::activation<dll::function::RELU>>::layer_t,
            dll::dense_desc<400, 10, dll::activation<dll::function::SOFTMAX>>::layer_t
        >, dll::trainer<dll::sgd_trainer>, dll::batch_size<20>>::dbn_t dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 1, 28, 28>>(500);
    REQUIRE(!dataset.training_images.empty());

    auto dbn = std::make_unique<dbn_t>();

    dbn->learning_rate = 0.01;

    dbn->display();

    FT_CHECK(25, 5e-2);
    TEST_CHECK(0.2);
}
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

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

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

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

#include "EglContextHandler.h"

#include <Utility/Debug.h>

#include "Context.h"

namespace Magnum { namespace Platform {

EglContextHandler::~EglContextHandler() {
    eglDestroyContext(display, context);
    eglDestroySurface(display, surface);
    eglTerminate(display);
}

VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
    /* Initialize */
    display = eglGetDisplay(nativeDisplay);
    if(!eglInitialize(display, nullptr, nullptr)) {
        Error() << "Cannot initialize EGL:" << errorString(eglGetError());
        std::exit(1);
    }

    #ifndef MAGNUM_TARGET_GLES
    EGLenum api = EGL_OPENGL_API;
    #else
    EGLenum api = EGL_OPENGL_ES_API;
    #endif
    if(!eglBindAPI(api)) {
        Error() << "Cannot bind EGL API:" << errorString(eglGetError());
        std::exit(1);
    }

    /* Choose EGL config */
    static const EGLint attribs[] = {
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_DEPTH_SIZE, 1,
        #ifndef MAGNUM_TARGET_GLES
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        #else
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        #endif
        EGL_NONE
    };
    EGLint configCount;
    if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) {
        Error() << "Cannot get EGL visual config:" << errorString(eglGetError());
        std::exit(1);
    }

    if(!configCount) {
        Error() << "No matching EGL visual config available";
        std::exit(1);
    }

    /* Get visual ID */
    EGLint visualId;
    if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
        Error() << "Cannot get native visual ID:" << errorString(eglGetError());
        std::exit(1);
    }

    return visualId;
}

void EglContextHandler::createContext(EGLNativeWindowType window) {
    static const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #endif
        EGL_NONE
    };
    if(!eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes)) {
        Error() << "Cannot create EGL context:" << errorString(eglGetError());
        std::exit(1);
    }
    if(!(surface = eglCreateWindowSurface(display, config, window, NULL))) {
        Error() << "Cannot create window surface:" << errorString(eglGetError());
        std::exit(1);
    }

    /** @bug Fixme: On desktop OpenGL and Mesa EGL implementation OpenGL version is 1.0, which is wrong */
}

const char* EglContextHandler::errorString(EGLint error) {
    switch(error) {
        #define _error(name) case name: return #name;
        _error(EGL_SUCCESS)
        _error(EGL_NOT_INITIALIZED)
        _error(EGL_BAD_ACCESS)
        _error(EGL_BAD_ALLOC)
        _error(EGL_BAD_ATTRIBUTE)
        _error(EGL_BAD_CONTEXT)
        _error(EGL_BAD_CONFIG)
        _error(EGL_BAD_CURRENT_SURFACE)
        _error(EGL_BAD_DISPLAY)
        _error(EGL_BAD_SURFACE)
        _error(EGL_BAD_MATCH)
        _error(EGL_BAD_PARAMETER)
        _error(EGL_BAD_NATIVE_PIXMAP)
        _error(EGL_BAD_NATIVE_WINDOW)
        _error(EGL_CONTEXT_LOST)
        #undef _error
    }

    return {};
}

}}
<commit_msg>Why the hell did I write this?<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

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

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

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

#include "EglContextHandler.h"

#include <Utility/Debug.h>

#include "Context.h"

namespace Magnum { namespace Platform {

EglContextHandler::~EglContextHandler() {
    eglDestroyContext(display, context);
    eglDestroySurface(display, surface);
    eglTerminate(display);
}

VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
    /* Initialize */
    display = eglGetDisplay(nativeDisplay);
    if(!eglInitialize(display, nullptr, nullptr)) {
        Error() << "Cannot initialize EGL:" << errorString(eglGetError());
        std::exit(1);
    }

    #ifndef MAGNUM_TARGET_GLES
    EGLenum api = EGL_OPENGL_API;
    #else
    EGLenum api = EGL_OPENGL_ES_API;
    #endif
    if(!eglBindAPI(api)) {
        Error() << "Cannot bind EGL API:" << errorString(eglGetError());
        std::exit(1);
    }

    /* Choose EGL config */
    static const EGLint attribs[] = {
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_DEPTH_SIZE, 1,
        #ifndef MAGNUM_TARGET_GLES
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        #else
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        #endif
        EGL_NONE
    };
    EGLint configCount;
    if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) {
        Error() << "Cannot get EGL visual config:" << errorString(eglGetError());
        std::exit(1);
    }

    if(!configCount) {
        Error() << "No matching EGL visual config available";
        std::exit(1);
    }

    /* Get visual ID */
    EGLint visualId;
    if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) {
        Error() << "Cannot get native visual ID:" << errorString(eglGetError());
        std::exit(1);
    }

    return visualId;
}

void EglContextHandler::createContext(EGLNativeWindowType window) {
    static const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #endif
        EGL_NONE
    };
    if(!eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes)) {
        Error() << "Cannot create EGL context:" << errorString(eglGetError());
        std::exit(1);
    }
    if(!(surface = eglCreateWindowSurface(display, config, window, nullptr))) {
        Error() << "Cannot create window surface:" << errorString(eglGetError());
        std::exit(1);
    }

    /** @bug Fixme: On desktop OpenGL and Mesa EGL implementation OpenGL version is 1.0, which is wrong */
}

const char* EglContextHandler::errorString(EGLint error) {
    switch(error) {
        #define _error(name) case name: return #name;
        _error(EGL_SUCCESS)
        _error(EGL_NOT_INITIALIZED)
        _error(EGL_BAD_ACCESS)
        _error(EGL_BAD_ALLOC)
        _error(EGL_BAD_ATTRIBUTE)
        _error(EGL_BAD_CONTEXT)
        _error(EGL_BAD_CONFIG)
        _error(EGL_BAD_CURRENT_SURFACE)
        _error(EGL_BAD_DISPLAY)
        _error(EGL_BAD_SURFACE)
        _error(EGL_BAD_MATCH)
        _error(EGL_BAD_PARAMETER)
        _error(EGL_BAD_NATIVE_PIXMAP)
        _error(EGL_BAD_NATIVE_WINDOW)
        _error(EGL_CONTEXT_LOST)
        #undef _error
    }

    return {};
}

}}
<|endoftext|>


<commit_before>#ifndef __FORK_JOIN_HPP__
#define __FORK_JOIN_HPP__

#include "SoftXMT.hpp"
#include "Addressing.hpp"
#include "tasks/Thread.hpp"
#include "Delegate.hpp"
#include "Tasking.hpp"
#include "Cache.hpp"
#include "common.hpp"

#include <iostream>
#include <fstream>

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

DECLARE_int64(max_forkjoin_threads_per_node);

class Semaphore {
protected:
  int total;
  int count;
  Thread * sleeper;
public:
  Semaphore(int total, int starting): total(total), count(starting), sleeper(NULL) {}
  void acquire_all(Thread * me) {
    while (count < total) {
      VLOG(3) << "Semaphore.count = " << count << " of " << total << ", suspending...";
      sleeper = me;
      SoftXMT_suspend();
    }
  }
  void release(int n=1) {
    count += n;
    if (count >= total && sleeper) {
      SoftXMT_wake(sleeper);
      sleeper = NULL;
    }
  }
  static void am_release(GlobalAddress<Semaphore>* gaddr, size_t sz, void* payload, size_t psz) {
    VLOG(3) << "in am_release()";
    assert(gaddr->node() == SoftXMT_mynode());
    int n = (int)*((int64_t*)payload);
    VLOG(3) << "am_release n=" << n;
    gaddr->pointer()->release((int)n);
  }
  static void release(const GlobalAddress<Semaphore>* gaddr, int n) {
    VLOG(3) << "about to call on " << gaddr->node();
    SoftXMT_call_on(gaddr->node(), &Semaphore::am_release, gaddr, sizeof(GlobalAddress<Semaphore>), &n, sizeof(int64_t));
  }
};

struct LocalTaskJoiner {
  ThreadQueue wakelist;
  int64_t outstanding;
  LocalTaskJoiner(): outstanding(0) {}
  void reset() {
    outstanding = 0;
    while (!wakelist.empty()) SoftXMT_wake(wakelist.dequeue());
  }
  void registerTask() {
    outstanding++;
  }
  void signal() {
    if (outstanding == 0) {
      LOG(ERROR) << "too many calls to signal()";
    } else {
      outstanding--;
    }
    VLOG(3) << "barrier(outstanding=" << outstanding << ")";
    if (outstanding == 0) {
      while (!wakelist.empty()) {
        SoftXMT_wake(wakelist.dequeue());
      }
    }
  }
  void wait() {
    if (outstanding > 0) {
      wakelist.enqueue(CURRENT_THREAD);
      while (outstanding > 0) SoftXMT_suspend();
    }
  }
  static void am_remoteSignal(GlobalAddress<LocalTaskJoiner>* joinAddr, size_t sz, void* payload, size_t psz) {
    CHECK(joinAddr->node() == SoftXMT_mynode());
    joinAddr->pointer()->signal();
  }
  static void remoteSignal(GlobalAddress<LocalTaskJoiner> joinAddr) {
    if (joinAddr.node() == SoftXMT_mynode()) {
      joinAddr.pointer()->signal();
    } else {
      //VLOG(1) << "remoteSignal -> " << joinAddr.node();
      SoftXMT_call_on(joinAddr.node(), &LocalTaskJoiner::am_remoteSignal, &joinAddr);
    }
  }
};

struct ForkJoinIteration {
  void operator()(int64_t index);
};

template<typename T>
struct NodeForkJoinArgs {
  BOOST_STATIC_ASSERT((boost::is_base_of<ForkJoinIteration, T>::value));
  size_t start;
  size_t end;
  T func;
  GlobalAddress<Semaphore> sem;
};

template<typename T>
struct forkjoin_data_t {
  const T* func;
  size_t nthreads;
  size_t* finished;
  Thread * node_th;
  size_t local_start;
  size_t local_end;

  forkjoin_data_t(Thread * me, const T* f, int64_t start, int64_t end, size_t * finished) {
    size_t each_n = (end-start);
    local_start = start;
    local_end = end;
    func = f;
    nthreads = MIN(FLAGS_max_forkjoin_threads_per_node, each_n);
    this->finished = finished;
    node_th = me;
  }
};

struct iters_args {
  size_t rank;
  const void* fjdata;
};

template<typename T>
void task_iters(iters_args * arg) {
  const forkjoin_data_t<T> * fj = static_cast<const forkjoin_data_t<T>*>(arg->fjdata);
  range_t myblock = blockDist(fj->local_start, fj->local_end, arg->rank, fj->nthreads);
  VLOG(4) << "iters_block: " << myblock.start << " - " << myblock.end;

  for (int64_t i=myblock.start; i < myblock.end; i++) {
    (*fj->func)(i);
  }
  (*fj->finished)++;
  if (*fj->finished == fj->nthreads) {
    SoftXMT_wake(fj->node_th);
  }
}

template<typename T>
void fork_join_onenode(const T* func, int64_t start, int64_t end) {
  size_t finished = 0;

  forkjoin_data_t<T> fj(CURRENT_THREAD, func, start, end, &finished);
  iters_args args[fj.nthreads];
  VLOG(2) << "fj.nthreads = " << fj.nthreads;

  for (int i=0; i<fj.nthreads; i++) {
    args[i].fjdata = &fj;
    args[i].rank = i;

    SoftXMT_privateTask(task_iters<T>, &args[i]);
  }
  while (*fj.finished < fj.nthreads) SoftXMT_suspend();

}

template<typename T>
void th_node_fork_join(const NodeForkJoinArgs<T>* a) {
  range_t myblock = blockDist(a->start, a->end, SoftXMT_mynode(), SoftXMT_nodes());
  VLOG(2) << "myblock: " << myblock.start << " - " << myblock.end;
  fork_join_onenode(&a->func, myblock.start, myblock.end);

  VLOG(2) << "about to update sem on " << a->sem.node();
  Semaphore::release(&a->sem, 1);
}

template<typename T>
void fork_join(T* func, int64_t start, int64_t end) {
  Semaphore sem(SoftXMT_nodes(), 0);

  NodeForkJoinArgs<T> fj;
  fj.start = start;
  fj.end = end;
  fj.func = *func;
  fj.sem = make_global(&sem);

  for (Node i=0; i < SoftXMT_nodes(); i++) {
    SoftXMT_remote_privateTask(CACHE_WRAP(th_node_fork_join, &fj), i);

    SoftXMT_flush(i); // TODO: remove this?
  }
  VLOG(2) << "waiting to acquire all";
  sem.acquire_all(CURRENT_THREAD);

  VLOG(2) << "fork_join done";
}

template<typename T>
void th_node_fork_join_custom(const NodeForkJoinArgs<T>* a) {
  a->func(SoftXMT_mynode());

  VLOG(2) << "about to update sem on " << a->sem.node();
  Semaphore::release(&a->sem, 1);
}

template<typename T>
void fork_join_custom(T* func) {
  Semaphore sem(SoftXMT_nodes(), 0);

  NodeForkJoinArgs<T> fj;
  fj.start = 0;
  fj.end = 0;
  fj.func = *func;
  fj.sem = make_global(&sem);

  for (Node i=0; i < SoftXMT_nodes(); i++) {
    SoftXMT_remote_privateTask(CACHE_WRAP(th_node_fork_join_custom, &fj), i);
    SoftXMT_flush(i); // TODO: remove this?
  }
  VLOG(2) << "waiting to acquire all";
  sem.acquire_all(CURRENT_THREAD);

  VLOG(2) << "fork_join done";
}

/// Create a functor for iterations of a loop. This automatically creates a struct which is a subtype of ForkJoinIteration, with the given "state" arguments as fields and a constructor with the fields enumerated in the given order.
///
/// Arguments:
///   name: struct which is created
///   index: name of variable used for loop iteration
///   state: seq of type/name pairs for functor state, of the form:
///     ((type1,name1)) ((type2,name2)) ...
///
/// Example:
///   LOOP_FUNCTOR(set_all, i, ((GlobalAddress<int64_t>,array)) ((int64_t,value)) ) {
///     SoftXMT_delegate_write_word(array+i, value);
///   }
#define LOOP_FUNCTOR(name, index_var, members) \
struct name : ForkJoinIteration { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()(int64_t) const; \
}; \
inline void name::operator()(int64_t index_var) const

#define LOOP_FUNCTOR_TEMPLATED(T, name, index_var, members) \
template< typename T > \
struct name : ForkJoinIteration { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()(int64_t) const; \
}; \
template< typename T > \
inline void name<T>::operator()(int64_t index_var) const

#define LOOP_FUNCTION(name, index_var) \
struct name : ForkJoinIteration { \
inline void operator()(int64_t) const; \
}; \
inline void name::operator()(int64_t index_var) const

struct ConstReplyArgs {
  int64_t replies_left;
  Thread * sleeper;
};

template< typename T >
struct ConstRequestArgs {
  GlobalAddress<T> addr;
  size_t count;
  T value;
  GlobalAddress<ConstReplyArgs> reply;
};

static void memset_reply_am(GlobalAddress<ConstReplyArgs> * reply, size_t sz, void * payload, size_t psz) {
  CHECK(reply->node() == SoftXMT_mynode());
  ConstReplyArgs * r = reply->pointer();
  (r->replies_left)--;
  if (r->replies_left == 0) {
    SoftXMT_wake(r->sleeper);
  }
}

template< typename T >
static void memset_request_am(ConstRequestArgs<T> * args, size_t sz, void* payload, size_t psz) {
  CHECK(args->addr.node() == SoftXMT_mynode()) << "args->addr.node() = " << args->addr.node();
  T * ptr = args->addr.pointer();
  for (size_t i=0; i<args->count; i++) {
    ptr[i] = args->value;
  }
  SoftXMT_call_on(args->reply.node(), &memset_reply_am, &args->reply);
}

template< typename T >
static void SoftXMT_memset(GlobalAddress<T> request_address, T value, size_t count) {
  size_t offset = 0;
  size_t request_bytes = 0;

  ConstReplyArgs reply;
  reply.replies_left = 0;
  reply.sleeper = CURRENT_THREAD;

  ConstRequestArgs<T> args;
  args.addr = request_address;
  args.value = value;
  args.reply = make_global(&reply);

  for (size_t total_bytes = count*sizeof(T); offset < total_bytes; offset += request_bytes) {
    // compute number of bytes remaining in the block containing args.addr
    request_bytes = (args.addr.first_byte().block_max() - args.addr.first_byte());
    if (request_bytes > total_bytes - offset) {
      request_bytes = total_bytes - offset;
    }
    CHECK(request_bytes % sizeof(T) == 0);
    args.count = request_bytes / sizeof(T);

    reply.replies_left++;
    SoftXMT_call_on(args.addr.node(), &memset_request_am, &args);

    args.addr += args.count;
  }

  while (reply.replies_left > 0) SoftXMT_suspend();
}

#endif /* define __FORK_JOIN_HPP__ */
<commit_msg>New version of memset using localize()<commit_after>#ifndef __FORK_JOIN_HPP__
#define __FORK_JOIN_HPP__

#include "SoftXMT.hpp"
#include "Addressing.hpp"
#include "tasks/Thread.hpp"
#include "Delegate.hpp"
#include "Tasking.hpp"
#include "Cache.hpp"
#include "common.hpp"

#include <iostream>
#include <fstream>

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

DECLARE_int64(max_forkjoin_threads_per_node);

class Semaphore {
protected:
  int total;
  int count;
  Thread * sleeper;
public:
  Semaphore(int total, int starting): total(total), count(starting), sleeper(NULL) {}
  void acquire_all(Thread * me) {
    while (count < total) {
      VLOG(3) << "Semaphore.count = " << count << " of " << total << ", suspending...";
      sleeper = me;
      SoftXMT_suspend();
    }
  }
  void release(int n=1) {
    count += n;
    if (count >= total && sleeper) {
      SoftXMT_wake(sleeper);
      sleeper = NULL;
    }
  }
  static void am_release(GlobalAddress<Semaphore>* gaddr, size_t sz, void* payload, size_t psz) {
    VLOG(3) << "in am_release()";
    assert(gaddr->node() == SoftXMT_mynode());
    int n = (int)*((int64_t*)payload);
    VLOG(3) << "am_release n=" << n;
    gaddr->pointer()->release((int)n);
  }
  static void release(const GlobalAddress<Semaphore>* gaddr, int n) {
    VLOG(3) << "about to call on " << gaddr->node();
    SoftXMT_call_on(gaddr->node(), &Semaphore::am_release, gaddr, sizeof(GlobalAddress<Semaphore>), &n, sizeof(int64_t));
  }
};

struct LocalTaskJoiner {
  ThreadQueue wakelist;
  int64_t outstanding;
  LocalTaskJoiner(): outstanding(0) {}
  void reset() {
    outstanding = 0;
    while (!wakelist.empty()) SoftXMT_wake(wakelist.dequeue());
  }
  void registerTask() {
    outstanding++;
  }
  void signal() {
    if (outstanding == 0) {
      LOG(ERROR) << "too many calls to signal()";
    } else {
      outstanding--;
    }
    VLOG(3) << "barrier(outstanding=" << outstanding << ")";
    if (outstanding == 0) {
      while (!wakelist.empty()) {
        SoftXMT_wake(wakelist.dequeue());
      }
    }
  }
  void wait() {
    if (outstanding > 0) {
      wakelist.enqueue(CURRENT_THREAD);
      while (outstanding > 0) SoftXMT_suspend();
    }
  }
  static void am_remoteSignal(GlobalAddress<LocalTaskJoiner>* joinAddr, size_t sz, void* payload, size_t psz) {
    CHECK(joinAddr->node() == SoftXMT_mynode());
    joinAddr->pointer()->signal();
  }
  static void remoteSignal(GlobalAddress<LocalTaskJoiner> joinAddr) {
    if (joinAddr.node() == SoftXMT_mynode()) {
      joinAddr.pointer()->signal();
    } else {
      //VLOG(1) << "remoteSignal -> " << joinAddr.node();
      SoftXMT_call_on(joinAddr.node(), &LocalTaskJoiner::am_remoteSignal, &joinAddr);
    }
  }
};

struct ForkJoinIteration {
  void operator()(int64_t index);
};

template<typename T>
struct NodeForkJoinArgs {
  BOOST_STATIC_ASSERT((boost::is_base_of<ForkJoinIteration, T>::value));
  size_t start;
  size_t end;
  T func;
  GlobalAddress<Semaphore> sem;
};

template<typename T>
struct forkjoin_data_t {
  const T* func;
  size_t nthreads;
  size_t* finished;
  Thread * node_th;
  size_t local_start;
  size_t local_end;

  forkjoin_data_t(Thread * me, const T* f, int64_t start, int64_t end, size_t * finished) {
    size_t each_n = (end-start);
    local_start = start;
    local_end = end;
    func = f;
    nthreads = MIN(FLAGS_max_forkjoin_threads_per_node, each_n);
    this->finished = finished;
    node_th = me;
  }
};

struct iters_args {
  size_t rank;
  const void* fjdata;
};

template<typename T>
void task_iters(iters_args * arg) {
  const forkjoin_data_t<T> * fj = static_cast<const forkjoin_data_t<T>*>(arg->fjdata);
  range_t myblock = blockDist(fj->local_start, fj->local_end, arg->rank, fj->nthreads);
  VLOG(4) << "iters_block: " << myblock.start << " - " << myblock.end;

  for (int64_t i=myblock.start; i < myblock.end; i++) {
    (*fj->func)(i);
  }
  (*fj->finished)++;
  if (*fj->finished == fj->nthreads) {
    SoftXMT_wake(fj->node_th);
  }
}

template<typename T>
void fork_join_onenode(const T* func, int64_t start, int64_t end) {
  size_t finished = 0;

  forkjoin_data_t<T> fj(CURRENT_THREAD, func, start, end, &finished);
  iters_args args[fj.nthreads];
  VLOG(2) << "fj.nthreads = " << fj.nthreads;

  for (int i=0; i<fj.nthreads; i++) {
    args[i].fjdata = &fj;
    args[i].rank = i;

    SoftXMT_privateTask(task_iters<T>, &args[i]);
  }
  while (*fj.finished < fj.nthreads) SoftXMT_suspend();

}

template<typename T>
void th_node_fork_join(const NodeForkJoinArgs<T>* a) {
  range_t myblock = blockDist(a->start, a->end, SoftXMT_mynode(), SoftXMT_nodes());
  VLOG(2) << "myblock: " << myblock.start << " - " << myblock.end;
  fork_join_onenode(&a->func, myblock.start, myblock.end);

  VLOG(2) << "about to update sem on " << a->sem.node();
  Semaphore::release(&a->sem, 1);
}

template<typename T>
void fork_join(T* func, int64_t start, int64_t end) {
  Semaphore sem(SoftXMT_nodes(), 0);

  NodeForkJoinArgs<T> fj;
  fj.start = start;
  fj.end = end;
  fj.func = *func;
  fj.sem = make_global(&sem);

  for (Node i=0; i < SoftXMT_nodes(); i++) {
    SoftXMT_remote_privateTask(CACHE_WRAP(th_node_fork_join, &fj), i);

    SoftXMT_flush(i); // TODO: remove this?
  }
  VLOG(2) << "waiting to acquire all";
  sem.acquire_all(CURRENT_THREAD);

  VLOG(2) << "fork_join done";
}

template<typename T>
void th_node_fork_join_custom(const NodeForkJoinArgs<T>* a) {
  a->func(SoftXMT_mynode());

  VLOG(2) << "about to update sem on " << a->sem.node();
  Semaphore::release(&a->sem, 1);
}

template<typename T>
void fork_join_custom(T* func) {
  Semaphore sem(SoftXMT_nodes(), 0);

  NodeForkJoinArgs<T> fj;
  fj.start = 0;
  fj.end = 0;
  fj.func = *func;
  fj.sem = make_global(&sem);

  for (Node i=0; i < SoftXMT_nodes(); i++) {
    SoftXMT_remote_privateTask(CACHE_WRAP(th_node_fork_join_custom, &fj), i);
    SoftXMT_flush(i); // TODO: remove this?
  }
  VLOG(2) << "waiting to acquire all";
  sem.acquire_all(CURRENT_THREAD);

  VLOG(2) << "fork_join done";
}

/// Create a functor for iterations of a loop. This automatically creates a struct which is a subtype of ForkJoinIteration, with the given "state" arguments as fields and a constructor with the fields enumerated in the given order.
///
/// Arguments:
///   name: struct which is created
///   index: name of variable used for loop iteration
///   state: seq of type/name pairs for functor state, of the form:
///     ((type1,name1)) ((type2,name2)) ...
///
/// Example:
///   LOOP_FUNCTOR(set_all, i, ((GlobalAddress<int64_t>,array)) ((int64_t,value)) ) {
///     SoftXMT_delegate_write_word(array+i, value);
///   }
#define LOOP_FUNCTOR(name, index_var, members) \
struct name : ForkJoinIteration { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()(int64_t) const; \
}; \
inline void name::operator()(int64_t index_var) const

#define LOOP_FUNCTOR_TEMPLATED(T, name, index_var, members) \
template< typename T > \
struct name : ForkJoinIteration { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()(int64_t) const; \
}; \
template< typename T > \
inline void name<T>::operator()(int64_t index_var) const

#define LOOP_FUNCTION(name, index_var) \
struct name : ForkJoinIteration { \
inline void operator()(int64_t) const; \
}; \
inline void name::operator()(int64_t index_var) const

struct ConstReplyArgs {
  int64_t replies_left;
  Thread * sleeper;
};

template< typename T >
struct ConstRequestArgs {
  GlobalAddress<T> addr;
  size_t count;
  T value;
  GlobalAddress<ConstReplyArgs> reply;
};

static void memset_reply_am(GlobalAddress<ConstReplyArgs> * reply, size_t sz, void * payload, size_t psz) {
  CHECK(reply->node() == SoftXMT_mynode());
  ConstReplyArgs * r = reply->pointer();
  (r->replies_left)--;
  if (r->replies_left == 0) {
    SoftXMT_wake(r->sleeper);
  }
}

template< typename T >
static void memset_request_am(ConstRequestArgs<T> * args, size_t sz, void* payload, size_t psz) {
  CHECK(args->addr.node() == SoftXMT_mynode()) << "args->addr.node() = " << args->addr.node();
  T * ptr = args->addr.pointer();
  for (size_t i=0; i<args->count; i++) {
    ptr[i] = args->value;
  }
  SoftXMT_call_on(args->reply.node(), &memset_reply_am, &args->reply);
}

template< typename T >
static void SoftXMT_memset(GlobalAddress<T> request_address, T value, size_t count) {
  size_t offset = 0;
  size_t request_bytes = 0;

  ConstReplyArgs reply;
  reply.replies_left = 0;
  reply.sleeper = CURRENT_THREAD;

  ConstRequestArgs<T> args;
  args.addr = request_address;
  args.value = value;
  args.reply = make_global(&reply);

  for (size_t total_bytes = count*sizeof(T); offset < total_bytes; offset += request_bytes) {
    // compute number of bytes remaining in the block containing args.addr
    request_bytes = (args.addr.first_byte().block_max() - args.addr.first_byte());
    if (request_bytes > total_bytes - offset) {
      request_bytes = total_bytes - offset;
    }
    CHECK(request_bytes % sizeof(T) == 0);
    args.count = request_bytes / sizeof(T);

    reply.replies_left++;
    SoftXMT_call_on(args.addr.node(), &memset_request_am, &args);

    args.addr += args.count;
  }

  while (reply.replies_left > 0) SoftXMT_suspend();
}

LOOP_FUNCTOR_TEMPLATED(T, memset_func, nid, ((GlobalAddress<T>,base)) ((T,value)) ((size_t,count))) {
  T * local_base = base.localize(), * local_end = (base+count).localize();
  for (size_t i=0; i<local_end-local_base; i++) {
    local_base[i] = value;
  }
}

/// Does memset across a global array using a single task on each node and doing local assignments
/// Uses 'GlobalAddress::localize()' to determine the range of actual memory from the global array
/// on a particular node.
template< typename T >
void SoftXMT_memset_local(GlobalAddress<T> base, T value, size_t count) {
  {
    memset_func<T> f(base, value, count);
    fork_join_custom(&f);
  }
}

#endif /* define __FORK_JOIN_HPP__ */
<|endoftext|>


<commit_before>#include "Genes/Castling_Possible_Gene.h"

#include <string>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

Castling_Possible_Gene::Castling_Possible_Gene() noexcept
{
    normalize_sides();
}

void Castling_Possible_Gene::normalize_sides() noexcept
{
    Math::normalize(opening_kingside_preference, opening_queenside_preference);
    Math::normalize(endgame_kingside_preference, endgame_queenside_preference);
}

void Castling_Possible_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Kingside Preference - Opening"] = opening_kingside_preference;
    properties["Queenside Preference - Opening"] = opening_queenside_preference;
    properties["Kingside Preference - Endgame"] = endgame_kingside_preference;
    properties["Queenside Preference - Endgame"] = endgame_queenside_preference;
    properties["Unmoved Rook Bonus - Opening"] = opening_rook_unmoved_score;
    properties["Unmoved Rook Bonus - Endgame"] = endgame_rook_unmoved_score;
}

void Castling_Possible_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    opening_kingside_preference = properties.at("Kingside Preference - Opening");
    opening_queenside_preference = properties.at("Queenside Preference - Opening");
    endgame_kingside_preference = properties.at("Kingside Preference - Endgame");
    endgame_queenside_preference = properties.at("Queenside Preference - Endgame");
    opening_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Opening");
    endgame_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Endgame");
    normalize_sides();
}

std::string Castling_Possible_Gene::name() const noexcept
{
    return "Castling Possible Gene";
}

double Castling_Possible_Gene::score_board(const Board& board, Piece_Color perspective, size_t depth, double game_progress) const noexcept
{
    auto kingside_preference = Math::interpolate(opening_kingside_preference, endgame_kingside_preference, game_progress);
    auto queenside_preference = Math::interpolate(opening_queenside_preference, endgame_queenside_preference, game_progress);

    // check if a castling move lies between here and the actual state of the board
    if(board.player_castled(perspective))
    {
        auto castling_index = board.castling_move_index(perspective);
        auto first_searched_move_index = board.game_length() - depth;
        if(castling_index >= first_searched_move_index) // castling has not occurred on the actual board
        {
            auto castling_distance = castling_index - first_searched_move_index + 1;
            return (board.castling_direction(perspective) > 0 ? kingside_preference : queenside_preference)/castling_distance;
        }
    }

    if( ! board.piece_has_moved(board.find_king(perspective)))
    {
        auto score = 0.0;
        auto base_rank = perspective == Piece_Color::WHITE ? 1 : 8;
        auto unmoved_rook_bonus = Math::interpolate(opening_rook_unmoved_score,
                                                    endgame_rook_unmoved_score,
                                                    game_progress);
        if( ! board.piece_has_moved({'a', base_rank}))
        {
            score += queenside_preference;
        }

        if( ! board.piece_has_moved({'h', base_rank}))
        {
            score += kingside_preference;
        }

        return score*unmoved_rook_bonus;
    }

    return 0.0;
}

void Castling_Possible_Gene::gene_specific_mutation() noexcept
{
    switch(Random::random_integer(1, 6))
    {
        case 1:
            opening_kingside_preference += Random::random_laplace(0.03);
            break;
        case 2:
            endgame_kingside_preference += Random::random_laplace(0.03);
            break;
        case 3:
            opening_queenside_preference += Random::random_laplace(0.03);
            break;
        case 4:
            endgame_queenside_preference += Random::random_laplace(0.03);
            break;
        case 5:
            opening_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        case 6:
            endgame_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        default:
            assert(false);
    }

    normalize_sides();
}
<commit_msg>Remove ternery from castling rook checks<commit_after>#include "Genes/Castling_Possible_Gene.h"

#include <string>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

Castling_Possible_Gene::Castling_Possible_Gene() noexcept
{
    normalize_sides();
}

void Castling_Possible_Gene::normalize_sides() noexcept
{
    Math::normalize(opening_kingside_preference, opening_queenside_preference);
    Math::normalize(endgame_kingside_preference, endgame_queenside_preference);
}

void Castling_Possible_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Kingside Preference - Opening"] = opening_kingside_preference;
    properties["Queenside Preference - Opening"] = opening_queenside_preference;
    properties["Kingside Preference - Endgame"] = endgame_kingside_preference;
    properties["Queenside Preference - Endgame"] = endgame_queenside_preference;
    properties["Unmoved Rook Bonus - Opening"] = opening_rook_unmoved_score;
    properties["Unmoved Rook Bonus - Endgame"] = endgame_rook_unmoved_score;
}

void Castling_Possible_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    opening_kingside_preference = properties.at("Kingside Preference - Opening");
    opening_queenside_preference = properties.at("Queenside Preference - Opening");
    endgame_kingside_preference = properties.at("Kingside Preference - Endgame");
    endgame_queenside_preference = properties.at("Queenside Preference - Endgame");
    opening_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Opening");
    endgame_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Endgame");
    normalize_sides();
}

std::string Castling_Possible_Gene::name() const noexcept
{
    return "Castling Possible Gene";
}

double Castling_Possible_Gene::score_board(const Board& board, Piece_Color perspective, size_t depth, double game_progress) const noexcept
{
    auto kingside_preference = Math::interpolate(opening_kingside_preference, endgame_kingside_preference, game_progress);
    auto queenside_preference = Math::interpolate(opening_queenside_preference, endgame_queenside_preference, game_progress);

    // check if a castling move lies between here and the actual state of the board
    if(board.player_castled(perspective))
    {
        auto castling_index = board.castling_move_index(perspective);
        auto first_searched_move_index = board.game_length() - depth;
        if(castling_index >= first_searched_move_index) // castling has not occurred on the actual board
        {
            auto castling_distance = castling_index - first_searched_move_index + 1;
            return (board.castling_direction(perspective) > 0 ? kingside_preference : queenside_preference)/castling_distance;
        }
    }

    auto king_square = board.find_king(perspective);
    if( ! board.piece_has_moved(king_square))
    {
        auto score = 0.0;
        auto base_rank = king_square.rank();
        auto unmoved_rook_bonus = Math::interpolate(opening_rook_unmoved_score,
                                                    endgame_rook_unmoved_score,
                                                    game_progress);
        if( ! board.piece_has_moved({'a', base_rank}))
        {
            score += queenside_preference;
        }

        if( ! board.piece_has_moved({'h', base_rank}))
        {
            score += kingside_preference;
        }

        return score*unmoved_rook_bonus;
    }

    return 0.0;
}

void Castling_Possible_Gene::gene_specific_mutation() noexcept
{
    switch(Random::random_integer(1, 6))
    {
        case 1:
            opening_kingside_preference += Random::random_laplace(0.03);
            break;
        case 2:
            endgame_kingside_preference += Random::random_laplace(0.03);
            break;
        case 3:
            opening_queenside_preference += Random::random_laplace(0.03);
            break;
        case 4:
            endgame_queenside_preference += Random::random_laplace(0.03);
            break;
        case 5:
            opening_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        case 6:
            endgame_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        default:
            assert(false);
    }

    normalize_sides();
}
<|endoftext|>