<commit_before>/**
 * @file kalmen.hpp
 * @author Vahid Bastani
 *
 */
#ifndef SSMPACK_FILTER_KALMAN_HPP
#define SSMPACK_FILTER_KALMAN_HPP

#include "ssmpack/distribution/gaussian.hpp"
#include "ssmpack/distribution/conditional.hpp"
#include "ssmpack/process/markov.hpp"
#include "ssmpack/process/memoryless.hpp"
#include "ssmpack/process/hierarchical.hpp"
#include "ssmpack/filter/recursive_bayesian_base.hpp"
#include <armadillo>

namespace ssmpack {
namespace filter {

using process::Hierarchical;
using process::Markov;
using process::Memoryless;
using distribution::Conditional;
using distribution::Gaussian;

template <class TProcess>
class Kalman;

template <class T1, class T2, size_t D1, size_t D2>
class Kalman<Hierarchical<Markov<Conditional<Gaussian<D1>, T1>, Gaussian<D1>>,
                          Memoryless<Conditional<Gaussian<D2>, T2>>>>
    : public RecursiveBayesianBase<Kalman<
          Hierarchical<Markov<Conditional<Gaussian<D1>, T1>, Gaussian<D1>>,
                       Memoryless<Conditional<Gaussian<D2>, T2>>>>> {
 public:
  using TProcess =
      Hierarchical<Markov<Conditional<Gaussian<D1>, T1>, Gaussian<D1>>,
                   Memoryless<Conditional<Gaussian<D2>, T2>>>;

  using TCompeleteState =
      std::tuple<arma::vec::fixed<D1>, arma::mat::fixed<D1, D1>>;
private:
  TProcess process_;
  const arma::mat::fixed<D1, D1> &dyn_mat_;
  const arma::mat::fixed<D2, D1> &mes_mat_;
  const arma::mat::fixed<D1, D1> &dyn_cov_;
  const arma::mat::fixed<D2, D2> &mes_cov_;
  arma::vec::fixed<D1> state_vec_;
  arma::mat::fixed<D1, D1> state_cov_;
  arma::vec::fixed<D1> p_state_vec_;
  arma::mat::fixed<D1, D1> p_state_cov_;

 public:
  Kalman(const TProcess &process)
      : process_(process),
        dyn_mat_(
            process_.template getProcess<0>().getCPDF().getParamMap().transfer),
        mes_mat_(
            process_.template getProcess<1>().getCPDF().getParamMap().transfer),
        dyn_cov_(process_.template getProcess<0>()
                     .getCPDF()
                     .getParamMap()
                     .covariance),
        mes_cov_(process_.template getProcess<1>()
                     .getCPDF()
                     .getParamMap()
                     .covariance) {}

  template <class... TArgs>
  void predict(const TArgs &... args) {
    // use the map function to pass controls, avoiding control definition
    // is move used here??
    p_state_vec_ =
        std::get<0>(process_.template getProcess<0>().getCPDF().getParamMap()(
            state_vec_, args...));
    p_state_cov_ = dyn_mat_ * state_cov_ * dyn_mat_.t() + dyn_cov_;
  }

  template <class... TArgs>
  TCompeleteState correct(const arma::vec::fixed<D2> &measurement,
                          const TArgs &... args) {
    arma::vec inovation =
        measurement -
        std::get<0>(process_.template getProcess<1>().getCPDF().getParamMap()(
            p_state_vec_, args...));

    arma::mat inovation_cov = mes_mat_ * p_state_cov_ * mes_mat_.t() + mes_cov_;
    arma::mat kalman_gain =
        p_state_cov_ * mes_mat_.t() * arma::inv_sympd(inovation_cov);

    state_vec_ = p_state_vec_ + kalman_gain * inovation;
    state_cov_ = p_state_cov_ - kalman_gain * mes_mat_ * p_state_cov_;
    return std::make_tuple(state_vec_, state_cov_);
  }

  TCompeleteState initialize() {
    state_vec_ = process_.template getProcess<0>().getInitialPDF().getMean();
    state_cov_ =
        process_.template getProcess<0>().getInitialPDF().getCovariance();
    return std::make_tuple(state_vec_, state_cov_);
  }
};

template <class TProcess>
Kalman<TProcess> makeKalman(TProcess process) {
  return Kalman<TProcess>(process);
}

} // namespace filter
} // namespace ssmpack

#endif // SSMPACK_FILTER_KALMAN_HPP
<commit_msg>refactoring: removing unnecessary template specialization<commit_after>/**
 * @file kalmen.hpp
 * @author Vahid Bastani
 *
 */
#ifndef SSMPACK_FILTER_KALMAN_HPP
#define SSMPACK_FILTER_KALMAN_HPP

#include "ssmpack/distribution/gaussian.hpp"
#include "ssmpack/distribution/conditional.hpp"
#include "ssmpack/process/markov.hpp"
#include "ssmpack/process/memoryless.hpp"
#include "ssmpack/process/hierarchical.hpp"
#include "ssmpack/filter/recursive_bayesian_base.hpp"
#include <armadillo>

namespace ssmpack {
namespace filter {

using process::Hierarchical;
using process::Markov;
using process::Memoryless;
using distribution::Conditional;
using distribution::Gaussian;

template <class STA_MAP, class OBS_MAP, size_t STA_D, size_t OBS_D>
class Kalman
    : public RecursiveBayesianBase<Kalman<STA_MAP, OBS_MAP, STA_D, OBS_D>> {

 public:
  using TProcess =
      Hierarchical<Markov<Conditional<Gaussian<STA_D>, STA_MAP>, Gaussian<STA_D>>,
                   Memoryless<Conditional<Gaussian<OBS_D>, OBS_MAP>>>;

  using TCompeleteState =
      std::tuple<arma::vec::fixed<STA_D>, arma::mat::fixed<STA_D, STA_D>>;
 private:
  TProcess process_;
  const arma::mat::fixed<STA_D, STA_D> &dyn_mat_;
  const arma::mat::fixed<OBS_D, STA_D> &mes_mat_;
  const arma::mat::fixed<STA_D, STA_D> &dyn_cov_;
  const arma::mat::fixed<OBS_D, OBS_D> &mes_cov_;
  arma::vec::fixed<STA_D> state_vec_;
  arma::mat::fixed<STA_D, STA_D> state_cov_;
  arma::vec::fixed<STA_D> p_state_vec_;
  arma::mat::fixed<STA_D, STA_D> p_state_cov_;

 public:
  Kalman(const TProcess &process)
      : process_(process),
        dyn_mat_(
            process_.template getProcess<0>().getCPDF().getParamMap().transfer),
        mes_mat_(
            process_.template getProcess<1>().getCPDF().getParamMap().transfer),
        dyn_cov_(process_.template getProcess<0>()
                     .getCPDF()
                     .getParamMap()
                     .covariance),
        mes_cov_(process_.template getProcess<1>()
                     .getCPDF()
                     .getParamMap()
                     .covariance) {}
  template <class... TArgs>
  void predict(const TArgs &... args) {
    // use the map function to pass controls, avoiding control definition
    // is move used here??
    p_state_vec_ =
        std::get<0>(process_.template getProcess<0>().getCPDF().getParamMap()(
            state_vec_, args...));
    p_state_cov_ = dyn_mat_ * state_cov_ * dyn_mat_.t() + dyn_cov_;
  }

  template <class... TArgs>
  TCompeleteState correct(const arma::vec::fixed<OBS_D> &measurement,
                          const TArgs &... args) {
    arma::vec inovation =
        measurement -
        std::get<0>(process_.template getProcess<1>().getCPDF().getParamMap()(
            p_state_vec_, args...));

    arma::mat inovation_cov = mes_mat_ * p_state_cov_ * mes_mat_.t() + mes_cov_;
    arma::mat kalman_gain =
        p_state_cov_ * mes_mat_.t() * arma::inv_sympd(inovation_cov);

    state_vec_ = p_state_vec_ + kalman_gain * inovation;
    state_cov_ = p_state_cov_ - kalman_gain * mes_mat_ * p_state_cov_;
    return std::make_tuple(state_vec_, state_cov_);
  }

  TCompeleteState initialize() {
    state_vec_ = process_.template getProcess<0>().getInitialPDF().getMean();
    state_cov_ =
        process_.template getProcess<0>().getInitialPDF().getCovariance();
    return std::make_tuple(state_vec_, state_cov_);
  }
};

template <class STA_MAP, class OBS_MAP, size_t STA_D, size_t OBS_D>
Kalman<STA_MAP, OBS_MAP, STA_D, OBS_D> makeKalman(
    Hierarchical<Markov<Conditional<Gaussian<STA_D>, STA_MAP>, Gaussian<STA_D>>,
                 Memoryless<Conditional<Gaussian<OBS_D>, OBS_MAP>>> process) {
  return Kalman<STA_MAP, OBS_MAP, STA_D, OBS_D>(process);
}

} // namespace filter
} // namespace ssmpack

#endif // SSMPACK_FILTER_KALMAN_HPP
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/properties/propertypresetmanager.h>
#include <inviwo/core/properties/property.h>
#include <inviwo/core/metadata/containermetadata.h>
#include <inviwo/core/util/stdextensions.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/network/networklock.h>
#include <inviwo/core/common/inviwoapplication.h>

