text:
/*
    Copyright (c) 2011-2014 University of Zurich

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

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

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

#ifndef PLLL_INCLUDE_GUARD__LLL2_GENERIC_CPP
#define PLLL_INCLUDE_GUARD__LLL2_GENERIC_CPP

#include "lll2-internal.hpp"

#include "lattice.cpp"
#include "lllimpl.cpp"
#include "enumimpl.hpp"
#include "enumimpl-preproc.cpp"
#include "bkzimpl.cpp"
#include "svpimpl.cpp"
#include "verifyimpl.cpp"
#include "matrixconversion.hpp"
#include "lll2-callback.cpp"
#include "lll2-deepinsertion.cpp"

#include <boost/bind.hpp>

namespace plll
{
    template<class RealTypeContext, class IntTypeContext>
    GSInterface<RealTypeContext, IntTypeContext> * createGSInterface(Verbose & verbose, RealTypeContext & rc, IntTypeContext & ic,
                                                                     LatticeReduction::GramSchmidt gs, bool restarts,
                                                                     linalg::math_matrix<typename IntTypeContext::Integer> & A);

    template<class RealTypeContext, class IntTypeContext>
    class LRIImplementation : public LRIInterface
    {
        class GSIImplementation;
        friend class GSIImplementation;

    private:
        mutable RealTypeContext d_rc;
        mutable IntTypeContext d_ic;
        MatrixConversion<IntTypeContext> d_intlattice;
        Verbose d_verbose;
        mutable STD_AUTO_PTR<GSInterface<RealTypeContext, IntTypeContext> > d_gs;
        mutable STD_AUTO_PTR<Lattice<RealTypeContext, IntTypeContext> > d_lattice_object;
        mutable Transform * d_lattice_object_trans;
        LatticeReduction::SVPMode d_svp;
        unsigned d_max_cores;

        void handle_exception(std::exception * e) const
        {
            if (reduction_error * ee = dynamic_cast<reduction_error*>(e))
            {
                d_verbose(LatticeReduction::VL_Error) << "FATAL ERROR during reduction: " << ee->what();
            }
            else if (change_interface_exception * ee = dynamic_cast<change_interface_exception*>(e))
            {
                d_verbose(LatticeReduction::VL_Error) << ee->what();
            }
            else if (feature_not_implemented * ee = dynamic_cast<feature_not_implemented*>(e))
            {
                d_verbose(LatticeReduction::VL_Error) << ee->what();
            }
            else if (dynamic_cast<LatticeReduction::stop_reduction*>(e) != NULL)
            {
                d_verbose(LatticeReduction::VL_Information) << "Stopping reduction requested";
            }
            else if (dynamic_cast<LatticeReduction::stop_enumeration*>(e) != NULL)
            {
                d_verbose(LatticeReduction::VL_Error) << "FATAL ERROR: Enumeration stopping request caught outside enumeration code.";
            }
            else if (dynamic_cast<std::bad_alloc*>(e) != NULL)
            {
                d_verbose(LatticeReduction::VL_Error) << "FATAL ERROR: Memory allocation failed!";
            }
            else
                d_verbose(LatticeReduction::VL_Error) << "FATAL ERROR: Unhandled standard exception: " << e->what();
        }

        void handle_unknown_exception() const
        {
            d_verbose(LatticeReduction::VL_Error) << "FATAL ERROR: Unknown exception! Re-throwing.";
        }

        void setupLattice(Transform * transform) const
        {
            if (d_lattice_object.get() == NULL)
                d_lattice_object.reset(new Lattice<RealTypeContext, IntTypeContext>(d_gs.get(), d_rc, d_ic, d_stats, 0, d_gs->getDimension() - 1));
            else
            {
                if (transform == d_lattice_object_trans)
                    return;
            }
            if (d_lattice_object_trans)
            {
                d_lattice_object->removeAllNotifiers();
                d_lattice_object_trans->releaseTransformObject();
                d_lattice_object_trans = NULL;
            }
            if (transform)
            {
                d_lattice_object_trans = transform;
                d_lattice_object->addNotifier(transform->createTransformObject<IntTypeContext>(d_ic));
            }
        }

        void freeLattice() const
        {
            if (d_lattice_object_trans)
            {
                if (d_lattice_object.get())
                    d_lattice_object->removeAllNotifiers();
                d_lattice_object_trans->releaseTransformObject();
                d_lattice_object_trans = NULL;
            }
            d_lattice_object.reset();
        }

        class GSIImplementation : public LatticeReduction::GramSchmidtInformer
        {
        private:
            LRIImplementation & d_i;

        public:
            GSIImplementation(LRIImplementation & i)
                : d_i(i)
            {
            }

            virtual ~GSIImplementation()
            {
            }

            virtual double getGSCoefficientD(unsigned i, unsigned j) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert<double>(d_i.d_lattice_object->getCoeff(i, j));
            }

            virtual long double getGSCoefficientLD(unsigned i, unsigned j) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert<long double>(d_i.d_lattice_object->getCoeff(i, j));
            }

            virtual arithmetic::Real getGSCoefficientR(unsigned i, unsigned j, const arithmetic::RealContext & rc) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert(d_i.d_lattice_object->getCoeff(i, j), rc);
            }

            virtual double getGSSqNormD(unsigned i) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert<double>(d_i.d_lattice_object->getNormSq(i));
            }

            virtual long double getGSSqNormLD(unsigned i) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert<long double>(d_i.d_lattice_object->getNormSq(i));
            }

            virtual arithmetic::Real getGSSqNormR(unsigned i, const arithmetic::RealContext & rc) const
            {
                d_i.setupLattice(NULL);
                d_i.d_lattice_object->update(i + 1);
                return arithmetic::convert(d_i.d_lattice_object->getNormSq(i), rc);
            }

            virtual double computeProjectionLengthD(unsigned k, unsigned b,
                                                    const linalg::math_rowvector<arithmetic::Integer> & vec) const
            {
                d_i.setupLattice(NULL);
                typename RealTypeContext::Real result(d_i.d_rc);
                VectorConversionConst<IntTypeContext> v(d_i.d_ic, vec);
                d_i.d_lattice_object->computeProjectionLength(result, k, b, v.vector());
                return arithmetic::convert<double>(result);
            }

            virtual long double computeProjectionLengthLD(unsigned k, unsigned b,
                                                          const linalg::math_rowvector<arithmetic::Integer> & vec) const
            {
                d_i.setupLattice(NULL);
                typename RealTypeContext::Real result(d_i.d_rc);
                VectorConversionConst<IntTypeContext> v(d_i.d_ic, vec);
                d_i.d_lattice_object->computeProjectionLength(result, k, b, v.vector());
                return arithmetic::convert<long double>(result);
            }

            virtual arithmetic::Real computeProjectionLengthR(unsigned k, unsigned b,
                                                              const linalg::math_rowvector<arithmetic::Integer> & vec,
                                                              const arithmetic::RealContext & rc) const
            {
                d_i.setupLattice(NULL);
                typename RealTypeContext::Real result(d_i.d_rc);
                VectorConversionConst<IntTypeContext> v(d_i.d_ic, vec);
                d_i.d_lattice_object->computeProjectionLength(result, k, b, v.vector());
                return arithmetic::convert(result, rc);
            }
        };

        GSIImplementation d_gsi;

    public:
        LRIImplementation(LatticeReduction::VerboseOutputLevel vol, LatticeReduction::VerboseFunction vf, linalg::math_matrix<arithmetic::Integer> & lattice,
                          LatticeReduction::GramSchmidt gs, bool gsr, LatticeReduction::SVPMode svp, unsigned max_cores,
                          const RealTypeContext & rc, const IntTypeContext & ic)
            : LRIInterface(lattice), d_rc(rc), d_ic(ic), d_intlattice(d_ic, d_lattice, true, true), d_verbose(vol, vf),
              d_gs(createGSInterface(d_verbose, d_rc, d_ic, gs, gsr, d_intlattice.matrix())),
              d_lattice_object(), d_lattice_object_trans(NULL), d_svp(svp), d_max_cores(max_cores), d_gsi(*this)
        {
        }

        virtual ~LRIImplementation()
        {
        }

        virtual void setupVerbose(LatticeReduction::VerboseOutputLevel vol, LatticeReduction::VerboseFunction vf)
        {
            d_verbose.setup(vol, vf);
        }

        virtual void ensureMinimumPrecision(unsigned long p)
        {
            if (RealTypeContext::is_variable_precision && (p > d_rc.getRealPrecision()))
                d_rc.setRealPrecision((p + 7) & ~7); // make multiple of 8
        }

        virtual const LatticeReduction::GramSchmidtInformer * getInformer() const
        {
            return &d_gsi;
        }

        virtual void forceGSRebuild(bool makeSureAllComputed)
        {
            if (d_lattice_object.get())
            {
                d_lattice_object->reset();
                if (makeSureAllComputed)
                    d_lattice_object->update(d_lattice_object->dimension());
            }
        }

        virtual double getGSCoefficientD(unsigned i, unsigned j) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert<double>(d_lattice_object->getCoeff(i, j));
        }

        virtual long double getGSCoefficientLD(unsigned i, unsigned j) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert<long double>(d_lattice_object->getCoeff(i, j));
        }

        virtual arithmetic::Real getGSCoefficientR(unsigned i, unsigned j, const arithmetic::RealContext & rc) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert(d_lattice_object->getCoeff(i, j), rc);
        }

        virtual double getGSSqNormD(unsigned i) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert<double>(d_lattice_object->getNormSq(i));
        }

        virtual long double getGSSqNormLD(unsigned i) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert<long double>(d_lattice_object->getNormSq(i));
        }

        virtual arithmetic::Real getGSSqNormR(unsigned i, const arithmetic::RealContext & rc) const
        {
            setupLattice(NULL);
            d_lattice_object->update(i + 1);
            return arithmetic::convert(d_lattice_object->getNormSq(i), rc);
        }

        virtual void modFlip(Transform & transform, unsigned i)
        {
            setupLattice(&transform);
            d_lattice_object->flip(i);
        }

        virtual void modSwap(Transform & transform, unsigned i, unsigned j)
        {
            setupLattice(&transform);
            d_lattice_object->swap(i, j);
        }

        virtual void modAdd(Transform & transform, unsigned i, unsigned j, const arithmetic::Integer & lambda)
        {
            setupLattice(&transform);
            d_lattice_object->add(i, arithmetic::convert(lambda, d_ic), j);
        }

        template<class Enumerator, class CallbackFunction>
        static void removeZeroVectors(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                                      Lattice<RealTypeContext, IntTypeContext> & lattice)
        {
            unsigned r = 0, c = 0;
            while (r < lattice.dimension())
            {
                if (lattice.isRowZero(r))
                {
                    lattice.removeZeroVector(r);
                    ++c;
                }
                else
                    ++r;
            }
            if (c > 0)
                if (workspace.verbose().yieldsOutput(LatticeReduction::VL_Information))
                    workspace.verbose()(LatticeReduction::VL_Information) << "Removed " << c << " additional zero vectors!";
            lattice.compactify();
        }

        static void setupPruning(StandardEnumSettings & settings, bool enable, double p = 0.5, bool extreme = false)
        {
            if (enable)
            {
                if (extreme)
                    settings.d_pruning = StandardEnumSettings::PM_GNR110_Poly8;
                else
                {
                    settings.d_pruning = StandardEnumSettings::PM_Piecewise;
                    settings.d_pruning_parameter = p;
                    // ...
                }
            }
            else
                settings.d_pruning = StandardEnumSettings::PM_None;
        }

        template<class Enumerator>
        void prepareEnumerator(Enumerator & enumerator, bool LLLonly = false) const
        {
            typedef typename Enumerator::PreprocessorStackT::Entry EntryT;
            EntryT entry, lllentry;
            entry.d_minalpha.setContext(d_rc);
            arithmetic::convert(entry.d_minalpha, 0.999, d_rc);
            lllentry.d_method = EntryT::RM_LLL;
            lllentry.d_minalpha.setContext(d_rc);
            lllentry.d_minalpha = entry.d_minalpha;

            // Add simple LLL
            enumerator.getPreprocessorStack().begin_add(entry);
            enumerator.getPreprocessorStack().end_add();
            if (LLLonly)
                return;

            // For higher dimensions, add better preprocessing
            entry.d_min_dim = 21;
            entry.d_max_dim = 30;
            entry.d_method = EntryT::RM_BKZ;
            entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
            entry.d_windowsize = 10;
            entry.d_force_tours = true;
            entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(100);
            entry.d_enumboundselectionmethod = EBS_Standard;
            entry.d_enum_repetitions = 1;
            setupPruning(entry.d_enumsettings, false); // no pruning
            enumerator.getPreprocessorStack().begin_add(entry);
            {
                enumerator.getPreprocessorStack().begin_add(lllentry);
                enumerator.getPreprocessorStack().end_add();
            }
            enumerator.getPreprocessorStack().end_add();
            // For higher dimensions, add better preprocessing
            entry.d_min_dim = 31;
            entry.d_max_dim = 40;
            entry.d_method = EntryT::RM_BKZ;
            entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
            entry.d_windowsize = 16;
            entry.d_force_tours = true;
            entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(400);
            entry.d_enumboundselectionmethod = EBS_Standard;
            entry.d_enum_repetitions = 1;
            setupPruning(entry.d_enumsettings, false); // no pruning
            enumerator.getPreprocessorStack().begin_add(entry);
            {
                enumerator.getPreprocessorStack().begin_add(lllentry);
                enumerator.getPreprocessorStack().end_add();
            }
            enumerator.getPreprocessorStack().end_add();
            // For higher dimensions, add better preprocessing
            entry.d_min_dim = 41;
            entry.d_max_dim = std::numeric_limits<unsigned>::max();
            entry.d_method = EntryT::RM_BKZ;
            entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
            entry.d_windowsize = 20;
            entry.d_force_tours = true;
            entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(1200);
            entry.d_enumboundselectionmethod = EBS_Standard;
//        entry.d_enumboundselectionmethod = EBS_GaussianHeuristic105;
            entry.d_enum_repetitions = 1;
            setupPruning(entry.d_enumsettings, false); // no pruning
            enumerator.getPreprocessorStack().begin_add(entry);
            {
                enumerator.getPreprocessorStack().begin_add(lllentry);
                enumerator.getPreprocessorStack().end_add();
                entry.d_min_dim = 10;
                entry.d_max_dim = std::numeric_limits<unsigned>::max();
                entry.d_method = EntryT::RM_BKZ;
                entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
                entry.d_windowsize = 10;
                entry.d_force_tours = true;
                entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(100);
                entry.d_enumboundselectionmethod = EBS_Standard;
                entry.d_enum_repetitions = 1;
                setupPruning(entry.d_enumsettings, false); // no pruning
                enumerator.getPreprocessorStack().begin_add(entry);
                {
                    enumerator.getPreprocessorStack().begin_add(lllentry);
                    enumerator.getPreprocessorStack().end_add();
                }
                enumerator.getPreprocessorStack().end_add();
            }
            enumerator.getPreprocessorStack().end_add();
/*
            // For higher dimensions, add better preprocessing
            entry.d_min_dim = 50;
            entry.d_max_dim = std::numeric_limits<unsigned>::max();
            entry.d_method = EntryT::RM_BKZ;
            entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
            entry.d_windowsize = 40;
            entry.d_force_tours = true;
            entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(2400);
            entry.d_enumboundselectionmethod = EBS_Standard;
//        entry.d_enumboundselectionmethod = EBS_GaussianHeuristic105;
            entry.d_enum_repetitions = 1;
            setupPruning(entry.d_enumsettings, true, 0.1); // pruning
            enumerator.getPreprocessorStack().begin_add(entry);
            {
                enumerator.getPreprocessorStack().begin_add(lllentry);
                enumerator.getPreprocessorStack().end_add();
                entry.d_min_dim = 10;
                entry.d_max_dim = std::numeric_limits<unsigned>::max();
                entry.d_method = EntryT::RM_BKZ;
                entry.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
                entry.d_windowsize = 16;
                entry.d_force_tours = true;
                entry.d_bkz_tours = arithmetic::convert<arithmetic::Integer>(250);
                entry.d_enumboundselectionmethod = EBS_Standard;
                entry.d_enum_repetitions = 1;
                setupPruning(entry.d_enumsettings, false); // no pruning
                enumerator.getPreprocessorStack().begin_add(entry);
                {
                    enumerator.getPreprocessorStack().begin_add(lllentry);
                    enumerator.getPreprocessorStack().end_add();
                }
                enumerator.getPreprocessorStack().end_add();
            }
            enumerator.getPreprocessorStack().end_add();
*/
        }

        /////////////// PROJECTED SORTING ///////////////

        void sortProjected(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T)
        {
            freeLattice();
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), 0, d_max_cores, NULL);
                // Implement a simple insertion sort
                typename RealTypeContext::Real len(d_rc), minlen(d_rc);
                for (unsigned i = begin; i < end; ++i)
                {
                    lattice.update(end + 1);
                    minlen = lattice.getNormSq(i);
                    unsigned mini = i;
                    for (unsigned j = i + 1; j <= end; ++j)
                    {
                        lattice.computeProjectionLengthBV(len, i, j);
                        if (len < minlen)
                        {
                            mini = j;
                            minlen = len;
                        }
                    }
                    for (unsigned j = mini; j > i; --j)
                        lattice.swap(j, j - 1);
                }
                removeZeroVectors(workspace, lattice);
                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// SIZE REDUCTION ///////////////

        void sizereduction(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T)
        {
            freeLattice();
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), 0, d_max_cores, NULL);
                workspace.sizereduction(lattice);
                removeZeroVectors(workspace, lattice);
                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        template<typename CallbackObject, typename LatticeObject>
        void setupCallback_impl(CallbackObject & cb,
                                LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                                LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                                unsigned & begin, LatticeObject & lattice, arithmetic::IntegerContext *)
        {
            if ((cf != NULL) || (cf2 != NULL))
            {
                if (cf != NULL)
                    cb.setCallback(cf, cf_int, begin);
                else
                    cb.setCallback(boost::bind(CallbackAdaptor, _1, cf2), cf_int, begin);
            }
            if ((mcf != NULL) || (mcf2 != NULL))
            {
                if (mcf != NULL)
                    cb.setMinCallback(lattice, mcf);
                else
                    cb.setMinCallback(lattice, boost::bind(MinCallbackAdaptor, _1, _2, _3, mcf2));
            }
        }

        template<typename CallbackObject, typename LatticeObject>
        void setupCallback_impl(CallbackObject & cb,
                                LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                                LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                                unsigned & begin, LatticeObject & lattice, arithmetic::NIntContext<long int> *)
        {
            if ((cf != NULL) || (cf2 != NULL))
            {
                if (cf2 != NULL)
                    cb.setCallback(cf2, cf_int, begin);
                else
                    cb.setCallback(boost::bind(CallbackAdaptor_LI, _1, cf), cf_int, begin);
            }
            if ((mcf != NULL) || (mcf2 != NULL))
            {
                if (mcf2 != NULL)
                    cb.setMinCallback(lattice, mcf2);
                else
                    cb.setMinCallback(lattice, boost::bind(MinCallbackAdaptor_LI, _1, _2, _3, mcf));
            }
        }

        template<typename CallbackObject, typename LatticeObject>
        void setupCallback(CallbackObject & cb,
                           LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                           LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                           MaxBitsCallbackFunction mbcf,
                           unsigned & begin, LatticeObject & lattice)
        {
            setupCallback_impl(cb, cf, cf2, cf_int, mcf, mcf2, begin, lattice, static_cast<IntTypeContext*>(NULL));
            if (mbcf != NULL)
                cb.setMaxBitsCallback(lattice, mbcf);
        }

        /////////////// LLL ///////////////

        template<class Enumerator, class CallbackFunction, class Reorderer>
        void lll_internal(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                          Lattice<RealTypeContext, IntTypeContext> & lattice, LatticeReduction::LLLMode mode,
                          bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::LLL_AnnealFunction af, Reorderer & reorder)
        {
            if (anneal)
            {
                lattice.range().dupRange();
                typedef typename Enumerator::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_None;
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().getPreprocessorStack().begin_preprocess();
                switch (mode)
                {
                case LatticeReduction::LLL_Classic:
                {
                    if (af == NULL)
                        workspace.partialLLL_Anneal(lattice, acf, &DefaultLLLAnnealFunction<IntTypeContext>, reorder);
                    else
                        workspace.partialLLL_Anneal(lattice, acf, LLLAnnealWrapper<IntTypeContext>(af, &d_gsi), reorder);
                }
                break;
                case LatticeReduction::LLL_Unprojected:
                case LatticeReduction::LLL_Siegel:
                    lattice.range().popRange();
                    workspace.verbose()(LatticeReduction::VL_Warning) << "No annealing implemented for this LLL mode!";
                    throw feature_not_implemented();
                }
                workspace.enumerator().getPreprocessorStack().end_preprocess();
            }
            else
            {
                typedef typename Enumerator::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_LLL;
                entry.d_lll_mode = mode;
                entry.d_enumalg = d_svp;
                setupPruning(entry.d_enumsettings, false); // no pruning
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().preprocess(workspace, lattice, reorder);
            }
            return;
        }

        template<class Enumerator, class CallbackFunction>
        void lll_internal(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                          Lattice<RealTypeContext, IntTypeContext> & lattice, LatticeReduction::LLLMode mode,
                          bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::LLL_AnnealFunction af,
                          LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode, LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            switch (di)
            {
            case LatticeReduction::DI_None:
            {
                NoReorder<RealTypeContext, IntTypeContext> r;
                lll_internal(workspace, lattice, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_Classic:
            {
                DoClassicDeepInsertion<RealTypeContext, IntTypeContext> r(di_mode, di_choice, di_bs, d_stats);
                lll_internal(workspace, lattice, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_MinimizePotential1:
            {
                DoMinPotDeepInsertion<RealTypeContext, IntTypeContext> r(d_intlattice.matrix().rows(), di_mode, di_choice, di_bs, d_stats, true);
                lll_internal(workspace, lattice, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_MinimizePotential2:
            {
                DoMinPotDeepInsertion<RealTypeContext, IntTypeContext> r(d_intlattice.matrix().rows(), di_mode, di_choice, di_bs, d_stats, false);
                lll_internal(workspace, lattice, mode, anneal, acf, af, r);
                break;
            }
            }
        }

        void lll(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T, double alpha, LatticeReduction::LLLMode mode,
                 LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                 LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2, MaxBitsCallbackFunction mbcf,
                 bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::LLL_AnnealFunction af,
                 LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode, LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            freeLattice();
            try
            {
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, Callback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, Callback<RealTypeContext, IntTypeContext>(end - begin + 1), 0, d_max_cores, NULL, NULL);
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                setupCallback(workspace.getCallbackObject(), cf, cf2, cf_int, mcf, mcf2, mbcf, begin, lattice);
                d_gs->adjustAlpha(alpha);

                lll_internal(workspace, lattice, mode, anneal, acf, af, di, di_mode, di_choice, di_bs);
                removeZeroVectors(workspace, lattice);

                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// BKZ ///////////////

        template<class Enumerator, class CallbackFunction, class Reorderer>
        inline void bkz_internal(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                                 Lattice<RealTypeContext, IntTypeContext> & lattice,
                                 unsigned blocksize, LatticeReduction::BKZMode mode,
                                 bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::BKZ_AnnealFunction af,
                                 Reorderer & reorder)
        {
            if (anneal)
            {
                lattice.range().dupRange();
                typedef typename Enumerator::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_None;
                entry.d_enumalg = d_svp;
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().getPreprocessorStack().begin_preprocess();
                switch (mode)
                {
                case LatticeReduction::BKZ_SchnorrEuchner:
                {
                    if (af == NULL)
                        workspace.partialBKZ_Anneal(lattice, blocksize, acf, &DefaultBKZAnnealFunction<IntTypeContext>, reorder, false);
                    else
                        workspace.partialBKZ_Anneal(lattice, blocksize, acf, BKZAnnealWrapper<IntTypeContext>(af, &d_gsi), reorder, false);
                }
                break;
                case LatticeReduction::BKZ_Simplified:
                {
                    if (af == NULL)
                        workspace.partialBKZ_Anneal(lattice, blocksize, acf, &DefaultBKZAnnealFunction<IntTypeContext>, reorder, true);
                    else
                        workspace.partialBKZ_Anneal(lattice, blocksize, acf, BKZAnnealWrapper<IntTypeContext>(af, &d_gsi), reorder, true);
                }
                break;
                case LatticeReduction::BKZ_HanrotPujolStehleSVP:
                case LatticeReduction::BKZ_HanrotPujolStehleHKZ:
                case LatticeReduction::BKZ_SemiBlock2k: // Schnorr's Semi-block-2k-reduction (blocksize is made even by rounding up)
                case LatticeReduction::BKZ_PrimalDual: // Koy's primal-dual BKZ
                case LatticeReduction::BKZ_SlideReduction: // Gama-Nguyen Slide Reduction (Gama, Nguyen: "Finding Short Lattice Vectors within Mordell's Inequality")
                case LatticeReduction::BKZ_ImprovedSlideReduction: // Schnorr's improved and accelerated Slide Reduction
                case LatticeReduction::BKZ_ImprovedSlideReduction2: // Schnorr's improved and accelerated Slide Reduction (using a larger DSVP and a single SVP)
                case LatticeReduction::BKZ_ImprovedSlideReduction3: // Schnorr's improved and accelerated Slide Reduction (using a single larger SVP and a DSVP)
                case LatticeReduction::BKZ_SamplingReduction:
                case LatticeReduction::BKZ_Experimental:
                    lattice.range().popRange();
                    workspace.verbose()(LatticeReduction::VL_Warning) << "No annealing implemented for this BKZ mode!";
                    throw feature_not_implemented();
                }
                workspace.enumerator().getPreprocessorStack().end_preprocess();
            }
            else
            {
                typedef typename Enumerator::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_BKZ;
                entry.d_bkz_mode = mode;
                entry.d_windowsize = blocksize;
                entry.d_enumalg = d_svp;
                setupPruning(entry.d_enumsettings, false); // no pruning
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().preprocess(workspace, lattice, reorder);
            }
            return;
        }

        template<class Enumerator, class CallbackFunction>
        inline void bkz_internal(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                                 Lattice<RealTypeContext, IntTypeContext> & lattice,
                                 unsigned blocksize, LatticeReduction::BKZMode mode,
                                 bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::BKZ_AnnealFunction af,
                                 LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode, LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            switch (di)
            {
            case LatticeReduction::DI_None:
            {
                NoReorder<RealTypeContext, IntTypeContext> r;
                bkz_internal(workspace, lattice, blocksize, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_Classic:
            {
                DoClassicDeepInsertion<RealTypeContext, IntTypeContext> r(di_mode, di_choice, di_bs, d_stats);
                bkz_internal(workspace, lattice, blocksize, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_MinimizePotential1:
            {
                DoMinPotDeepInsertion<RealTypeContext, IntTypeContext> r(lattice.dimension(), di_mode, di_choice, di_bs, d_stats, true);
                bkz_internal(workspace, lattice, blocksize, mode, anneal, acf, af, r);
                break;
            }
            case LatticeReduction::DI_MinimizePotential2:
            {
                DoMinPotDeepInsertion<RealTypeContext, IntTypeContext> r(lattice.dimension(), di_mode, di_choice, di_bs, d_stats, false);
                bkz_internal(workspace, lattice, blocksize, mode, anneal, acf, af, r);
                break;
            }
            }
        }

        void bkz(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T, double alpha, unsigned blocksize,
                 LatticeReduction::BKZMode mode, LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2,
                 double cf_int, LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                 MaxBitsCallbackFunction mbcf, LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2,
                 bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::BKZ_AnnealFunction af,
                 LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode, LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            freeLattice();
            try
            {
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, Callback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, Callback<RealTypeContext, IntTypeContext>(end - begin + 1), blocksize, d_max_cores, ecf, ecf2);
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                setupCallback(workspace.getCallbackObject(), cf, cf2, cf_int, mcf, mcf2, mbcf, begin, lattice);
                d_gs->adjustAlpha(alpha);

                bkz_internal(workspace, lattice, blocksize, mode, anneal, acf, af, di, di_mode, di_choice, di_bs);
                removeZeroVectors(workspace, lattice);

                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// HKZ ///////////////

        void hkz(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T, bool dual,
                 LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                 LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                 MaxBitsCallbackFunction mbcf,
                 LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2)
        {
            freeLattice();
            try
            {
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, Callback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, Callback<RealTypeContext, IntTypeContext>(end - begin + 1), end - begin + 1, d_max_cores, ecf, ecf2);
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                setupCallback(workspace.getCallbackObject(), cf, cf2, cf_int, mcf, mcf2, mbcf, begin, lattice);
                d_gs->adjustAlpha(0.999);

                typedef typename Enumerator<RealTypeContext, IntTypeContext>::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = dual ? EntryT::RM_HKZDual : EntryT::RM_HKZ;
                entry.d_enumalg = d_svp;
                setupPruning(entry.d_enumsettings, false); // no pruning
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().preprocess(workspace, lattice);
                removeZeroVectors(workspace, lattice);

                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// SVP ///////////////

        inline void svp(unsigned & begin, unsigned & end, TransformNotifier<IntTypeContext> * T, bool make_basis, bool extreme, bool dual,
                        LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                        LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                        MaxBitsCallbackFunction mbcf,
                        LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2)
        {
            freeLattice();
            try
            {
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, Callback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, Callback<RealTypeContext, IntTypeContext>(end - begin + 1), end - begin + 1, d_max_cores, ecf, ecf2);
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end);
                lattice.addNotifier(T);
                setupCallback(workspace.getCallbackObject(), cf, cf2, cf_int, mcf, mcf2, mbcf, begin, lattice);
                d_gs->adjustAlpha(0.999);

                lattice.range().dupRange();
                typedef typename Enumerator<RealTypeContext, IntTypeContext>::PreprocessorStackT::Entry EntryT;
                EntryT entry, entry2;
                entry.d_method = dual ? EntryT::RM_SVPDual : EntryT::RM_SVP;
                entry.d_enumalg = d_svp;
                setOne(entry.d_minalpha);
                if (extreme)
                {
                    entry.d_enumboundselectionmethod = EBS_GaussianHeuristic105;
                    entry.d_enum_repetitions = 256;
                    setupPruning(entry.d_enumsettings, true, 0, true); // extreme pruning
                    workspace.enumerator().getPreprocessorStack().begin_add(entry);
                    prepareEnumerator(workspace.enumerator(), true); // add LLL step
                    entry2.d_method = EntryT::RM_BKZ;
                    entry2.d_bkz_mode = LatticeReduction::BKZ_HanrotPujolStehleSVP;
                    entry2.d_windowsize = (end - begin + 1) / 5 + 10; // 110 => 30, 120 => 32
                    workspace.enumerator().getPreprocessorStack().begin_add(entry2);
                    prepareEnumerator(workspace.enumerator());
                    workspace.enumerator().getPreprocessorStack().end_add();
                    workspace.enumerator().getPreprocessorStack().end_add();
                }
                else
                {
                    setupPruning(entry.d_enumsettings, false); // no pruning
                    workspace.enumerator().getPreprocessorStack().begin_add(entry);
                    prepareEnumerator(workspace.enumerator());
                    workspace.enumerator().getPreprocessorStack().end_add();
                }
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().preprocess(workspace, lattice);
                removeZeroVectors(workspace, lattice);

                begin = lattice.range().begin();
                end = lattice.range().end();
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// VERIFICATION ///////////////

        virtual bool isSizeReduced(unsigned begin, unsigned end) const
        {
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end, true);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), 0, d_max_cores, NULL);
                return isSR(workspace, lattice);
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
                return false;
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        template<class Enumerator, class CallbackFunction>
        bool isDI_Classic(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                          Lattice<RealTypeContext, IntTypeContext> & lattice,
                          LatticeReduction::DIChoice di_choice, unsigned di_bs) const
        {
            lattice.update(d_intlattice.matrix().rows());
            typename RealTypeContext::Real res(lattice.rc());

            for (unsigned j = lattice.range().begin() + 1; j <= lattice.range().end(); ++j)
            {
                unsigned i = lattice.range().begin();
                for (; i < j; ++i)
                {
                    if (i >= lattice.range().begin() + di_bs)
                    {
                        if (di_choice == LatticeReduction::DIC_First)
                        {
                            i = j;
                            break;
                        }
                        if ((di_choice != LatticeReduction::DIC_All) && (i + di_bs < j))
                            i = j - di_bs;
                    }

                    lattice.computeProjectionLengthBV(res, i, j);
                    if (res < lattice.getLLLalpha() * lattice.getNormSq(i))
                    {
                        if (workspace.verbose().yieldsOutput(LatticeReduction::VL_Information))
                            workspace.verbose()(LatticeReduction::VL_Information) << "Deep Insertion condition failed for (" << i << ", " << j << ")\n";
                        return false;
                    }
                }
            }
            return true;
        }

        template<class Enumerator, class CallbackFunction>
        bool isDI_MinPot(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                         Lattice<RealTypeContext, IntTypeContext> & lattice,
                         LatticeReduction::DIChoice di_choice, unsigned di_bs, int mode = 0) const
        {
            lattice.update(d_intlattice.matrix().rows());
            typedef typename arithmetic::HugeExponent<RealTypeContext>::Type Huge;
            typename RealTypeContext::Real t(lattice.rc());
            Huge minpot(lattice.rc()), pot(lattice.rc());
            for (unsigned j = lattice.range().begin() + 1; j <= lattice.range().end(); ++j)
            {
                unsigned i = j - 1;
                minpot = Huge(lattice.getLLLalpha());
                setOne(pot);

                unsigned blockbegin = lattice.range().begin();
                if ((di_choice == LatticeReduction::DIC_Block) && (blockbegin + di_bs < i))
                    blockbegin = i - di_bs;
                if (blockbegin == i)
                    continue;

                for (; i >= blockbegin; --i)
                {
                    // Update potential
                    pot *= square(Huge(lattice.getNormSq(i - 1)));
                    lattice.computeProjectionLengthBV(t, i - 1, i);
                    pot /= square(Huge(t));

                    // Check whether we want to actually compare the potential for this position
                    bool doComp = true;
                    if (i > lattice.range().begin() + di_bs)
                    {
                        if (di_choice == LatticeReduction::DIC_First)
                            doComp = false;
                        if ((di_choice != LatticeReduction::DIC_All) && (i + di_bs <= j))
                            doComp = false;
                    }
                    else
                        if ((di_choice == LatticeReduction::DIC_Block) && (i + di_bs <= j))
                            doComp = false;

                    // Compare potential
                    if (doComp)
                        if (pot < minpot)
                        {
                            if (workspace.verbose().yieldsOutput(LatticeReduction::VL_Information))
                                workspace.verbose()(LatticeReduction::VL_Information) << "MinPot Deep Insertion condition failed for (" << i << ", " << j << ")\n";
                            return false;
                        }
                }
            }
            return true;
        }

        template<class Enumerator, class CallbackFunction>
        bool isDI(Workspace<RealTypeContext, IntTypeContext, Enumerator, CallbackFunction> & workspace,
                  Lattice<RealTypeContext, IntTypeContext> & lattice,
                  LatticeReduction::DIMethod di, LatticeReduction::DIChoice di_choice, unsigned di_bs) const
        {
            switch (di)
            {
            case LatticeReduction::DI_None: return true;
            case LatticeReduction::DI_Classic: return isDI_Classic(workspace, lattice, di_choice, di_bs);
            case LatticeReduction::DI_MinimizePotential1: return isDI_MinPot(workspace, lattice, di_choice, di_bs, 0);
            case LatticeReduction::DI_MinimizePotential2: return isDI_MinPot(workspace, lattice, di_choice, di_bs, 1);
            }
            return true; // unnecessary, but g++ complains if this is missing...
        }

        virtual bool isLLLBasis(unsigned begin, unsigned end, double alpha, LatticeReduction::LLLMode mode,
                                LatticeReduction::DIMethod di, LatticeReduction::DIChoice di_choice, unsigned di_bs) const
        {
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end, true);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), 0, d_max_cores, NULL);
                d_gs->adjustAlpha(alpha);
                if (!(isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs)))
                    return false;
                switch (mode)
                {
                case LatticeReduction::LLL_Classic:
                    return isLLL(workspace, lattice,
                                 Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >::LovaszCondition);
                case LatticeReduction::LLL_Unprojected:
                    return isLLL(workspace, lattice,
                                 Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >::UnprojectedLovaszCondition);
                case LatticeReduction::LLL_Siegel:
                    return isLLL(workspace, lattice,
                                 Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >::SiegelCondition);
                }
                return false;
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
                return false;
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        virtual bool isBKZBasis(unsigned begin, unsigned end, double alpha, unsigned blocksize, LatticeReduction::BKZMode mode,
                                LatticeReduction::DIMethod di, LatticeReduction::DIChoice di_choice, unsigned di_bs) const
        {
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end, true);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), blocksize, d_max_cores);
                d_gs->adjustAlpha(alpha);
                typedef typename Enumerator<RealTypeContext, IntTypeContext>::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_None;
                entry.d_enumalg = d_svp;
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().getPreprocessorStack().begin_preprocess();
                bool result = true;
                switch (mode)
                {
                case LatticeReduction::BKZ_SchnorrEuchner:
                case LatticeReduction::BKZ_Simplified:
                case LatticeReduction::BKZ_SamplingReduction:
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs) && isBKZ(workspace, lattice, blocksize);
                    break;
                case LatticeReduction::BKZ_HanrotPujolStehleSVP:
                case LatticeReduction::BKZ_HanrotPujolStehleHKZ:
                case LatticeReduction::BKZ_Experimental:
                    // Don't know how to check this!!! ??? ...
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs)
                        && isLLL(workspace, lattice,
                                 Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >::LovaszCondition);
                    break;
                case LatticeReduction::BKZ_SemiBlock2k: // Schnorr's Semi-block-2k-reduction (blocksize is made even by rounding up)
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs) && isBKZ_SemiBlock2k(workspace, lattice, blocksize);
                    break;
                case LatticeReduction::BKZ_PrimalDual: // Koy's primal-dual BKZ
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs) && isBKZ_PrimalDual(workspace, lattice, blocksize);
                    break;
                case LatticeReduction::BKZ_SlideReduction: // Gama-Nguyen Slide Reduction (Gama, Nguyen: "Finding Short Lattice Vectors within Mordell's Inequality")
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs) && isBKZ_Slide(workspace, lattice, blocksize);
                    break;
                case LatticeReduction::BKZ_ImprovedSlideReduction: // Schnorr's improved and accelerated Slide Reduction
                case LatticeReduction::BKZ_ImprovedSlideReduction2: // Schnorr's improved and accelerated Slide Reduction (using a larger DSVP and a single SVP)
                case LatticeReduction::BKZ_ImprovedSlideReduction3: // Schnorr's improved and accelerated Slide Reduction (using a single larger SVP and a DSVP)
                    result = isSR(workspace, lattice) && isDI(workspace, lattice, di, di_choice, di_bs) && isBKZ_ImprovedSlide(workspace, lattice, blocksize);
                    break;
                }
                workspace.enumerator().getPreprocessorStack().end_preprocess();
                // Default:
                return result;
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
                return false;
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        virtual bool isHKZBasis(unsigned begin, unsigned end, bool dual) const
        {
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end, true);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), lattice.range().dimension(), d_max_cores);
                d_gs->adjustAlpha(1);
                if (!isSR(workspace, lattice))
                    return false;
                typedef typename Enumerator<RealTypeContext, IntTypeContext>::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_None;
                entry.d_enumalg = d_svp;
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().getPreprocessorStack().begin_preprocess();
                bool result = isHKZ(workspace, lattice, dual);
                workspace.enumerator().getPreprocessorStack().end_preprocess();
                return result;
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
                return false;
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        virtual bool isSVPBasis(unsigned begin, unsigned end, bool dual) const
        {
            try
            {
                Lattice<RealTypeContext, IntTypeContext> lattice(d_gs.get(), d_rc, d_ic, d_stats, begin, end, true);
                Workspace<RealTypeContext, IntTypeContext, Enumerator<RealTypeContext, IntTypeContext>, EmptyCallback<RealTypeContext, IntTypeContext> >
                    workspace(d_verbose, EmptyCallback<RealTypeContext, IntTypeContext>(), lattice.range().dimension(), d_max_cores);
                d_gs->adjustAlpha(1);
                typedef typename Enumerator<RealTypeContext, IntTypeContext>::PreprocessorStackT::Entry EntryT;
                EntryT entry;
                entry.d_method = EntryT::RM_None;
                entry.d_enumalg = d_svp;
                workspace.enumerator().getPreprocessorStack().begin_add(entry);
                prepareEnumerator(workspace.enumerator());
                workspace.enumerator().getPreprocessorStack().end_add();
                workspace.enumerator().getPreprocessorStack().finalize_adding();
                workspace.enumerator().getPreprocessorStack().begin_preprocess();
                bool result = isSVP(workspace, lattice, dual);
                workspace.enumerator().getPreprocessorStack().end_preprocess();
                return result;
            }
            catch (std::exception & e)
            {
                handle_exception(&e);
                return false;
            }
            catch (...)
            {
                handle_unknown_exception();
                throw;
            }
        }

        /////////////// WRAPPERS ///////////////

        virtual void sortProjected(unsigned & begin, unsigned & end, Transform & transform)
        {
            sortProjected(begin, end, transform.createTransformObject<IntTypeContext>(d_ic));
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }

        virtual void sizereduction(unsigned & begin, unsigned & end, Transform & transform)
        {
            sizereduction(begin, end, transform.createTransformObject<IntTypeContext>(d_ic));
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }

        virtual void lll(unsigned & begin, unsigned & end, Transform & transform, double alpha, LatticeReduction::LLLMode mode,
                         LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                         LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                         MaxBitsCallbackFunction mbcf, bool anneal, LatticeReduction::AnnealCallbackFunction acf,
                         LatticeReduction::LLL_AnnealFunction af, LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode,
                         LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            lll(begin, end, transform.createTransformObject<IntTypeContext>(d_ic), alpha, mode, cf, cf2, cf_int,
                mcf, mcf2, mbcf, anneal, acf, af, di, di_mode, di_choice, di_bs);
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }

        virtual void bkz(unsigned & begin, unsigned & end, Transform & transform, double alpha, unsigned blocksize, LatticeReduction::BKZMode mode,
                         LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                         LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2, MaxBitsCallbackFunction mbcf,
                         LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2,
                         bool anneal, LatticeReduction::AnnealCallbackFunction acf, LatticeReduction::BKZ_AnnealFunction af,
                         LatticeReduction::DIMethod di, LatticeReduction::DIMode di_mode, LatticeReduction::DIChoice di_choice, unsigned di_bs)
        {
            bkz(begin, end, transform.createTransformObject<IntTypeContext>(d_ic), alpha, blocksize, mode, cf, cf2, cf_int,
                mcf, mcf2, mbcf, ecf, ecf2, anneal, acf, af, di, di_mode, di_choice, di_bs);
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }

        virtual void hkz(unsigned & begin, unsigned & end, Transform & transform, bool dual,
                         LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                         LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                         MaxBitsCallbackFunction mbcf,
                         LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2)
        {
            hkz(begin, end, transform.createTransformObject<IntTypeContext>(d_ic), dual,
                cf, cf2, cf_int, mcf, mcf2, mbcf, ecf, ecf2);
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }

        virtual void svp(unsigned & begin, unsigned & end, Transform & transform, bool make_basis, bool extreme, bool dual,
                         LatticeReduction::CallbackFunction cf, LatticeReduction::CallbackFunction_LI cf2, double cf_int,
                         LatticeReduction::MinCallbackFunction mcf, LatticeReduction::MinCallbackFunction_LI mcf2,
                         MaxBitsCallbackFunction mbcf,
                         LatticeReduction::EnumCallbackFunction ecf, LatticeReduction::EnumCallbackFunction_LI ecf2)
        {
            svp(begin, end, transform.createTransformObject<IntTypeContext>(d_ic), make_basis, extreme, dual,
                cf, cf2, cf_int, mcf, mcf2, mbcf, ecf, ecf2);
            d_intlattice.update_original();
            transform.releaseTransformObject();
        }
    };

    template<class RealTypeContext, class IntTypeContext>
    LRIInterface * CreateLRIInterfaceWithContexts(LatticeReduction::VerboseOutputLevel vol, LatticeReduction::VerboseFunction vf,
                                                  linalg::math_matrix<arithmetic::Integer> & lattice, LatticeReduction::GramSchmidt gs, bool gsr,
                                                  LatticeReduction::SVPMode svp, unsigned max_cores,
                                                  const RealTypeContext & rc, const IntTypeContext & ic)
    {
        return new LRIImplementation<RealTypeContext, IntTypeContext>(vol, vf, lattice, gs, gsr, svp, max_cores, rc, ic);
    }
}

