<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>

#ifdef HAS_GSL
#include "gsl_helper.h"
#endif

template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
{
  /* this test covers the following files:
     EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
  */
  int rows = m.rows();
  int cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType a1 = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
  symmA.template triangularView<StrictlyUpper>().setZero();

  MatrixType b = MatrixType::Random(rows,cols);
  MatrixType b1 = MatrixType::Random(rows,cols);
  MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
  symmB.template triangularView<StrictlyUpper>().setZero();

  SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
  // generalized eigen pb
  GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);

  #ifdef HAS_GSL
  if (ei_is_same_type<RealScalar,double>::ret)
  {
    // restore symmA and symmB.
    symmA = MatrixType(symmA.template selfadjointView<Lower>());
    symmB = MatrixType(symmB.template selfadjointView<Lower>());
    typedef GslTraits<Scalar> Gsl;
    typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
    typename GslTraits<RealScalar>::Vector gEval=0;
    RealVectorType _eval;
    MatrixType _evec;
    convert<MatrixType>(symmA, gSymmA);
    convert<MatrixType>(symmB, gSymmB);
    convert<MatrixType>(symmA, gEvec);
    gEval = GslTraits<RealScalar>::createVector(rows);

    Gsl::eigen_symm(gSymmA, gEval, gEvec);
    convert(gEval, _eval);
    convert(gEvec, _evec);

    // test gsl itself !
    VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));

    // compare with eigen
    VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
    VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymm.eigenvectors().cwiseAbs());

    // generalized pb
    Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
    convert(gEval, _eval);
    convert(gEvec, _evec);
    // test GSL itself:
    VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));

    // compare with eigen
    MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
    VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
    VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());

    Gsl::free(gSymmA);
    Gsl::free(gSymmB);
    GslTraits<RealScalar>::free(gEval);
    Gsl::free(gEvec);
  }
  #endif

  VERIFY_IS_EQUAL(eiSymm.info(), Success);
  VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox(
          eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
  VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());

  SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
  VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
  VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());

  // generalized eigen problem Ax = lBx
  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
  VERIFY((symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox(
          symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));

  MatrixType sqrtSymmA = eiSymm.operatorSqrt();
  VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA);
  VERIFY_IS_APPROX(sqrtSymmA, symmA.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1));

  SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized;
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.info());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());

  eiSymmUninitialized.compute(symmA, false);
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());

  if (rows > 1)
  {
    // Test matrix with NaN
    symmA(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmA);
    VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
  }
}

void test_eigensolver_selfadjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    // very important to test a 3x3 matrix since we provide a special path for it
    CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
    CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
    CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(10,10)) );
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(19,19)) );
    CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(17,17)) );

    // some trivial but implementation-wise tricky cases
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(1,1)) );
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(2,2)) );
    CALL_SUBTEST_6( selfadjointeigensolver(Matrix<double,1,1>()) );
    CALL_SUBTEST_7( selfadjointeigensolver(Matrix<double,2,2>()) );
  }

  // Test problem size constructors
  CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf>(10));
  CALL_SUBTEST_8(Tridiagonalization<MatrixXf>(10));
}

<commit_msg>add unit tests for other generalized variants<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>

#ifdef HAS_GSL
#include "gsl_helper.h"
#endif

template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
{
  /* this test covers the following files:
     EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
  */
  int rows = m.rows();
  int cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  MatrixType a = MatrixType::Random(rows,cols);
  MatrixType a1 = MatrixType::Random(rows,cols);
  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
  symmA.template triangularView<StrictlyUpper>().setZero();

  MatrixType b = MatrixType::Random(rows,cols);
  MatrixType b1 = MatrixType::Random(rows,cols);
  MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
  symmB.template triangularView<StrictlyUpper>().setZero();

  SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
  // generalized eigen pb
  GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);

  #ifdef HAS_GSL
  if (ei_is_same_type<RealScalar,double>::ret)
  {
    // restore symmA and symmB.
    symmA = MatrixType(symmA.template selfadjointView<Lower>());
    symmB = MatrixType(symmB.template selfadjointView<Lower>());
    typedef GslTraits<Scalar> Gsl;
    typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
    typename GslTraits<RealScalar>::Vector gEval=0;
    RealVectorType _eval;
    MatrixType _evec;
    convert<MatrixType>(symmA, gSymmA);
    convert<MatrixType>(symmB, gSymmB);
    convert<MatrixType>(symmA, gEvec);
    gEval = GslTraits<RealScalar>::createVector(rows);

    Gsl::eigen_symm(gSymmA, gEval, gEvec);
    convert(gEval, _eval);
    convert(gEvec, _evec);

    // test gsl itself !
    VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));

    // compare with eigen
    VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
    VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymm.eigenvectors().cwiseAbs());

    // generalized pb
    Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
    convert(gEval, _eval);
    convert(gEvec, _evec);
    // test GSL itself:
    VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));

    // compare with eigen
    MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
    VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
    VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());

    Gsl::free(gSymmA);
    Gsl::free(gSymmB);
    GslTraits<RealScalar>::free(gEval);
    Gsl::free(gEvec);
  }
  #endif

  VERIFY_IS_EQUAL(eiSymm.info(), Success);
  VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox(
          eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
  VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());

  SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
  VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
  VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());

  // generalized eigen problem Ax = lBx
  eiSymmGen.compute(symmA, symmB,Ax_lBx);
  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
  VERIFY((symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox(
          symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));

  // generalized eigen problem BAx = lx
  eiSymmGen.compute(symmA, symmB,BAx_lx);
  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
  VERIFY((symmB.template selfadjointView<Lower>() * (symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
         (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));

  // generalized eigen problem ABx = lx
  eiSymmGen.compute(symmA, symmB,ABx_lx);
  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
  VERIFY((symmA.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
         (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));

  MatrixType sqrtSymmA = eiSymm.operatorSqrt();
  VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA);
  VERIFY_IS_APPROX(sqrtSymmA, symmA.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt());

  MatrixType id = MatrixType::Identity(rows, cols);
  VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1));

  SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized;
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.info());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());

  eiSymmUninitialized.compute(symmA, false);
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());

  if (rows > 1)
  {
    // Test matrix with NaN
    symmA(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
    SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmA);
    VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
  }
}

void test_eigensolver_selfadjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    // very important to test a 3x3 matrix since we provide a special path for it
    CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
    CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
    CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(10,10)) );
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(19,19)) );
    CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(17,17)) );

    // some trivial but implementation-wise tricky cases
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(1,1)) );
    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(2,2)) );
    CALL_SUBTEST_6( selfadjointeigensolver(Matrix<double,1,1>()) );
    CALL_SUBTEST_7( selfadjointeigensolver(Matrix<double,2,2>()) );
  }

  // Test problem size constructors
  CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf>(10));
  CALL_SUBTEST_8(Tridiagonalization<MatrixXf>(10));
}

<|endoftext|>


<commit_before>// @(#)root/thread:$Id$
// Author: Xavier Valls March 2016

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TThreadExecutor
#define ROOT_TThreadExecutor

#include "RConfigure.h"

// exclude in case ROOT does not have IMT support
#ifndef R__USE_IMT
// No need to error out for dictionaries.
# if !defined(__ROOTCLING__) && !defined(G__DICTIONARY)
#  error "Cannot use ROOT::TThreadExecutor without defining R__USE_IMT."
# endif
#else

#include "ROOT/TExecutor.hxx"
#include <functional>
#include <memory>
#include <numeric>

namespace tbb { class task_scheduler_init;}

namespace ROOT {

class TThreadExecutor: public TExecutor<TThreadExecutor> {
template<class T>
friend class ParallelReductionResolver;

public:
   explicit TThreadExecutor();

   explicit TThreadExecutor(size_t nThreads);

   TThreadExecutor(TThreadExecutor &) = delete;
   TThreadExecutor & operator=(TThreadExecutor &) = delete;

   ~TThreadExecutor();

   template<class F, class Cond = noReferenceCond<F>>
   auto Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
   /// \cond
   template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
   auto Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
   template<class F, class T, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
   // / \endcond
   using TExecutor<TThreadExecutor>::Map;

   // // MapReduce
   // // the late return types also check at compile-time whether redfunc is compatible with func,
   // // other than checking that func is compatible with the type of arguments.
   // // a static_assert check in TThreadExecutor::Reduce is used to check that redfunc is compatible with the type returned by func
   template<class F, class R, class Cond = noReferenceCond<F>>
   auto MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type;
   template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
   auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type;
   // /// \cond doxygen should ignore these methods
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
   // /// \endcond
   using TExecutor<TThreadExecutor>::MapReduce;

  template<class T, class BINARYOP> auto Reduce(const std::vector<T> &objs, BINARYOP redfunc) -> decltype(redfunc(objs.front(), objs.front()));
  template<class T, class R> auto Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));
  using TExecutor<TThreadExecutor>::Reduce;

protected:

   template<class F, class R, class Cond = noReferenceCond<F>>
   auto Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F()>::type>;
   template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
   auto Map(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>;

private:
    void   ParallelFor(unsigned start, unsigned end, unsigned step, const std::function<void(unsigned int i)> &f);
    double ParallelReduce(const std::vector<double> &objs, const std::function<double(double a, double b)> &redfunc);
    float  ParallelReduce(const std::vector<float> &objs, const std::function<float(float a, float b)> &redfunc);
    template<class T, class R>
    auto SeqReduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));

    std::unique_ptr<tbb::task_scheduler_init> fInitTBB;
    static unsigned fgPoolSize;
};

/************ TEMPLATE METHODS IMPLEMENTATION ******************/