namespace inviwo {

PropertyPresetManager::PropertyPresetManager() { loadApplicationPresets(); }

bool PropertyPresetManager::loadPreset(const std::string& name, Property* property,
                                       PropertyPresetType type) const {
    auto apply = [](Property* p, const std::string& data) {
        NetworkLock lock(p);
        std::stringstream ss;
        ss << data;
        Deserializer deserializer(ss, "");
        auto app = InviwoApplication::getPtr();
        deserializer.registerFactory(app->getPropertyFactory());
        deserializer.registerFactory(app->getMetaDataFactory());
        // save current status, except property value, as the preset might overwrite it
        const auto identifier = p->getIdentifier();
        const auto displayName = p->getDisplayName();
        const auto semantics = p->getSemantics();
        const auto readOnly = p->getReadOnly();
        const auto usage = p->getUsageMode();
        p->deserialize(deserializer);
        // restore property state
        p->setIdentifier(identifier);
        p->setDisplayName(displayName);
        p->setSemantics(semantics);
        p->setReadOnly(readOnly);
        p->setUsageMode(usage);
    };

    switch (type) {
        case PropertyPresetType::Property:
        {
            auto pmap = getPropertyPresets(property);
            auto it = std::find_if(pmap.begin(), pmap.end(),
                                   [&](const auto& pair) { return pair.first == name; });
            if (it != pmap.end()) {
                apply(property, it->second);
                return true;
            }
            break;
        }
        case PropertyPresetType::Workspace:
        {
            auto it = std::find_if(workspacePresets_.begin(), workspacePresets_.end(),
                                   [&](const auto& item) { return item.name == name; });
            if (it != workspacePresets_.end() &&
                it->classIdentifier == property->getClassIdentifier()) {
                apply(property, it->data);
                return true;
            }
            break;
        }
        case PropertyPresetType::Application:
        {
            auto it = std::find_if(appPresets_.begin(), appPresets_.end(),
                                   [&](const auto& item) { return item.name == name; });
            if (it != appPresets_.end() && it->classIdentifier == property->getClassIdentifier()) {
                apply(property, it->data);
                return true;
            }
            break;
        }
        default:
            break;
    }
    return false;
}

void PropertyPresetManager::savePreset(const std::string& name, Property* property,
                                       PropertyPresetType type) {
    if (!property) return;

    Serializer serializer("");
    property->serialize(serializer);
    std::stringstream ss;
    serializer.writeFile(ss);

    switch (type) {
        case PropertyPresetType::Property: {
            auto& pmap = getPropertyPresets(property);
            pmap[name] = ss.str();
            break;
        }
        case PropertyPresetType::Workspace: {
            workspacePresets_.emplace_back(property->getClassIdentifier(), name, ss.str());
            break;
        }
        case PropertyPresetType::Application: {
            appPresets_.emplace_back(property->getClassIdentifier(), name, ss.str());
            saveApplicationPresets();
            break;
        }
        default:
            break;
    }
}

bool PropertyPresetManager::removePreset(const std::string& name, PropertyPresetType type,
                                         Property* property) {
    switch (type) {
        case PropertyPresetType::Property: {
            if (!property) false;
            auto& pmap = getPropertyPresets(property);
            return pmap.erase(name) > 0;
        }
        case PropertyPresetType::Workspace: {
            return util::erase_remove_if(workspacePresets_,
                                         [&](const auto& item) { return item.name == name; }) > 0;
        }
        case PropertyPresetType::Application: {
            auto removed = util::erase_remove_if(
                appPresets_, [&](const auto& item) { return item.name == name; });
            saveApplicationPresets();
            return removed > 0;
        }
        default:
            return false;
    }
}

std::vector<std::string> PropertyPresetManager::getAvailablePresets(
    Property* property, PropertyPresetTypes types) const {
    std::vector<std::string> result;
    if (types & PropertyPresetType::Property) {
        auto pmap = getPropertyPresets(property);
        std::transform(pmap.begin(), pmap.end(), std::back_inserter(result),
                       [&](const auto& pair) { return pair.first; });
    }
    if (types & PropertyPresetType::Workspace) {
        std::accumulate(workspacePresets_.begin(), workspacePresets_.end(),
                        std::back_inserter(result), [&](auto it, const auto& item) {
                            if (item.classIdentifier == property->getClassIdentifier()) {
                                *(it++) = item.name;
                            }
                            return it;
                        });
    }
    if (types & PropertyPresetType::Application) {
        std::accumulate(appPresets_.begin(), appPresets_.end(), std::back_inserter(result),
                        [&](auto it, const auto& item) {
                            if (item.classIdentifier == property->getClassIdentifier()) {
                                *(it++) = item.name;
                            }
                            return it;
                        });
    }
    return result;
}

void PropertyPresetManager::loadApplicationPresets() {
    std::string filename = filesystem::getPath(PathType::Settings, "/PropertyPresets.ivs");
    if (filesystem::fileExists(filename)) {
        try {
            Deserializer d(filename);
            d.deserialize("PropertyPresets", appPresets_, "Preset");
        } catch (AbortException& e) {
            LogError(e.getMessage());
        } catch (std::exception& e) {
            LogError(e.what());
        }
    }
}

void PropertyPresetManager::saveApplicationPresets() {
    try {
        Serializer s(filesystem::getPath(PathType::Settings, "/PropertyPresets.ivs", true));
        s.serialize("PropertyPresets", appPresets_, "Preset");
        s.writeFile();
    } catch (std::exception e) {
        LogWarn("Could not write application presets");
    }
}

void PropertyPresetManager::clearPropertyPresets(Property *property) {
    if (!property) return;
    auto& pmap = getPropertyPresets(property);
    pmap.clear();
}

void PropertyPresetManager::clearWorkspacePresets() { workspacePresets_.clear(); }

void PropertyPresetManager::loadWorkspacePresets(Deserializer& d) {
    workspacePresets_.clear();
    d.deserialize("PropertyPresets", workspacePresets_, "Preset");
}

void PropertyPresetManager::saveWorkspacePresets(Serializer& s) {
    s.serialize("PropertyPresets", workspacePresets_, "Preset");
}

PropertyPresetManager::Preset::Preset() = default;

PropertyPresetManager::Preset::Preset(std::string id, std::string n, std::string d)
    : classIdentifier(id), name(n), data(d) {}

PropertyPresetManager::Preset::~Preset() = default;

void PropertyPresetManager::Preset::serialize(Serializer& s) const {
    s.serialize("classIdentifier", classIdentifier);
    s.serialize("name", name);
    s.serialize("data", data);
}

void PropertyPresetManager::Preset::deserialize(Deserializer& d) {
    d.deserialize("classIdentifier", classIdentifier);
    d.deserialize("name", name);
    d.deserialize("data", data);
}

std::map<std::string, std::string>& PropertyPresetManager::getPropertyPresets(Property* property) {
    using MT = StdUnorderedMapMetaData<std::string, std::string>;
    return property->createMetaData<MT>("SavedState")->getMap();
}

}  // namespace
<commit_msg>Core: Clang fix for inviwo/inviwo-dev#1523<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/properties/propertypresetmanager.h>
#include <inviwo/core/properties/property.h>
#include <inviwo/core/metadata/containermetadata.h>
#include <inviwo/core/util/stdextensions.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/network/networklock.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/properties/propertyfactory.h>
#include <inviwo/core/metadata/metadatafactory.h>

namespace inviwo {

PropertyPresetManager::PropertyPresetManager() { loadApplicationPresets(); }

bool PropertyPresetManager::loadPreset(const std::string& name, Property* property,
                                       PropertyPresetType type) const {
    auto apply = [](Property* p, const std::string& data) {
        NetworkLock lock(p);
        std::stringstream ss;
        ss << data;
        Deserializer deserializer(ss, "");
        auto app = InviwoApplication::getPtr();
        deserializer.registerFactory(app->getPropertyFactory());
        deserializer.registerFactory(app->getMetaDataFactory());
        // save current status, except property value, as the preset might overwrite it
        const auto identifier = p->getIdentifier();
        const auto displayName = p->getDisplayName();
        const auto semantics = p->getSemantics();
        const auto readOnly = p->getReadOnly();
        const auto usage = p->getUsageMode();
        p->deserialize(deserializer);
        // restore property state
        p->setIdentifier(identifier);
        p->setDisplayName(displayName);
        p->setSemantics(semantics);
        p->setReadOnly(readOnly);
        p->setUsageMode(usage);
    };

    switch (type) {
        case PropertyPresetType::Property:
        {
            auto pmap = getPropertyPresets(property);
            auto it = std::find_if(pmap.begin(), pmap.end(),
                                   [&](const auto& pair) { return pair.first == name; });
            if (it != pmap.end()) {
                apply(property, it->second);
                return true;
            }
            break;
        }
        case PropertyPresetType::Workspace:
        {
            auto it = std::find_if(workspacePresets_.begin(), workspacePresets_.end(),
                                   [&](const auto& item) { return item.name == name; });
            if (it != workspacePresets_.end() &&
                it->classIdentifier == property->getClassIdentifier()) {
                apply(property, it->data);
                return true;
            }
            break;
        }
        case PropertyPresetType::Application:
        {
            auto it = std::find_if(appPresets_.begin(), appPresets_.end(),
                                   [&](const auto& item) { return item.name == name; });
            if (it != appPresets_.end() && it->classIdentifier == property->getClassIdentifier()) {
                apply(property, it->data);
                return true;
            }
            break;
        }
        default:
            break;
    }
    return false;
}

void PropertyPresetManager::savePreset(const std::string& name, Property* property,
                                       PropertyPresetType type) {
    if (!property) return;

    Serializer serializer("");
    property->serialize(serializer);
    std::stringstream ss;
    serializer.writeFile(ss);

    switch (type) {
        case PropertyPresetType::Property: {
            auto& pmap = getPropertyPresets(property);
            pmap[name] = ss.str();
            break;
        }
        case PropertyPresetType::Workspace: {
            workspacePresets_.emplace_back(property->getClassIdentifier(), name, ss.str());
            break;
        }
        case PropertyPresetType::Application: {
            appPresets_.emplace_back(property->getClassIdentifier(), name, ss.str());
            saveApplicationPresets();
            break;
        }
        default:
            break;
    }
}

bool PropertyPresetManager::removePreset(const std::string& name, PropertyPresetType type,
                                         Property* property) {
    switch (type) {
        case PropertyPresetType::Property: {
            if (!property) return false;
            auto& pmap = getPropertyPresets(property);
            return pmap.erase(name) > 0;
        }
        case PropertyPresetType::Workspace: {
            return util::erase_remove_if(workspacePresets_,
                                         [&](const auto& item) { return item.name == name; }) > 0;
        }
        case PropertyPresetType::Application: {
            auto removed = util::erase_remove_if(
                appPresets_, [&](const auto& item) { return item.name == name; });
            saveApplicationPresets();
            return removed > 0;
        }
        default:
            return false;
    }
}

std::vector<std::string> PropertyPresetManager::getAvailablePresets(
    Property* property, PropertyPresetTypes types) const {
    std::vector<std::string> result;
    if (types & PropertyPresetType::Property) {
        auto pmap = getPropertyPresets(property);
        std::transform(pmap.begin(), pmap.end(), std::back_inserter(result),
                       [&](const auto& pair) { return pair.first; });
    }
    if (types & PropertyPresetType::Workspace) {
        std::accumulate(workspacePresets_.begin(), workspacePresets_.end(),
                        std::back_inserter(result), [&](auto it, const auto& item) {
                            if (item.classIdentifier == property->getClassIdentifier()) {
                                *(it++) = item.name;
                            }
                            return it;
                        });
    }
    if (types & PropertyPresetType::Application) {
        std::accumulate(appPresets_.begin(), appPresets_.end(), std::back_inserter(result),
                        [&](auto it, const auto& item) {
                            if (item.classIdentifier == property->getClassIdentifier()) {
                                *(it++) = item.name;
                            }
                            return it;
                        });
    }
    return result;
}

void PropertyPresetManager::loadApplicationPresets() {
    std::string filename = filesystem::getPath(PathType::Settings, "/PropertyPresets.ivs");
    if (filesystem::fileExists(filename)) {
        try {
            Deserializer d(filename);
            d.deserialize("PropertyPresets", appPresets_, "Preset");
        } catch (AbortException& e) {
            LogError(e.getMessage());
        } catch (std::exception& e) {
            LogError(e.what());
        }
    }
}

void PropertyPresetManager::saveApplicationPresets() {
    try {
        Serializer s(filesystem::getPath(PathType::Settings, "/PropertyPresets.ivs", true));
        s.serialize("PropertyPresets", appPresets_, "Preset");
        s.writeFile();
    } catch (std::exception e) {
        LogWarn("Could not write application presets");
    }
}

void PropertyPresetManager::clearPropertyPresets(Property *property) {
    if (!property) return;
    auto& pmap = getPropertyPresets(property);
    pmap.clear();
}

void PropertyPresetManager::clearWorkspacePresets() { workspacePresets_.clear(); }

void PropertyPresetManager::loadWorkspacePresets(Deserializer& d) {
    workspacePresets_.clear();
    d.deserialize("PropertyPresets", workspacePresets_, "Preset");
}

void PropertyPresetManager::saveWorkspacePresets(Serializer& s) {
    s.serialize("PropertyPresets", workspacePresets_, "Preset");
}

PropertyPresetManager::Preset::Preset() = default;

PropertyPresetManager::Preset::Preset(std::string id, std::string n, std::string d)
    : classIdentifier(id), name(n), data(d) {}

PropertyPresetManager::Preset::~Preset() = default;

void PropertyPresetManager::Preset::serialize(Serializer& s) const {
    s.serialize("classIdentifier", classIdentifier);
    s.serialize("name", name);
    s.serialize("data", data);
}

void PropertyPresetManager::Preset::deserialize(Deserializer& d) {
    d.deserialize("classIdentifier", classIdentifier);
    d.deserialize("name", name);
    d.deserialize("data", data);
}

std::map<std::string, std::string>& PropertyPresetManager::getPropertyPresets(Property* property) {
    using MT = StdUnorderedMapMetaData<std::string, std::string>;
    return property->createMetaData<MT>("SavedState")->getMap();
}

}  // namespace
<|endoftext|>