#endif

max_stars_repo_name: KudrinMatvey/myfplll

max_issues_repo_name: KudrinMatvey/myfplll

max_forks_repo_name: KudrinMatvey/myfplll


text:
#ifndef AMO_STDINT_HPP
#define AMO_STDINT_HPP

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif

#ifdef BOOST_HAS_STDINT_H
#include <stdint.h>
#else
#include <amo/config.hpp>
#include <boost/cstdint.hpp>

using boost::int8_t;
using boost::int_least8_t;
using boost::int_fast8_t;
using boost::uint8_t;
using boost::uint_least8_t;
using boost::uint_fast8_t;

using boost::int16_t;
using boost::int_least16_t;
using boost::int_fast16_t;
using boost::uint16_t;
using boost::uint_least16_t;
using boost::uint_fast16_t;

using boost::int32_t;
using boost::int_least32_t;
using boost::int_fast32_t;
using boost::uint32_t;
using boost::uint_least32_t;
using boost::uint_fast32_t;

#ifndef BOOST_NO_INT64_T
using boost::int64_t;
using boost::int_least64_t;
using boost::int_fast64_t;
using boost::uint64_t;
using boost::uint_least64_t;
using boost::uint_fast64_t;
#endif
using boost::intmax_t;
using boost::uintmax_t;