//////////////////////////////////////////////////////////////////////////
/// Execute func (with no arguments) nTimes in parallel.
/// A vector containg executions' results is returned.
/// Functions that take more than zero arguments can be executed (with
/// fixed arguments) by wrapping them in a lambda or with std::bind.
template<class F, class Cond>
auto TThreadExecutor::Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>
{
   using retType = decltype(func());
   std::vector<retType> reslist(nTimes);
   auto lambda = [&](unsigned int i){
                     reslist[i] = func();
                 };
   ParallelFor(0U, nTimes, 1, lambda);

   return reslist;
}

template<class F, class R, class Cond>
auto TThreadExecutor::Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F()>::type>
{
     if(nChunks == 0){
     return Map(func, nTimes);
   }

   using retType = decltype(func());
   std::vector<retType> reslist(nChunks);
   unsigned step = nChunks==0? 1 : (nTimes+nChunks-1)/nChunks;
   auto lambda = [&](unsigned int i){
                   std::vector<retType> partialResults(step);
                   for(unsigned j=0; j<step && (i+j)<nTimes; j++){
                     partialResults[j] = func();
                   }
                   reslist[i/step]=redfunc(partialResults);
                 };
   ParallelFor(0U, nTimes, step, lambda);

   return reslist;
}

template<class F, class INTEGER, class Cond>
auto TThreadExecutor::Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>
{
   unsigned start = *args.begin();
   unsigned end = *args.end();

   using retType = decltype(func(start));
   std::vector<retType> reslist(end-start);
   auto lambda = [&](unsigned int i){
                      reslist[i] = func(i);
                  };
   ParallelFor(start, end, 1, lambda);

   return reslist;
}