<commit_before>/******************************************************************//**
 * \file   string.hpp
 * \author Elliot Goodrich
 *
 * Modified by Davide Faconti
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *********************************************************************/

#ifndef INCLUDE_GUARD_2EE24263_BD1F_4E5D_8CDA_A3217E867BF0
#define INCLUDE_GUARD_2EE24263_BD1F_4E5D_8CDA_A3217E867BF0

#include <algorithm>
#include <cstddef>
#include <climits>
#include <cstring>
#include <ostream>
#include <string>
#include <type_traits>

#include <iostream>

namespace ssoX {

namespace detail {

static std::size_t const high_bit_mask = static_cast<std::size_t>(1) << (sizeof(std::size_t) * CHAR_BIT - 1);
static std::size_t const sec_high_bit_mask = static_cast<std::size_t>(1) << (sizeof(std::size_t) * CHAR_BIT - 2);

template <typename T>
unsigned char* uchar_cast(T* p) {
    return reinterpret_cast<unsigned char*>(p);
}

template <typename T>
unsigned char const* uchar_cast(T const* p) {
    return reinterpret_cast<unsigned char const*>(p);
}

template <typename T>
unsigned char& most_sig_byte(T& obj) {
    return *(reinterpret_cast<unsigned char*>(&obj) + sizeof(obj) - 1);
}

template <int N>
bool lsb(unsigned char byte) {
    return byte & (1u << N);
}

template <int N>
bool msb(unsigned char byte) {
    return byte & (1u << (CHAR_BIT - N - 1));
}

template <int N>
void set_lsb(unsigned char& byte, bool bit) {
    if(bit) {
        byte |= 1u << N;
    } else {
        byte &= ~(1u << N);
    }
}

template <int N>
void set_msb(unsigned char& byte, bool bit) {
    if(bit) {
        byte |= 1u << (CHAR_BIT - N - 1);
    } else {
        byte &= ~(1u << (CHAR_BIT - N - 1));
    }
}

}

template <size_t MAX_SIZE, typename CharT,
          typename Traits = std::char_traits<CharT>>
class basic_string {
    typedef typename std::make_unsigned<CharT>::type UCharT;
public:
    basic_string() noexcept
        : basic_string("", static_cast<std::size_t>(0)) {
    }

    basic_string(CharT const* string, std::size_t size) {

        static_assert( MAX_SIZE >= 24 && MAX_SIZE <= 63, "Size must be >=24 && <= 63" );

        if(size <= sso_capacity) {
            Traits::move(m_data.sso.string, string, size);
            Traits::assign(m_data.sso.string[size], static_cast<CharT>(0));
            set_sso_size(size);
        } else {
            size_t new_size = std::max( sso_capacity*2, size );
            m_data.non_sso.ptr = new CharT[new_size +1 ];
            Traits::move(m_data.non_sso.ptr, string, size);
            Traits::assign(m_data.non_sso.ptr[size], static_cast<CharT>(0));
            set_non_sso_data(size, size);
        }
    }

    basic_string(CharT const* string)
        : basic_string{string, std::strlen(string)} {
    }

    basic_string(const basic_string& other) {
        if(other.sso()) {
            m_data.sso = other.m_data.sso;
        } else {
            new (this) basic_string{other.data(), other.size() };
        }
    }

    basic_string(basic_string&& other) noexcept {
        m_data = other.m_data;
        other.set_moved_from();
    }

    void reserve(size_t) noexcept {
      //not implemented
    }

    basic_string(const std::basic_string<CharT>& other):
      basic_string(  other.c_str(), other.size() )
    {

    }

    basic_string& operator=(basic_string const& other) {
        auto copy = other;
        swap(copy, *this);
        return *this;
    }

    basic_string& operator=(basic_string&& other) {
        this->~basic_string();
        m_data = other.m_data;
        other.set_moved_from();
        return *this;
    }

    basic_string& operator=(const std::basic_string<CharT>& other) {
        *this = basic_string( other.data(), other.size() );
        return *this;
    }

    basic_string operator+(basic_string const& other) {
        basic_string out( *this) ;
        out.append( other.data(), other.size() );
        return out;
    }

    void resize( size_t new_size)
    {
        size_t old_size = this->size();
        if(new_size <= sso_capacity) {
            if( this->sso() == false ) {
                CharT* ptr = m_data.non_sso.ptr;
                Traits::move( m_data.sso.string, ptr, std::min(old_size, new_size) );
                delete[] ptr;
            }
            Traits::assign(m_data.sso.string[new_size], static_cast<CharT>(0));
            set_sso_size(new_size);
        } else {
            new_size = std::min( sso_capacity*2, new_size );
            CharT* ptr = new CharT[new_size + 1];

            if( this->sso() == false ) {
                Traits::move( ptr, m_data.non_sso.ptr, std::min(old_size, new_size) );
                delete[] m_data.non_sso.ptr ;
            }
            else{
                Traits::move( ptr, m_data.sso.string, std::min(old_size, new_size) );
                new_size = std::min( sso_capacity*2, new_size );
                m_data.non_sso.ptr = new CharT[new_size + 1];
            }
            m_data.non_sso.ptr = ptr;
            Traits::assign(m_data.non_sso.ptr[new_size], static_cast<CharT>(0));
            set_non_sso_data(new_size, new_size);
        }
    }

    basic_string& append(const basic_string& other)
    {
        return append( other.data(), other.size() );
    }

    basic_string& append(CharT const* string)
    {
        return append( string, std::strlen(string) );
    }

    basic_string& append(CharT const* string,size_t length)
    {
        size_t old_size = this->size();
        size_t new_size = old_size + length ;

        this->resize( new_size );

        if(new_size <= sso_capacity) {
            Traits::move( &m_data.sso.string[old_size], string, length);
            Traits::assign(m_data.sso.string[new_size], static_cast<CharT>(0));
        } else {
            Traits::move( &m_data.non_sso.ptr[old_size], string, length);
            Traits::assign(m_data.non_sso.ptr[new_size], static_cast<CharT>(0));
        }
        return *this;
    }

    ~basic_string() {
        if(!sso()) {
            delete[] m_data.non_sso.ptr;
        }
    }

    CharT const* data() const noexcept {
        return sso() ? m_data.sso.string : m_data.non_sso.ptr;
    }

    std::size_t size() const noexcept {
        if(sso()) {
            return sso_size();
        } else {
            return read_non_sso_data().first;
        }
    }

    const char at( size_t index )
    {
        return data()[index];
    }

    const char at( size_t index ) const
    {
        return data()[index];
    }

    std::size_t capacity() const noexcept {
        if(sso()) {
            return sizeof(m_data) - 1;
        } else {
            return read_non_sso_data().second;
        }
    }

    friend void swap(basic_string& lhs, basic_string& rhs) {
        std::swap(lhs.m_data, rhs.m_data);
    }

    // We are using sso if the last two bits are 0
    bool isSso() const noexcept {
        return sso();
    }

    int compare(const basic_string& other)
    {
        return strcmp( data(), other.data() );
    }

    std::basic_string<CharT> toStdString() const {
        return std::basic_string<CharT>(data(), size() );
    }

private:
    void set_moved_from() {
        set_sso_size(0);
    }

    // We are using sso if the last two bits are 0
    bool sso() const noexcept {
        return !detail::lsb<0>(m_data.sso.size) && !detail::lsb<1>(m_data.sso.size);
    }

    // good
    void set_sso_size(unsigned char size) noexcept {
        m_data.sso.size = static_cast<UCharT>(sso_capacity - size) << 2;
    }

    // good
    std::size_t sso_size() const noexcept {
        return sso_capacity - ((m_data.sso.size >> 2) & 63u);
    }

    void set_non_sso_data(std::size_t size, std::size_t capacity) {
        auto& size_hsb = detail::most_sig_byte(size);
        auto const size_high_bit = detail::msb<0>(size_hsb);

        auto& cap_hsb = detail::most_sig_byte(capacity);
        auto const cap_high_bit     = detail::msb<0>(cap_hsb);
        auto const cap_sec_high_bit = detail::msb<1>(cap_hsb);

        detail::set_msb<0>(size_hsb, cap_sec_high_bit);

        cap_hsb <<= 2;
        detail::set_lsb<0>(cap_hsb, cap_high_bit);
        detail::set_lsb<1>(cap_hsb, !size_high_bit);

        m_data.non_sso.size = size;
        m_data.non_sso.capacity = capacity;
    }