#endif // BOOST_HAS_STDINT_H

typedef unsigned int uint;

//#ifdef _MSC_VER
//typedef __int8  int8;
//typedef __int16 int16;
//typedef __int32 int32;
//typedef __int64 int64;
//
//typedef unsigned __int8  uint8;
//typedef unsigned __int16 uint16;
//typedef unsigned __int32 uint32;
//typedef unsigned __int64 uint64;
//#else
//typedef int8_t  int8;
//typedef int16_t int16;
//typedef int32_t int32;
//typedef int64_t int64;
//
//typedef uint8_t  uint8;
//typedef uint16_t uint16;
//typedef uint32_t uint32;
//typedef uint64_t uint64;
//#endif
#endif // AMO_STDINT_HPP

ext: hpp

max_stars_repo_name: amoylel/NCUI

max_issues_repo_name: amoylel/NCUI

max_forks_repo_name: amoylel/NCUI


text:
#define BOOST_TEST_MODULE wlce-test
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

ext: cpp

max_stars_repo_name: KazuhitoT/wlce

max_issues_repo_name: KazuhitoT/wlce

max_forks_repo_name: KazuhitoT/wlce


text:
/* Copyright (c) 2012 Cheese and Bacon Games, LLC */
/* This file is licensed under the MIT License. */
/* See the file docs/LICENSE.txt for the full license text. */