template<class F, class INTEGER, class R, class Cond>
auto TThreadExecutor::Map(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(INTEGER)>::type>
{
   if(nChunks == 0){
     return Map(func, args);
   }

   unsigned start = *args.begin();
   unsigned end = *args.end();
   unsigned step = nChunks==0? 1 :(end-start+nChunks-1)/nChunks; //ceiling the division

   using retType = decltype(func(start));
   std::vector<retType> reslist(nChunks);
   auto lambda = [&](unsigned int i){
                    std::vector<retType> partialResults(step);
                    for(unsigned j=0; j<step && (i+j)<end; j++){
                      partialResults[j] = func(i+j);
                    }
                    reslist[i/step]=redfunc(partialResults);
                  };
   ParallelFor(start, end, step, lambda);

   return reslist;
}

// tell doxygen to ignore this (\endcond closes the statement)
/// \cond

// actual implementation of the Map method. all other calls with arguments eventually
// call this one
template<class F, class T, class Cond>
auto TThreadExecutor::Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>
{
   // //check whether func is callable
   using retType = decltype(func(args.front()));

   unsigned int fNToProcess = args.size();
   std::vector<retType> reslist(fNToProcess);

   auto lambda = [&](unsigned int i){
                     reslist[i] = func(args[i]);
                 };

   ParallelFor(0U, fNToProcess, 1, lambda);

   return reslist;
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::Map(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>
{
   if(nChunks == 0){
     return Map(func, args);
   }
   // //check whether func is callable
   using retType = decltype(func(args.front()));

   unsigned int fNToProcess = args.size();
   std::vector<retType> reslist(nChunks);
   unsigned step = (fNToProcess+nChunks-1)/nChunks; //ceiling the division

   auto lambda = [&](unsigned int i){
                   std::vector<T> partialResults(step);
                   for(unsigned j=0; j<step && (i+j)<fNToProcess; j++){
                     partialResults[j] = func(args[i+j]);
                   }
                   reslist[i/step]=redfunc(partialResults);
                 };

   ParallelFor(0U, fNToProcess, step, lambda);

   return reslist;
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::Map(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>
{
   std::vector<T> vargs(std::move(args));
   const auto &reslist = Map(func, vargs, redfunc, nChunks);
   return reslist;
}

// // tell doxygen to stop ignoring code
// /// \endcond

// //////////////////////////////////////////////////////////////////////////
// /// This method behaves just like Map, but an additional redfunc function
// /// must be provided. redfunc is applied to the vector Map would return and
// /// must return the same type as func. In practice, redfunc can be used to
// /// "squash" the vector returned by Map into a single object by merging,
// /// adding, mixing the elements of the vector.
template<class F, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type
{
   return Reduce(Map(func, nTimes, redfunc, nChunks), redfunc);
}

/// \cond doxygen should ignore these methods
template<class F, class INTEGER, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type
{
  return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type
{
   return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type
{
   return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

/// Check that redfunc has the right signature and call it on objs
template<class T, class BINARYOP>
auto TThreadExecutor::Reduce(const std::vector<T> &objs, BINARYOP redfunc) -> decltype(redfunc(objs.front(), objs.front()))
{
   // check we can apply reduce to objs
   static_assert(std::is_same<decltype(redfunc(objs.front(), objs.front())), T>::value, "redfunc does not have the correct signature");
   return ParallelReduce(objs, redfunc);
}

template<class T, class R>
auto TThreadExecutor::Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs))
{
   // check we can apply reduce to objs
   static_assert(std::is_same<decltype(redfunc(objs)), T>::value, "redfunc does not have the correct signature");
   return SeqReduce(objs, redfunc);
}

template<class T, class R>
auto TThreadExecutor::SeqReduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs))
{
   return redfunc(objs);
}

} // namespace ROOT

#endif   // R__USE_IMT
#endif
<commit_msg>Add a getter for TThreadExecutor's pool size<commit_after>// @(#)root/thread:$Id$
// Author: Xavier Valls March 2016

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TThreadExecutor
#define ROOT_TThreadExecutor

#include "RConfigure.h"

// exclude in case ROOT does not have IMT support
#ifndef R__USE_IMT
// No need to error out for dictionaries.
# if !defined(__ROOTCLING__) && !defined(G__DICTIONARY)
#  error "Cannot use ROOT::TThreadExecutor without defining R__USE_IMT."
# endif
#else

#include "ROOT/TExecutor.hxx"
#include <functional>
#include <memory>
#include <numeric>

namespace tbb { class task_scheduler_init;}

namespace ROOT {

class TThreadExecutor: public TExecutor<TThreadExecutor> {
template<class T>
friend class ParallelReductionResolver;

public:
   explicit TThreadExecutor();

   explicit TThreadExecutor(size_t nThreads);

   TThreadExecutor(TThreadExecutor &) = delete;
   TThreadExecutor & operator=(TThreadExecutor &) = delete;

   ~TThreadExecutor();

   template<class F, class Cond = noReferenceCond<F>>
   auto Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
   /// \cond
   template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
   auto Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
   template<class F, class T, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
   // / \endcond
   using TExecutor<TThreadExecutor>::Map;

   // // MapReduce
   // // the late return types also check at compile-time whether redfunc is compatible with func,
   // // other than checking that func is compatible with the type of arguments.
   // // a static_assert check in TThreadExecutor::Reduce is used to check that redfunc is compatible with the type returned by func
   template<class F, class R, class Cond = noReferenceCond<F>>
   auto MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type;
   template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
   auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type;
   // /// \cond doxygen should ignore these methods
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
   // /// \endcond
   using TExecutor<TThreadExecutor>::MapReduce;

  template<class T, class BINARYOP> auto Reduce(const std::vector<T> &objs, BINARYOP redfunc) -> decltype(redfunc(objs.front(), objs.front()));
  template<class T, class R> auto Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));
  using TExecutor<TThreadExecutor>::Reduce;

  //Returns the number of threads set in the scheduler at call time.
  static int GetPoolSize(){return fgPoolSize;}

protected:

   template<class F, class R, class Cond = noReferenceCond<F>>
   auto Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F()>::type>;
   template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
   auto Map(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>;
   template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
   auto Map(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>;

private:
    void   ParallelFor(unsigned start, unsigned end, unsigned step, const std::function<void(unsigned int i)> &f);
    double ParallelReduce(const std::vector<double> &objs, const std::function<double(double a, double b)> &redfunc);
    float  ParallelReduce(const std::vector<float> &objs, const std::function<float(float a, float b)> &redfunc);
    template<class T, class R>
    auto SeqReduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));

    std::unique_ptr<tbb::task_scheduler_init> fInitTBB;
    static unsigned fgPoolSize;
};

/************ TEMPLATE METHODS IMPLEMENTATION ******************/

//////////////////////////////////////////////////////////////////////////
/// Execute func (with no arguments) nTimes in parallel.
/// A vector containg executions' results is returned.
/// Functions that take more than zero arguments can be executed (with
/// fixed arguments) by wrapping them in a lambda or with std::bind.
template<class F, class Cond>
auto TThreadExecutor::Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>
{
   using retType = decltype(func());
   std::vector<retType> reslist(nTimes);
   auto lambda = [&](unsigned int i){
                     reslist[i] = func();
                 };
   ParallelFor(0U, nTimes, 1, lambda);

   return reslist;
}

template<class F, class R, class Cond>
auto TThreadExecutor::Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F()>::type>
{
     if(nChunks == 0){
     return Map(func, nTimes);
   }

   using retType = decltype(func());
   std::vector<retType> reslist(nChunks);
   unsigned step = nChunks==0? 1 : (nTimes+nChunks-1)/nChunks;
   auto lambda = [&](unsigned int i){
                   std::vector<retType> partialResults(step);
                   for(unsigned j=0; j<step && (i+j)<nTimes; j++){
                     partialResults[j] = func();
                   }
                   reslist[i/step]=redfunc(partialResults);
                 };
   ParallelFor(0U, nTimes, step, lambda);

   return reslist;
}

template<class F, class INTEGER, class Cond>
auto TThreadExecutor::Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>
{
   unsigned start = *args.begin();
   unsigned end = *args.end();

   using retType = decltype(func(start));
   std::vector<retType> reslist(end-start);
   auto lambda = [&](unsigned int i){
                      reslist[i] = func(i);
                  };
   ParallelFor(start, end, 1, lambda);

   return reslist;
}

template<class F, class INTEGER, class R, class Cond>
auto TThreadExecutor::Map(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(INTEGER)>::type>
{
   if(nChunks == 0){
     return Map(func, args);
   }

   unsigned start = *args.begin();
   unsigned end = *args.end();
   unsigned step = nChunks==0? 1 :(end-start+nChunks-1)/nChunks; //ceiling the division

   using retType = decltype(func(start));
   std::vector<retType> reslist(nChunks);
   auto lambda = [&](unsigned int i){
                    std::vector<retType> partialResults(step);
                    for(unsigned j=0; j<step && (i+j)<end; j++){
                      partialResults[j] = func(i+j);
                    }
                    reslist[i/step]=redfunc(partialResults);
                  };
   ParallelFor(start, end, step, lambda);

   return reslist;
}

// tell doxygen to ignore this (\endcond closes the statement)
/// \cond

// actual implementation of the Map method. all other calls with arguments eventually
// call this one
template<class F, class T, class Cond>
auto TThreadExecutor::Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>
{
   // //check whether func is callable
   using retType = decltype(func(args.front()));

   unsigned int fNToProcess = args.size();
   std::vector<retType> reslist(fNToProcess);

   auto lambda = [&](unsigned int i){
                     reslist[i] = func(args[i]);
                 };

   ParallelFor(0U, fNToProcess, 1, lambda);

   return reslist;
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::Map(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>
{
   if(nChunks == 0){
     return Map(func, args);
   }
   // //check whether func is callable
   using retType = decltype(func(args.front()));

   unsigned int fNToProcess = args.size();
   std::vector<retType> reslist(nChunks);
   unsigned step = (fNToProcess+nChunks-1)/nChunks; //ceiling the division

   auto lambda = [&](unsigned int i){
                   std::vector<T> partialResults(step);
                   for(unsigned j=0; j<step && (i+j)<fNToProcess; j++){
                     partialResults[j] = func(args[i+j]);
                   }
                   reslist[i/step]=redfunc(partialResults);
                 };

   ParallelFor(0U, fNToProcess, step, lambda);

   return reslist;
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::Map(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> std::vector<typename std::result_of<F(T)>::type>
{
   std::vector<T> vargs(std::move(args));
   const auto &reslist = Map(func, vargs, redfunc, nChunks);
   return reslist;
}

// // tell doxygen to stop ignoring code
// /// \endcond

// //////////////////////////////////////////////////////////////////////////
// /// This method behaves just like Map, but an additional redfunc function
// /// must be provided. redfunc is applied to the vector Map would return and
// /// must return the same type as func. In practice, redfunc can be used to
// /// "squash" the vector returned by Map into a single object by merging,
// /// adding, mixing the elements of the vector.
template<class F, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type
{
   return Reduce(Map(func, nTimes, redfunc, nChunks), redfunc);
}

/// \cond doxygen should ignore these methods
template<class F, class INTEGER, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type
{
  return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type
{
   return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

template<class F, class T, class R, class Cond>
auto TThreadExecutor::MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type
{
   return Reduce(Map(func, args, redfunc, nChunks), redfunc);
}

/// Check that redfunc has the right signature and call it on objs
template<class T, class BINARYOP>
auto TThreadExecutor::Reduce(const std::vector<T> &objs, BINARYOP redfunc) -> decltype(redfunc(objs.front(), objs.front()))
{
   // check we can apply reduce to objs
   static_assert(std::is_same<decltype(redfunc(objs.front(), objs.front())), T>::value, "redfunc does not have the correct signature");
   return ParallelReduce(objs, redfunc);
}

template<class T, class R>
auto TThreadExecutor::Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs))
{
   // check we can apply reduce to objs
   static_assert(std::is_same<decltype(redfunc(objs)), T>::value, "redfunc does not have the correct signature");
   return SeqReduce(objs, redfunc);
}

template<class T, class R>
auto TThreadExecutor::SeqReduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs))
{
   return redfunc(objs);
}

} // namespace ROOT

#endif   // R__USE_IMT
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>

#include <Windows.h>
#include <ShlObj.h>

#include <conio.h> // _getch()

#include "Osiris.hpp"

#include "Modules/OsirisModules.hpp"

#include <Utils/Utils.hpp>

#include <Ausar\Ausar.hpp>

Osiris::Osiris()
{
    wchar_t Buffer[MAX_PATH] = { 0 };
    SHGetSpecialFolderPathW(nullptr, Buffer, CSIDL_PROFILE, false);

    std::wstring UserFolder(Buffer);
    UserFolder += L"\\AppData\\Local\\Packages\\Microsoft.Halo5Forge_8wekyb3d8bbwe\\LocalState\\Log.txt";

    Util::Log::Instance()->SetFile(UserFolder);

    LOG << "Osiris" << "---- ";
    LOG << '[' << __DATE__ << " : " << __TIME__ << ']' << std::endl;
    LOG << "\t-Wunkolo (Wunkolo@gmail.com)\n";
    LOG << std::wstring(80, '-') << std::endl;

    LOG << std::hex << std::uppercase << std::setfill(L'0');
    LOG << "Process Base: 0x" << Util::Process::Base() << std::endl;
    LOG << "Osiris Thread ID: 0x" << Util::Thread::GetCurrentThreadId() << std::endl;
    LOG << "Osiris Base: 0x" << Util::Process::GetModuleBase("Osiris.dll") << std::endl;

    const Ausar::ThreadTable *Table;

    Table = Util::Process::GetModuleBase()(0x58CA4B0).Point<Ausar::ThreadTable>();

    //for( size_t i = 0; i < 64; i++ )
    //{
    //    if( Table->Entries[i].Active == 0 )
    //    {
    //        continue;
    //    }
    //    LOG << "Thread Name: " << reinterpret_cast<const char*>(Table->Entries[i].ThreadName) << std::endl;
    //    LOG << "Thread ID: " << Table->Entries[i].ThreadID << std::endl;
    //}

    LOG << "Main Thread ID: " << Table->GetThreadIDByName("MAIN") << std::endl;

    // Push Commands
    //PushModule<Research>("research");
    //PushModule<Player>("player");
}

Osiris::~Osiris()
{
}

void Osiris::Tick(const std::chrono::high_resolution_clock::duration &DeltaTime)
{
    for( std::pair<std::string, std::shared_ptr<OsirisModule>> Command : Commands )
    {
        if( Command.second )
        {
            Command.second->Tick(DeltaTime);
        }
    }
}<commit_msg>Tls globals access draft<commit_after>#include <iostream>
#include <iomanip>

#include <Windows.h>
#include <ShlObj.h>

#include <conio.h> // _getch()

#include "Osiris.hpp"

#include "Modules/OsirisModules.hpp"

#include <Utils/Utils.hpp>

#include <Ausar\Ausar.hpp>

#include <winnt.h>
#include <winternl.h>

#include <vector>
#include <iterator>

Osiris::Osiris()
{
    wchar_t Buffer[MAX_PATH] = { 0 };
    SHGetSpecialFolderPathW(nullptr, Buffer, CSIDL_PROFILE, false);

    std::wstring UserFolder(Buffer);
    UserFolder += L"\\AppData\\Local\\Packages\\Microsoft.Halo5Forge_8wekyb3d8bbwe\\LocalState\\Log.txt";

    Util::Log::Instance()->SetFile(UserFolder);

    LOG << "Osiris" << "---- ";
    LOG << '[' << __DATE__ << " : " << __TIME__ << ']' << std::endl;
    LOG << "\t-Wunkolo (Wunkolo@gmail.com)\n";
    LOG << std::wstring(80, '-') << std::endl;

    LOG << std::hex << std::uppercase << std::setfill(L'0')
        << "Process Base: 0x" << Util::Process::Base() << std::endl;
    LOG << "Osiris Thread ID: 0x" << Util::Thread::GetCurrentThreadId() << std::endl;
    LOG << "Osiris Base: 0x" << Util::Process::GetModuleBase("Osiris.dll") << std::endl;

    const Ausar::ThreadTable *Table;

    Table = Util::Process::GetModuleBase()(0x58CA4B0).Point<Ausar::ThreadTable>();

    //for( size_t i = 0; i < 64; i++ )
    //{
    //    if( Table->Entries[i].Active == 0 )
    //    {
    //        continue;
    //    }
    //    LOG << "Thread Name: " << reinterpret_cast<const char*>(Table->Entries[i].ThreadName) << std::endl;
    //    LOG << "Thread ID: " << Table->Entries[i].ThreadID << std::endl;
    //}

    uint64_t ThreadID = Table->GetThreadIDByName("MAIN");

    LOG << "Main Thread ID: " << ThreadID << std::endl;

    typedef enum _THREADINFOCLASS {
        ThreadBasicInformation = 0,
    } THREADINFOCLASS;

    typedef LONG KPRIORITY;

    typedef struct _CLIENT_ID {
        HANDLE UniqueProcess;
        HANDLE UniqueThread;
    } CLIENT_ID;
    typedef CLIENT_ID *PCLIENT_ID;

    typedef struct _THREAD_BASIC_INFORMATION
    {
        NTSTATUS                ExitStatus;
        PVOID                   TebBaseAddress;
        CLIENT_ID               ClientId;
        KAFFINITY               AffinityMask;
        KPRIORITY               Priority;
        KPRIORITY               BasePriority;
    } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

    typedef NTSTATUS(WINAPI *InfoThreadProc)(HANDLE, LONG, PVOID, ULONG, PULONG);

    HANDLE ThreadHandle = OpenThread(
        THREAD_ALL_ACCESS,
        false,
        static_cast<DWORD>(ThreadID)
    );

    Util::Pointer TEB(nullptr);

    InfoThreadProc NtQueryInformationThread = (InfoThreadProc)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationThread");

    THREAD_BASIC_INFORMATION ThreadInfo = { 0 };

    NTSTATUS ntStatus = NtQueryInformationThread(
        ThreadHandle,
        ThreadBasicInformation,
        &ThreadInfo,
        sizeof(THREAD_BASIC_INFORMATION),
        nullptr
    );

    LOG << ResumeThread(ThreadHandle) << std::endl;

    CloseHandle(ThreadHandle);

    TEB = Util::Pointer(ThreadInfo.TebBaseAddress)[0x58][0];

    LOG << "Physics Constants: " << TEB[0x2D30] << std::endl;
    LOG << "DOF Globals: " << TEB[0x49B0] << std::endl;
    LOG << "DOF Data: " << TEB[0x1310] << std::endl;
    LOG << "Director globals: " << TEB[0x198] << std::endl;
    LOG << "Hue saturation control: " << TEB[0x2FF8] << std::endl;
    LOG << "Game engine globals: " << TEB[0x13A8] << std::endl;
    LOG << "Local Game engine globals: " << TEB[0x13B0] << std::endl;
    LOG << "Game engine render globals: " << TEB[0x13B8] << std::endl;
    LOG << "Game time globals: " << TEB[0x12A8] << std::endl;
    LOG << "Composer globals: " << TEB[0x1C8] << std::endl;
    LOG << "Fp weapons: " << TEB[0x1260] << std::endl;
    LOG << "Player Focus: " << TEB[0x1320] << std::endl;
    LOG << "Player Control Globals: " << TEB[0x1340] << std::endl;
    LOG << "Player Control Globals Deter.: " << TEB[0x1348] << std::endl;
    LOG << "Player Globals: " << TEB[0x1370] << std::endl;

    LOG << "AI Globals: " << TEB[0x2E40] << std::endl;
    LOG << "AI Player state Globals: " << TEB[0x2E18] << std::endl;

    LOG << "Interaction ripples: " << TEB[0x4960] << std::endl;

    LOG << "Rasterizer: " << TEB[0x49A0] << std::endl;
    LOG << "Render game globals: " << TEB[0x49A8] << std::endl;
    LOG << "fp orientations: " << TEB[0x4A10] << std::endl;

    LOG << "Objects: " << TEB[0x4B18] << std::endl;
    LOG << "Object name list: " << TEB[0x4B20] << std::endl;
    LOG << "Object placement globals: " << TEB[0x4B58] << std::endl;
    LOG << "Object globals: " << TEB[0x4C08] << std::endl;
    LOG << "orientations: " << TEB[0x110] << std::endl;

    // Push Commands
    //PushModule<Research>("research");
    //PushModule<Player>("player");
}

Osiris::~Osiris()
{
}

void Osiris::Tick(const std::chrono::high_resolution_clock::duration &DeltaTime)
{
    for( std::pair<std::string, std::shared_ptr<OsirisModule>> Command : Commands )
    {
        if( Command.second )
        {
            Command.second->Tick(DeltaTime);
        }
    }
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: customshapeproperties.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2008-01-17 08:05:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX
#define OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX

#include "oox/helper/propertymap.hxx"
#include "oox/drawingml/color.hxx"
#include <com/sun/star/graphic/XGraphic.hpp>
#include <boost/shared_ptr.hpp>
#include "tokens.hxx"
#include <vector>
#include <map>

#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEPARAMETERPAIR_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEPARAMETERTYPE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENT_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEGLUEPOINTTYPE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENTCOMMAND_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPETEXTFRAME_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEADJUSTMENTVALUE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPETEXTPATHMODE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
#endif
#ifndef __com_sun_star_beans_PropertyValues_hpp__
#include <com/sun/star/beans/PropertyValues.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_PROJECTIONMODE_HPP_
#include <com/sun/star/drawing/ProjectionMode.hpp>
#endif

namespace oox { namespace drawingml {

class CustomShapeProperties;

typedef boost::shared_ptr< CustomShapeProperties > CustomShapePropertiesPtr;

struct CustomShapeGuide
{
    rtl::OUString   maName;
    rtl::OUString   maFormula;
};

class CustomShapeProperties
{
public:

    CustomShapeProperties();
    virtual ~CustomShapeProperties();

    void apply( const CustomShapePropertiesPtr& );
    void pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase,
            const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > & xPropSet ) const;

    void setShapePresetType( const rtl::OUString& rShapePresetType ){ maShapePresetType = rShapePresetType; };
    std::vector< CustomShapeGuide >& getAdjustmentValues(){ return maAdjustmentValues; };

    double getValue( const std::vector< CustomShapeGuide >&, sal_uInt32 nIndex ) const;

private:

    rtl::OUString                   maShapePresetType;
    std::vector< CustomShapeGuide > maAdjustmentValues;
};

} }

#endif  //  OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX
<commit_msg>INTEGRATION: CWS xmlfilter03_DEV300 (1.2.4); FILE MERGED 2008/01/22 16:41:23 hbrinkm 1.2.4.1: pushToPropertySet: new parameter xShape<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: customshapeproperties.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 17:39:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX
#define OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX

#include "oox/helper/propertymap.hxx"
#include "oox/drawingml/color.hxx"
#include <com/sun/star/graphic/XGraphic.hpp>
#include <boost/shared_ptr.hpp>
#include "tokens.hxx"
#include <vector>
#include <map>

#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEPARAMETERPAIR_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEPARAMETERTYPE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENT_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEGLUEPOINTTYPE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENTCOMMAND_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPETEXTFRAME_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPEADJUSTMENTVALUE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPETEXTPATHMODE_HPP_
#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
#endif
#ifndef __com_sun_star_beans_PropertyValues_hpp__
#include <com/sun/star/beans/PropertyValues.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_PROJECTIONMODE_HPP_
#include <com/sun/star/drawing/ProjectionMode.hpp>
#endif
#include <com/sun/star/drawing/XShape.hpp>

namespace oox { namespace drawingml {

class CustomShapeProperties;

typedef boost::shared_ptr< CustomShapeProperties > CustomShapePropertiesPtr;

struct CustomShapeGuide
{
    rtl::OUString   maName;
    rtl::OUString   maFormula;
};

class CustomShapeProperties
{
public:

    CustomShapeProperties();
    virtual ~CustomShapeProperties();

    void apply( const CustomShapePropertiesPtr& );
    void pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase,
            const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > & xPropSet,
                        const ::com::sun::star::uno::Reference < ::com::sun::star::drawing::XShape > & xShape) const;

    void setShapePresetType( const rtl::OUString& rShapePresetType ){ maShapePresetType = rShapePresetType; };
    std::vector< CustomShapeGuide >& getAdjustmentValues(){ return maAdjustmentValues; };

    double getValue( const std::vector< CustomShapeGuide >&, sal_uInt32 nIndex ) const;

private:

    rtl::OUString                   maShapePresetType;
    std::vector< CustomShapeGuide > maAdjustmentValues;
};

} }

#endif  //  OOX_DRAWINGML_CUSTOMSHAPEPROPERTIES_HXX
<|endoftext|>


<commit_before>#include "ParticleModel.h"

ParticleModel::ParticleModel(Transform * transform) : _transform(transform)
{
	_transform = transform;

	gravity = -9.81f;
	_mass = 1.0f;

	_velocity = XMFLOAT3(0.0f, 0.0f, 0.0f);
	_acceleration = XMFLOAT3(0.0f, 0.0f, 0.0f);

	// Swap between velocity
	_useConstAcc = true;
	laminar = true;
	slideOn = false;

	force = XMFLOAT3(0.0f, 0.0f, 0.0f);
	netForce = XMFLOAT3(0.0f, 0.0f, 0.0f);

	forceMag = 0.0f;
	dragFactor = 1.0f;

	_radius = 0.5f;
}

ParticleModel::~ParticleModel()
{
}

void ParticleModel::Move(float xAmount, float yAmount, float zAmount)
{
	XMFLOAT3 position = _transform->GetPosition();

	position.x += xAmount;
	position.y += yAmount;
	position.z += zAmount;

	_transform->SetPosition(position);
}

// AI Move
void ParticleModel::Move(XMFLOAT3 move)
{
	XMFLOAT3 position = _transform->GetPosition();
	position.x += move.x;
	position.y += move.y;
	position.z += move.z;
	_transform->SetPosition(position);
}

void ParticleModel::MoveConstantVelocity(float t)
{
	t = t / 1000;

	XMFLOAT3 position = _transform->GetPosition();

	position.x += _velocity.x * t;
	position.y += _velocity.y * t;
	position.z += _velocity.z * t;

	_transform->SetPosition(position);
}

void ParticleModel::MoveConstantAcceleration(float t)
{
	t = t / 1000;

	XMFLOAT3 position = _transform->GetPosition();

	// S = UT + 0.5AT^2
	position.x += _velocity.x * t + 0.5f * _acceleration.x * t * t;
	position.y += _velocity.y * t + 0.5f * _acceleration.y * t * t;
	position.z += _velocity.z * t + 0.5f * _acceleration.z * t * t;

	// V = U + AT
	_velocity.x += _acceleration.x * t;
	_velocity.y += _acceleration.y * t;
	_velocity.z += _acceleration.z * t;

	_transform->SetPosition(position);
}

void ParticleModel::UpdateNetForce()
{
	netForce.x = dragForce.x + slidingForce.x;
	netForce.y = dragForce.y + slidingForce.y;
	netForce.z = dragForce.z + slidingForce.z;
}

void ParticleModel::UpdateAccel()
{
	_acceleration.x = netForce.x / _mass;
	_acceleration.y = netForce.y / _mass;
	_acceleration.z = netForce.z / _mass;
}

void ParticleModel::UpdateState(float t)
{
	UpdateNetForce();

	UpdateAccel();

	MoveConstantAcceleration(t);
}

void ParticleModel::Update(float t)
{
	if (_useConstAcc)
	{
		if (slideOn == true)
		{
			SlidingForce(XMConvertToRadians(90.0f), 10.0f);
		}
		else
		{
			slidingForce.x = 0.0f;
			slidingForce.y = _mass * gravity;
			slidingForce.z = 0.0f;
		}

		DragForce();

		UpdateState(t);
	}
	else
	{
		MoveConstantVelocity(t);
	}
}

void ParticleModel::SlidingForce(float theta, float frCoef)
{
	// Calculate magnitude of force
	forceMag = _mass * gravity * (sin(theta) - frCoef * cos(theta));

	// Calculate x- and y-components of force (NOTE: x-axis assumed positive rightwards and y-axis positive downwards)
	slidingForce.x = forceMag * cos(theta);
	slidingForce.y = forceMag * sin(theta);
	slidingForce.z = forceMag * cos(theta);

	if (slidingForce.y > 0.0f)
	{
		slidingForce.x = 0.0f;
		slidingForce.y = 0.0f;
		//slidingForce.z = 0.0f;
	}

	// TODO: Check to ensure that magnitude is not negative
	//if (forceMag <= 0.0f)
	//	forceMag = -forceMag;
}

void ParticleModel::SetSlidingForce(bool slideBool)
{
	slideOn = slideBool;
}

void ParticleModel::SlidingMotion(float t)
{
	//SlidingForce(XMConvertToRadians(25.0f), 0.2f);

	UpdateState(t);

	MoveConstantAcceleration(t);
}

void ParticleModel::MotionInFluid()
{
	DragForce();

	//UpdateState();
	//
	//Move();
}

void ParticleModel::DragForce()
{
	if (laminar)
		// Calculate drag force for laminar flow
		DragLamFlow();
	else
		// Calculate drag force for turbulent flow
		DragTurbFlow();

}

void ParticleModel::DragLamFlow()
{
	// Calculate of x- and y-components of drag force
	dragForce.x = -dragFactor * _velocity.x;
	dragForce.y = -dragFactor * _velocity.y;
	dragForce.z = -dragFactor * _velocity.z;
}

void ParticleModel::DragTurbFlow()
{
	// Calculate magnitude of velocity
	float velMag;
	velMag = sqrt((_velocity.x * _velocity.x) + (_velocity.y * _velocity.y) + (_velocity.z * _velocity.z));

	// Calculate unit vector/normalised vector of velocity
	XMFLOAT3 unitVel;
	unitVel.x = (_velocity.x / velMag);
	unitVel.y = (_velocity.y / velMag);
	unitVel.z = (_velocity.z / velMag);

	// Calculate magnitude of drag force
	float dragMag;
	dragMag = dragFactor * velMag * velMag;

	// Calculate of x- and y-components of drag force
	dragForce.x = -dragMag * unitVel.x;
	dragForce.y = -dragMag * unitVel.y;
	dragForce.z = -dragMag * unitVel.z;

}

bool ParticleModel::CheckCollision(XMFLOAT3 position2, float radius2)
{
	XMFLOAT3 position = _transform->GetPosition();

	XMFLOAT3 difference;
	difference.x = position.x - position2.x;
	difference.y = position.y - position2.y;
	difference.z = position.z - position2.z;

	float differenceMag = sqrt((difference.x * difference.x) + (difference.y * difference.y) + (difference.z * difference.z));

	float rDistance = _radius + radius2;

	if (differenceMag <= rDistance)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void ParticleModel::CheckFloorCollision(XMFLOAT3 floorPos)
{
	XMFLOAT3 objectPosition = _transform->GetPosition();

	XMFLOAT3 difference;
	difference.y = objectPosition.y - floorPos.y;

	float differenceMag = sqrt(difference.y * difference.y);

	if (differenceMag <= _radius)
	{
		slideOn = true;
		_velocity.y = -_velocity.y;
	}
	else
	{
		slideOn = false;
	}
}

void ParticleModel::ResolveCollision(ParticleModel* particleModel1, ParticleModel* particleModel2)
{
	float rCoef = 0.8f;

	XMFLOAT3 prevPos1 = particleModel1->_transform->GetOldPosition();
	XMFLOAT3 prevPos2 = particleModel2->_transform->GetOldPosition();

	float mass1 = particleModel1->GetMass();
	float mass2 = particleModel2->GetMass();

	XMFLOAT3 initialVelocity1 = particleModel1->GetVelocity();
	XMFLOAT3 initialVelocity2 = particleModel2->GetVelocity();

	particleModel1->_transform->SetPosition(prevPos1);
	particleModel2->_transform->SetPosition(prevPos2);

	XMFLOAT3 velocity1;
	XMFLOAT3 velocity2;

	velocity1.x = (mass1 * initialVelocity1.x) + (mass2 * initialVelocity2.x) + ((mass2 * rCoef) * (initialVelocity2.x - initialVelocity1.x)) / (mass1 + mass2);
	velocity1.y = (mass1 * initialVelocity1.y) + (mass2 * initialVelocity2.y) + ((mass2 * rCoef) * (initialVelocity2.y - initialVelocity1.y)) / (mass1 + mass2);
	velocity1.z = (mass1 * initialVelocity1.z) + (mass2 * initialVelocity2.z) + ((mass2 * rCoef) * (initialVelocity2.z - initialVelocity1.z)) / (mass1 + mass2);

	velocity2.x = (mass1 * initialVelocity1.x) + (mass2 * initialVelocity2.x) + ((mass1 * rCoef) * (initialVelocity1.x - initialVelocity2.x)) / (mass1 + mass2);
	velocity2.y = (mass1 * initialVelocity1.y) + (mass2 * initialVelocity2.y) + ((mass1 * rCoef) * (initialVelocity1.y - initialVelocity2.y)) / (mass1 + mass2);
	velocity2.z = (mass1 * initialVelocity1.z) + (mass2 * initialVelocity2.z) + ((mass1 * rCoef) * (initialVelocity1.z - initialVelocity2.z)) / (mass1 + mass2);

	particleModel1->SetVelocity(velocity1);
	particleModel2->SetVelocity(velocity2);
} <commit_msg>Updated comments<commit_after>#include "ParticleModel.h"

ParticleModel::ParticleModel(Transform * transform) : _transform(transform)
{
	_transform = transform;

	gravity = -9.81f;
	_mass = 1.0f;

	_velocity = XMFLOAT3(0.0f, 0.0f, 0.0f);
	_acceleration = XMFLOAT3(0.0f, 0.0f, 0.0f);

	// Swap between velocity
	_useConstAcc = true;
	laminar = true;
	slideOn = false;

	force = XMFLOAT3(0.0f, 0.0f, 0.0f);
	netForce = XMFLOAT3(0.0f, 0.0f, 0.0f);

	forceMag = 0.0f;
	dragFactor = 1.0f;

	_radius = 0.5f;
}

ParticleModel::~ParticleModel()
{
}

void ParticleModel::Move(float xAmount, float yAmount, float zAmount)
{
	XMFLOAT3 position = _transform->GetPosition();

	position.x += xAmount;
	position.y += yAmount;
	position.z += zAmount;

	_transform->SetPosition(position);
}

// AI Move
void ParticleModel::Move(XMFLOAT3 move)
{
	XMFLOAT3 position = _transform->GetPosition();
	position.x += move.x;
	position.y += move.y;
	position.z += move.z;
	_transform->SetPosition(position);
}

void ParticleModel::MoveConstantVelocity(float t)
{
	t = t / 1000;

	XMFLOAT3 position = _transform->GetPosition();

	position.x += _velocity.x * t;
	position.y += _velocity.y * t;
	position.z += _velocity.z * t;

	_transform->SetPosition(position);
}

void ParticleModel::MoveConstantAcceleration(float t)
{
	t = t / 1000;

	XMFLOAT3 position = _transform->GetPosition();

	// S = UT + 0.5AT^2
	position.x += _velocity.x * t + 0.5f * _acceleration.x * t * t;
	position.y += _velocity.y * t + 0.5f * _acceleration.y * t * t;
	position.z += _velocity.z * t + 0.5f * _acceleration.z * t * t;

	// V = U + AT
	_velocity.x += _acceleration.x * t;
	_velocity.y += _acceleration.y * t;
	_velocity.z += _acceleration.z * t;

	_transform->SetPosition(position);
}

void ParticleModel::UpdateNetForce()
{
	netForce.x = dragForce.x + slidingForce.x;
	netForce.y = dragForce.y + slidingForce.y;
	netForce.z = dragForce.z + slidingForce.z;
}

void ParticleModel::UpdateAccel()
{
	_acceleration.x = netForce.x / _mass;
	_acceleration.y = netForce.y / _mass;
	_acceleration.z = netForce.z / _mass;
}

void ParticleModel::UpdateState(float t)
{
	UpdateNetForce();

	UpdateAccel();

	MoveConstantAcceleration(t);
}

void ParticleModel::Update(float t)
{
	if (_useConstAcc)
	{
		if (slideOn == true)
		{
			SlidingForce(XMConvertToRadians(90.0f), 10.0f);
		}
		else
		{
			slidingForce.x = 0.0f;
			slidingForce.y = _mass * gravity;
			slidingForce.z = 0.0f;
		}

		DragForce();

		UpdateState(t);
	}
	else
	{
		MoveConstantVelocity(t);
	}
}

void ParticleModel::SlidingForce(float theta, float frCoef)
{
	// Calculate magnitude of force
	forceMag = _mass * gravity * (sin(theta) - frCoef * cos(theta));

	// Calculate x- and y-components of force (NOTE: x-axis assumed positive rightwards and y-axis positive downwards)
	slidingForce.x = forceMag * cos(theta);
	slidingForce.y = forceMag * sin(theta);
	slidingForce.z = forceMag * cos(theta);

	if (slidingForce.y > 0.0f)
	{
		slidingForce.x = 0.0f;
		slidingForce.y = 0.0f;
		slidingForce.z = 0.0f;
	}

	// TODO: Check to ensure that magnitude is not negative
	//if (forceMag <= 0.0f)
	//	forceMag = -forceMag;
}

void ParticleModel::SetSlidingForce(bool slideBool)
{
	slideOn = slideBool;
}

void ParticleModel::SlidingMotion(float t)
{
	//SlidingForce(XMConvertToRadians(25.0f), 0.2f);

	UpdateState(t);

	MoveConstantAcceleration(t);
}

void ParticleModel::MotionInFluid()
{
	DragForce();

	//UpdateState();
	//Move();
}

void ParticleModel::DragForce()
{
	if (laminar)
		// Calculate drag force for laminar flow
		DragLamFlow();
	else
		// Calculate drag force for turbulent flow
		DragTurbFlow();

}

void ParticleModel::DragLamFlow()
{
	// Calculate of x- and y-components of drag force
	dragForce.x = -dragFactor * _velocity.x;
	dragForce.y = -dragFactor * _velocity.y;
	dragForce.z = -dragFactor * _velocity.z;
}

void ParticleModel::DragTurbFlow()
{
	// Calculate magnitude of velocity
	float velMag;
	velMag = sqrt((_velocity.x * _velocity.x) + (_velocity.y * _velocity.y) + (_velocity.z * _velocity.z));

	// Calculate unit vector/normalised vector of velocity
	XMFLOAT3 unitVel;
	unitVel.x = (_velocity.x / velMag);
	unitVel.y = (_velocity.y / velMag);
	unitVel.z = (_velocity.z / velMag);

	// Calculate magnitude of drag force
	float dragMag;
	dragMag = dragFactor * velMag * velMag;

	// Calculate of x- and y-components of drag force
	dragForce.x = -dragMag * unitVel.x;
	dragForce.y = -dragMag * unitVel.y;
	dragForce.z = -dragMag * unitVel.z;

}

bool ParticleModel::CheckCollision(XMFLOAT3 position2, float radius2)
{
	XMFLOAT3 position = _transform->GetPosition();

	XMFLOAT3 difference;
	difference.x = position.x - position2.x;
	difference.y = position.y - position2.y;
	difference.z = position.z - position2.z;

	float differenceMag = sqrt((difference.x * difference.x) + (difference.y * difference.y) + (difference.z * difference.z));

	float rDistance = _radius + radius2;

	if (differenceMag <= rDistance)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void ParticleModel::CheckFloorCollision(XMFLOAT3 floorPos)
{
	XMFLOAT3 objectPosition = _transform->GetPosition();

	XMFLOAT3 difference;
	difference.y = objectPosition.y - floorPos.y;

	float differenceMag = sqrt(difference.y * difference.y);

	if (differenceMag <= _radius)
	{
		slideOn = true;
		_velocity.y = -_velocity.y;
	}
	else
	{
		slideOn = false;
	}
}

void ParticleModel::ResolveCollision(ParticleModel* particleModel1, ParticleModel* particleModel2)
{
	float rCoef = 0.8f;

	XMFLOAT3 prevPos1 = particleModel1->_transform->GetOldPosition();
	XMFLOAT3 prevPos2 = particleModel2->_transform->GetOldPosition();

	float mass1 = particleModel1->GetMass();
	float mass2 = particleModel2->GetMass();

	XMFLOAT3 initialVelocity1 = particleModel1->GetVelocity();
	XMFLOAT3 initialVelocity2 = particleModel2->GetVelocity();

	particleModel1->_transform->SetPosition(prevPos1);
	particleModel2->_transform->SetPosition(prevPos2);

	XMFLOAT3 velocity1;
	XMFLOAT3 velocity2;

	velocity1.x = (mass1 * initialVelocity1.x) + (mass2 * initialVelocity2.x) + ((mass2 * rCoef) * (initialVelocity2.x - initialVelocity1.x)) / (mass1 + mass2);
	velocity1.y = (mass1 * initialVelocity1.y) + (mass2 * initialVelocity2.y) + ((mass2 * rCoef) * (initialVelocity2.y - initialVelocity1.y)) / (mass1 + mass2);
	velocity1.z = (mass1 * initialVelocity1.z) + (mass2 * initialVelocity2.z) + ((mass2 * rCoef) * (initialVelocity2.z - initialVelocity1.z)) / (mass1 + mass2);

	velocity2.x = (mass1 * initialVelocity1.x) + (mass2 * initialVelocity2.x) + ((mass1 * rCoef) * (initialVelocity1.x - initialVelocity2.x)) / (mass1 + mass2);
	velocity2.y = (mass1 * initialVelocity1.y) + (mass2 * initialVelocity2.y) + ((mass1 * rCoef) * (initialVelocity1.y - initialVelocity2.y)) / (mass1 + mass2);
	velocity2.z = (mass1 * initialVelocity1.z) + (mass2 * initialVelocity2.z) + ((mass1 * rCoef) * (initialVelocity1.z - initialVelocity2.z)) / (mass1 + mass2);

	particleModel1->SetVelocity(velocity1);
	particleModel2->SetVelocity(velocity2);
} <|endoftext|>


<commit_before>#ifndef RESOLVER_PIXEL_SORTER_HPP
#define RESOLVER_PIXEL_SORTER_HPP

#include "data_type.hpp"
#include "splitter.hpp"

template<class Algorithm>
class pixel_sorter
{
public:
    // 座標(j,i)と座標(l,k)の比較結果としては，compared_type[i][j][k][l]にtuple<上,右,下,左>で入る
    // compared_typeより，一番距離が近い断片画像をadjacent_typeに整理する
    typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;
    typedef std::vector<std::vector<direction_type<point_type>>> adjacent_type;
    typedef std::vector<std::vector<point_type>> return_type;

    pixel_sorter<Algorithm>() : split_(){}
    virtual ~pixel_sorter<Algorithm>() = default;

    return_type operator() (question_raw_data const& raw) const
    {
        auto const& proposed = proposed_answer(raw);

        // TODO: ここで返却されたデータのうち，適しているものを選択してreturn

        return proposed[0];
    }

    std::vector<return_type> proposed_answer(question_raw_data const& raw) const
    {
        //
        // Sub Algorithm
        // 正しい位置に並べた時に左上から，1~nまでの番号をふり，それが今どこにあるのかという情報をreturn
        //

        split_image_type const& splited_image = split_.split_image(raw);
        compared_type const& comp = this->image_comp(splited_image);

        Algorithm algo(raw, comp);
        auto const& proposed = algo();

        return proposed;
    }

private:
    //2つのピクセル間の距離を2乗した値を返却．result = r^2 + g^2 + b^2
    int pixel_comparison(pixel_type const& lhs, pixel_type const& rhs) const
    {
        int s = 0;
        for(int i=0; i<3; ++i) s += static_cast<int>(std::pow(std::abs(lhs[i] - rhs[i]), 2));
        return s;
    }

    //2つのピクセル列を比較した値を返す
    int pixel_line_comparison(image_type const& lhs, image_type const& rhs) const
    {
        auto lhs_it = lhs.begin(), lhs_end = lhs.end();
        auto rhs_it = rhs.begin(), rhs_end = rhs.end();

        int s = 0;
        for(; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it)
        {
            s += pixel_comparison(*lhs_it, *rhs_it);
        }
        return s;
    }

    //一枚目の右端と二枚目の左端を見る関数, 一致が多いほど低いを返す
    uint64_t rl_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.col(lhs.cols - 1), rhs.col(0));
    }

    //一枚目の左端と二枚目の右端を見る関数, 一致が多いほど低いを返す
    uint64_t lr_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.col(0), rhs.col(rhs.cols - 1));
    }

    //一枚目の上端と二枚目の下端を見る関数, 一致が多いほど低いを返す
    uint64_t ud_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.row(0), rhs.row(rhs.rows - 1));
    }

    //一枚目の下端と二枚目の上端を見る関数, 一致が多いほど低いを返す
    uint64_t du_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.row(rhs.rows - 1), rhs.row(0));
    }

    compared_type image_comp(split_image_type const& image) const
    {
        //返却用変数
        //"最大距離が収納されたtuple"の4次元配列になる
        compared_type comp(
            image.size(),
            std::vector<std::vector<std::vector<direction_type<uint64_t>>>>(
                image[0].size(),
                std::vector<std::vector<direction_type<uint64_t>>>(
                    image.size(),
                    std::vector<direction_type<uint64_t>>(
                        image[0].size(),
                        {
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max()
                        })
                    )
                )
            );

        for(int i=0; i<image.size(); ++i) for(int j=0; j<image[0].size(); ++j)
        {
            for(int k=0; k<image.size(); ++k) for(int l=0; l<image[0].size(); ++l)
            {
                if(k > i || (k == i && l > j)) // (j,i)より(l,k)の方が，探索順として後半に或るための条件
                {
                    //順序を変えて逆の逆の組み合わせの相対評価は同じであることを使用して探索量を半分にする
                    //例えば，Aから見たBは上なら，Bから見たAは下．
                    comp[i][j][k][l].up    = comp[k][l][i][j].down  = ud_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].right = comp[k][l][i][j].left  = rl_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].down  = comp[k][l][i][j].up    = du_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].left  = comp[k][l][i][j].right = lr_comparison(image[i][j], image[k][l]);
                }
            }
        }
        return comp;
    }

    splitter const split_;
};