    std::pair<std::size_t, std::size_t> read_non_sso_data() const {
        auto size = m_data.non_sso.size;
        auto capacity = m_data.non_sso.capacity;

        auto& size_hsb = detail::most_sig_byte(size);
        auto& cap_hsb  = detail::most_sig_byte(capacity);

        // Remember to negate the high bits
        auto const cap_high_bit     = detail::lsb<0>(cap_hsb);
        auto const size_high_bit    = !detail::lsb<1>(cap_hsb);
        auto const cap_sec_high_bit = detail::msb<0>(size_hsb);

        detail::set_msb<0>(size_hsb, size_high_bit);

        cap_hsb >>= 2;
        detail::set_msb<0>(cap_hsb, cap_high_bit);
        detail::set_msb<1>(cap_hsb, cap_sec_high_bit);

        return std::make_pair(size, capacity);
    }

private:
    union Data {
        struct NonSSO {
            CharT overhead[MAX_SIZE + sizeof(UCharT)  - sizeof(CharT*) -2*sizeof(std::size_t) ]; //waster memory to keep the alignment
            CharT* ptr;
            std::size_t size;
            std::size_t capacity;
        } non_sso;
        struct SSO {
            CharT string [ sizeof(NonSSO) / sizeof(CharT) - 1];
            UCharT size;
        } sso;
    } m_data;

public:
    static std::size_t const sso_capacity =  sizeof(typename Data::NonSSO) / sizeof(CharT)  - 1;
};

template <size_t MAX_SIZE, typename CharT, typename Traits>
bool operator==(const basic_string<MAX_SIZE,CharT, Traits>& lhs, const CharT* rhs) noexcept {
    return !std::strcmp(lhs.data(), rhs);
}

template <size_t MAX_SIZE, typename CharT, typename Traits>
bool operator==(const CharT* lhs, const basic_string<MAX_SIZE,CharT, Traits>& rhs) noexcept {
    return rhs == lhs;
}

template <size_t MAX_SIZE_A, size_t MAX_SIZE_B,
          typename CharT, typename Traits>
bool operator==(const basic_string<MAX_SIZE_A, CharT, Traits>& lhs,
                const basic_string<MAX_SIZE_B, CharT, Traits>& rhs) noexcept {
    if(lhs.size() != rhs.size()) return false;
    return !std::strcmp(lhs.data(), rhs.data());
}

template <size_t MAX_SIZE,typename CharT, typename Traits>
std::ostream& operator<<(std::ostream& stream, const basic_string<MAX_SIZE,CharT, Traits>& string) {
    return stream << string.data();
}

template <size_t MAX_SIZE_A, size_t MAX_SIZE_B,
          typename CharT, typename Traits>
bool operator < (const basic_string<MAX_SIZE_A,CharT, Traits>& lhs,
                 const basic_string<MAX_SIZE_B,CharT, Traits>& rhs) noexcept {
    return std::strcmp(lhs.data(), rhs.data()) < 0;
}

}

#endif
<commit_msg>fixing issue in resize (to be tested)<commit_after>/******************************************************************//**
 * \file   string.hpp
 * \author Elliot Goodrich
 *
 * Modified by Davide Faconti
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *********************************************************************/

#ifndef INCLUDE_GUARD_2EE24263_BD1F_4E5D_8CDA_A3217E867BF0
#define INCLUDE_GUARD_2EE24263_BD1F_4E5D_8CDA_A3217E867BF0

#include <algorithm>
#include <cstddef>
#include <climits>
#include <cstring>
#include <ostream>
#include <string>
#include <type_traits>

#include <iostream>

namespace ssoX {

namespace detail {

static std::size_t const high_bit_mask = static_cast<std::size_t>(1) << (sizeof(std::size_t) * CHAR_BIT - 1);
static std::size_t const sec_high_bit_mask = static_cast<std::size_t>(1) << (sizeof(std::size_t) * CHAR_BIT - 2);

template <typename T>
unsigned char* uchar_cast(T* p) {
    return reinterpret_cast<unsigned char*>(p);
}

template <typename T>
unsigned char const* uchar_cast(T const* p) {
    return reinterpret_cast<unsigned char const*>(p);
}

template <typename T>
unsigned char& most_sig_byte(T& obj) {
    return *(reinterpret_cast<unsigned char*>(&obj) + sizeof(obj) - 1);
}

template <int N>
bool lsb(unsigned char byte) {
    return byte & (1u << N);
}

template <int N>
bool msb(unsigned char byte) {
    return byte & (1u << (CHAR_BIT - N - 1));
}

template <int N>
void set_lsb(unsigned char& byte, bool bit) {
    if(bit) {
        byte |= 1u << N;
    } else {
        byte &= ~(1u << N);
    }
}

template <int N>
void set_msb(unsigned char& byte, bool bit) {
    if(bit) {
        byte |= 1u << (CHAR_BIT - N - 1);
    } else {
        byte &= ~(1u << (CHAR_BIT - N - 1));
    }
}

}

template <typename CharT, typename Traits = std::char_traits<CharT>>
class basic_string {
    typedef typename std::make_unsigned<CharT>::type UCharT;
public:
    basic_string() noexcept
        : basic_string("", static_cast<std::size_t>(0)) {
    }

    basic_string(CharT const* string, std::size_t size) {

        if(size <= sso_capacity) {
            Traits::move(m_data.sso.string, string, size);
            Traits::assign(m_data.sso.string[size], static_cast<CharT>(0));
            set_sso_size(size);
        } else {
            size_t new_size = std::max( sso_capacity*2, size );
            m_data.non_sso.ptr = new CharT[new_size +1 ];
            Traits::move(m_data.non_sso.ptr, string, size);
            Traits::assign(m_data.non_sso.ptr[size], static_cast<CharT>(0));
            set_non_sso_data(size, size);
        }
    }

    basic_string(CharT const* string)
        : basic_string{string, std::strlen(string)} {
    }

    basic_string(const basic_string& other) {
        if(other.sso()) {
            m_data.sso = other.m_data.sso;
        } else {
            new (this) basic_string{other.data(), other.size() };
        }
    }

    basic_string(basic_string&& other) noexcept {
        m_data = other.m_data;
        other.set_moved_from();
    }

    void reserve(size_t) noexcept {
      //not implemented
    }

    basic_string(const std::basic_string<CharT>& other):
      basic_string(  other.c_str(), other.size() )
    {

    }

    basic_string& operator=(basic_string const& other) {
        auto copy = other;
        swap(copy, *this);
        return *this;
    }

    basic_string& operator=(basic_string&& other) {
        this->~basic_string();
        m_data = other.m_data;
        other.set_moved_from();
        return *this;
    }

    basic_string& operator=(const std::basic_string<CharT>& other) {
        *this = basic_string( other.data(), other.size() );
        return *this;
    }

    basic_string operator+(basic_string const& other) {
        basic_string out( *this) ;
        out.append( other.data(), other.size() );
        return out;
    }

    void resize( size_t new_size)
    {
        size_t old_size = this->size();
        if(new_size <= sso_capacity) {
            if( this->sso() == false ) {
                CharT* ptr = m_data.non_sso.ptr;
                Traits::move( m_data.sso.string, ptr, std::min(old_size, new_size) );
                delete[] ptr;
            }
            Traits::assign(m_data.sso.string[new_size], static_cast<CharT>(0));
            set_sso_size(new_size);
        } else {
            size_t new_capacity;
            CharT* ptr;

            if( this->sso() ){
                // it was sso. Need to allocate new memory
                new_capacity =  sso_capacity*2;
                ptr = new CharT[ new_capacity + 1];
                Traits::move( ptr, m_data.sso.string, std::min(old_size, new_size) );
                m_data.non_sso.ptr = ptr;
            }
            else if( new_size < capacity() ){
                // it was non_sso. capacity is sufficient. do nothing
                new_capacity = m_data.non_sso.capacity;
            }
            else{
                // was non_sso, but I need to allocate more memory
                new_capacity = std::max(new_size, capacity()*3/2);
                ptr = new CharT[ new_capacity + 1];
                Traits::move( ptr, m_data.non_sso.ptr, std::min(old_size, new_size) );
                delete[] m_data.non_sso.ptr ;
                m_data.non_sso.ptr = ptr;
            }

            Traits::assign(m_data.non_sso.ptr[new_size], static_cast<CharT>(0));
            set_non_sso_data(new_size, new_capacity);
        }
    }

    basic_string& append(const basic_string& other)
    {
        return append( other.data(), other.size() );
    }

    basic_string& append(CharT const* string)
    {
        return append( string, std::strlen(string) );
    }

    basic_string& append(CharT const* string,size_t length)
    {
        size_t old_size = this->size();
        size_t new_size = old_size + length ;

        this->resize( new_size );

        if(new_size <= sso_capacity) {
            Traits::move( &m_data.sso.string[old_size], string, length);
            Traits::assign(m_data.sso.string[new_size], static_cast<CharT>(0));
        } else {
            Traits::move( &m_data.non_sso.ptr[old_size], string, length);
            Traits::assign(m_data.non_sso.ptr[new_size], static_cast<CharT>(0));
        }
        return *this;
    }

    ~basic_string() {
        if(!sso()) {
            delete[] m_data.non_sso.ptr;
        }
    }

    CharT const* data() const noexcept {
        return sso() ? m_data.sso.string : m_data.non_sso.ptr;
    }

    std::size_t size() const noexcept {
        if(sso()) {
            return sso_size();
        } else {
            return read_non_sso_data().first;
        }
    }

    const char at( size_t index )
    {
        return data()[index];
    }

    const char at( size_t index ) const
    {
        return data()[index];
    }

    std::size_t capacity() const noexcept {
        if(sso()) {
            return sizeof(m_data) - 1;
        } else {
            return read_non_sso_data().second;
        }
    }

    friend void swap(basic_string& lhs, basic_string& rhs) {
        std::swap(lhs.m_data, rhs.m_data);
    }

    // We are using sso if the last two bits are 0
    bool isSso() const noexcept {
        return sso();
    }

    int compare(const basic_string& other)
    {
        return strcmp( data(), other.data() );
    }

    std::basic_string<CharT> toStdString() const {
        return std::basic_string<CharT>(data(), size() );
    }

private:
    void set_moved_from() {
        set_sso_size(0);
    }

    // We are using sso if the last two bits are 0
    bool sso() const noexcept {
        return !detail::lsb<0>(m_data.sso.size) && !detail::lsb<1>(m_data.sso.size);
    }

    // good
    void set_sso_size(unsigned char size) noexcept {
        m_data.sso.size = static_cast<UCharT>(sso_capacity - size) << 2;
    }

    // good
    std::size_t sso_size() const noexcept {
        return sso_capacity - ((m_data.sso.size >> 2) & 63u);
    }

    void set_non_sso_data(std::size_t size, std::size_t capacity) {
        auto& size_hsb = detail::most_sig_byte(size);
        auto const size_high_bit = detail::msb<0>(size_hsb);

        auto& cap_hsb = detail::most_sig_byte(capacity);
        auto const cap_high_bit     = detail::msb<0>(cap_hsb);
        auto const cap_sec_high_bit = detail::msb<1>(cap_hsb);

        detail::set_msb<0>(size_hsb, cap_sec_high_bit);

        cap_hsb <<= 2;
        detail::set_lsb<0>(cap_hsb, cap_high_bit);
        detail::set_lsb<1>(cap_hsb, !size_high_bit);

        m_data.non_sso.size = size;
        m_data.non_sso.capacity = capacity;
    }