#include "main.h"
#include "string_stuff.h"
#include "file_io.h"

#include <iostream>
#include <vector>
#include <fstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;

Version::Version(){
    major=-1;
    minor=-1;
    micro=-1;
}

void Version::increment_major(){
    major++;
    minor=0;
    micro=0;
}

void Version::increment_minor(){
    minor++;
    micro=0;
}

void Version::increment_micro(){
    micro++;
}

void print_error(string error_message){
    cout<<"Error: "<<error_message<<"\n";
}

void print_usage(string program_name){
    cout<<program_name<<" - increment a component of a Cheese Engine project's version number\n";
    cout<<"Usage: "<<program_name<<" PROJECT-DIRECTORY VERSION-COMPONENT STATUS\n";
    cout<<"VERSION-COMPONENT must be one of: 'major' 'minor' 'micro'\n";
    cout<<"STATUS is optional and can be any string\n";
}

int main(int argc,char* args[]){
    File_IO file_io;
    String_Stuff string_stuff;

    //Can this even happen?
    if(argc<=0){
        print_error("Did not receive the program name");

        return 1;
    }
    else if(argc<3 || argc>4){
        print_usage(args[0]);

        return 0;
    }

    string project_directory=args[1];

    if(project_directory.length()==0){
        print_error("The PROJECT-DIRECTORY argument has a length of 0");

        return 1;
    }

    if(boost::algorithm::ends_with(project_directory,"/") || boost::algorithm::ends_with(project_directory,"\\")){
        project_directory.erase(project_directory.begin()+project_directory.length()-1);
    }

    if(!boost::filesystem::is_directory(project_directory)){
        print_error("No such directory: "+project_directory);

        return 1;
    }

    string version_component=args[2];

    if(version_component!="major" && version_component!="minor" && version_component!="micro"){
        print_usage(args[0]);

        return 0;
    }

    string status="";

    if(argc==4){
        status=args[3];
    }

    Version version_old=get_version(project_directory);
    Version version_new=version_old;

    if(version_new.major<0 || version_new.minor<0 || version_new.micro<0){
        return 1;
    }

    if(version_component=="major"){
        version_new.increment_major();
    }
    else if(version_component=="minor"){
        version_new.increment_minor();
    }
    else if(version_component=="micro"){
        version_new.increment_micro();
    }

    if(!update_version_file(project_directory,version_new,status)){
        return 1;
    }

    if(!update_info_plist(project_directory,version_old,version_new)){
        return 1;
    }

    if(!update_android_manifest(project_directory,version_old,version_new)){
        return 1;
    }

    return 0;
}