#endif
<commit_msg>yrange2が答え返せなかった時の処理追加　pixcel_sorterとmainに書いたけどyrange2専用<commit_after>#ifndef RESOLVER_PIXEL_SORTER_HPP
#define RESOLVER_PIXEL_SORTER_HPP

#include "data_type.hpp"
#include "splitter.hpp"

template<class Algorithm>
class pixel_sorter
{
public:
    // 座標(j,i)と座標(l,k)の比較結果としては，compared_type[i][j][k][l]にtuple<上,右,下,左>で入る
    // compared_typeより，一番距離が近い断片画像をadjacent_typeに整理する
    typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;
    typedef std::vector<std::vector<direction_type<point_type>>> adjacent_type;
    typedef std::vector<std::vector<point_type>> return_type;

    pixel_sorter<Algorithm>() : split_(){}
    virtual ~pixel_sorter<Algorithm>() = default;

    return_type operator() (question_raw_data const& raw) const
    {
        auto const& proposed = proposed_answer(raw);

        // TODO: ここで返却されたデータのうち，適しているものを選択してreturn

		if (proposed.size() == 0) return std::vector < std::vector<point_type> > {};
		else return proposed[0];
    }

    std::vector<return_type> proposed_answer(question_raw_data const& raw) const
    {
        //
        // Sub Algorithm
        // 正しい位置に並べた時に左上から，1~nまでの番号をふり，それが今どこにあるのかという情報をreturn
        //

        split_image_type const& splited_image = split_.split_image(raw);
        compared_type const& comp = this->image_comp(raw,splited_image);

        Algorithm algo(raw, comp);
        auto const& proposed = algo();

        return proposed;
    }

private:
    //2つのピクセル間の距離を2乗した値を返却．result = r^2 + g^2 + b^2
    int pixel_comparison(pixel_type const& lhs, pixel_type const& rhs) const
    {
        int s = 0;
        for(int i=0; i<3; ++i) s += static_cast<int>(std::pow(std::abs(lhs[i] - rhs[i]), 2));
        return s;
    }