    std::pair<std::size_t, std::size_t> read_non_sso_data() const {
        auto size = m_data.non_sso.size;
        auto capacity = m_data.non_sso.capacity;

        auto& size_hsb = detail::most_sig_byte(size);
        auto& cap_hsb  = detail::most_sig_byte(capacity);

        // Remember to negate the high bits
        auto const cap_high_bit     = detail::lsb<0>(cap_hsb);
        auto const size_high_bit    = !detail::lsb<1>(cap_hsb);
        auto const cap_sec_high_bit = detail::msb<0>(size_hsb);

        detail::set_msb<0>(size_hsb, size_high_bit);

        cap_hsb >>= 2;
        detail::set_msb<0>(cap_hsb, cap_high_bit);
        detail::set_msb<1>(cap_hsb, cap_sec_high_bit);

        return std::make_pair(size, capacity);
    }

private:
    union Data {
        struct NonSSO {
            CharT overhead[ 24 - sizeof(CharT*) - 2*sizeof(CharT*)];
            CharT* ptr;
            std::size_t size;
            std::size_t capacity;
        } non_sso;
        struct SSO {
            CharT string [ sizeof(NonSSO) / sizeof(CharT) - 1];
            UCharT size;
        } sso;
    } m_data;

public:
    static std::size_t const sso_capacity =  sizeof(typename Data::NonSSO) / sizeof(CharT)  - 1;
};

template <typename CharT, typename Traits>
bool operator==(const basic_string<CharT, Traits>& lhs, const CharT* rhs) noexcept {
    return !std::strcmp(lhs.data(), rhs);
}

template <typename CharT, typename Traits>
bool operator==(const CharT* lhs, const basic_string<CharT, Traits>& rhs) noexcept {
    return rhs == lhs;
}

template <typename CharT, typename Traits>
bool operator==(const basic_string<CharT, Traits>& lhs,
                const basic_string<CharT, Traits>& rhs) noexcept {
    if(lhs.size() != rhs.size()) return false;
    return !std::strcmp(lhs.data(), rhs.data());
}

template <typename CharT, typename Traits>
std::ostream& operator<<(std::ostream& stream, const basic_string<CharT, Traits>& string) {
    return stream << string.data();
}

template <typename CharT, typename Traits>
bool operator < (const basic_string<CharT, Traits>& lhs,
                 const basic_string<CharT, Traits>& rhs) noexcept {
    return std::strcmp(lhs.data(), rhs.data()) < 0;
}

}

#endif
<|endoftext|>


<commit_before>#include <functional>
#include <iostream>
#include <vector>

template<typename T, typename Key=std::less_equal<T>>
class Heap {
    using vt = std::vector<T>;
    using iterator = typename vt::iterator;

    vt xs;
    Key key;

    void swim(const iterator xit, iterator yit) {
        while (xit != yit) {
            auto it = xit + std::distance(xit, yit) / 2;

            if (key(*it, *yit)) {break;}

            std::swap(*it, *yit);
        }
    }

    void sink(const iterator xit, const iterator yit, iterator zit) {
        auto lit = zit + std::distance(xit, zit) + 1;

        while (lit < yit) {
            auto rit = lit + 1;

            auto it = rit < yit && key(*rit, *lit) ? rit : lit;

            if (key(*zit, *it)) {break;}

            std::swap(*it, *zit);
            zit = it;
            lit = zit + std::distance(xit, zit) + 1;
        }
    }

public:
    Heap() : Heap(vt()) {}
    Heap(const vt &xs) : Heap(xs, Key()) {}

    Heap(const vt &xs, Key key) : xs(xs), key(key) {
        auto xit = this->xs.rbegin();
        auto yit = this->xs.rend();

        auto it = xit + std::distance(xit, yit) / 2;

        for (; it != yit; ++it) {
            sink(this->xs.begin(), this->xs.end(), it.base() - 1);
        }
    }

    typename vt::size_type size() {
        return this->xs.size();
    }

    void push(const T &val) {
        xs.push_back(val);
        swim(xs.begin(), xs.end() - 1);
    }

    void pop() {
        if (xs.size() == 0) {return;}

        std::swap(*xs.begin(), *xs.rbegin());

        xs.pop_back();

        this->sink(xs.begin(), xs.end(), xs.begin());
    }

    T top() {
        return *xs.begin();
    }

    vt sort() {
        vt ys(xs.begin(), xs.end());

        for (auto it = ys.rbegin(); it != ys.rend(); ++it) {
            std::swap(*it, *ys.begin());
            this->sink(ys.begin(), it.base() - 1, ys.begin());
        }

        return ys;
    }

    friend std::ostream &
    operator<<(std::ostream &os, const Heap<T, Key> &heap) {
        for (const auto x : heap.xs) {
            os << x << " ";
        } os << std::endl;

        return os;
    }
};
<commit_msg>Heap: improve custom ordering support via key<commit_after>#include <functional>
#include <iostream>
#include <vector>

template<typename T, typename Key=std::less_equal<T>>
class Heap {
    using vt = std::vector<T>;
    using iterator = typename vt::iterator;

    vt xs;
    Key key;

    void swim(const iterator xit, iterator yit) {
        while (xit != yit) {
            auto it = xit + std::distance(xit, yit) / 2;

            if (key(*it, *yit)) {break;}

            std::swap(*it, *yit);
        }
    }

    void sink(const iterator xit, const iterator yit, iterator zit) {
        auto lit = zit + std::distance(xit, zit) + 1;

        while (lit < yit) {
            auto rit = lit + 1;

            auto it = rit < yit && key(*rit, *lit) ? rit : lit;

            if (key(*zit, *it)) {break;}

            std::swap(*it, *zit);
            zit = it;
            lit = zit + std::distance(xit, zit) + 1;
        }
    }

public:
    Heap() : Heap(vt()) {}
    Heap(Key key) : Heap(vt(), key) {}
    Heap(const vt &xs) : Heap(xs, Key()) {}

    Heap(const vt &xs, Key key) : xs(xs), key(key) {
        auto xit = this->xs.rbegin();
        auto yit = this->xs.rend();

        auto it = xit + std::distance(xit, yit) / 2;

        for (; it != yit; ++it) {
            sink(this->xs.begin(), this->xs.end(), it.base() - 1);
        }
    }

    typename vt::size_type size() {
        return this->xs.size();
    }

    void push(const T &val) {
        xs.push_back(val);
        swim(xs.begin(), xs.end() - 1);
    }

    void pop() {
        if (xs.size() == 0) {return;}

        std::swap(*xs.begin(), *xs.rbegin());

        xs.pop_back();

        this->sink(xs.begin(), xs.end(), xs.begin());
    }

    T top() {
        return *xs.begin();
    }

    vt sort() {
        vt ys(xs.begin(), xs.end());

        for (auto it = ys.rbegin(); it != ys.rend(); ++it) {
            std::swap(*it, *ys.begin());
            this->sink(ys.begin(), it.base() - 1, ys.begin());
        }

        return ys;
    }

    friend std::ostream &
    operator<<(std::ostream &os, const Heap<T, Key> &heap) {
        for (const auto x : heap.xs) {
            os << x << " ";
        } os << std::endl;

        return os;
    }
};
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 * $Log$
 * Revision 1.20  2004/01/29 11:48:46  cargilld
 * Code cleanup changes to get rid of various compiler diagnostic messages.
 *
 * Revision 1.19  2004/01/13 19:50:56  peiyongz
 * remove parseContent()
 *
 * Revision 1.17  2003/12/17 00:18:35  cargilld
 * Update to memory management so that the static memory manager (one used to call Initialize) is only for static data.
 *
 * Revision 1.16  2003/12/11 21:38:12  peiyongz
 * support for Canonical Representation for Datatype
 *
 * Revision 1.15  2003/10/15 14:50:01  peiyongz
 * Bugzilla#22821: locale-sensitive function used to validate 'double' type, patch
 * from jsweeney@spss.com (Jeff Sweeney)
 *
 * Revision 1.14  2003/09/23 18:16:07  peiyongz
 * Inplementation for Serialization/Deserialization
 *
 * Revision 1.13  2003/05/18 14:02:05  knoaman
 * Memory manager implementation: pass per instance manager.
 *
 * Revision 1.12  2003/05/16 06:01:53  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.11  2003/05/15 19:07:46  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.10  2003/05/09 15:13:46  peiyongz
 * Deprecated toString() in XMLNumber family
 *
 * Revision 1.9  2003/03/10 20:55:58  peiyongz
 * Schema Errata E2-40 double/float
 *
 * Revision 1.8  2003/02/02 23:54:43  peiyongz
 * getFormattedString() added to return original and converted value.
 *
 * Revision 1.7  2003/01/30 21:55:22  tng
 * Performance: create getRawData which is similar to toString but return the internal data directly, user is not required to delete the returned memory.
 *
 * Revision 1.6  2002/12/11 00:20:02  peiyongz
 * Doing businesss in value space. Converting out-of-bound value into special values.
 *
 * Revision 1.5  2002/11/04 15:22:05  tng
 * C++ Namespace Support.
 *
 * Revision 1.4  2002/03/06 19:13:12  peiyongz
 * Patch: more valid lexcial representation for positive/negative zero
 *
 * Revision 1.3  2002/03/01 18:47:37  peiyongz
 * fix: more valid lexcial representation forms for "neural zero"
 *
 * Revision 1.2  2002/02/20 18:17:02  tng
 * [Bug 5977] Warnings on generating apiDocs.
 *
 * Revision 1.1.1.1  2002/02/01 22:22:14  peiyongz
 * sane_include
 *
 * Revision 1.4  2001/11/28 15:39:26  peiyongz
 * return Type& for operator=
 *
 * Revision 1.3  2001/11/22 21:39:00  peiyongz
 * Allow "0.0" to be a valid lexcial representation of ZERO.
 *
 * Revision 1.2  2001/11/22 20:23:00  peiyongz
 * _declspec(dllimport) and inline warning C4273
 *
 * Revision 1.1  2001/11/19 21:33:42  peiyongz
 * Reorganization: Double/Float
 *
 *
 */

#ifndef XML_ABSTRACT_DOUBLE_FLOAT_HPP
#define XML_ABSTRACT_DOUBLE_FLOAT_HPP