Version get_version(string project_directory){
    Version version;

    if(!boost::filesystem::exists(project_directory+"/version.cpp")){
        print_error("No such file: "+project_directory+"/version.cpp");

        return version;
    }

    cout<<"Reading current version number for the project in "<<project_directory<<"\n";

    String_Stuff string_stuff;

    ifstream file(project_directory+"/version.cpp");

    if(file.is_open()){
        while(!file.eof()){
            string line="";

            getline(file,line);

            boost::algorithm::trim(line);

            if(boost::algorithm::contains(line,"MAJOR")){
                boost::algorithm::erase_first(line,"return");
                boost::algorithm::erase_first(line,";");
                boost::algorithm::erase_first(line,"//MAJOR");
                boost::algorithm::trim(line);

                version.major=string_stuff.string_to_long(line);
            }
            else if(boost::algorithm::contains(line,"MINOR")){
                boost::algorithm::erase_first(line,"return");
                boost::algorithm::erase_first(line,";");
                boost::algorithm::erase_first(line,"//MINOR");
                boost::algorithm::trim(line);

                version.minor=string_stuff.string_to_long(line);
            }
            else if(boost::algorithm::contains(line,"MICRO")){
                boost::algorithm::erase_first(line,"return");
                boost::algorithm::erase_first(line,";");
                boost::algorithm::erase_first(line,"//MICRO");
                boost::algorithm::trim(line);

                version.micro=string_stuff.string_to_long(line);
            }
        }
    }
    else{
        print_error("Failed to open version.cpp for reading version information");
    }

    file.close();
    file.clear();

    return version;
}