    //2つのピクセル列を比較した値を返す
    int pixel_line_comparison(image_type const& lhs, image_type const& rhs) const
    {
        auto lhs_it = lhs.begin(), lhs_end = lhs.end();
        auto rhs_it = rhs.begin(), rhs_end = rhs.end();

        int s = 0;
        for(; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it)
        {
            s += pixel_comparison(*lhs_it, *rhs_it);
        }
        return s;
    }

    //一枚目の右端と二枚目の左端を見る関数, 一致が多いほど低いを返す
    uint64_t rl_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.col(lhs.cols - 1), rhs.col(0));
    }

    //一枚目の左端と二枚目の右端を見る関数, 一致が多いほど低いを返す
    uint64_t lr_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.col(0), rhs.col(rhs.cols - 1));
    }

    //一枚目の上端と二枚目の下端を見る関数, 一致が多いほど低いを返す
    uint64_t ud_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.row(0), rhs.row(rhs.rows - 1));
    }

    //一枚目の下端と二枚目の上端を見る関数, 一致が多いほど低いを返す
    uint64_t du_comparison(image_type const& lhs, image_type const& rhs) const
    {
        return pixel_line_comparison(lhs.row(rhs.rows - 1), rhs.row(0));
    }

	/*一枚目の右端と二枚目の左端を見る関数　一致が多いほど低いを返す*/
	uint64_t rl_comparison(cv::Mat file1, cv::Mat file2)
	{
		uint64_t s = 0;
		for (int i = 0; i < file1.rows; i++) {//縦ピクセル数ループ
			for (int c = 0; c < file1.channels(); ++c){// 画像のチャネル数分だけループ。白黒の場合は1回、カラーの場合は3回
				s += abs((file1.data[file1.step * (i + 1) - file1.channels() + c]) - (file2.data[file2.step * i + c]));
			}
		}
		return s;
	}

	/*一枚目の左端と二枚目の右端を見る関数　一致が多いほど低いを返す*/
	uint64_t lr_comparison(cv::Mat file1, cv::Mat file2)
	{
		uint64_t s = 0;
		for (int i = 0; i < file1.rows; i++) {//縦ピクセル数ループ
			for (int c = 0; c < file1.channels(); ++c){// 画像のチャネル数分だけループ。白黒の場合は1回、カラーの場合は3回
				s += abs((file1.data[file1.step * i + c]) - (file2.data[file2.step * (i + 1) - file1.channels() + c]));

			}
		}
		return s;
	}

	/*一枚目の上端と二枚目の下端を見る関数　一致が多いほど低いを返す*/
	uint64_t ud_comparison(cv::Mat file1, cv::Mat file2)
	{
		uint64_t s = 0;
		for (unsigned int i = 0; i < file1.step; i++) {//横ピクセル数ループ
			s += abs((file1.data[i]) - (file2.data[(file2.rows - 1)* file2.step + i]));
		}
		return s;
	}

	/*一枚目の下端と二枚目の上端を見る関数　一致が多いほど低いを返す*/
	uint64_t du_comparison(cv::Mat file1, cv::Mat file2)
	{
		uint64_t s = 0;
		for (unsigned int i = 0; i < file1.step; i++) {//横ピクセル数ループ
			s += abs((file1.data[(file2.rows - 1)*file2.step + i]) - (file2.data[i]));
		}
		return s;
	}

    compared_type image_comp(question_raw_data const& data_,split_image_type const& image) const
    {
        //返却用変数
        //"最大距離が収納されたtuple"の4次元配列になる
        compared_type comp(
            image.size(),
            std::vector<std::vector<std::vector<direction_type<uint64_t>>>>(
                image[0].size(),
                std::vector<std::vector<direction_type<uint64_t>>>(
                    image.size(),
                    std::vector<direction_type<uint64_t>>(
                        image[0].size(),
                        {
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max(),
                            std::numeric_limits<uint64_t>::max()
                        })
                    )
                )
            );

		splitter sp;
		split_image_type splited = sp.split_image(data_);

        for(int i=0; i<image.size(); ++i) for(int j=0; j<image[0].size(); ++j)
        {
            for(int k=0; k<image.size(); ++k) for(int l=0; l<image[0].size(); ++l)
            {
                if(k > i || (k == i && l > j)) // (j,i)より(l,k)の方が，探索順として後半に或るための条件
                {
                    //順序を変えて逆の逆の組み合わせの相対評価は同じであることを使用して探索量を半分にする
                    //例えば，Aから見たBは上なら，Bから見たAは下．
					/*
                    comp[i][j][k][l].up    = comp[k][l][i][j].down  = ud_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].right = comp[k][l][i][j].left  = rl_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].down  = comp[k][l][i][j].up    = du_comparison(image[i][j], image[k][l]);
                    comp[i][j][k][l].left  = comp[k][l][i][j].right = lr_comparison(image[i][j], image[k][l]);
					*/

					comp[i][j][k][l].up    = comp[k][l][i][j].down  = ud_comparison(splited[i][j], splited[k][l]);
					comp[i][j][k][l].right = comp[k][l][i][j].left  = rl_comparison(splited[i][j], splited[k][l]);
					comp[i][j][k][l].down  = comp[k][l][i][j].up    = du_comparison(splited[i][j], splited[k][l]);
					comp[i][j][k][l].left  = comp[k][l][i][j].right = lr_comparison(splited[i][j], splited[k][l]);

                }
            }
        }
        return comp;
    }

    splitter const split_;
};