#include <xercesc/util/XMLNumber.hpp>
#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/***
 * 3.2.5.1 Lexical representation
 *
 *   double values have a lexical representation consisting of a mantissa followed,
 *   optionally, by the character "E" or "e", followed by an exponent.
 *
 *   The exponent must be an integer.
 *   The mantissa must be a decimal number.
 *   The representations for exponent and mantissa must follow the lexical rules
 *   for integer and decimal.
 *
 *   If the "E" or "e" and the following exponent are omitted,
 *   an exponent value of 0 is assumed.
***/

/***
 * 3.2.4.1 Lexical representation
 *
 *   float values have a lexical representation consisting of a mantissa followed,
 *   optionally, by the character "E" or "e", followed by an exponent.
 *
 *   The exponent must be an integer.
 *   The mantissa must be a decimal number.
 *   The representations for exponent and mantissa must follow the lexical rules
 *   for integer and decimal.
 *
 *   If the "E" or "e" and the following exponent are omitted,
 *   an exponent value of 0 is assumed.
***/

class XMLUTIL_EXPORT XMLAbstractDoubleFloat : public XMLNumber
{
public:

    enum LiteralType
    {
        NegINF,
        PosINF,
        NaN,
        SpecialTypeNum,
        Normal
    };

    virtual ~XMLAbstractDoubleFloat();

    static XMLCh* getCanonicalRepresentation
                        (
                          const XMLCh*         const rawData
                        ,       MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager
                        );

    /**
     *
     *  Deprecated: please use getRawData
     *
     */
    virtual XMLCh*        toString() const;

    virtual XMLCh*        getRawData() const;

    virtual const XMLCh*  getFormattedString() const;

    virtual int           getSign() const;

    MemoryManager*        getMemoryManager() const;

    /***
     *
     * The decimal point delimiter for the schema double/float type is
     * defined to be a period and is not locale-specific. So, it must
     * be replaced with the local-specific delimiter before converting
     * from string to double/float.
     *
     ***/
    void                  normalizeDecimalPoint(char* const toNormal);

    /***
     * Support for Serialization/De-serialization
     ***/
    DECL_XSERIALIZABLE(XMLAbstractDoubleFloat)

protected:

    //
    // To be used by derived class exclusively
    //
    XMLAbstractDoubleFloat(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);

    void                  init(const XMLCh* const strValue);

    /**
	 * Compares this object to the specified object.
	 * The result is true if and only if the argument is not
	 * null and is an XMLAbstractDoubleFloat object that contains
	 * the same int value as this object.
	 *
	 * @param   lValue the object to compare with.
	 * @param   rValue the object to compare against.
	 * @return  true if the objects are the same;
	 *          false otherwise.
	 */

    static int            compareValues(const XMLAbstractDoubleFloat* const lValue
                                      , const XMLAbstractDoubleFloat* const rValue
                                      , MemoryManager* const manager);

    //
    // to be overwritten by derived class
    //
    virtual void          checkBoundary(const XMLCh* const strValue) = 0;

private:
    //
    // Unimplemented
    //
    // copy ctor
    // assignment ctor
    //
    XMLAbstractDoubleFloat(const XMLAbstractDoubleFloat& toCopy);
    XMLAbstractDoubleFloat& operator=(const XMLAbstractDoubleFloat& toAssign);

	void                  normalizeZero(XMLCh* const);

    inline bool           isSpecialValue() const;

    static int            compareSpecial(const XMLAbstractDoubleFloat* const specialValue
                                       , MemoryManager* const manager);

    void                  formatString();

protected:
    double                  fValue;
    LiteralType             fType;
    bool                    fDataConverted;

private:
    int                     fSign;
    XMLCh*                  fRawData;

    //
    // If the original string is not lexcially the same as the five
    // special value notations, and the value is converted to
    // special value due underlying platform restriction on data
    // representation, then this string is constructed and
    // takes the form "original_string (special_value_notation)",
    // otherwise it is empty.
    //
    XMLCh*                  fFormattedString;
    MemoryManager*          fMemoryManager;
};

inline bool XMLAbstractDoubleFloat::isSpecialValue() const
{
    return (fType < SpecialTypeNum);
}

inline MemoryManager* XMLAbstractDoubleFloat::getMemoryManager() const
{
    return fMemoryManager;
}

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>getValue()/isDataConverted()<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 * $Log$
 * Revision 1.21  2004/08/11 16:50:47  peiyongz
 * getValue()/isDataConverted()
 *
 * Revision 1.20  2004/01/29 11:48:46  cargilld
 * Code cleanup changes to get rid of various compiler diagnostic messages.
 *
 * Revision 1.19  2004/01/13 19:50:56  peiyongz
 * remove parseContent()
 *
 * Revision 1.17  2003/12/17 00:18:35  cargilld
 * Update to memory management so that the static memory manager (one used to call Initialize) is only for static data.
 *
 * Revision 1.16  2003/12/11 21:38:12  peiyongz
 * support for Canonical Representation for Datatype
 *
 * Revision 1.15  2003/10/15 14:50:01  peiyongz
 * Bugzilla#22821: locale-sensitive function used to validate 'double' type, patch
 * from jsweeney@spss.com (Jeff Sweeney)
 *
 * Revision 1.14  2003/09/23 18:16:07  peiyongz
 * Inplementation for Serialization/Deserialization
 *
 * Revision 1.13  2003/05/18 14:02:05  knoaman
 * Memory manager implementation: pass per instance manager.
 *
 * Revision 1.12  2003/05/16 06:01:53  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.11  2003/05/15 19:07:46  knoaman
 * Partial implementation of the configurable memory manager.
 *
 * Revision 1.10  2003/05/09 15:13:46  peiyongz
 * Deprecated toString() in XMLNumber family
 *
 * Revision 1.9  2003/03/10 20:55:58  peiyongz
 * Schema Errata E2-40 double/float
 *
 * Revision 1.8  2003/02/02 23:54:43  peiyongz
 * getFormattedString() added to return original and converted value.
 *
 * Revision 1.7  2003/01/30 21:55:22  tng
 * Performance: create getRawData which is similar to toString but return the internal data directly, user is not required to delete the returned memory.
 *
 * Revision 1.6  2002/12/11 00:20:02  peiyongz
 * Doing businesss in value space. Converting out-of-bound value into special values.
 *
 * Revision 1.5  2002/11/04 15:22:05  tng
 * C++ Namespace Support.
 *
 * Revision 1.4  2002/03/06 19:13:12  peiyongz
 * Patch: more valid lexcial representation for positive/negative zero
 *
 * Revision 1.3  2002/03/01 18:47:37  peiyongz
 * fix: more valid lexcial representation forms for "neural zero"
 *
 * Revision 1.2  2002/02/20 18:17:02  tng
 * [Bug 5977] Warnings on generating apiDocs.
 *
 * Revision 1.1.1.1  2002/02/01 22:22:14  peiyongz
 * sane_include
 *
 * Revision 1.4  2001/11/28 15:39:26  peiyongz
 * return Type& for operator=
 *
 * Revision 1.3  2001/11/22 21:39:00  peiyongz
 * Allow "0.0" to be a valid lexcial representation of ZERO.
 *
 * Revision 1.2  2001/11/22 20:23:00  peiyongz
 * _declspec(dllimport) and inline warning C4273
 *
 * Revision 1.1  2001/11/19 21:33:42  peiyongz
 * Reorganization: Double/Float
 *
 *
 */

#ifndef XML_ABSTRACT_DOUBLE_FLOAT_HPP
#define XML_ABSTRACT_DOUBLE_FLOAT_HPP

#include <xercesc/util/XMLNumber.hpp>
#include <xercesc/util/PlatformUtils.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/***
 * 3.2.5.1 Lexical representation
 *
 *   double values have a lexical representation consisting of a mantissa followed,
 *   optionally, by the character "E" or "e", followed by an exponent.
 *
 *   The exponent must be an integer.
 *   The mantissa must be a decimal number.
 *   The representations for exponent and mantissa must follow the lexical rules
 *   for integer and decimal.
 *
 *   If the "E" or "e" and the following exponent are omitted,
 *   an exponent value of 0 is assumed.
***/

/***
 * 3.2.4.1 Lexical representation
 *
 *   float values have a lexical representation consisting of a mantissa followed,
 *   optionally, by the character "E" or "e", followed by an exponent.
 *
 *   The exponent must be an integer.
 *   The mantissa must be a decimal number.
 *   The representations for exponent and mantissa must follow the lexical rules
 *   for integer and decimal.
 *
 *   If the "E" or "e" and the following exponent are omitted,
 *   an exponent value of 0 is assumed.
***/

class XMLUTIL_EXPORT XMLAbstractDoubleFloat : public XMLNumber
{
public:

    enum LiteralType
    {
        NegINF,
        PosINF,
        NaN,
        SpecialTypeNum,
        Normal
    };

    virtual ~XMLAbstractDoubleFloat();

    static XMLCh* getCanonicalRepresentation
                        (
                          const XMLCh*         const rawData
                        ,       MemoryManager* const memMgr = XMLPlatformUtils::fgMemoryManager
                        );

    /**
     *
     *  Deprecated: please use getRawData
     *
     */
    virtual XMLCh*        toString() const;

    virtual XMLCh*        getRawData() const;

    virtual const XMLCh*  getFormattedString() const;

    virtual int           getSign() const;

    MemoryManager*        getMemoryManager() const;

    inline  bool          isDataConverted()  const;

    inline  double        getValue() const;

    /***
     *
     * The decimal point delimiter for the schema double/float type is
     * defined to be a period and is not locale-specific. So, it must
     * be replaced with the local-specific delimiter before converting
     * from string to double/float.
     *
     ***/
    void                  normalizeDecimalPoint(char* const toNormal);

    /***
     * Support for Serialization/De-serialization
     ***/
    DECL_XSERIALIZABLE(XMLAbstractDoubleFloat)

protected:

    //
    // To be used by derived class exclusively
    //
    XMLAbstractDoubleFloat(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);

    void                  init(const XMLCh* const strValue);

    /**
	 * Compares this object to the specified object.
	 * The result is true if and only if the argument is not
	 * null and is an XMLAbstractDoubleFloat object that contains
	 * the same int value as this object.
	 *
	 * @param   lValue the object to compare with.
	 * @param   rValue the object to compare against.
	 * @return  true if the objects are the same;
	 *          false otherwise.
	 */

    static int            compareValues(const XMLAbstractDoubleFloat* const lValue
                                      , const XMLAbstractDoubleFloat* const rValue
                                      , MemoryManager* const manager);

    //
    // to be overwritten by derived class
    //
    virtual void          checkBoundary(const XMLCh* const strValue) = 0;

private:
    //
    // Unimplemented
    //
    // copy ctor
    // assignment ctor
    //
    XMLAbstractDoubleFloat(const XMLAbstractDoubleFloat& toCopy);
    XMLAbstractDoubleFloat& operator=(const XMLAbstractDoubleFloat& toAssign);

	void                  normalizeZero(XMLCh* const);