bool update_version_file(string project_directory,const Version& version,const string& status){
    if(!boost::filesystem::exists(project_directory+"/version.cpp")){
        print_error("No such file: "+project_directory+"/version.cpp");

        return false;
    }

    cout<<"Incrementing the version.cpp version number for the project in "<<project_directory<<"\n";

    vector<string> file_data;

    String_Stuff string_stuff;

    ifstream file(project_directory+"/version.cpp");

    if(file.is_open()){
        while(!file.eof()){
            string line="";

            getline(file,line);

            file_data.push_back(line);
        }
    }
    else{
        print_error("Failed to open version.cpp for updating (input phase)");

        file.close();
        file.clear();

        return false;
    }

    file.close();
    file.clear();

    for(int i=0;i<file_data.size();i++){
        if(boost::algorithm::contains(file_data[i],"MAJOR") || boost::algorithm::contains(file_data[i],"MINOR") || boost::algorithm::contains(file_data[i],"MICRO") ||
           boost::algorithm::contains(file_data[i],"STATUS")){
            for(int n=0;n<file_data[i].length();n++){
                if(file_data[i][n]=='n'){
                    string component="";
                    string end_string="";
                    bool status_line=false;
                    if(boost::algorithm::contains(file_data[i],"MAJOR")){
                        component=string_stuff.num_to_string(version.major);
                        end_string="//MAJOR";
                    }
                    else if(boost::algorithm::contains(file_data[i],"MINOR")){
                        component=string_stuff.num_to_string(version.minor);
                        end_string="//MINOR";
                    }
                    else if(boost::algorithm::contains(file_data[i],"MICRO")){
                        component=string_stuff.num_to_string(version.micro);
                        end_string="//MICRO";
                    }
                    else{
                        status_line=true;
                        end_string="//STATUS";
                    }

                    file_data[i].erase(file_data[i].begin()+n,file_data[i].end());

                    if(status_line){
                        file_data[i]+="n \""+status+"\"; "+end_string;
                    }
                    else{
                        file_data[i]+="n "+component+"; "+end_string;
                    }

                    break;
                }
            }
        }
    }

    ofstream file_save(project_directory+"/version.cpp");

    if(file_save.is_open()){
        for(int i=0;i<file_data.size();i++){
            file_save<<file_data[i];

            if(i<file_data.size()-1){
                file_save<<"\n";
            }
        }
    }
    else{
        print_error("Failed to open version.cpp for updating (output phase)");

        file_save.close();
        file_save.clear();

        return false;
    }

    file_save.close();
    file_save.clear();

    return true;
}

bool update_info_plist(string project_directory,const Version& version_old,const Version& version_new){
    if(!boost::filesystem::is_directory(project_directory+"/development")){
        print_error("No such directory: "+project_directory+"/development");

        return false;
    }

    cout<<"Incrementing the Info.plist version number for the project in "<<project_directory<<"\n";

    String_Stuff string_stuff;

    string app_directory="";

    for(File_IO_Directory_Iterator it(project_directory+"/development/");it.evaluate();it.iterate()){
        if(it.is_directory()){
            string file_name=it.get_file_name();

            if(boost::algorithm::ends_with(file_name,".app")){
                app_directory=file_name;

                break;
            }
        }
    }

    if(app_directory.length()>0){
        string info_plist=project_directory+"/development/"+app_directory+"/Contents/Info.plist";

        string str_old_version=string_stuff.num_to_string(version_old.major)+"."+string_stuff.num_to_string(version_old.minor)+"."+string_stuff.num_to_string(version_old.micro);
        string str_new_version=string_stuff.num_to_string(version_new.major)+"."+string_stuff.num_to_string(version_new.minor)+"."+string_stuff.num_to_string(version_new.micro);

        if(!replace_in_file(info_plist,str_old_version,str_new_version)){
            return false;
        }
    }
    else{
        print_error("Failed to locate .app directory");

        return false;
    }

    return true;
}