#endif
<|endoftext|>


<commit_before>/*
 * integer.cpp
 */
#include "integer.h"

namespace c8 {
    /*
     * Construct an integer using a string.
     *
     * The string can have an optional '-' sign to indicate that it's negative,
     * and then the usual C++-like hex, octal, * or decimal representations.
     */
    integer::integer(const std::string &v) {
        negative_ = false;

        /*
         * Does our integer have a '-' sign?
         */
        if (v.length()) {
            if (v[0] == '-') {
                negative_ = true;
            }
        }

        magnitude_ = natural(negative_ ? v.substr(1) : v);
    }

    /*
     * Add another integer to this one.
     */
    auto integer::operator +(const integer &v) const -> integer {
        integer res;

        /*
         * If our two numbers have the same sign then we just add and retain the
         * sign for this number.
         */
        if (negative_ == v.negative_) {
            res.negative_ = negative_;
            res.magnitude_ = magnitude_ + v.magnitude_;
            return res;
        }

        /*
         * If we are adding a larger magnitude value then subtract the smaller
         * from the larger, and retain the sign of the larger.
         */
        if (magnitude_ < v.magnitude_) {
            res.negative_ = v.negative_;
            res.magnitude_ = v.magnitude_ - magnitude_;
            return res;
        }

        /*
         * We're adding a smaller magnitude value, so subtract the smaller
         * from the larger, and, again, retain the sign of the larger.
         */
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ - v.magnitude_;
        return res;
    }