    inline bool           isSpecialValue() const;

    static int            compareSpecial(const XMLAbstractDoubleFloat* const specialValue
                                       , MemoryManager* const manager);

    void                  formatString();

protected:
    double                  fValue;
    LiteralType             fType;
    bool                    fDataConverted;

private:
    int                     fSign;
    XMLCh*                  fRawData;

    //
    // If the original string is not lexcially the same as the five
    // special value notations, and the value is converted to
    // special value due underlying platform restriction on data
    // representation, then this string is constructed and
    // takes the form "original_string (special_value_notation)",
    // otherwise it is empty.
    //
    XMLCh*                  fFormattedString;
    MemoryManager*          fMemoryManager;

};

inline bool XMLAbstractDoubleFloat::isSpecialValue() const
{
    return (fType < SpecialTypeNum);
}

inline MemoryManager* XMLAbstractDoubleFloat::getMemoryManager() const
{
    return fMemoryManager;
}

inline bool XMLAbstractDoubleFloat::isDataConverted() const
{
    return fDataConverted;
}

inline double XMLAbstractDoubleFloat::getValue() const
{
    return fValue;
}

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <cstring>
#include <string>
#include <vector>

#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/shared/platform/nacl_time.h"
#include "native_client/src/shared/srpc/nacl_srpc.h"

#include "native_client/src/trusted/sel_universal/parsing.h"
#include "native_client/src/trusted/sel_universal/pnacl_emu_handler.h"
#include "native_client/src/trusted/sel_universal/rpc_universal.h"

using std::string;
using std::vector;

namespace {

int
SendDataChunk(NaClCommandLoop* ncl, nacl_abi_size_t size, const char *data) {
  const string signature = string("StreamChunk:C:");
  NaClSrpcArg in[1];
  NaClSrpcArg* inv[2];
  BuildArgVec(inv, in, 1);
  in[0].tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
  in[0].arrays.carr = static_cast<char*>(malloc(size));
  if (0 == in[0].arrays.carr) {
    NaClLog(LOG_ERROR, "allocation failed\n");
    FreeArrayArgs(inv);
    return -1;
  }
  in[0].u.count = size;
  memcpy(in[0].arrays.carr, data, size);

  NaClSrpcArg* outv[1];
  outv[0] = NULL;
  if (!ncl->InvokeNexeRpc(signature, inv, outv)) {
    NaClLog(LOG_ERROR, "StreamChunk failed\n");
    FreeArrayArgs(inv);
    return -1;
  }
  return 0;
}

// Stream the file to the client with a series of StreamChunk RPCs.
// Rate-limit the sending to bits_per_sec to emulate a download
bool PnaclStreamFile(NaClCommandLoop* ncl, FILE* input_file,
                            int chunk_size, int bits_per_sec) {
  char* data = new char[chunk_size];
  NaClLog(LOG_INFO, "Streaming file at %d bps\n", bits_per_sec);
  uint64_t start_time = NaClGetTimeOfDayMicroseconds();
  size_t data_sent = 0;
  while (!feof(input_file) && !ferror(input_file)) {
    size_t data_read = fread(data, 1, chunk_size, input_file);
    uint64_t cur_elapsed_us = NaClGetTimeOfDayMicroseconds() - start_time;
    uint64_t target_elapsed_us = static_cast<uint64_t>(data_sent + data_read)
        * 8 * 1000000 / bits_per_sec;
    if (cur_elapsed_us < target_elapsed_us) {
      uint64_t sleep_us = target_elapsed_us - cur_elapsed_us;
      struct nacl_abi_timespec req;
      struct nacl_abi_timespec rem;
      req.tv_sec = sleep_us / 1000000;
      req.tv_nsec = sleep_us % 1000000 * 1000;
      int ret = NaClNanosleep(&req, &rem);
      if (ret == -1) {
        NaClLog(LOG_ERROR, "NaClNanosleep failed");
        return false;
      }
    }
    if (SendDataChunk(ncl, static_cast<nacl_abi_size_t>(data_read), data)) {
      return false;
    }
    data_sent += data_read;
  }
  delete data;
  return true;
}

}  // namespace

bool HandlerPnaclFileStream(NaClCommandLoop* ncl,
                            const vector<string>& args) {
  if (args.size() != 4) {
    NaClLog(LOG_ERROR, "not enough args to file_stream\n");
    return false;
  }

  FILE* input_file = fopen(args[1].c_str(), "rb");
  if (NULL == input_file) {
    NaClLog(LOG_ERROR, "could not open input file %s\n", args[1].c_str());
    return false;
  }
  return PnaclStreamFile(ncl, input_file, strtol(args[2].c_str(), 0, 0),
                         strtol(args[3].c_str(), 0, 0));
}
<commit_msg>Use scoped_array in pnacl stream tester. This avoids leaking the buffer in the error case.<commit_after>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <cstring>
#include <string>
#include <vector>

#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/shared/platform/nacl_time.h"
#include "native_client/src/shared/srpc/nacl_srpc.h"

#include "native_client/src/trusted/sel_universal/parsing.h"
#include "native_client/src/trusted/sel_universal/pnacl_emu_handler.h"
#include "native_client/src/trusted/sel_universal/rpc_universal.h"

using std::string;
using std::vector;

namespace {

int
SendDataChunk(NaClCommandLoop* ncl, nacl_abi_size_t size, const char *data) {
  const string signature = string("StreamChunk:C:");
  NaClSrpcArg in[1];
  NaClSrpcArg* inv[2];
  BuildArgVec(inv, in, 1);
  in[0].tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
  in[0].arrays.carr = static_cast<char*>(malloc(size));
  if (0 == in[0].arrays.carr) {
    NaClLog(LOG_ERROR, "allocation failed\n");
    FreeArrayArgs(inv);
    return -1;
  }
  in[0].u.count = size;
  memcpy(in[0].arrays.carr, data, size);

  NaClSrpcArg* outv[1];
  outv[0] = NULL;
  if (!ncl->InvokeNexeRpc(signature, inv, outv)) {
    NaClLog(LOG_ERROR, "StreamChunk failed\n");
    FreeArrayArgs(inv);
    return -1;
  }
  return 0;
}

// Stream the file to the client with a series of StreamChunk RPCs.
// Rate-limit the sending to bits_per_sec to emulate a download
bool PnaclStreamFile(NaClCommandLoop* ncl, FILE* input_file,
                            int chunk_size, int bits_per_sec) {
  nacl::scoped_array<char> data(new char[chunk_size]);
  NaClLog(LOG_INFO, "Streaming file at %d bps\n", bits_per_sec);
  uint64_t start_time = NaClGetTimeOfDayMicroseconds();
  size_t data_sent = 0;
  while (!feof(input_file) && !ferror(input_file)) {
    size_t data_read = fread(data.get(), 1, chunk_size, input_file);
    uint64_t cur_elapsed_us = NaClGetTimeOfDayMicroseconds() - start_time;
    uint64_t target_elapsed_us = static_cast<uint64_t>(data_sent + data_read)
        * 8 * 1000000 / bits_per_sec;
    if (cur_elapsed_us < target_elapsed_us) {
      uint64_t sleep_us = target_elapsed_us - cur_elapsed_us;
      struct nacl_abi_timespec req;
      struct nacl_abi_timespec rem;
      req.tv_sec = sleep_us / 1000000;
      req.tv_nsec = sleep_us % 1000000 * 1000;
      int ret = NaClNanosleep(&req, &rem);
      if (ret == -1) {
        NaClLog(LOG_ERROR, "NaClNanosleep failed");
        return false;
      }
    }
    if (SendDataChunk(ncl, static_cast<nacl_abi_size_t>(data_read),
                      data.get())) {
      return false;
    }
    data_sent += data_read;
  }
  return true;
}

}  // namespace

bool HandlerPnaclFileStream(NaClCommandLoop* ncl,
                            const vector<string>& args) {
  if (args.size() != 4) {
    NaClLog(LOG_ERROR, "not enough args to file_stream\n");
    return false;
  }

  FILE* input_file = fopen(args[1].c_str(), "rb");
  if (NULL == input_file) {
    NaClLog(LOG_ERROR, "could not open input file %s\n", args[1].c_str());
    return false;
  }
  return PnaclStreamFile(ncl, input_file, strtol(args[2].c_str(), 0, 0),
                         strtol(args[3].c_str(), 0, 0));
}
<|endoftext|>


<commit_before>#ifndef __STAN__MCMC__DUALAVERAGE_H__
#define __STAN__MCMC__DUALAVERAGE_H__

#include <cmath>
#include <cstddef>

#include <vector>
#include <cstdio>

#include <sstream>

namespace stan {

  namespace mcmc {

    /**
     * Class implementing Nesterov's dual average algorithm.  Use by
     * repeatedly calling update() with the gradient evaluated at
     * xk(). When finished, use the average value of all the xk's by
     * calling xbar().
     *
     * Iterates are shrunk towards a prespecified point x0. The level
     * of shrinkage is controlled by the parameter gamma and gets
     * weaker with each iteration.
     *
     * Note that this is an algorithm for MINIMIZATION, not MAXIMIZATION.
     */
    class DualAverage {
    protected:
      std::vector<double> _gbar, _xbar, _x0, _lastx;
      int _k;
      double _gamma;

    public:
      /**
       * Constructor.
       *
       * @param gamma Regularization parameter. Higher values mean that
       * iterates will be shrunk towards x0 more strongly.
       * @param x0 Point towards which iterates are shrunk.
       */
      DualAverage(double gamma, const std::vector<double>& x0)
        : _gbar(x0.size(), 0), _xbar(x0.size(), 0), _x0(x0), _lastx(x0),
          _k(0), _gamma(gamma){
      }

      /**
       * Produces the next iterate xk given the current gradient g.
       *
       * @param g The new subgradient/stochastic gradient.
       * @param xk The next iterate produced by the algorithm.
       */
      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        xk.resize(_gbar.size());
        double avgeta = 1.0 / (_k + 10);
        double xbar_avgeta = pow(_k, -0.75);
        double muk = 0.5 * sqrt(_k) / _gamma;
        for (size_t i = 0; i < _gbar.size(); ++i) {
          _gbar[i] = avgeta * g[i] + (1 - avgeta) * _gbar[i];
          xk[i] = _x0[i] - muk * _gbar[i];
//           fprintf(stderr, "DUALAVERAGE update %d: g = %f, gbar = %f, lastx = %f",
//                   _k, g[0], _gbar[0], _lastx[0]);
          _lastx[i] = xk[i];
          _xbar[i] = xbar_avgeta * xk[i] + (1 - xbar_avgeta) * _xbar[i];
        }
//         fprintf(stderr, ", xk = %f\n", xk[0]);
      }