bool update_android_manifest(string project_directory,const Version& version_old,const Version& version_new){
    if(!boost::filesystem::exists(project_directory+"/development/android/AndroidManifest.xml")){
        print_error("No such file: "+project_directory+"/development/android/AndroidManifest.xml");

        return false;
    }

    cout<<"Incrementing the AndroidManifest.xml version number for the project in "<<project_directory<<"\n";

    String_Stuff string_stuff;

    string str_old_version=string_stuff.num_to_string(version_old.major)+"."+string_stuff.num_to_string(version_old.minor)+"."+string_stuff.num_to_string(version_old.micro);
    string str_new_version=string_stuff.num_to_string(version_new.major)+"."+string_stuff.num_to_string(version_new.minor)+"."+string_stuff.num_to_string(version_new.micro);

    if(!replace_in_file(project_directory+"/development/android/AndroidManifest.xml",str_old_version,str_new_version)){
        return false;
    }

    vector<string> file_data;

    ifstream file(project_directory+"/development/android/AndroidManifest.xml");

    if(file.is_open()){
        while(!file.eof()){
            string line="";

            getline(file,line);

            file_data.push_back(line);
        }
    }
    else{
        print_error("Failed to open AndroidManifest.xml for updating (input phase)");

        file.close();
        file.clear();

        return false;
    }

    file.close();
    file.clear();

    for(int i=0;i<file_data.size();i++){
        if(boost::algorithm::contains(file_data[i],"android:versionCode")){
            string get_version_code=file_data[i];

            boost::algorithm::erase_first(get_version_code,"android:versionCode=\"");
            boost::algorithm::erase_first(get_version_code,"\"");
            boost::algorithm::trim(get_version_code);

            uint32_t version_code=string_stuff.string_to_unsigned_long(get_version_code);

            for(int n=0;n<file_data[i].length();n++){
                if(file_data[i][n]=='"'){
                    file_data[i].erase(file_data[i].begin()+n,file_data[i].end());

                    file_data[i]+="\""+string_stuff.num_to_string(++version_code)+"\"";

                    break;
                }
            }
        }
    }

    ofstream file_save(project_directory+"/development/android/AndroidManifest.xml");

    if(file_save.is_open()){
        for(int i=0;i<file_data.size();i++){
            file_save<<file_data[i];

            if(i<file_data.size()-1){
                file_save<<"\n";
            }
        }
    }
    else{
        print_error("Failed to open AndroidManifest.xml for updating (output phase)");

        file_save.close();
        file_save.clear();

        return false;
    }

    file_save.close();
    file_save.clear();

    return true;
}

bool replace_in_file(string filename,string target,string replacement){
    if(!boost::filesystem::exists(filename)){
        print_error("No such file: "+filename);

        return false;
    }

    cout<<"Renaming all occurrences of "<<target<<" to "<<replacement<<" in "<<filename<<"\n";

    vector<string> file_data;

    ifstream file(filename.c_str());

    if(file.is_open()){
        while(!file.eof()){
            string line="";

            getline(file,line);

            file_data.push_back(line);
        }
    }
    else{
        print_error("Failed to open "+filename+" for updating (input phase)");

        file.close();
        file.clear();

        return false;
    }

    file.close();
    file.clear();

    for(int i=0;i<file_data.size();i++){
        boost::algorithm::replace_all(file_data[i],target,replacement);
    }

    ofstream file_save(filename.c_str());

    if(file_save.is_open()){
        for(int i=0;i<file_data.size();i++){
            file_save<<file_data[i];

            if(i<file_data.size()-1){
                file_save<<"\n";
            }
        }
    }
    else{
        print_error("Failed to open "+filename+" for updating (output phase)");

        file_save.close();
        file_save.clear();

        return false;
    }

    file_save.close();
    file_save.clear();

    return true;
}

max_stars_repo_name: darkoppressor/template-version

max_issues_repo_name: darkoppressor/template-version

max_forks_repo_name: darkoppressor/template-version


text:
// Copyright Takatoshi Kondo 2018
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#if !defined(MQTT_VARIANT_HPP)
#define MQTT_VARIANT_HPP

#if defined(MQTT_STD_VARIANT)

#include <variant>

#else  // defined(MQTT_STD_VARIANT)

#include <boost/variant.hpp>
#include <boost/variant/apply_visitor.hpp>

#endif // defined(MQTT_STD_VARIANT)

namespace mqtt {

#if defined(MQTT_STD_VARIANT)

template <typename... Types>
using variant = std::variant<Types...>;

template <typename Visitor, typename... Variants>
constexpr auto visit(Visitor&& vis, Variants&&... vars) {
    return std::visit(std::forward<Visitor>(vis), std::forward<Variants>(vars)...);
}

#else  // defined(MQTT_STD_VARIANT)

template <typename... Types>
using variant = boost::variant<Types...>;

template <typename Visitor, typename... Variants>
constexpr auto visit(Visitor&& vis, Variants&&... vars)
    -> decltype(boost::apply_visitor(std::forward<Visitor>(vis), std::forward<Variants>(vars)...))
{
    return boost::apply_visitor(std::forward<Visitor>(vis), std::forward<Variants>(vars)...);
}

#endif // defined(MQTT_STD_VARIANT)

} // namespace mqtt

#endif // MQTT_VARIANT_HPP

max_stars_repo_name: solosTec/node

max_issues_repo_name: solosTec/node

max_forks_repo_name: solosTec/node


text:
#pragma once

#include "defines.hpp"
#include "chrono.hpp"

#include <assert.h>

#include <utility>
#include <functional>
#include <set>
#include <memory>

#include <boost/optional.hpp>

namespace msrv {

class Timer;
class TimerFactory;
class TimeSource;
class SimpleTimer;
class SimpleTimerQueue;

using TimerPtr = std::unique_ptr<Timer>;
using TimerCallback = std::function<void(Timer*)>;

enum class TimerState
{
    STOPPED,
    WILL_RESTART,
    RUNNING
};

class Timer
{
public:
    Timer() = default;
    virtual ~Timer();

    virtual TimerState state() const = 0;
    virtual DurationMs period() const = 0;

    virtual void setCallback(TimerCallback callback) = 0;
    virtual void runOnce(DurationMs delay = DurationMs::zero()) = 0;
    virtual void runPeriodic(DurationMs period) = 0;
    virtual void stop() = 0;

    bool isActive() const { return state() != TimerState::STOPPED; }
    bool isPeriodic() const { return period() > DurationMs::zero(); }

private:
    MSRV_NO_COPY_AND_ASSIGN(Timer);
};

class TimerFactory
{
public:
    TimerFactory() = default;
    virtual ~TimerFactory();
    virtual TimerPtr createTimer() = 0;

private:
    MSRV_NO_COPY_AND_ASSIGN(TimerFactory);
};

class TimeSource
{
public:
    TimeSource() = default;
    virtual ~TimeSource();
    virtual TimePointMs currentTime() = 0;

private:
    MSRV_NO_COPY_AND_ASSIGN(TimeSource);
};

class SimpleTimer final : public Timer
{
public:
    SimpleTimer(SimpleTimerQueue* queue)
        : queue_(queue), state_(TimerState::STOPPED)
    {
    }

    virtual ~SimpleTimer();

    virtual TimerState state() const override { return state_; }
    virtual DurationMs period() const override { return period_; }

    virtual void setCallback(TimerCallback callback) override { callback_ = std::move(callback); }
    virtual void runOnce(DurationMs delay) override;
    virtual void runPeriodic(DurationMs period) override;
    virtual void stop() override;

    TimePointMs runAt() const { return runAt_; }

private:
    friend class SimpleTimerQueue;

    void run(TimePointMs now);

    SimpleTimerQueue* queue_;
    TimerCallback callback_;
    TimerState state_;
    DurationMs period_;
    TimePointMs runAt_;

    MSRV_NO_COPY_AND_ASSIGN(SimpleTimer);
};

class SimpleTimerQueue final : public TimerFactory
{
public:
    SimpleTimerQueue(TimeSource* source);
    virtual ~SimpleTimerQueue();

    virtual TimerPtr createTimer() override
    {
        return std::make_unique<SimpleTimer>(this);
    }

    boost::optional<TimePointMs> nextTimeout() const
    {
        if (timers_.empty())
            return boost::none;

        return (*timers_.begin())->runAt_;
    }

    void execute()
    {
        bool wantExit = false;
        execute(&wantExit);
    }

    void execute(const bool* wantExit);

private:
    friend class SimpleTimer;

    struct TimerComparer
    {
        bool operator()(SimpleTimer* left, SimpleTimer* right) const noexcept
        {
            if (left->runAt_ < right->runAt_)
                return true;

            if (left->runAt_ == right->runAt_)
                return left < right;

            return false;
        }
    };

    TimeSource* source_;
    std::set<SimpleTimer*, TimerComparer> timers_;

    void add(SimpleTimer* timer)
    {
        timers_.insert(timer);
    }