    /*
     * Subtract another integer from this one.
     *
     * Note that there is a subtle difference between the integer subtract operation
     * and the natural number version:  We don't have to worry about throwing
     * exceptions for negative results.
     */
    auto integer::operator -(const integer &v) const -> integer {
        integer res;

        /*
         * If we're subtracting a negative number from a positive, or a positive from
         * a negative, then we add the magnitudes of both and retain the sign of this one.
         */
        if (negative_ != v.negative_) {
            res.negative_ = negative_;
            res.magnitude_ = magnitude_ + v.magnitude_;
            return res;
        }

        /*
         * If we're subtracting a number that has a larger magnitude than this one, then
         * subtract the magnitudes and use the inverse of the sign for the larger.
         */
        if (magnitude_ < v.magnitude_) {
            res.negative_ = !v.negative_;
            res.magnitude_ = v.magnitude_ - magnitude_;
            return res;
        }

        /*
         * We're subtracting a number with a smaller magnitude than this one, so subtract
         * the magnitudes and use the sign of this one.
         */
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ - v.magnitude_;
        return res;
    }

    /*
     * Left shift this integer by a number of bits.
     */
    auto integer::operator <<(unsigned int count) const -> integer {
        integer res;
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ << count;
        return res;
    }

    /*
     * Right shift this integer by a number of bits.
     */
    auto integer::operator >>(unsigned int count) const -> integer {
        integer res;
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ >> count;
        return res;
    }