      /**
       * Set the point towards which each iterate is shrunk.
       *
       * @param x0 The point towards each iterate will be shrunk.
       */
      void setx0(const std::vector<double>& x0) {
        _x0.assign(x0.begin(), x0.end());
      }

      /**
       * Get the exponentially weighted moving average of all previous
       * iterates.
       *
       * @param xbar Where to return the exponentially weighted moving
       * average of all previous iterates.
       */
      void xbar(std::vector<double>& xbar) {
        xbar.assign(_xbar.begin(), _xbar.end());
      }
      /**
       * Get the average of all previous gradients.
       *
       * @param gbar Where to return the average of all previous gradients.
       */
      void gbar(std::vector<double>& gbar) {
        gbar.assign(_gbar.begin(), _gbar.end());
      }
      /**
       * Get the current iterate.
       *
       * @param xk Where to return the current iterate.
       */
      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      /**
       * Get the point towards which we're shrinking the iterates.
       *
       * @param x0 Where to return the point towards which we're
       * shrinking the iterates.
       */
      void x0(std::vector<double>& x0) {
        x0.assign(_x0.begin(), _x0.end());
      }
      /**
       * Return how many iterations we've run for.
       *
       * @return how many iterations we've run for.
       */
      int k() { return _k; }
      /**
       * Return the regularization parameter gamma.
       *
       * @return the regularization parameter gamma.
       */
      double gamma() { return _gamma; }
    };

    class GrowingBatches {
    protected:
      std::vector<double> _gbar, _xbar, _x0, _lastx;
      int _k, _lastk, _nextk;
      double _gamma;

    public:
      GrowingBatches(double gamma, const std::vector<double>& x0)
        : _gbar(x0.size(), 0), _xbar(x0.size(), 0), _x0(x0), _lastx(x0),
          _k(0), _lastk(0), _nextk(1), _gamma(gamma){
      }

      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        for (size_t i = 0; i < g.size(); ++i)
          _gbar[i] += g[i];
        if (_k == _nextk) {
          for (size_t i = 0; i < g.size(); ++i) {
            std::cerr << "_lastx[" << i << "]"
                      << " = " << _lastx[i]
                      << ", _gbar[" << i << "]"
                      << " = " << _gbar[i]
                      << std::endl;
            _lastx[i] -= _gamma * _gbar[i] / (_nextk - _lastk);
          }
          _gbar.assign(_gbar.size(), 0);
          int temp = _lastk;
          _lastk = _nextk;
          _nextk = _lastk + (_nextk - temp + 1);
        }
        xk = _lastx;
        _xbar = _lastx;
      }

      void setx0(const std::vector<double>& x0) {
        _x0 = x0;
        _lastx = x0;
        _xbar = x0;
        fprintf(stderr, "_lastx[0] = %f\n", x0[0]);
      }

      void xbar(std::vector<double>& xbar) {
        xbar.assign(_xbar.begin(), _xbar.end());
      }
      void gbar(std::vector<double>& gbar) {
        gbar.assign(_gbar.begin(), _gbar.end());
      }
      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      void x0(std::vector<double>& x0) {
        x0.assign(_x0.begin(), _x0.end());
      }
      int k() { return _k; }
      double gamma() { return _gamma; }
    };

    class StochasticGradient {
    protected:
      std::vector<double> _lastx;
      int _k;
      double _gamma, _a;

    public:
      StochasticGradient(const std::vector<double>& x0, double gamma = 0.5,
                         double a = 1.0)
        : _lastx(x0), _k(0), _gamma(gamma), _a(a) {
      }

      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        xk.resize(g.size());
        double eta = _a * pow(_k, -_gamma);
        for (size_t i = 0; i < g.size(); ++i) {
          xk[i] = _lastx[i] - eta * g[i];
          _lastx[i] = xk[i];
        }
      }

      void setlastx(const std::vector<double>& lastx) {
        _lastx.assign(lastx.begin(), lastx.end());
      }
      void setx0(const std::vector<double>& lastx) {
        _lastx.assign(lastx.begin(), lastx.end());
      }

      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      void xbar(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      int k() { return _k; }
      double gamma() { return _gamma; }
    };
  }
}

#endif
<commit_msg>#include <iostream> in dualaverage.hpp<commit_after>#ifndef __STAN__MCMC__DUALAVERAGE_H__
#define __STAN__MCMC__DUALAVERAGE_H__

#include <cmath>
#include <cstddef>

#include <vector>
#include <cstdio>

#include <sstream>
#include <iostream>

namespace stan {

  namespace mcmc {

    /**
     * Class implementing Nesterov's dual average algorithm.  Use by
     * repeatedly calling update() with the gradient evaluated at
     * xk(). When finished, use the average value of all the xk's by
     * calling xbar().
     *
     * Iterates are shrunk towards a prespecified point x0. The level
     * of shrinkage is controlled by the parameter gamma and gets
     * weaker with each iteration.
     *
     * Note that this is an algorithm for MINIMIZATION, not MAXIMIZATION.
     */
    class DualAverage {
    protected:
      std::vector<double> _gbar, _xbar, _x0, _lastx;
      int _k;
      double _gamma;

    public:
      /**
       * Constructor.
       *
       * @param gamma Regularization parameter. Higher values mean that
       * iterates will be shrunk towards x0 more strongly.
       * @param x0 Point towards which iterates are shrunk.
       */
      DualAverage(double gamma, const std::vector<double>& x0)
        : _gbar(x0.size(), 0), _xbar(x0.size(), 0), _x0(x0), _lastx(x0),
          _k(0), _gamma(gamma){
      }

      /**
       * Produces the next iterate xk given the current gradient g.
       *
       * @param g The new subgradient/stochastic gradient.
       * @param xk The next iterate produced by the algorithm.
       */
      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        xk.resize(_gbar.size());
        double avgeta = 1.0 / (_k + 10);
        double xbar_avgeta = pow(_k, -0.75);
        double muk = 0.5 * sqrt(_k) / _gamma;
        for (size_t i = 0; i < _gbar.size(); ++i) {
          _gbar[i] = avgeta * g[i] + (1 - avgeta) * _gbar[i];
          xk[i] = _x0[i] - muk * _gbar[i];
//           fprintf(stderr, "DUALAVERAGE update %d: g = %f, gbar = %f, lastx = %f",
//                   _k, g[0], _gbar[0], _lastx[0]);
          _lastx[i] = xk[i];
          _xbar[i] = xbar_avgeta * xk[i] + (1 - xbar_avgeta) * _xbar[i];
        }
//         fprintf(stderr, ", xk = %f\n", xk[0]);
      }

      /**
       * Set the point towards which each iterate is shrunk.
       *
       * @param x0 The point towards each iterate will be shrunk.
       */
      void setx0(const std::vector<double>& x0) {
        _x0.assign(x0.begin(), x0.end());
      }

      /**
       * Get the exponentially weighted moving average of all previous
       * iterates.
       *
       * @param xbar Where to return the exponentially weighted moving
       * average of all previous iterates.
       */
      void xbar(std::vector<double>& xbar) {
        xbar.assign(_xbar.begin(), _xbar.end());
      }
      /**
       * Get the average of all previous gradients.
       *
       * @param gbar Where to return the average of all previous gradients.
       */
      void gbar(std::vector<double>& gbar) {
        gbar.assign(_gbar.begin(), _gbar.end());
      }
      /**
       * Get the current iterate.
       *
       * @param xk Where to return the current iterate.
       */
      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      /**
       * Get the point towards which we're shrinking the iterates.
       *
       * @param x0 Where to return the point towards which we're
       * shrinking the iterates.
       */
      void x0(std::vector<double>& x0) {
        x0.assign(_x0.begin(), _x0.end());
      }
      /**
       * Return how many iterations we've run for.
       *
       * @return how many iterations we've run for.
       */
      int k() { return _k; }
      /**
       * Return the regularization parameter gamma.
       *
       * @return the regularization parameter gamma.
       */
      double gamma() { return _gamma; }
    };

    class GrowingBatches {
    protected:
      std::vector<double> _gbar, _xbar, _x0, _lastx;
      int _k, _lastk, _nextk;
      double _gamma;

    public:
      GrowingBatches(double gamma, const std::vector<double>& x0)
        : _gbar(x0.size(), 0), _xbar(x0.size(), 0), _x0(x0), _lastx(x0),
          _k(0), _lastk(0), _nextk(1), _gamma(gamma){
      }

      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        for (size_t i = 0; i < g.size(); ++i)
          _gbar[i] += g[i];
        if (_k == _nextk) {
          for (size_t i = 0; i < g.size(); ++i) {
            std::cerr << "_lastx[" << i << "]"
                      << " = " << _lastx[i]
                      << ", _gbar[" << i << "]"
                      << " = " << _gbar[i]
                      << std::endl;
            _lastx[i] -= _gamma * _gbar[i] / (_nextk - _lastk);
          }
          _gbar.assign(_gbar.size(), 0);
          int temp = _lastk;
          _lastk = _nextk;
          _nextk = _lastk + (_nextk - temp + 1);
        }
        xk = _lastx;
        _xbar = _lastx;
      }

      void setx0(const std::vector<double>& x0) {
        _x0 = x0;
        _lastx = x0;
        _xbar = x0;
        fprintf(stderr, "_lastx[0] = %f\n", x0[0]);
      }

      void xbar(std::vector<double>& xbar) {
        xbar.assign(_xbar.begin(), _xbar.end());
      }
      void gbar(std::vector<double>& gbar) {
        gbar.assign(_gbar.begin(), _gbar.end());
      }
      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      void x0(std::vector<double>& x0) {
        x0.assign(_x0.begin(), _x0.end());
      }
      int k() { return _k; }
      double gamma() { return _gamma; }
    };

    class StochasticGradient {
    protected:
      std::vector<double> _lastx;
      int _k;
      double _gamma, _a;

    public:
      StochasticGradient(const std::vector<double>& x0, double gamma = 0.5,
                         double a = 1.0)
        : _lastx(x0), _k(0), _gamma(gamma), _a(a) {
      }

      void update(const std::vector<double>& g, std::vector<double>& xk) {
        _k++;
        xk.resize(g.size());
        double eta = _a * pow(_k, -_gamma);
        for (size_t i = 0; i < g.size(); ++i) {
          xk[i] = _lastx[i] - eta * g[i];
          _lastx[i] = xk[i];
        }
      }

      void setlastx(const std::vector<double>& lastx) {
        _lastx.assign(lastx.begin(), lastx.end());
      }
      void setx0(const std::vector<double>& lastx) {
        _lastx.assign(lastx.begin(), lastx.end());
      }

      void xk(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      void xbar(std::vector<double>& xk) {
        xk.assign(_lastx.begin(), _lastx.end());
      }
      int k() { return _k; }
      double gamma() { return _gamma; }
    };
  }
}

#endif
<|endoftext|>