    void remove(SimpleTimer* timer)
    {
        auto it = timers_.find(timer);
        assert(it != timers_.end());
        timers_.erase(it);
    }

    MSRV_NO_COPY_AND_ASSIGN(SimpleTimerQueue);
};

}

max_stars_repo_name: courtarro/beefweb

max_issues_repo_name: courtarro/beefweb

max_forks_repo_name: courtarro/beefweb


text:
//  (C) Copyright Jeremy Siek 1999-2004.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include <boost/config.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/cstdlib.hpp>  // for exit_success
#include <algorithm>
#include <functional>
#include <iostream>

struct is_positive_number {
  bool operator()(int x) { return 0 < x; }
};

struct is_even_number {
  bool operator()(int x) { return !(x % 2); }
};

struct is_gt_n {
  int n;
  explicit is_gt_n(int n) : n(n) {}
  bool operator()(int x) { return x > n; }
};

int main() {
  int numbers_[] = { 0, -1, 4, -3, 5, 8, -2, 1, 2, 3, 4, 5, 6 };
  const int N = sizeof(numbers_)/sizeof(int);

  typedef int* base_iterator;
  base_iterator numbers(numbers_);

  // Example using make_filter_iterator()
  std::copy(
    boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
    boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
    std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // Example using filter_iterator
  typedef boost::filter_iterator<is_positive_number, base_iterator>
    FilterIter;

  is_positive_number predicate;
  FilterIter filter_iter_first(predicate, numbers, numbers + N);
  FilterIter filter_iter_last(predicate, numbers + N, numbers + N);

  std::copy(
    filter_iter_first,
    filter_iter_last,
    std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

// Example using filter_iterator
  typedef boost::filter_iterator<is_gt_n, base_iterator>
    FilterIter2;

  is_gt_n pred(3);
  FilterIter2 filter_iter_first2(pred, numbers, numbers + N);
  FilterIter2 filter_iter_last2(pred, numbers + N, numbers + N);

  std::copy(
    filter_iter_first2,
    filter_iter_last2,
    std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // Example using make_filter_iterator()
  std::copy(
    boost::make_filter_iterator<is_even_number>(numbers, numbers + N),
    boost::make_filter_iterator<is_even_number>(numbers + N, numbers + N),
    std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // Another example using make_filter_iterator()
  std::copy(
      boost::make_filter_iterator(
          std::bind2nd(std::greater<int>(), -2)
        , numbers, numbers + N)

    , boost::make_filter_iterator(
          std::bind2nd(std::greater<int>(), -2)
        , numbers + N, numbers + N)

    , std::ostream_iterator<int>(std::cout, " "));

  std::cout << std::endl;

  return boost::exit_success;
}

ext: cc

max_stars_repo_name: Zomega/transverse

max_issues_repo_name: Zomega/transverse

max_forks_repo_name: Zomega/transverse


text:
/*
 * libfreelan - A C++ library to establish peer-to-peer virtual private
 * networks.
 * Copyright (C) 2010-2011 Julien KAUFFMANN <julien.kauffmann@freelan.org>
 *
 * This file is part of libfreelan.
 *
 * libfreelan is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * libfreelan is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.
 *
 * If you intend to use libfreelan in a commercial software, please
 * contact me : we may arrange this for a small fee or no fee at all,
 * depending on the nature of your project.
 */

/**
 * \file switch.cpp
 * \author Julien KAUFFMANN <julien.kauffmann@freelan.org>
 * \brief A switch class.
 */

#include "switch.hpp"

#include <cassert>

#include <boost/foreach.hpp>
#include <boost/random/mersenne_twister.hpp>

#include <boost/version.hpp>

#if BOOST_VERSION >= 104700
#include <boost/random/uniform_int_distribution.hpp>
#else
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#endif

#include <boost/thread/mutex.hpp>
#include <boost/make_shared.hpp>

#include <asiotap/osi/ethernet_helper.hpp>

namespace freelan
{
	namespace
	{
		template <typename KeyType, typename ValueType, typename Handler>
		class results_gatherer
		{
			public:

				typedef std::set<KeyType> set_type;
				typedef std::map<KeyType, ValueType> map_type;

				results_gatherer(Handler handler, const set_type& keys) :
					m_handler(handler),
					m_keys(keys)
				{
					if (m_keys.empty())
					{
						m_handler(m_results);
					}
				}

				void gather(const KeyType& key, const ValueType& value)
				{
					boost::mutex::scoped_lock lock(m_mutex);

					const size_t erased_count = m_keys.erase(key);

					// Ensure that gather was called only once for a given key.
					assert(erased_count == 1);

					m_results[key] = value;

					if (m_keys.empty())
					{
						m_handler(m_results);
					}
				}

			private:

				boost::mutex m_mutex;
				Handler m_handler;
				set_type m_keys;
				map_type m_results;
		};
	}

	const unsigned int switch_::MAX_ENTRIES_DEFAULT = 1024;

	void switch_::async_write(port_index_type index, boost::asio::const_buffer data, multi_write_handler_type handler)
	{
		typedef results_gatherer<port_index_type, boost::system::error_code, multi_write_handler_type> results_gatherer_type;

		const auto targets = get_targets_for(index, data);

#if FREELAN_DEBUG
		if (!targets.empty())
		{
			std::cerr << "Switching " << buffer_size(data) << " byte(s) of data from " << index << " to " << targets.size() << " host(s)." << std::endl;
		}
		else
		{
			std::cerr << "Switching " << buffer_size(data) << " byte(s) of data from " << index << ": no targets." << std::endl;
		}
#endif

		boost::shared_ptr<results_gatherer_type> rg = boost::make_shared<results_gatherer_type>(handler, targets);

		for (auto&& target : targets)
		{
#if FREELAN_DEBUG
			std::cerr << index << "-> " << target << std::endl;
#endif

			m_ports[target].async_write(data, boost::bind(&results_gatherer_type::gather, rg, target, _1));
		}
	}

	std::set<port_index_type> switch_::get_targets_for(port_index_type index, boost::asio::const_buffer data)
	{
		const port_list_type::iterator source_port_entry = m_ports.find(index);

		if (source_port_entry != m_ports.end())
		{
			switch (m_configuration.routing_method)
			{
				case switch_configuration::RM_HUB:
				{
					return get_targets_for(source_port_entry);
				}
				case switch_configuration::RM_SWITCH:
				{
					asiotap::osi::const_helper<asiotap::osi::ethernet_frame> ethernet_helper(data);

					const ethernet_address_type target_address = to_ethernet_address(ethernet_helper.target());

					if (is_multicast_address(target_address))
					{
						return get_targets_for(source_port_entry);
					}
					else
					{
						m_ethernet_address_map[to_ethernet_address(ethernet_helper.sender())] = index;

						// We exceeded the maximum count for entries: we delete random entries to fix it.
						while (m_ethernet_address_map.size() > m_max_entries)
						{
							ethernet_address_map_type::iterator entry = m_ethernet_address_map.begin();

#if BOOST_VERSION >= 104700
							boost::random::mt19937 gen;

							std::advance(entry, boost::random::uniform_int_distribution<>(0, static_cast<int>(m_ethernet_address_map.size()) - 1)(gen));
#else
							boost::mt19937 gen;

							boost::variate_generator<boost::mt19937&, boost::uniform_int<> > vgen(gen, boost::uniform_int<>(0, m_ethernet_address_map.size() - 1));
							std::advance(entry, vgen());
#endif

							m_ethernet_address_map.erase(entry);
						}

						// We look in the ethernet address map

						const ethernet_address_map_type::iterator target_entry = m_ethernet_address_map.find(target_address);

						if (target_entry == m_ethernet_address_map.end())
						{
							// No target entry: we send the message to everybody.
							return get_targets_for(source_port_entry);
						}

						const port_index_type target_port_index = target_entry->second;

						if (!is_registered(target_port_index))
						{
							// The port does not exist: we delete the entry and send to everybody.
							m_ethernet_address_map.erase(target_entry);

							return get_targets_for(source_port_entry);
						}

						std::set<port_index_type> targets;

						targets.insert(target_port_index);

						return targets;
					}
				}
			}
		}

		return std::set<port_index_type>();
	}

	std::set<port_index_type> switch_::get_targets_for(port_list_type::const_iterator source_port_entry)
	{
		std::set<port_index_type> targets;

		for (port_list_type::const_iterator port_entry = m_ports.begin(); port_entry != m_ports.end(); ++port_entry)
		{
			if (source_port_entry != port_entry)
			{
				if (m_configuration.relay_mode_enabled || (source_port_entry->second.group() != port_entry->second.group()))
				{
					targets.insert(port_entry->first);
				}
			}
		}

		return targets;
	}

	switch_::ethernet_address_type switch_::to_ethernet_address(boost::asio::const_buffer buf)
	{
		assert(boost::asio::buffer_size(buf) == ethernet_address_type::static_size);

		ethernet_address_type result;

		std::memcpy(result.c_array(), boost::asio::buffer_cast<const ethernet_address_type::value_type*>(buf), result.size());

		return result;
	}

	bool switch_::is_multicast_address(const switch_::ethernet_address_type& address)
	{
		return ((address[0] & 0x01) != 0x00);
	}
}

max_stars_repo_name: krattai/AEBL

max_issues_repo_name: krattai/AEBL

max_forks_repo_name: krattai/AEBL