    /*
     * Multiply another integer with this one.
     */
    auto integer::operator *(const integer &v) const -> integer {
        integer res;
        res.negative_ = negative_ ^ v.negative_;
        res.magnitude_ = magnitude_ * v.magnitude_;
        return res;
    }

    /*
     * Divide this integer by another one, returning the quotient and remainder.
     */
    auto integer::divide_modulus(const integer &v) const -> std::pair<integer, integer> {
        std::pair<natural, natural> dm = magnitude_.divide_modulus(v.magnitude_);

        std::pair<integer, integer> res;
        res.first.negative_ = negative_ ^ v.negative_;
        res.first.magnitude_ = std::move(dm.first);
        res.second.magnitude_ = std::move(dm.second);

        return res;
    }

    /*
     * Divide this integer by another one, returning the quotient.
     */
    auto integer::operator /(const integer &v) const -> integer {
        integer res;
        res.negative_ = negative_ ^ v.negative_;
        res.magnitude_ = magnitude_ / v.magnitude_;
        return res;
    }

    /*
     * Divide this integer by another one, returning the remainder.
     */
    auto integer::operator %(const integer &v) const -> integer {
        integer res;
        res.negative_ = negative_ ^ v.negative_;
        res.magnitude_ = magnitude_ % v.magnitude_;
        return res;
    }

    /*
     * Compare a integer with this one.
     */
    auto integer::compare(const integer &v) const -> comparison {
        /*
         * Is this number non-negative?
         */
        if (!negative_) {
            /*
             * If the number we're comparing with is non-negative too then we can
             * just do a simple comparison of the magnitudes.
             */
            if (!v.negative_) {
                return magnitude_.compare(v.magnitude_);
            }

            /*
             * The number we're comparing with is negative so we're definitely greater
             * than it.
             */
            return comparison::gt;
        }

        /*
         * This integer is negative, so if the number we're comparing with is also
         * negative then we compare magnitudes, but we reverse the result.  The most
         * negative value is smaller, not larger.
         */
        if (v.negative_) {
            auto ures = magnitude_.compare(v.magnitude_);
            switch (ures) {
            case comparison::lt:
                return comparison::gt;

            case comparison::eq:
                return comparison::eq;

            case comparison::gt:
                return comparison::lt;
            }
        }

        /*
         * This integer is negative, but the one we're comparing with is not, so we're
         * smaller.
         */
        return comparison::lt;
    }

    /*
     * Convert this integer to a long long.
     */
    auto integer::to_long_long() const -> long long {
        /*
         * Will this number fit in a long long?  If not then throw an exception.
         */
        if (magnitude_.count_bits() > ((8 * sizeof(long long)) - 1)) {
            throw overflow_error();
        }

        /*
         * Convert the result, and, if necessary, flip the sign.
         */
        long long res = static_cast<long long>(to_unsigned_long_long(magnitude_));

        if (negative_) {
            res = -res;
        }

        return res;
    }

    /*
     * << operator to print a integer.
     */
    auto operator <<(std::ostream &outstr, const integer &v) -> std::ostream & {
        if (v.negative_) {
            outstr << '-';
        }

        outstr << v.magnitude_;

        return outstr;
    }
}

<commit_msg>Fix % operator<commit_after>/*
 * integer.cpp
 */
#include "integer.h"

namespace c8 {
    /*
     * Construct an integer using a string.
     *
     * The string can have an optional '-' sign to indicate that it's negative,
     * and then the usual C++-like hex, octal, * or decimal representations.
     */
    integer::integer(const std::string &v) {
        negative_ = false;

        /*
         * Does our integer have a '-' sign?
         */
        if (v.length()) {
            if (v[0] == '-') {
                negative_ = true;
            }
        }

        magnitude_ = natural(negative_ ? v.substr(1) : v);
    }

    /*
     * Add another integer to this one.
     */
    auto integer::operator +(const integer &v) const -> integer {
        integer res;

        /*
         * If our two numbers have the same sign then we just add and retain the
         * sign for this number.
         */
        if (negative_ == v.negative_) {
            res.negative_ = negative_;
            res.magnitude_ = magnitude_ + v.magnitude_;
            return res;
        }

        /*
         * If we are adding a larger magnitude value then subtract the smaller
         * from the larger, and retain the sign of the larger.
         */
        if (magnitude_ < v.magnitude_) {
            res.negative_ = v.negative_;
            res.magnitude_ = v.magnitude_ - magnitude_;
            return res;
        }

        /*
         * We're adding a smaller magnitude value, so subtract the smaller
         * from the larger, and, again, retain the sign of the larger.
         */
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ - v.magnitude_;
        return res;
    }

    /*
     * Subtract another integer from this one.
     *
     * Note that there is a subtle difference between the integer subtract operation
     * and the natural number version:  We don't have to worry about throwing
     * exceptions for negative results.
     */
    auto integer::operator -(const integer &v) const -> integer {
        integer res;

        /*
         * If we're subtracting a negative number from a positive, or a positive from
         * a negative, then we add the magnitudes of both and retain the sign of this one.
         */
        if (negative_ != v.negative_) {
            res.negative_ = negative_;
            res.magnitude_ = magnitude_ + v.magnitude_;
            return res;
        }

        /*
         * If we're subtracting a number that has a larger magnitude than this one, then
         * subtract the magnitudes and use the inverse of the sign for the larger.
         */
        if (magnitude_ < v.magnitude_) {
            res.negative_ = !v.negative_;
            res.magnitude_ = v.magnitude_ - magnitude_;
            return res;
        }

        /*
         * We're subtracting a number with a smaller magnitude than this one, so subtract
         * the magnitudes and use the sign of this one.
         */
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ - v.magnitude_;
        return res;
    }

    /*
     * Left shift this integer by a number of bits.
     */
    auto integer::operator <<(unsigned int count) const -> integer {
        integer res;
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ << count;
        return res;
    }

    /*
     * Right shift this integer by a number of bits.
     */
    auto integer::operator >>(unsigned int count) const -> integer {
        integer res;
        res.negative_ = negative_;
        res.magnitude_ = magnitude_ >> count;
        return res;
    }

    /*
     * Multiply another integer with this one.
     */
    auto integer::operator *(const integer &v) const -> integer {
        integer res;
        res.negative_ = negative_ ^ v.negative_;
        res.magnitude_ = magnitude_ * v.magnitude_;
        return res;
    }

    /*
     * Divide this integer by another one, returning the quotient and remainder.
     */
    auto integer::divide_modulus(const integer &v) const -> std::pair<integer, integer> {
        std::pair<natural, natural> dm = magnitude_.divide_modulus(v.magnitude_);

        std::pair<integer, integer> res;
        res.first.negative_ = negative_ ^ v.negative_;
        res.first.magnitude_ = std::move(dm.first);
        res.second.magnitude_ = std::move(dm.second);

        return res;
    }

    /*
     * Divide this integer by another one, returning the quotient.
     */
    auto integer::operator /(const integer &v) const -> integer {
        integer res;
        res.negative_ = negative_ ^ v.negative_;
        res.magnitude_ = magnitude_ / v.magnitude_;
        return res;
    }

    /*
     * Divide this integer by another one, returning the remainder.
     */
    auto integer::operator %(const integer &v) const -> integer {
        integer res;
        res.magnitude_ = magnitude_ % v.magnitude_;
        return res;
    }

    /*
     * Compare a integer with this one.
     */
    auto integer::compare(const integer &v) const -> comparison {
        /*
         * Is this number non-negative?
         */
        if (!negative_) {
            /*
             * If the number we're comparing with is non-negative too then we can
             * just do a simple comparison of the magnitudes.
             */
            if (!v.negative_) {
                return magnitude_.compare(v.magnitude_);
            }

            /*
             * The number we're comparing with is negative so we're definitely greater
             * than it.
             */
            return comparison::gt;
        }

        /*
         * This integer is negative, so if the number we're comparing with is also
         * negative then we compare magnitudes, but we reverse the result.  The most
         * negative value is smaller, not larger.
         */
        if (v.negative_) {
            auto ures = magnitude_.compare(v.magnitude_);
            switch (ures) {
            case comparison::lt:
                return comparison::gt;

            case comparison::eq:
                return comparison::eq;

            case comparison::gt:
                return comparison::lt;
            }
        }

        /*
         * This integer is negative, but the one we're comparing with is not, so we're
         * smaller.
         */
        return comparison::lt;
    }

    /*
     * Convert this integer to a long long.
     */
    auto integer::to_long_long() const -> long long {
        /*
         * Will this number fit in a long long?  If not then throw an exception.
         */
        if (magnitude_.count_bits() > ((8 * sizeof(long long)) - 1)) {
            throw overflow_error();
        }

        /*
         * Convert the result, and, if necessary, flip the sign.
         */
        long long res = static_cast<long long>(to_unsigned_long_long(magnitude_));

        if (negative_) {
            res = -res;
        }

        return res;
    }

    /*
     * << operator to print a integer.
     */
    auto operator <<(std::ostream &outstr, const integer &v) -> std::ostream & {
        if (v.negative_) {
            outstr << '-';
        }

        outstr << v.magnitude_;

        return outstr;
    }
}

<|endoftext|>