text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP

#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/expand.hpp>

namespace geofeatures_boost {} namespace boost = geofeatures_boost; namespace geofeatures_boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace section
{

struct get_section_box
{
    template <typename Box, typename Section>
    static inline void apply(Box& total, Section const& section)
    {
        geometry::expand(total, section.bounding_box);
    }
};

struct overlaps_section_box
{
    template <typename Box, typename Section>
    static inline bool apply(Box const& box, Section const& section)
    {
        return ! detail::disjoint::disjoint_box_box(box, section.bounding_box);
    }
};

}} // namespace detail::section
#endif

}} // namespace geofeatures_boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP

max_stars_repo_name: xarvey/Yuuuuuge

max_issues_repo_name: xarvey/Yuuuuuge

max_forks_repo_name: xarvey/Yuuuuuge


text:
// Copyright (C) 2015 Vicente J. Botet Escriba
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 2013/10 Vicente J. Botet Escriba
//   Creation.

#ifndef BOOST_CSBL_QUEUE_HPP
#define BOOST_CSBL_QUEUE_HPP

#include <boost/config.hpp>
// MSVC has some trouble instantiating a non_copyable type
//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable'
//        ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable'
//        ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable'
//        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
//        with
//        [
//            _Ty=non_copyable
//        ]
#if defined BOOST_THREAD_USES_BOOST_QUEUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827)
#ifndef BOOST_THREAD_USES_BOOST_QUEUE
#define BOOST_THREAD_USES_BOOST_QUEUE
#endif
#include <boost/container/queue.hpp>
#else
#include <queue>
#endif

namespace boost
{
  namespace csbl
  {
#if defined BOOST_THREAD_USES_BOOST_QUEUE
    using ::boost::container::queue;

#else
    using ::std::queue;

#endif

  }
}
#endif // header

ext: hpp

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
// The code is open source under the MIT license.
// Copyright 2019-2020, Phillip Keldenich, TU Braunschweig, Algorithms Group
// https://ibr.cs.tu-bs.de/alg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//
// Created by Phillip Keldenich on 2019-09-23.
//

#pragma once

#include "ivarp/symbol_export.hpp"
#include "ivarp/metaprogramming.hpp"
#include <type_traits>
#include <utility>
#include <boost/io/ios_state.hpp>

namespace ivarp {
    namespace impl {
        template<typename BoolType> struct BoolTraitsImpl {
            static IVARP_HD constexpr bool definitely(BoolType b) noexcept {
                return b;
            }

            static IVARP_HD constexpr bool possibly(BoolType b) noexcept {
                return b;
            }

            static IVARP_HD constexpr bool singleton(BoolType b) noexcept {
                return true;
            }
        };

        template<typename BoolType> struct IBoolTraitsImpl {
            static IVARP_HD bool definitely(BoolType b) noexcept {
                return b.definitely();
            }

            static IVARP_HD bool possibly(BoolType b) noexcept {
                return b.possibly();
            }

            static IVARP_HD bool singleton(BoolType b) noexcept {
                return b.singleton();
            }
        };
    }

    template<typename BoolType> struct BoolTraits;
    template<> struct BoolTraits<bool> : impl::BoolTraitsImpl<bool> {};
    template<> struct BoolTraits<const bool> : impl::BoolTraitsImpl<const bool> {};

    class IBool {
    public:
        IBool() = default;
        IVARP_HD IBool(bool lb, bool ub) noexcept : lb(lb), ub(ub) {}
        IVARP_HD IBool(bool b) noexcept : lb(b), ub(b) {} // NOLINT (this is an implicit conversion by design)

        IVARP_HD bool definitely() const noexcept {
            return lb;
        }

        IVARP_HD bool possibly() const noexcept {
            return ub;
        }

        IVARP_HD IBool operator|(IBool other) const noexcept {
            IBool result{*this};
            result |= other;
            return result;
        }

        IVARP_HD IBool &operator|=(IBool other) noexcept {
            lb |= other.lb;
            ub |= other.ub;
            return *this;
        }

        IVARP_HD IBool operator&(IBool other) const noexcept {
            IBool result{*this};
            result &= other;
            return result;
        }

        IVARP_HD IBool &operator&=(IBool other) noexcept {
            lb &= other.lb;
            ub &= other.ub;
            return *this;
        }

        IVARP_HD IBool operator^(IBool other) const noexcept {
            IBool result{*this};
            result ^= other;
            return result;
        }

        IVARP_HD IBool &operator^=(IBool other) noexcept {
            if(lb == ub && other.lb == other.ub) {
                lb = ub = (lb ^ other.lb);
            } else {
                lb = false;
                ub = true;
            }
            return *this;
        }

        IVARP_HD IBool operator!() const noexcept {
            return {!ub, !lb};
        }

        IVARP_HD IBool join(IBool other) const noexcept {
            IBool result{*this};
            result.do_join(other);
            return result;
        }

        IVARP_HD void do_join(IBool other) noexcept {
            lb &= other.lb;
            ub |= other.ub;
        }

        IVARP_HD bool same(IBool other) const noexcept {
            return lb == other.lb && ub == other.ub;
        }

        IVARP_HD bool singleton() const noexcept {
            return lb == ub;
        }

    private:
        bool lb, ub;
    };

    static inline std::ostream& operator<<(std::ostream& o, IBool i) {
        boost::io::ios_flags_saver saver(o);
        o << '[' << std::boolalpha << i.definitely() << ", " << i.possibly() << ']';
        return o;
    }

    template<typename T> using IsBoolean = std::integral_constant<bool,
            std::is_same<BareType<T>,bool>::value || std::is_same<BareType<T>, IBool>::value
        >;

    template<> struct BoolTraits<IBool> : impl::IBoolTraitsImpl<IBool> {};
    template<> struct BoolTraits<const IBool> : impl::IBoolTraitsImpl<const IBool> {};

    template<typename BoolType> static inline IVARP_HD bool definitely(const BoolType& b) noexcept {
        return BoolTraits<BareType<BoolType>>::definitely(b);
    }

    template<typename BoolType> static inline IVARP_HD bool possibly(const BoolType& b) noexcept {
        return BoolTraits<BareType<BoolType>>::possibly(b);
    }

    template<typename BoolType> static inline IVARP_HD bool singleton(const BoolType& b) noexcept {
        return BoolTraits<BareType<BoolType>>::singleton(b);
    }
}

max_stars_repo_name: phillip-keldenich/squares-in-disk

max_issues_repo_name: phillip-keldenich/squares-in-disk

max_forks_repo_name: phillip-keldenich/squares-in-disk


text:
#pragma once

#ifndef BOOST_EXTREMA_MAX_ARITY
#	define BOOST_EXTREMA_MAX_ARITY 10
#endif

#ifdef BOOST_EXTREMA_INTEGRATE_WITH_STD
#	if defined(BOOST_EXTREMA_MIN_NAME) || defined(BOOST_EXTREMA_MAX_NAME) || defined(BOOST_EXTREMA_NAMESPACE)
#		error When integrating with the std namespace, don't define a custom namespace or custom names for the min and max functions.
#	endif
#	define BOOST_EXTREMA_MAX_NAME max
#	define BOOST_EXTREMA_MIN_NAME min
#	define BOOST_EXTREMA_NAMESPACE std
#else
#	ifndef BOOST_EXTREMA_MIN_NAME
#		define BOOST_EXTREMA_MIN_NAME minimum
#	endif
#	ifndef BOOST_EXTREMA_MAX_NAME
#		define BOOST_EXTREMA_MAX_NAME maximum
#	endif
#	ifndef BOOST_EXTREMA_NAMESPACE
#		define BOOST_EXTREMA_NAMESPACE boost
#	endif
#endif

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/identity.hpp>
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/seq/elem.hpp>

#include <boost/mpl/and.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_void.hpp>

#include "comparison_type.hpp"

#ifdef BOOST_EXTREMA_INTEGRATE_WITH_STD
#	include <boost/mpl/not.hpp>
#	include <boost/type_traits/is_same.hpp>
#	include <boost/utility/enable_if.hpp>
#endif

namespace BOOST_EXTREMA_NAMESPACE {

#ifdef BOOST_EXTREMA_INTEGRATE_WITH_STD
#	define BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD(function_name) \
	typename boost::lazy_enable_if<boost::mpl::not_<boost::is_same<A, B>> \
		, boost::BOOST_PP_CAT(function_name, _return_type)<A, B>>::type
#else
#	define BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD(function_name) \
		typename boost::BOOST_PP_CAT(function_name, _return_type)<A, B>::type
#endif

#define BOOST_EXTREMA_BASE_FUNCTION_IMPL(function_name, op, semantic, cast_type, caster) \
	template <typename A, typename B> \
	BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD(semantic) \
	BOOST_PP_CAT(function_name, _impl)(const A& a, const B& b, boost::cast_type /*dont_cast_comparends*/) \
	{ \
		typedef typename boost::comparison_type<A, B>::type C; \
		typedef BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD(semantic) R; \
		if (caster(a) op caster(b)) \
			return (R)a; \
		else return (R)b; \
	}

#define BOOST_EXTREMA_CASTER(x) C(x)

#define BOOST_EXTREMA_BASE_FUNCTION(function_name, op, semantic) \
	BOOST_EXTREMA_BASE_FUNCTION_IMPL(function_name, op, semantic, false_type, C) \
	BOOST_EXTREMA_BASE_FUNCTION_IMPL(function_name, op, semantic, true_type, ) \
	template <typename A, typename B> \
	BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD(semantic) \
	function_name(const A& a, const B& b) \
	{ \
		typedef typename boost::comparison_type<A, B>::type C; \
		return BOOST_PP_CAT(function_name, _impl)(a, b, boost::is_void<C>()); \
	}

BOOST_EXTREMA_BASE_FUNCTION(BOOST_EXTREMA_MIN_NAME, <, min)
BOOST_EXTREMA_BASE_FUNCTION(BOOST_EXTREMA_MAX_NAME, >, max)

#ifndef BOOST_EXTREMA_NO_OVERLOADS_OF_GREATER_ARITY

#define BOOST_EXTREMA_FUNCTION_CALL_PREFIX(z, n, data) data(BOOST_PP_CAT(t, n),
#define BOOST_EXTREMA_FUNCTION_CALL_SUFFIX(z, n, data) BOOST_PP_RPAREN()
#define BOOST_EXTREMA_COMPOUND_RESULT_PREFIX(z, n, data) typename boost::BOOST_PP_CAT(data, _return_type)<BOOST_PP_CAT(T, n),
#define BOOST_EXTREMA_COMPOUND_RESULT_SUFFIX(z, n, data) >::type

#define BOOST_EXTREMA_PREFIX_AND_SUFFIX(n, data, prefix, middle, suffix) \
	BOOST_PP_REPEAT(n, prefix, data) \
	middle \
	BOOST_PP_REPEAT(n, suffix, data)

#define BOOST_EXTREMA_FUNCTION_TEMPLATE(z, n, data) \
template <BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename T)> \
BOOST_EXTREMA_PREFIX_AND_SUFFIX(n, BOOST_PP_SEQ_ELEM(1, data), BOOST_EXTREMA_COMPOUND_RESULT_PREFIX, BOOST_PP_CAT(T, n), BOOST_EXTREMA_COMPOUND_RESULT_SUFFIX) \
BOOST_PP_SEQ_ELEM(0, data)(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n), T, t)) \
{ \
	return BOOST_EXTREMA_PREFIX_AND_SUFFIX(n, BOOST_PP_SEQ_ELEM(0, data), BOOST_EXTREMA_FUNCTION_CALL_PREFIX, BOOST_PP_CAT(t, n), BOOST_EXTREMA_FUNCTION_CALL_SUFFIX); \
}

#define BOOST_EXTREMA_FUNCTION_TEMPLATE_DEC_N(z, n, data) BOOST_EXTREMA_FUNCTION_TEMPLATE(z, BOOST_PP_DEC(n), data)

BOOST_PP_REPEAT_FROM_TO(3, BOOST_PP_INC(BOOST_EXTREMA_MAX_ARITY), BOOST_EXTREMA_FUNCTION_TEMPLATE_DEC_N, (BOOST_EXTREMA_MIN_NAME)(min))
BOOST_PP_REPEAT_FROM_TO(3, BOOST_PP_INC(BOOST_EXTREMA_MAX_ARITY), BOOST_EXTREMA_FUNCTION_TEMPLATE_DEC_N, (BOOST_EXTREMA_MAX_NAME)(max))

#undef BOOST_EXTREMA_RETURN_TYPE_OF_BINARY_OVERLOAD
#undef BOOST_EXTREMA_BASE_FUNCTION_IMPL
#undef BOOST_EXTREMA_BASE_FUNCTION
#undef BOOST_EXTREMA_FUNCTION_CALL_PREFIX
#undef BOOST_EXTREMA_FUNCTION_CALL_SUFFIX
#undef BOOST_EXTREMA_TYPE_PROMOTION_PREFIX
#undef BOOST_EXTREMA_TYPE_PROMOTION_SUFFIX
#undef BOOST_EXTREMA_PREFIX_AND_SUFFIX
#undef BOOST_EXTREMA_FUNCTION_TEMPLATE
#undef BOOST_EXTREMA_FUNCTION_TEMPLATE_DEC_N

#endif

}


text:
/***********************************************************************************************************************
*  OpenStudio(R), Copyright (c) 2008-2021, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
*  following conditions are met:
*
*  (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*  disclaimer.
*
*  (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
*  disclaimer in the documentation and/or other materials provided with the distribution.
*
*  (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products
*  derived from this software without specific prior written permission from the respective party.
*
*  (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
*  may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
*  written permission from Alliance for Sustainable Energy, LLC.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
*  STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
*  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************************************************************/

#ifndef UTILITIES_GEOMETRY_GEOMETRY_HPP
#define UTILITIES_GEOMETRY_GEOMETRY_HPP

#include "../UtilitiesAPI.hpp"

#include <vector>
#include <boost/optional.hpp>

namespace openstudio {

class Point3d;
class PointLatLon;
class Vector3d;

/// convert degrees to radians
UTILITIES_API double degToRad(double degrees);

/// convert radians to degrees
UTILITIES_API double radToDeg(double radians);

// Forces an angle in degrees to be in the [0,360[ range
UTILITIES_API constexpr double normalizeAngle0to360(double angleDegrees) {
  while (angleDegrees < 0.0) {
    angleDegrees += 360.0;
  }

  // This is twice as fast as using std::fmod(angleDegrees, 360.0)
  while (angleDegrees >= 360.0) {
    angleDegrees -= 360.0;
  }
  return angleDegrees;
}

/// compute area from surface as Point3dVector
UTILITIES_API boost::optional<double> getArea(const std::vector<Point3d>& points);

/// compute Newall vector from surface as Point3dVector, direction is same as outward normal
/// magnitude is twice the area
UTILITIES_API boost::optional<Vector3d> getNewallVector(const std::vector<Point3d>& points);

/// compute outward normal from surface as Point3dVector
UTILITIES_API boost::optional<Vector3d> getOutwardNormal(const std::vector<Point3d>& points);

/// compute centroid from surface as Point3dVector
UTILITIES_API boost::optional<Point3d> getCentroid(const std::vector<Point3d>& points);

/// reorder points to upper-left-corner convention
UTILITIES_API std::vector<Point3d> reorderULC(const std::vector<Point3d>& points);

/// removes collinear points
UTILITIES_API std::vector<Point3d> removeCollinear(const std::vector<Point3d>& points, double tol = 0.001);

/// removes collinear points, tolerance is for length of cross product after normalizing each line segment
UTILITIES_API std::vector<Point3d> removeCollinearLegacy(const std::vector<Point3d>& points, double tol = 0.001);

/// return distance between two points
UTILITIES_API double getDistance(const Point3d& point1, const Point3d& point2);

/// return distance squared between two points
/// faster than getDistance; can be used to compare distances
UTILITIES_API double getDistanceSquared(const Point3d& point1, const Point3d& point2);

/// return distance between a point and a line segment
/// returns 0 if lineSegment does not have length 2
UTILITIES_API double getDistancePointToLineSegment(const Point3d& point, const std::vector<Point3d>& lineSegment);

/// return distance between a point and a triangle
/// returns 0 if triangle does not have length 3
UTILITIES_API double getDistancePointToTriangle(const Point3d& point, const std::vector<Point3d>& triangle);

/// return angle (in radians) between two vectors
UTILITIES_API double getAngle(const Vector3d& vector1, const Vector3d& vector2);

/// check if two vectors of points are equal (within tolerance) irregardless of initial ordering.
UTILITIES_API bool circularEqual(const std::vector<Point3d>& points1, const std::vector<Point3d>& points2, double tol = 0.001);

/// if point3d is within tol of any existing points then returns existing point
/// otherwise adds point3d to allPoints and returns point3d
UTILITIES_API Point3d getCombinedPoint(const Point3d& point3d, std::vector<Point3d>& allPoints, double tol = 0.001);

/// compute triangulation of vertices, holes are removed in the triangulation
/// requires that vertices and holes are in clockwise order on the z = 0 plane (i.e. in face coordinates but reversed)
UTILITIES_API std::vector<std::vector<Point3d>> computeTriangulation(const std::vector<Point3d>& vertices,
                                                                     const std::vector<std::vector<Point3d>>& holes, double tol = 0.001);

/// move all vertices towards point by distance, pass negative distance to move away from point
/// no guarantee that resulting polygon will be valid
UTILITIES_API std::vector<Point3d> moveVerticesTowardsPoint(const std::vector<Point3d>& vertices, const Point3d& point, double distance);

/// reverse order of vertices
UTILITIES_API std::vector<Point3d> reverse(const std::vector<Point3d>& vertices);

/// Sets view and daylighting window, overhang and light shelf vertices by reference.  Returns true if successful, false otherwise.
UTILITIES_API bool applyViewAndDaylightingGlassRatios(double viewGlassToWallRatio, double daylightingGlassToWallRatio,
                                                      double desiredViewGlassSillHeight, double desiredDaylightingGlassHeaderHeight,
                                                      double exteriorShadingProjectionFactor, double interiorShelfProjectionFactor,
                                                      const std::vector<Point3d>& surfaceVertices, std::vector<Point3d>& viewVertices,
                                                      std::vector<Point3d>& daylightingVertices, std::vector<Point3d>& exteriorShadingVertices,
                                                      std::vector<Point3d>& interiorShelfVertices);

}  // namespace openstudio

#endif  //UTILITIES_GEOMETRY_GEOMETRY_HPP

max_stars_repo_name: MingboPeng/OpenStudio

max_issues_repo_name: NREL/OpenStudio

max_forks_repo_name: NREL/OpenStudio


text:
#include "tasktorrent/tasktorrent.hpp"
#ifdef USE_MKL
#include <mkl_cblas.h>
#include <mkl_lapacke.h>
#else
#include <cblas.h>
#include <lapacke.h>
#endif
#include <Eigen/Core>
#include <Eigen/Cholesky>
#include <fstream>
#include <array>
#include <random>
#include <mutex>
#include <iostream>
#include <map>
#include <memory>
#include <set>

#include <mpi.h>
#include <cxxopts.hpp>

using namespace std;
using namespace Eigen;
using namespace ttor;

typedef array<int, 2> int2;
typedef array<int, 3> int3;

/*
Parametrized priorities for cholesky:
0. No priority, only enforces potrf>trsm>gemm
1. Row-based priority, prioritize tasks with smaller row number in addition to priority 0.
2. Critical path priority, prioritize tasks with longest distance to the exit task. For references, check out the paper
    Beaumont, Olivier, et al. "A Makespan Lower Bound for the Scheduling of the Tiled Cholesky Factorization based on ALAP Schedule." (2020).
3. Critical path and row priority, prioritize tasks with smaller row number in addition to priority 2. We also enforces potrf>trsm>gemm
*/

enum PrioKind { no = 0, row = 1, cp = 2, cp_row = 3};

void cholesky(const int n_threads, const int verb, const int block_size, const int num_blocks, const int nprows, const int npcols,
              const PrioKind prio_kind, const bool log, const bool deps_log, const bool test, const int accumulate_parallel, const int upper_block_size)
{
    const int rank = comm_rank();
    const int n_ranks = comm_size();
    const int matrix_size = block_size * num_blocks;
    assert(nprows * npcols == n_ranks);
    std::atomic<long long int> potrf_us_t(0);
    std::atomic<long long int> trsm_us_t(0);
    std::atomic<long long int> gemm_us_t(0);
    std::atomic<long long int> accu_us_t(0);

    // Warmup MKL
    {
        Eigen::MatrixXd A = Eigen::MatrixXd::Identity(256,256);
        Eigen::MatrixXd B = Eigen::MatrixXd::Identity(256,256);
        Eigen::MatrixXd C = Eigen::MatrixXd::Identity(256,256);
        for(int i = 0; i < 10; i++) {
            cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 256, 256, 256, 1.0, A.data(), 256, B.data(), 256, 1.0, C.data(), 256);
        }
    }

    // Compute random sizes
    std::mt19937 gen(2020);
    assert(upper_block_size <= 2*block_size);
    const int lower_block_size = 2*block_size - upper_block_size;
    std::uniform_int_distribution<> distrib(lower_block_size,upper_block_size); // average is block_size
    if(rank == 0) printf("lower_block_size %d, upper_block_size %d\n", lower_block_size, upper_block_size);
    std::vector<int> block_sizes(num_blocks, block_size);
    {
        int n = 0;
        for(int i = 0; i < num_blocks-1; i++) {
            int bs = std::min(matrix_size - n, distrib(gen));
            n += bs;
            block_sizes[i] = bs;
        }
        assert(matrix_size - n >= 0);
        block_sizes[num_blocks-1] = matrix_size - n;
    }
    int total = std::accumulate(block_sizes.begin(), block_sizes.end(), 0);
    assert(total == matrix_size);
    std::vector<int> block_displ(num_blocks+1, 0);
    for(int i = 1; i < num_blocks+1; i++) {
        block_displ[i] = block_displ[i-1] + block_sizes[i-1];
    }
    std::vector<int> block_sizes_lda(num_blocks, 0);
    for(int i = 0; i < num_blocks; i++) {
        block_sizes_lda[i] = std::max(1, block_sizes[i]);
    }
    assert(block_displ[num_blocks] == matrix_size);
    if(rank == 0) {
        printf("block sizes: ");
        for(int i = 0; i < num_blocks; i++) {
            assert(block_sizes[i] >= 0);
            printf("%d ", block_sizes[i]);
        };
        printf("\n");
        printf("block displ: ");
        for(int i = 0; i < num_blocks+1; i++) {
            assert(block_displ[i] >= 0);
            printf("%d ", block_displ[i]);
        };
        printf("\n");
    }

    // Map tasks to ranks
    auto block_2_rank = [&](int i, int j) {
        assert(i >= 0 && i < num_blocks);
        assert(j >= 0 && j < num_blocks);
        int r = (j % npcols) * nprows + (i % nprows);
        assert(r >= 0 && r < n_ranks);
        return r;
    };

    const int rank_row = (rank % nprows);
    const int rank_col = (rank / nprows);
    auto block_2_rank_row = [&](int i, int j) {
        return i % nprows;
    };
    auto block_2_rank_col = [&](int i, int j) {
        return j % npcols;
    };

    // Map threads to ranks
    auto block_2_thread = [&](int i, int j) {
        int ii = i / nprows;
        int jj = j / npcols;
        int num_blocksit = num_blocks / nprows;
        return (ii + jj * num_blocksit) % n_threads;
    };

    // Initializes the matrix
    auto val = [&](int i, int j) { return 1/(double)((i-j)*(i-j)+1); };
    vector<unique_ptr<MatrixXd>> blocks(num_blocks*num_blocks);
    for (int ii=0; ii<num_blocks; ii++) {
        for (int jj=0; jj<num_blocks; jj++) {
            auto val_loc = [&](int i, int j) { return val(block_displ[ii]+i,block_displ[jj]+j); };
            if(ii >= jj) {
                if(block_2_rank(ii,jj) == rank) {
                    blocks[ii+jj*num_blocks]=make_unique<MatrixXd>(block_sizes[ii],block_sizes[jj]);
                    *blocks[ii+jj*num_blocks]=MatrixXd::NullaryExpr(block_sizes[ii],block_sizes[jj], val_loc);
                } else {
                    blocks[ii+jj*num_blocks]=make_unique<MatrixXd>(0,0);
                }
            }
        }
    }

    // Holds the temporary matrices result of gemm to be accumulated by accu
    // Each block holds data to be accumulated into a given block[ii+jj*num_blocks]
    struct acc_data {
        std::map<int, std::unique_ptr<MatrixXd>> to_accumulate; // to_accumulate[k] holds matrix result of gemm(k,i,j)
        std::mutex mtx; // Protects that map
    };
    std::vector<acc_data> gemm_results(num_blocks*num_blocks); // gemm_results[ii+jj*num_blocks] holds the data to be accumulated into blocks[ii+jj*num_blocks]

    // Set priorities
    auto potf_block_2_prio = [&](int j) {
        if (prio_kind == PrioKind::cp_row) {
            return (double)(9*(num_blocks - j)-1) + 18 * num_blocks * num_blocks;
        }
        else if(prio_kind == PrioKind::cp) {
            return (double)(9*(num_blocks - j)-1);
        }
        else if(prio_kind == PrioKind::row) {
            return 3.0*(double)(num_blocks-j);
        }
        else {
            return 3.0;
        }
    };
    auto trsm_block_2_prio = [&](int2 ij) {
        if (prio_kind == PrioKind::cp_row) {
            return (double)((num_blocks - ij[0]) + num_blocks * (9.0 * num_blocks - 9.0 * ij[1] - 2.0) + 9 * num_blocks * num_blocks);
        }
        else if(prio_kind == PrioKind::cp) {
            return (double)(9*(num_blocks - ij[1])-2);
        }
        else if(prio_kind == PrioKind::row) {
            return 2.0*(double)(num_blocks - ij[0]);
        }
        else {
            return 2.0;
        }
    };
    auto gemm_block_2_prio = [&](int3 kij) {
        if (prio_kind == PrioKind::cp_row) {
            if (accumulate_parallel) {
                return (double)(num_blocks - kij[1]) + num_blocks * (9.0 * num_blocks - 9.0 * kij[2] - 2.0);
            }
            else {
                return (double)(num_blocks - kij[1]) + num_blocks * (9.0 * num_blocks - 3.0 * kij[2] - 6.0 * kij[0] - 2.0);
            }
        }
        else if(prio_kind == PrioKind::cp) {
            return (double)(9*num_blocks-9*kij[2]-2);
        }
        else if(prio_kind == PrioKind::row) {
            return (double)(num_blocks - kij[1]);
        }
        else {
            return 1.0;
        }
    };
    // Names
    auto potrf_name = [](int j) {
        return "POTRF_" + to_string(j);
    };
    auto trsm_name = [](int2 ij) {
        return "TRSM_" + to_string(ij[0]) + "_" + to_string(ij[1]);
    };
    auto gemm_name = [](int3 kij) {
        return "GEMM_" + to_string(kij[0]) + "_" + to_string(kij[1]) + "_" + to_string(kij[2]);
    };
    auto accu_name = [](int3 kij) {
        return "ACCU_" + to_string(kij[0]) + "_" + to_string(kij[1]) + "_" + to_string(kij[2]);
    };

    const int num_blocksmax = 15;
    MPI_Barrier(MPI_COMM_WORLD);
    if(comm_rank() == 0) {
        printf("Block -> Rank\n");
        for(int i = 0; i < min(num_blocksmax, num_blocks); i++) {
            for(int j = 0; j < min(num_blocksmax, num_blocks); j++) {
                if(i >= j) {
                    printf("%2d ", block_2_rank(i, j));
                }
            }
            printf("\n");
        }
        printf("Potf/trsm -> Priority\n");
        for(int i = 0; i < min(num_blocksmax, num_blocks); i++) {
            for(int j = 0; j < min(num_blocksmax, num_blocks); j++) {
                if(i == j) {
                    printf("%5f ", potf_block_2_prio(i));
                } else if (i > j) {
                    printf("%5f ", trsm_block_2_prio({i,j}));
                };
            }
            printf("\n");
        }
        printf("Gemm -> Priority\n");
        for(int k = 0; k < min(num_blocksmax, num_blocks); k++) {
            printf("k = %d\n", k);
            for(int i = 0; i < min(num_blocksmax, num_blocks); i++) {
                for(int j = 0; j < min(num_blocksmax, num_blocks); j++) {
                    if(i >= j) {
                        if(k < j) {
                            printf("%5f ", gemm_block_2_prio({k,i,j}));
                        } else {
                            printf(".     ");
                        }
                    }
                }
                printf("\n");
            }
        }
    }
    for(int r = 0; r < ttor::comm_size(); r++) {
        if(r == comm_rank()) {
            printf("[%d] Block -> thread\n", r);
            for(int i = 0; i < min(num_blocksmax, num_blocks); i++) {
                for(int j = 0; j < min(num_blocksmax, num_blocks); j++) {
                    if(i >= j && block_2_rank(i,j) == r) {
                        printf("%2d ", block_2_thread(i, j));
                    } else {
                        printf(" . ");
                    }
                }
                printf("\n");
            }
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }

    // Initialize the communicator structure
    Communicator comm(MPI_COMM_WORLD, verb);

    // Initialize the runtime structures
    Threadpool tp(n_threads, &comm, verb, "Wk_Chol_" + to_string(rank) + "_");
    Taskflow<int>  potrf(&tp, verb);
    Taskflow<int2> trsm(&tp, verb);
    Taskflow<int3> gemm(&tp, verb);
    Taskflow<int3> accu(&tp, verb);

    Logger logger(1000000);
    if(log) {
        tp.set_logger(&logger);
        comm.set_logger(&logger);
    }

    DepsLogger dlog(1000000);

    // Send a potrf'ed pivot A(k,k) and trigger trsms below requiring A(k,k)
    auto am_trsm = comm.make_large_active_msg(
            [&](int& j) {
                int off = (nprows + rank_row - block_2_rank_row(j,j)) % nprows;
                assert(off > 0); // Can't be me
                assert(off < nprows);
                for (int i = j + off; i < num_blocks; i += nprows) {
                    assert(block_2_rank(i,j) == rank);
                    trsm.fulfill_promise({i,j});
                }
            },
            [&](int& j) {
                blocks[j+j*num_blocks]->resize(block_sizes[j],block_sizes[j]);
                return blocks[j+j*num_blocks]->data();
            },
            [&](int&){
                return;
            });

    /**
     * j is the pivot's position at A(j,j)
     */
    potrf.set_task([&](int j) { // A[j,j] -> A[j,j]
            assert(block_2_rank(j,j) == rank);
            timer t_ = wctime();
            LAPACKE_dpotrf(LAPACK_COL_MAJOR, 'L', block_sizes[j], blocks[j+j*num_blocks]->data(), block_sizes_lda[j]);
            timer t__ = wctime();
            potrf_us_t += 1e6 * elapsed(t_, t__);
        })
        .set_fulfill([&](int j) { // Triggers all trsms on rows i > j, A[i,j]
            assert(block_2_rank(j,j) == rank);
            if(deps_log) {
                for(int i = j+1; i < num_blocks; i++) {
                    dlog.add_event(make_unique<DepsEvent>(potrf.name(j), trsm.name({i,j})));
                }
            }
            // Trigger myself
            for (int i = j + nprows; i < num_blocks; i += nprows) {
                assert(block_2_rank(i,j) == rank);
                trsm.fulfill_promise({i,j});
            }
            // Send to other procs in column
            auto Ljjv = view<double>(blocks[j+j*num_blocks]->data(), block_sizes[j]*block_sizes[j]);
            for(int p = 0; p < nprows; p++) {
                if(j+p >= num_blocks) break;
                int dest = block_2_rank(j+p,j);
                if(dest != rank) {
                    am_trsm->send_large(dest, Ljjv, j);
                }
            }

        })
        .set_indegree([&](int j) {
            assert(block_2_rank(j,j) == rank);
            if(accumulate_parallel) {
                return j == 0 ? 1 : j; // Need j accumulations into (j,j) to trigger the potf
            } else {
                return 1;
            }
        })
        .set_priority(potf_block_2_prio)
        .set_mapping([&](int j) {
            assert(block_2_rank(j,j) == rank);
            return block_2_thread(j, j);
        })
        .set_name([&](int j) { // This is just for debugging and profiling
            return potrf_name(j);
        });

    // Sends a panel (trsm'ed block A(i,j)) and trigger gemms requiring A(i,j)
    auto am_gemm = comm.make_large_active_msg(
        [&](int& i, int& j) {
            if(block_2_rank_row(i,j) == rank_row) {
                const int off_right = (npcols + rank_col - block_2_rank_col(i,j)) % npcols;
                assert(off_right > 0); // Can't be me
                assert(off_right < npcols);
                assert(i >= 0 && i < num_blocks);
                assert(j >= 0 && j < num_blocks);
                for (int k = j + off_right; k < i; k += npcols) {
                    assert(block_2_rank(i,k) == rank);
                    gemm.fulfill_promise({j,i,k});
                }
            }
            if(block_2_rank_col(i,i) == rank_col) {
                const int off_below = (nprows + rank_row - block_2_rank_row(i,i)) % nprows;
                assert(off_below >= 0); // Could be me
                assert(off_below < nprows);
                for (int k = i + off_below; k < num_blocks; k += nprows) {
                    assert(block_2_rank(k,i) == rank);
                    gemm.fulfill_promise({j,k,i});
                }
            }
        },
        [&](int& i, int& j) {
            blocks[i+j*num_blocks]->resize(block_sizes[i],block_sizes[j]);
            return blocks[i+j*num_blocks]->data();
        },
        [&](int& i, int& j) {
            return;
        });

    /**
     * ij is (Row, Col) of the block in the matrix at A(i,j)
     **/
    trsm.set_task([&](int2 ij) { // A[j,j] & A[i,j] -> A[i,j]
            int i=ij[0];
            int j=ij[1];
            assert(block_2_rank(i,j) == rank);
            assert(i > j);
            timer t_ = wctime();
            cblas_dtrsm(CblasColMajor, CblasRight, CblasLower, CblasTrans, CblasNonUnit,
                block_sizes[i], block_sizes[j], 1.0, blocks[j+j*num_blocks]->data(), block_sizes_lda[j], blocks[i+j*num_blocks]->data(), block_sizes_lda[i]);
            timer t__ = wctime();
            trsm_us_t += 1e6 * elapsed(t_, t__);
        })
        .set_fulfill([&](int2 ij) {
            int i=ij[0];
            int j=ij[1];
            assert(block_2_rank(i,j) == rank);
            assert(i > j);
            if(deps_log) {
                for(int k = j+1; k < num_blocks; k++) {
                    dlog.add_event(make_unique<DepsEvent>(trsm.name(ij), gemm.name({j,std::max(i,k),std::min(i,k)})));
                }
            }
            // Local
            // Careful to not count the pivot (syrk) twice
            for (int k = j + npcols; k < i; k += npcols) {
                assert(block_2_rank(i,k) == rank);
                gemm.fulfill_promise({j,i,k});
            }
            if(block_2_rank_col(i,i) == rank_col) {
                int off_below = (nprows + rank_row - block_2_rank_row(i,i)) % nprows;
                for (int k = i + off_below; k < num_blocks; k += nprows) {
                    assert(block_2_rank(k,i) == rank);
                    gemm.fulfill_promise({j,k,i});
                }
            }
            // Remote
            auto Lijv = view<double>(blocks[i+j*num_blocks]->data(), block_sizes[i]*block_sizes[j]);
            std::set<int> dests;
            for (int c = 0; c < npcols; c++) {
                if(j+c >= num_blocks) break;
                int dest = block_2_rank(i,j+c);
                if(dest != rank) dests.insert(dest);
            }
            for (int r = 0; r < nprows; r++) {
                if(i+r >= num_blocks) break;
                int dest = block_2_rank(i+r,i);
                if(dest != rank) dests.insert(dest);
            }
            for(auto& dest: dests) {
                am_gemm->send_large(dest, Lijv, i, j);
            }
        })
        .set_indegree([&](int2 ij) {
            assert(block_2_rank(ij[0],ij[1]) == rank);
            if(accumulate_parallel) {
                return 1 + ij[1]; // Potrf above and all gemms before
            } else {
                return 1 + (ij[1] == 0 ? 0 : 1); // Potrf and last gemm before
            }
        })
        .set_priority(trsm_block_2_prio)
        .set_mapping([&](int2 ij) {
            assert(block_2_rank(ij[0],ij[1]) == rank);
            return block_2_thread(ij[0], ij[1]);
        })
        .set_name([&](int2 ij) { // This is just for debugging and profiling
            return trsm_name(ij);
        });

    /**
     * k is the step (the pivot's position), ij are Row and Column, at A(i,j)
     **/
    gemm.set_task([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            const int k=kij[0];
            const int i=kij[1];
            const int j=kij[2];
            assert(j <= i);
            assert(k < j);
            std::unique_ptr<MatrixXd> Atmp;
            MatrixXd* Aij;
            double beta = 1.0;
            if(accumulate_parallel) {
                beta = 0.0;
                Atmp = make_unique<MatrixXd>(block_sizes[i], block_sizes[j]); // The matrix is allocated with garbage. The 0 in the BLAS call make sure its overwritten by 0's before doing any math
                Aij = Atmp.get();
            } else {
                beta = 1.0;
                Aij = blocks[i+j*num_blocks].get();
            }
            assert(Aij->rows() == block_sizes[i] && Aij->cols() == block_sizes[j]);
            timer t_ = wctime();
            if (i == j) {
                cblas_dsyrk(CblasColMajor, CblasLower, CblasNoTrans,
                    block_sizes[i], block_sizes[k], -1.0, blocks[i+k*num_blocks]->data(), block_sizes_lda[i], beta, Aij->data(), block_sizes_lda[i]);
            } else {
                cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,
                    block_sizes[i], block_sizes[j], block_sizes[k], -1.0, blocks[i+k*num_blocks]->data(), block_sizes_lda[i], blocks[j+k*num_blocks]->data(), block_sizes_lda[j], beta, Aij->data(), block_sizes_lda[i]);
            }
            timer t__ = wctime();
            gemm_us_t += 1e6 * elapsed(t_, t__);
            if(accumulate_parallel) {
                lock_guard<mutex> lock(gemm_results[i+j*num_blocks].mtx);
                gemm_results[i+j*num_blocks].to_accumulate[k] = move(Atmp);
            }
        })
        .set_fulfill([&](int3 kij) {
            const int k=kij[0];
            const int i=kij[1];
            const int j=kij[2];
            assert(block_2_rank(kij[1],kij[2]) == rank);
            if(accumulate_parallel) {
                if(deps_log) {
                    dlog.add_event(make_unique<DepsEvent>(gemm.name(kij), accu.name(kij)));
                }
                accu.fulfill_promise(kij);
            } else {
                if (k < j-1) {
                    if(deps_log) {
                        dlog.add_event(make_unique<DepsEvent>(gemm.name(kij), gemm.name({k+1, i, j})));
                    }
                    gemm.fulfill_promise({k+1, i, j});
                } else {
                    if (i == j) {
                        if(deps_log) {
                            dlog.add_event(make_unique<DepsEvent>(gemm.name(kij), potrf.name(i)));
                        }
                        potrf.fulfill_promise(i);
                    } else {
                        if(deps_log) {
                            dlog.add_event(make_unique<DepsEvent>(gemm.name(kij), trsm.name({i,j})));
                        }
                        trsm.fulfill_promise({i,j});
                    }
                }
            }
        })
        .set_indegree([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            if(accumulate_parallel) {
                return kij[1] == kij[2] ? 1 : 2; // Either one potf or two trsms
            } else {
                return (kij[1] == kij[2] ? 1 : 2) + (kij[0] == 0 ? 0 : 1); // one potrf or two trsms + the gemm before
            }
        })
        .set_priority(gemm_block_2_prio)
        .set_mapping([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            return block_2_thread(kij[1], kij[2]); // IMPORTANT if accumulate_parallel is true
        })
        .set_binding([&](int3 kij) {
            return false; // If we accumulate in parallel, there is no order for the gemm so it doesnt matter ; If we don't then we do the gemm in sequence anyway
        }).set_name([&](int3 kij) { // This is just for debugging and profiling
            return gemm_name(kij);
        });

    /**
     * k is the step (the pivot's position), ij are Row and Column, at A(i,j)
     **/
    accu.set_task([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            int k=kij[0]; // Step (gemm's pivot)
            int i=kij[1]; // Row
            int j=kij[2]; // Col
            assert(j <= i);
            assert(k < j);
            std::unique_ptr<Eigen::MatrixXd> Atmp;
            {
                lock_guard<mutex> lock(gemm_results[i+j*num_blocks].mtx);
                Atmp = move(gemm_results[i+j*num_blocks].to_accumulate[k]);
                gemm_results[i+j*num_blocks].to_accumulate.erase(k);
            }
            timer t_ = wctime();
            *blocks[i+j*num_blocks] += (*Atmp);
            timer t__ = wctime();
            accu_us_t += 1e6 * elapsed(t_, t__);
        })
        .set_fulfill([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            int k=kij[0];
            int i=kij[1];
            int j=kij[2];
            assert(j <= i);
            assert(k < j);
            if(i == j) {
                if(deps_log) {
                    dlog.add_event(make_unique<DepsEvent>(accu.name(kij), potrf.name(i)));
                }
                potrf.fulfill_promise(i);
            } else {
                if(deps_log) {
                    dlog.add_event(make_unique<DepsEvent>(accu.name(kij), trsm.name({i,j})));
                }
                trsm.fulfill_promise({i,j});
            }
        })
        .set_indegree([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            return 1;
        })
        .set_mapping([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            return block_2_thread(kij[1], kij[2]); // IMPORTANT. Every (i,j) should map to a given fixed thread
        })
        .set_priority(gemm_block_2_prio)
        .set_binding([&](int3 kij) {
            assert(block_2_rank(kij[1],kij[2]) == rank);
            return true; // IMPORTANT
        })
        .set_name([&](int3 kij) { // This is just for debugging and profiling
            return accu_name(kij);
        });

    printf("Starting Cholesky factorization...\n");
    MPI_Barrier(MPI_COMM_WORLD);
    timer t0 = wctime();
    if (rank == 0){
        potrf.fulfill_promise(0);
    }
    tp.join();
    MPI_Barrier(MPI_COMM_WORLD);
    timer t1 = wctime();
    double total_time = elapsed(t0, t1);
    printf("Done with Cholesky factorization...\n");
    printf("Elapsed time: %e\n", total_time);
    printf("Potrf time: %e\n", potrf_us_t.load() * 1e-6);
    printf("Trsm time: %e\n", trsm_us_t.load() * 1e-6);
    printf("Gemm time: %e\n", gemm_us_t.load() * 1e-6);
    printf("Accu time: %e\n", accu_us_t.load() * 1e-6);

    printf("++++rank nranks n_threads matrix_size block_size num_blocks priority_kind accumulate upper_block_size total_time\n");
    printf("[%d]>>>>%d %d %d %d %d %d %d %d %d %e\n",rank,rank,n_ranks,n_threads,matrix_size,block_size,num_blocks,(int)prio_kind,(int)accumulate_parallel,upper_block_size,total_time);

    if(log) {
        std::ofstream logfile;
        string filename = "ttor_dist_"+to_string(block_size)+"_"+to_string(num_blocks)+"_"+ to_string(n_ranks)+"_"+to_string(n_threads)+"_"+to_string(prio_kind)+".log."+to_string(rank);
        logfile.open(filename);
        logfile << logger;
        logfile.close();
    }

    if(deps_log) {
        std::ofstream depsfile;
        string depsfilename = "deps_ttor_dist_"+to_string(block_size)+"_"+to_string(num_blocks)+"_"+ to_string(n_ranks)+"_"+to_string(n_threads)+"_"+to_string(prio_kind)+".dot."+to_string(rank);
        depsfile.open(depsfilename);
        depsfile << dlog;
        depsfile.close();
    }

    if(test) {
        printf("Starting sending matrix to rank 0...\n");
        MatrixXd A = MatrixXd::NullaryExpr(matrix_size,matrix_size,val);
        MatrixXd L = MatrixXd::Zero(matrix_size,matrix_size);
        // Send the matrix to rank 0
        for (int ii=0; ii<num_blocks; ii++) {
            for (int jj=0; jj<num_blocks; jj++) {
                if (jj<=ii)  {
                    int owner = block_2_rank(ii,jj);
                    MPI_Status status;
                    if (rank == 0 && rank != owner) { // Careful with deadlocks here
                        blocks[ii+jj*num_blocks] = make_unique<Eigen::MatrixXd>(block_sizes[ii], block_sizes[jj]);
                        MPI_Recv(blocks[ii+jj*num_blocks]->data(), block_sizes[ii]*block_sizes[jj], MPI_DOUBLE, owner, 0, MPI_COMM_WORLD, &status);
                    } else if (rank != 0 && rank == owner) {
                        MPI_Send(blocks[ii+jj*num_blocks]->data(), block_sizes[ii]*block_sizes[jj], MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
                    }
                }
            }
        }

        // Rank 0 test
        if(rank == 0) {
            printf("Starting test on rank 0...\n");
            for (int ii=0; ii<num_blocks; ii++) {
                for (int jj=0; jj<num_blocks; jj++) {
                    if (jj<=ii) {
                        L.block(block_displ[ii],block_displ[jj],block_sizes[ii],block_sizes[jj])=*blocks[ii+jj*num_blocks];
                    }
                }
            }
            auto L1=L.triangularView<Lower>();
            VectorXd x = VectorXd::Random(matrix_size);
            VectorXd b = A*x;
            VectorXd bref = b;
            L1.solveInPlace(b);
            L1.transpose().solveInPlace(b);
            double error = (b - x).norm() / x.norm();
            printf("\n=> Error solve %e\n\n", error);
            if(error > 1e-6) {
                printf("\n\nERROR: error is too large!\n\n");
                exit(1);
            }
        }
    }
}

int main(int argc, const char **argv)
{
    int req = MPI_THREAD_FUNNELED;
    int prov = -1;

    MPI_Init_thread(NULL, NULL, req, &prov);

    assert(prov == req);

    std::stringstream sstr;
    sstr << comm_size();
    const std::string comm_size_str = sstr.str();

    cxxopts::Options options("2d_cholesky", "2D dense cholesky using TaskTorrent");
    options.add_options()
        ("help", "Print help")
        ("n_threads", "Number of threads", cxxopts::value<int>()->default_value("2"))
        ("verb", "Verbosity level", cxxopts::value<int>()->default_value("0"))
        ("block_size", "Block size", cxxopts::value<int>()->default_value("5"))
        ("num_blocks", "Number of blocks", cxxopts::value<int>()->default_value("10"))
        ("nprows", "Number of processors accross rows", cxxopts::value<int>()->default_value("1"))
        ("npcols", "Number of processors accross columns", cxxopts::value<int>()->default_value(comm_size_str.c_str()))
        ("kind", "Priority kind", cxxopts::value<int>()->default_value("0"))
        ("log", "Enable logging", cxxopts::value<bool>()->default_value("false"))
        ("depslog", "Enable dependency logging", cxxopts::value<bool>()->default_value("false"))
        ("test", "Test or not", cxxopts::value<bool>()->default_value("true"))
        ("accumulate", "Accumulate block GEMMs in parallel", cxxopts::value<bool>()->default_value("false"))
        ("upper_block_size", "Upper block size", cxxopts::value<int>()->default_value("-1"));
    auto result = options.parse(argc, argv);

    const int n_threads = result["n_threads"].as<int>();
    const int verb = result["verb"].as<int>();
    const int block_size = result["block_size"].as<int>();
    const int num_blocks = result["num_blocks"].as<int>();
    const int nprows = result["nprows"].as<int>();
    const int npcols = result["npcols"].as<int>();
    const PrioKind kind = (PrioKind) result["kind"].as<int>();
    const bool log = result["log"].as<bool>();
    const bool depslog = result["depslog"].as<bool>();
    const bool test = result["test"].as<bool>();
    const bool accumulate = result["accumulate"].as<bool>();
    const int upper_block_size = (result["upper_block_size"].as<int>() == -1 ? block_size : result["upper_block_size"].as<int>());

    assert(block_size > 0);
    assert(num_blocks > 0);
    assert(n_threads > 0);
    assert(verb >= 0);
    assert(nprows >= 0);
    assert(npcols >= 0);
    assert(upper_block_size >= block_size && upper_block_size <= 2 * block_size);

    if (result.count("help")) {
        std::cout << options.help({"", "Group"}) << endl;
        exit(0);
    }
    if(comm_rank() == 0) printf("Arguments: block_size (size of blocks) %d\nnum_blocks (# of blocks) %d\nn_threads %d\nverb %d\nnprows %d\nnpcols %d\nkind %d\nlog %d\ndeplog %d\ntest %d\naccumulate %d\nupper_block_size %d\n", block_size, num_blocks, n_threads, verb, nprows, npcols, (int)kind, log, depslog, test, accumulate, upper_block_size);

    cholesky(n_threads, verb, block_size, num_blocks, nprows, npcols, kind, log, depslog, test, accumulate, upper_block_size);

    MPI_Finalize();
}

ext: cpp

max_stars_repo_name: Abeynaya/tasktorrent

max_issues_repo_name: Abeynaya/tasktorrent

max_forks_repo_name: Abeynaya/tasktorrent


text:
#include <sbmodelstl.h>

#include <boost/cstdint.hpp>
using namespace boost;

namespace Scenebuilder{;

///////////////////////////////////////////////////////////////////////////////////////////////////

LoaderSTL::LoaderSTL(bool _useColor, bool _binary){
	useColor  = _useColor;
	binary    = _binary;
	facetOpen = false;
	vertexIdx = 0;
	Clear();
}

void LoaderSTL::Clear(){
	facets.clear();
}

void LoaderSTL::ParseBinary(){
	byte* ptr = (byte*)&contents[0];
	ptr += 80;

	int numTri = *(int*)ptr;
	ptr += sizeof(int);

	int szTri = 4 * (sizeof(float) * 3) + sizeof(uint16_t);
	Assert(80 + sizeof(int) + szTri * numTri <= contents.size());

	facets.resize(numTri);
	for(int i = 0; i < numTri; i++){
		Facet& f = facets[i];
		f.normal      = *(Vec3f   *)ptr; ptr += sizeof(Vec3f   );
		f.vertices[0] = *(Vec3f   *)ptr; ptr += sizeof(Vec3f   );
		f.vertices[1] = *(Vec3f   *)ptr; ptr += sizeof(Vec3f   );
		f.vertices[2] = *(Vec3f   *)ptr; ptr += sizeof(Vec3f   );
		f.attr        = *(uint16_t*)ptr; ptr += sizeof(uint16_t);
		if(useColor){
			float r = (float)((f.attr >>  0) & 0x1f) / 31.0f;
			float g = (float)((f.attr >>  5) & 0x1f) / 31.0f;
			float b = (float)((f.attr >> 10) & 0x1f) / 31.0f;
			f.color = Vec4f(r, g, b, 1.0f);
		}
	}
}

void LoaderSTL::Assert(bool eval){
	if(!eval)
		throw SyntaxError();
}

void LoaderSTL::Parse(){
	if(rowTok.IsEnd())
		return;
	colTok.Set(rowTok.GetToken(), " \t", true);

	Clear();
	string_iterator_pair str;

	// テキストSTLは一行目が"solid name". ただしnameはオプショナル
	// solidで始まらない場合はバイナリとして読む
	/*
	str = colTok.GetToken();
	if(str != "solid"){
		ParseBinary();
		return;
	}
	*/
	// バイナリSTLでも80byteヘッダが"solid"で始まる場合があるので
	// テキストかバイナリかは手動で指定する
	if(binary){
		ParseBinary();
		return;
	}

	colTok.Next();
	if(!colTok.IsEnd()){
		str = colTok.GetToken();
		name.assign(str.begin(), str.end());
	}

	rowTok.Next();

	while(!rowTok.IsEnd()){
		colTok.Set(rowTok.GetToken(), " \t", true);

		// 行頭の空トークンを読み飛ばす
		str = colTok.GetToken();
		while(str.empty() && !colTok.IsEnd()){
			colTok.Next();
			str = colTok.GetToken();
		}

		if(str == "facet"){
			Assert(!facetOpen);
			colTok.Next();
			Assert(colTok.GetToken() == "normal");

			facets.push_back(LoaderSTL::Facet());
			LoaderSTL::Facet& f = facets.back();
			f.attr  = 0;
			f.color = Vec4f(1.0f, 1.0f, 1.0f, 1.0f);
			for(int i = 0; i < 3; i++){
				colTok.Next();
				f.normal[i] = (float)to_real(colTok.GetToken());
			}
			facetOpen = true;
		}
		else if(str == "outer"){
			Assert(facetOpen && vertexIdx == 0);
			colTok.Next();
			Assert(colTok.GetToken() == "loop");
			vertexIdx = 0;
		}
		else if(str == "vertex"){
			Assert(facetOpen);
			Assert(0 <= vertexIdx && vertexIdx < 3);
			LoaderSTL::Facet& f = facets.back();
			for(int i = 0; i < 3; i++){
				colTok.Next();
				f.vertices[vertexIdx][i] = (float)to_real(colTok.GetToken());
			}
			vertexIdx++;
		}
		else if(str == "endloop"){
			Assert(vertexIdx == 3);
			vertexIdx = 0;
		}
		else if(str == "endfacet"){
			Assert(facetOpen);
			facetOpen = false;
		}
		else if(str == "endsolid"){

		}

		rowTok.Next();
	}
}

void LoaderSTL::Load(const string& filename){
	ifstream ifs;
	// 改行コードの変換を避けるためbinary指定
	ifs.open(filename.c_str(), ios_base::in | ios_base::binary);

	if(!ifs.is_open())
		throw FileError();

	ifs.seekg(0, ifs.end);
	int len = (int)ifs.tellg();
	ifs.seekg(0, ifs.beg);

	contents.resize(len);
	ifs.read(&contents[0], len);

	ifs.close();

	// tokenize
	rowTok.Set(contents, "\n", true);

	Parse();
	contents.clear();
}

void LoaderSTL::Save(const string& filename){

}

void LoaderSTL::Convert(Model* model, const Affinef& aff){
	// facetのcolorからマテリアルを作成
	vector<uint16_t> attrs;
	vector<Vec4f>    colors;
	uint nmat = 1;

	if(useColor){
		for(uint i = 0; i < facets.size(); i++){
			Facet& f = facets[i];
			if(find(attrs.begin(), attrs.end(), f.attr) == attrs.end()){
				attrs .push_back(f.attr );
				colors.push_back(f.color);
			}
		}

		nmat = (uint)attrs.size();
		model->materials   .resize(nmat);
		model->materialList.resize(nmat);
		for(uint i = 0; i < nmat; i++){
			model->materials[i].diffuse = colors[i];
			model->materialList[i] = i;
		}
	}

	model->meshSolid .resize(nmat);
	model->meshWire  .resize(nmat);
	model->meshPoints.resize(nmat);
	for(uint i = 0; i < nmat; i++){
		model->meshSolid [i].type = Mesh::Type::Solid;
		model->meshWire  [i].type = Mesh::Type::Wireframe;
		model->meshPoints[i].type = Mesh::Type::Points;
		model->meshSolid [i].aff  = aff;
		model->meshWire  [i].aff  = aff;
		model->meshPoints[i].aff  = aff;
	}

	for(uint i = 0; i < nmat; i++){
		Mesh* m[3] = {
			&model->meshSolid [i],
			&model->meshWire  [i],
			&model->meshPoints[i]
		};
		for(int k = 0; k < 3; k++){
			m[k]->Begin(Mesh::Triangles);
			for(uint j = 0; j < facets.size(); j++){
				Facet& f = facets[j];
				if(useColor && f.attr != attrs[i])
					continue;
				m[k]->Normal(f.normal     );
				m[k]->Vertex(f.vertices[0]);
				m[k]->Vertex(f.vertices[1]);
				m[k]->Vertex(f.vertices[2]);
				if(useColor)
					m[k]->Color(f.color);
			}
			m[k]->End();
		}
	}
}

}

max_stars_repo_name: ytazz/Scenebuilder

max_issues_repo_name: ytazz/Scenebuilder

max_forks_repo_name: ytazz/Scenebuilder


text:
/*
Copyright (c) 2021, Sergei Ilinykh <rion4ik@gmail.com>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "restio_api_mapper.hpp"

#include <boost/lexical_cast.hpp>

namespace restio::api {

void API::buildParser()
{
    for (auto const &m : methods) {
        std::vector<std::string> strs;
        boost::split(strs, m.uri, boost::is_any_of("/"));
        if (strs.back() == "")
            strs.pop_back();
        auto currentNode = roots.end();
        for (auto const &s : strs) { // path parts
            assert(s.size() > 0);
            ParsedNode newNode;
            if (s.starts_with('<')) {
                assert(s.size() > 2);
                std::vector<std::string> typeName;
                boost::split(typeName, s.substr(1, s.size() - 2), boost::is_any_of(":"));
                assert(typeName.size() == 2 && typeName[0].size() > 0 && typeName[1].size() > 0);
                newNode.id = typeName[1];
                if (typeName[0] == "string")
                    newNode.type = ParsedNode::Type::VarString;
                else if (typeName[0] == "int")
                    newNode.type = ParsedNode::Type::Integer;
                else
                    assert(false); // unreachable
            } else {
                newNode.type = ParsedNode::Type::ConstString;
                newNode.id   = s;
            }
            auto &nodes = currentNode == roots.end() ? roots : currentNode->children;
            auto  it    = std::find(nodes.begin(), nodes.end(), newNode);
            if (it == nodes.end()) {
                nodes.push_back(std::move(newNode));
                currentNode = nodes.end() - 1;
            } else {
                currentNode = it;
            }
        }
        currentNode->methods.push_back(std::cref(m));
    }
}

static std::optional<API::LookupResult>
lookup_helper(http::verb method, std::span<std::string> target, const std::vector<API::ParsedNode> &nodes)
{
    auto const &view         = target[0];
    bool        numeric      = std::isdigit(view[0]);
    int         numericValue = 0;
    if (numeric) {
        try {
            numericValue = boost::lexical_cast<int>(view);
        } catch (boost::bad_lexical_cast &) {
            numeric = false;
        }
    }
    using Type     = API::ParsedNode::Type;
    auto nodeMatch = [numeric, &view](auto const &node) {
        return (node.type == Type::VarString || (numeric && node.type == Type::Integer)
                || (node.type == Type::ConstString && node.id == view));
    };
    std::optional<API::LookupResult> result;
    for (auto const &node : nodes) {
        if ((target.size() > 1 && node.children.empty()) || !nodeMatch(node))
            continue;
        if (target.size() > 1)
            result = lookup_helper(method, target.subspan(1), node.children);
        else {
            for (auto const &node : nodes) {
                if (!nodeMatch(node))
                    continue;
                auto it = std::find_if(node.methods.begin(), node.methods.end(), [method](auto const &m) {
                    return m.get().method == method;
                });
                if (it != node.methods.end())
                    result = API::LookupResult { {}, *it };
            }
        }
        if (result) {
            if (node.type == Type::Integer)
                result->properties[node.id] = numericValue;
            else if (node.type == Type::VarString)
                result->properties[node.id] = std::string(view);
            return result;
        }
    }
    return std::nullopt;
}

std::optional<API::LookupResult> API::lookup(http::verb method, std::string_view target) const
{
    std::vector<std::string> strs;
    auto                     pos = target.find_first_not_of('/');
    if (pos == std::string_view::npos)
        return std::nullopt;
    target = target.substr(pos);
    boost::split(strs, target, boost::is_any_of("/"), boost::token_compress_on);
    if (strs.back().empty())
        strs.pop_back();
    if (strs.empty())
        return std::nullopt;
    return lookup_helper(method, std::span { strs }, roots);
}

} // namespace restio::api


text:
/*
 * utilities_cumtrapz_test.cpp Test fixtures for the cumtrapz function
 *
 * Author:                   Tom Clark (thclark @ github)
 *
 * Copyright (c) 2016-9 Octue Ltd. All Rights Reserved.
 *
 */

#include "gtest/gtest.h"
#include <Eigen/Dense>

#include "utilities/interp.h"

using namespace utilities;

class InterpTest : public ::testing::Test {};

TEST_F(InterpTest, test_linear_interp_double) {

    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);

    x << 0, 1, 2, 3, 4;
    y << 0, 2, 4, 6, 8;
    double xi = 1.5;

    utilities::LinearInterpolant s(x, y);
    double yi = s(xi);

    ASSERT_NEAR(yi, 3.0, 0.00001);

}

TEST_F(InterpTest, test_linear_interp_at_nodes) {

    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);
    x << 0, 1, 2, 3, 4;
    y << 0, 2, 4, 6, 8;
    utilities::LinearInterpolant s(x, y);

    // First node (endpoint)
    double xi = 0.0;
    double yi = s(xi);
    ASSERT_NEAR(yi, 0.0, 0.00001);

    // Any inter node
    xi = 3.0;
    yi = s(xi);
    ASSERT_NEAR(yi, 6.0, 0.00001);

    // Last node (endpoint)
    xi = 4.0;
    yi = s(xi);
    ASSERT_NEAR(yi, 8.0, 0.00001);

}

TEST_F(InterpTest, test_linear_interp_beyond_endpoints) {

    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);
    x << 0, 1, 2, 3, 4;
    y << 0, 2, 4, 6, 8;
    utilities::LinearInterpolant s(x, y);

    double xi = -1.0;
    double yi = s(xi);
    ASSERT_NEAR(yi, 0.0, 0.00001);

    xi = 5.0;
    yi = s(xi);
    ASSERT_NEAR(yi, 8.0, 0.00001);

}

TEST_F(InterpTest, test_linear_interp_vector) {

    Eigen::ArrayXd x(5);
    Eigen::ArrayXd xi(2);
    Eigen::ArrayXd y(5);
    Eigen::ArrayXd yi(2);
    Eigen::ArrayXd yi_correct(2);

    x << 0, 1, 2, 3, 4;
    y << 0, 2, 4, 6, 8;
    xi << 0.5, 1.5;
    yi_correct << 1.0, 3.0;

    utilities::LinearInterpolant s(x, y);
    yi = s(xi);

    ASSERT_TRUE(yi.isApprox(yi_correct));

}

TEST_F(InterpTest, test_cubic_interp_double) {

    Eigen::VectorXd x(5);
    Eigen::VectorXd y(5);

    x << 0, 1, 2, 3, 4;
    y << 0, 1, 4, 9, 16;
    double xi = 1.5;

    utilities::CubicSplineInterpolant s(x, y);
    double yi = s(xi);

    ASSERT_NEAR(yi, 2.25, 0.00001);

}

TEST_F(InterpTest, test_cubic_interp_vector) {

    Eigen::VectorXd x(5);
    Eigen::VectorXd xi(2);
    Eigen::VectorXd y(5);
    Eigen::VectorXd yi(2);
    Eigen::VectorXd yi_correct(2);

    x << 0, 1, 2, 3, 4;
    y << 0, 1, 4, 9, 16;
    xi << 0.5, 1.5;
    yi_correct << 0.25, 2.25;

    utilities::CubicSplineInterpolant s(x, y);
    yi = s(xi);

    ASSERT_TRUE(yi.isApprox(yi_correct));

}

max_stars_repo_name: octue/es-flow

max_stars_repo_licenses: Intel MIT

max_issues_repo_name: octue/es-flow

max_issues_repo_licenses: Intel MIT

max_forks_repo_name: octue/es-flow

max_forks_repo_licenses: Intel MIT


text:
#ifndef string_hpp_
#define string_hpp_

#include <boost/xml/dom.hpp>
#ifdef USE_STD_STRING
# include <boost/xml/unicode/std_string.hpp>
typedef std::string S;
#elif USE_QSTRING
# include <boost/xml/unicode/qstring.hpp>
typedef QString S;
#elif USE_GSTRING
# include <boost/xml/unicode/gstring.hpp>
typedef Glib::ustring S;
#else
# error "no string type defined"
#endif

typedef boost::xml::dom::node_ptr<boost::xml::dom::node<S> > node_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::node<S> const> const_node_ptr;
typedef boost::xml::dom::element<S> element;
typedef boost::xml::dom::node_ptr<element> element_ptr;
typedef boost::xml::dom::node_ptr<element const> const_element_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::attribute<S> > attribute_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::attribute<S> const> const_attribute_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::text<S> > text_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::text<S> const> const_text_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::pi<S> > pi_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::pi<S> const> const_pi_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::comment<S> > comment_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::comment<S> const> const_comment_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::cdata<S> > cdata_ptr;
typedef boost::xml::dom::node_ptr<boost::xml::dom::cdata<S> const> const_cdata_ptr;
typedef std::auto_ptr<boost::xml::dom::document<S> > document_ptr;
typedef boost::xml::dom::dtd_ptr<S> dtd_ptr;
typedef boost::xml::dom::node_set<S> node_set;
typedef boost::xml::dom::xpath<S> xpath;

#endif


text:
#include "messages.hpp"

#include <base/assert.hpp>

#include <boost/process.hpp>

#include <set>

namespace bp = ::boost::process;

namespace
{
std::tuple<std::string, std::string> parseInfoLine(const std::string& path)
{
    constexpr std::size_t DELIM_SIZE = 8;
    auto shrinked = path.substr(DELIM_SIZE, path.size() - DELIM_SIZE * 2);
    auto delimiter_pos = shrinked.find(':');
    auto source_file = shrinked.substr(0, delimiter_pos);
    auto contract_name = shrinked.substr(delimiter_pos + 1, shrinked.size());
    return std::make_tuple(source_file, contract_name);
}

std::pair<base::Bytes, std::string> parseContractMembers(const std::string& contract_members)
{

    if (auto space_pos = contract_members.find(' '); space_pos != contract_members.npos) {
        auto hash = base::fromHex<base::Bytes>(contract_members.substr(0, space_pos - 1));
        auto signature = contract_members.substr(space_pos + 1, contract_members.size() - space_pos - 1);
        return { hash, signature };
    }
    else {
        RAISE_ERROR(base::InvalidArgument, "Invalid string for contract members parsing");
    }
}
} // namespace

namespace vm
{

void CompiledContract::setName(const std::string& name)
{
    _name = name;
}

const std::string& CompiledContract::getName() const
{
    return _name;
}

void CompiledContract::setRuntimeCode(const base::Bytes& code)
{
    _runtime_code = code;
}

const base::Bytes& CompiledContract::getRuntimeCode() const
{
    return _runtime_code;
}

void CompiledContract::setFullCode(const base::Bytes& code)
{
    _full_code = code;
}

const base::Bytes& CompiledContract::getFullCode() const
{
    return _full_code;
}

void CompiledContract::setAbiSpecification(const base::PropertyTree& abi_specification)
{
    _abi_specification = abi_specification;
}

const base::PropertyTree& CompiledContract::getAbiSpecification() const
{
    return _abi_specification;
}

void CompiledContract::setMetadata(const base::PropertyTree& metadata)
{
    _metadata = metadata;
}

const base::PropertyTree& CompiledContract::getMetadata() const
{
    return _metadata;
}

void CompiledContract::setSignatures(const std::vector<std::pair<base::Bytes, std::string>>& signatures)
{
    _signatures = signatures;
}

const std::vector<std::pair<base::Bytes, std::string>>& CompiledContract::getSignatures() const
{
    return _signatures;
}

Solc::Solc()
  : _path_to_solc{ bp::search_path(_SOLC_NAME) }
{
    if (!boost::filesystem::exists(_path_to_solc)) {
        RAISE_ERROR(base::InaccessibleFile, "Solidity compiler was not found");
    }
}

std::optional<Contracts> Solc::compile(const std::string& path_to_solidity_code) const
{
    auto full_compilation_output = call_full_compilation_command(path_to_solidity_code);
    auto metadata_output = call_metadata_command(path_to_solidity_code);

    Contracts contracts{};
    for (const auto& contract_name_full_code_pair : full_compilation_output) {
        CompiledContract contract;
        contract.setName(contract_name_full_code_pair.first);
        contract.setFullCode(contract_name_full_code_pair.second);

        for (const auto& contract_name_metadata_pair : metadata_output) {
            if (contract_name_metadata_pair.first == contract.getName()) {
                contract.setMetadata(contract_name_metadata_pair.second);
            }
        }

        contracts.push_back(std::move(contract));
    }

    return contracts;
}

std::vector<std::string> Solc::call_command(std::vector<std::string> args) const
{
    bp::ipstream out;
    bp::child c(_path_to_solc, args, bp::std_out > out);
    c.wait();

    std::vector<std::string> out_put_result_values;
    std::string out_result;
    while (std::getline(out, out_result)) {
        out_put_result_values.push_back(out_result);
    }

    if (c.exit_code()) {
        std::ostringstream s;
        for (const auto& item : out_put_result_values) {
            s << item;
        }
        RAISE_ERROR(base::SystemCallFailed, s.str());
    }

    return out_put_result_values;
}

std::vector<std::pair<std::string, base::Bytes>> Solc::call_full_compilation_command(
  const std::string& path_to_solidity_code) const
{
    std::vector<std::string> args{ "--bin", path_to_solidity_code };
    auto res = call_command(args);

    std::vector<std::pair<std::string, base::Bytes>> contracts_byte_codes;
    constexpr const size_t GROUP_SIZE = 4;
    for (std::size_t i = 0; i < res.size() / GROUP_SIZE; i++) {
        auto current_contract_index = i * GROUP_SIZE;

        auto info_line = res[current_contract_index + 1];
        auto bytecode = base::fromHex<base::Bytes>(res[current_contract_index + 3]);

        auto info = parseInfoLine(info_line);

        contracts_byte_codes.push_back({ std::get<1>(info), std::move(bytecode) });
    }

    return contracts_byte_codes;
}

std::vector<std::pair<std::string, base::PropertyTree>> Solc::call_metadata_command(
  const std::string& path_to_solidity_code) const
{
    std::vector<std::string> args{ "--metadata", path_to_solidity_code };

    auto res = call_command(args);

    std::vector<std::pair<std::string, base::PropertyTree>> contracts_metadatas;
    constexpr const size_t GROUP_SIZE = 4;
    for (std::size_t i = 0; i < res.size() / GROUP_SIZE; i++) {
        auto current_contract_index = i * GROUP_SIZE;

        auto info_line = res[current_contract_index + 1];
        auto metadata = base::parseJson(res[current_contract_index + 3]);

        auto info = parseInfoLine(info_line);

        contracts_metadatas.push_back({ std::get<1>(info), std::move(metadata) });
    }

    return contracts_metadatas;
}

} // namespace vm

max_stars_repo_name: heshu-by/likelib

max_issues_repo_name: heshu-by/likelib

max_forks_repo_name: heshu-by/likelib


text:
#include "design.hpp"

#include <passes/transforms/synthesize_mem.hpp>
#include <passes/transforms/synthesize_forks.hpp>
#include <passes/transforms/pipeline.hpp>
#include <passes/print.hpp>
#include <passes/manager.hpp>
#include <passes/transforms/simplify.hpp>
#include <passes/transforms/refine.hpp>
#include <passes/analysis/checks.hpp>
#include <libraries/core/tags.hpp>

#include <backends/verilog/synthesize.hpp>
#include <backends/ipxact/ipxact.hpp>
#include <backends/graphviz/graphviz.hpp>

#include <wedges/verilator/verilator.hpp>
#include <wedges/axi/axi_wedge.hpp>

#include <boost/program_options.hpp>
#include <boost/program_options/errors.hpp>

using namespace boost::program_options;
using namespace std;

namespace llpm {

enum class WedgeEnum {
    Verilator,
    AXI
};
char const* WedgeEnumStrings [] = {
    "verilator",
    "axi"
};
ENUM_SER(WedgeEnum, WedgeEnumStrings);

enum class WrapperEnum {
    None,
    AXI
};
char const* WrapperEnumStrings [] = {
    "none",
    "axi"
};
ENUM_SER(WrapperEnum, WrapperEnumStrings);

enum class BackendEnum {
    Verilog,
    IPXACT
};
char const* BackendEnumStrings [] = {
    "verilog",
    "ipxact"
};
ENUM_SER(BackendEnum, BackendEnumStrings);

void Design::buildOpts() {
    _optDesc.add_options()
        ("wedge", value<WedgeEnum>()->default_value(WedgeEnum::Verilator)
                                    ->required(),
            "Selects which wedge to use (e.g. verilator, axi)")
        ("wrapper", value<WrapperEnum>()->default_value(WrapperEnum::None)
                                    ->required(),
            "Selects a wrapper (e.g. none, axi)")
        ("backend", value<BackendEnum>()->default_value(BackendEnum::Verilog)
                                    ->required(),
            "Selects which backend to use (e.g. verilog, ipxact)")
        ("clk", value<float>()->default_value(-1.0)
                              ->required(),
            "Pipeline the design targeting this clock frequency, in MHz")
        ("control_regions", value<bool>()->default_value(true)
                                         ->required(),
            "Controls whether or not control regions are built")
    ;
    _workingDir.addOpts(_optDesc);
}

void Design::notify(variables_map& vm) {
    _workingDir.notify(vm);

    switch (vm["backend"].as<BackendEnum>()) {
    case BackendEnum::Verilog:
        backend(new VerilogSynthesizer(*this));
        break;
    case BackendEnum::IPXACT:
        backend(new IPXactBackend(*this));
        break;
    }

    bool axiWedge = false;
    switch (vm["wedge"].as<WedgeEnum>()) {
    case WedgeEnum::Verilator:
        wedge(new VerilatorWedge(*this));
        break;
    case WedgeEnum::AXI: {
        auto aw = new AXIWedge(*this);
        wedge(aw);
        wrapper(aw);
        axiWedge = true;
        break;
    }
    }

    switch (vm["wrapper"].as<WrapperEnum>()) {
    case WrapperEnum::None:
        break;
    case WrapperEnum::AXI:
        if (!axiWedge)
            wrapper(new AXIWedge(*this));
        break;
    }

    float clkFreq = vm["clk"].as<float>() * 1e6;

    elaborations()->append<SynthesizeMemoryPass>();
    elaborations()->append<SynthesizeTagsPass>();
    elaborations()->append<RefinePass>();

    // optimizations()->append<SimplifyPass>();
    // optimizations()->append<CanonicalizeInputs>();
    // optimizations()->append<SimplifyWaits>();
    // optimizations()->append<SimplifyPass>();

    if (vm["control_regions"].as<bool>()) {
        optimizations()->append<SimplifyPass>();
        optimizations()->append<FormControlRegionPass>();
    }
    optimizations()->append<SimplifyPass>();
    optimizations()->append<PipelineDependentsPass>();
    // optimizations()->append<GVPrinterPass>();

    optimizations()->append<LatchUntiedOutputs>(clkFreq > 0.0);
    optimizations()->append<SynthesizeForksPass>(clkFreq > 0.0);

    if (clkFreq > 0.0) {
        Time period = Time::s(1.0 / clkFreq);
        optimizations()->append<PipelineFrequencyPass>(period);
    }
    optimizations()->append<PipelineCyclesPass>();

    optimizations()->append<CheckConnectionsPass>();
    optimizations()->append<CheckOutputsPass>();
    optimizations()->append<CheckCyclesPass>();
    optimizations()->append<TextPrinterPass>();
    optimizations()->append<StatsPrinterPass>();
}

} // namespace llpm

max_stars_repo_name: llpm/llpm

max_issues_repo_name: llpm/llpm

max_forks_repo_name: llpm/llpm


text:
//-----------------------------------------------------------------------------
// boost variant/detail/has_result_type.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2015 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
#define BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP

#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>

namespace boost { namespace detail { namespace variant {

template <typename T >
struct has_result_type {
private:
    typedef char                      yes;
    typedef struct { char array[2]; } no;

    template<typename C> static yes test(typename boost::remove_reference<typename C::result_type>::type*);
    template<typename C> static no  test(...);

public:
    BOOST_STATIC_CONSTANT(bool, value = sizeof(test<T>(0)) == sizeof(yes));
};

}}} // namespace boost::detail::variant

#endif // BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP

max_stars_repo_name: cfsengineering/tigl

max_issues_repo_name: cfsengineering/tigl

max_forks_repo_name: cfsengineering/tigl


text:
/*
 * Common.hpp
 *
 *  Created on: Feb 9, 2014
 *      Author: Bloeschm
 */

#ifndef LWF_COMMON_HPP_
#define LWF_COMMON_HPP_

#include <map>
#include <type_traits>
#include <tuple>
#include <Eigen/Dense>
#include <iostream>
#include "kindr/Core"
#include "lightweight_filtering/PropertyHandler.hpp"

typedef kindr::RotationQuaternionPD QPD;
typedef kindr::RotationMatrixPD MPD;
typedef Eigen::Vector3d V3D;
typedef Eigen::Matrix3d M3D;
typedef Eigen::VectorXd VXD;
typedef Eigen::MatrixXd MXD;
inline M3D gSM(const V3D& vec){
  return kindr::getSkewMatrixFromVector(vec);
}

static void enforceSymmetry(MXD& mat){
  mat = 0.5*(mat+mat.transpose()).eval();
}

inline M3D Lmat (const V3D& a) {
  return kindr::getJacobianOfExponentialMap(a);
}

namespace LWF{
  enum FilteringMode{
    ModeEKF,
    ModeUKF,
    ModeIEKF
  };
}

#endif /* LWF_COMMON_HPP_ */


text:
/*
 * Copyright (C) 2014-2015 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

#ifndef _GAZEBO_ARRANGE_PLUGIN_HH_
#define _GAZEBO_ARRANGE_PLUGIN_HH_

#include <map>
#include <string>

#include <boost/shared_ptr.hpp>

#include <sdf/sdf.hh>

#include <gazebo/common/Plugin.hh>
#include <gazebo/transport/transport.hh>
#include <gazebo/math/Pose.hh>
#include <gazebo/physics/PhysicsTypes.hh>
#include <gazebo/util/system.hh>
#include <gazebo/msgs/msgs.hh>

namespace gazebo
{
  class GAZEBO_VISIBLE ArrangePlugin : public WorldPlugin
  {
    /// \brief Constructor.
    public: ArrangePlugin();

    /// \brief Destructor.
    public: ~ArrangePlugin();

    /// \brief Load the plugin.
    /// \param[in] _world Pointer to world
    /// \param[in] _sdf Pointer to the SDF configuration.
    public: virtual void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf);

    /// \brief Initialize the plugin.
    public: virtual void Init();

    /// \brief Reset the plugin.
    public: virtual void Reset();

    /// \brief Set up the arrangement with name given by input parameter.
    /// \param[in] _arrangement Name of arrangement.
    /// \return True if arrangement was set successfully.
    public: bool SetArrangement(const std::string &_arrangement);

    /// \brief Callback function which receives a requested arrangement name.
    public: void ArrangementCallback(ConstGzStringPtr &_msg);

    /// \brief World pointer.
    protected: physics::WorldPtr world;

    /// \brief SDF pointer.
    protected: sdf::ElementPtr sdf;

    /// \brief Class to store info about each object.
    protected: class Object
               {
                 /// \brief Model pointer.
                 public: physics::ModelPtr model;

                 /// \brief Initial object pose.
                 public: math::Pose pose;
               };
    typedef boost::shared_ptr<Object> ObjectPtr;

    /// \brief Map of strings to model pointers.
    typedef std::map<std::string, ObjectPtr> Object_M;

    /// \brief Collection of models.
    protected: Object_M objects;

    /// \brief Map of strings to model poses.
    typedef std::map<std::string, math::Pose> Pose_M;

    /// \brief Map of strings to Pose_M (arrangement map).
    typedef std::map<std::string, Pose_M> Arrangement_M;

    /// \brief Information about arrangements.
    protected: Arrangement_M arrangements;

    /// \brief Initial arrangement name.
    protected: std::string initialArrangementName;

    /// \brief Current arrangement name.
    protected: std::string currentArrangementName;

    /// \brief Topic to listen on for changing arrangments.
    protected: std::string eventTopicName;

    /// \brief Node for Gazebo transport.
    protected: transport::NodePtr node;

    /// \brief Subscriber for listening to changing arrangements.
    protected: transport::SubscriberPtr sub;
  };
}
#endif

ext: hh

max_stars_repo_name: harderthan/gazebo

max_issues_repo_name: harderthan/gazebo

max_forks_repo_name: harderthan/gazebo


text:
/* CirKit: A circuit toolkit
 * Copyright (C) 2009-2015  University of Bremen
 * Copyright (C) 2015-2017  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "gia.hpp"

#include <iostream>

#include <boost/format.hpp>

#include <classical/abc/functions/cirkit_to_gia.hpp>
#include <classical/abc/gia/gia_bdd.hpp>
#include <classical/abc/gia/gia_esop.hpp>
#include <classical/optimization/esop_minimization.hpp>

#include <map/if/if.h>
#include <misc/util/utilTruth.h>
#include <misc/vec/vecInt.h>

namespace abc
{
Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes );
void Gia_ManLutSat( Gia_Man_t * p, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose );
void Gia_WriteDotAigSimple( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold );
void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict );
}

/******************************************************************************
 * Missing ABC methods                                                        *
 ******************************************************************************/

namespace abc
{

void Gia_ManGetCone_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
  if ( Vec_IntFind( vNodes, Gia_ObjId( p, pObj ) ) >= 0 ) return;

  Gia_ManGetCone_rec( p, Gia_ObjFanin0( pObj ), vNodes );
  Gia_ManGetCone_rec( p, Gia_ObjFanin1( pObj ), vNodes );
  if ( Gia_ObjIsMux( p, pObj ) )
  {
    Gia_ManGetCone_rec( p, Gia_ObjFanin2( p, pObj ), vNodes );
  }
  Vec_IntPush( vNodes, Gia_ObjId( p, pObj ) );
}

void Gia_ManGetCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes )
{
  int i;

  Vec_IntClear( vNodes );

  for ( i = 0; i < nLeaves; ++i )
  {
    Vec_IntPush( vNodes, pLeaves[i] );
  }
  Gia_ManGetCone_rec( p, pObj, vNodes );
}

Gia_Man_t * Gia_ManDupLUT( Gia_Man_t* p, int index )
{
  int i, j = 0, nLeaves, nNodes;
  Gia_Man_t * pNew;
  Gia_Obj_t * pObj;
  Vec_Int_t * vNodes;

  vNodes = Vec_IntAlloc( 20 );
  nLeaves = Gia_ObjLutSize( p, index );
  Gia_ManGetCone( p, Gia_ManObj( p, index ), Gia_ObjLutFanins( p, index ), nLeaves, vNodes );
  nNodes = Vec_IntSize( vNodes );

  Gia_ManFillValue( p );
  pNew = Gia_ManStart( nNodes + 2 );

  assert( !p->pMuxes ); /* for now */
  pNew->nConstrs = p->nConstrs;
  pNew->pName = Abc_UtilStrsav( p->pName );
  pNew->pSpec = Abc_UtilStrsav( p->pSpec );
  Gia_ManConst0( p )->Value = 0;

  for ( i = 0; i < nLeaves; ++i )
  {
    Gia_ManObj( p, Vec_IntEntry( vNodes, i ) )->Value = Gia_ManAppendCi( pNew );
  }

  for ( i = nLeaves; i < nNodes; ++i )
  {
    pObj = Gia_ManObj( p, Vec_IntEntry( vNodes, i ) );
    j = pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy( pObj ), Gia_ObjFanin1Copy( pObj ) );
  }

  /* add PO */
  Gia_ManAppendCo( pNew, j );

  Vec_IntFree( vNodes );

  return pNew;
}

}

namespace cirkit
{

/******************************************************************************
 * (De)Constructors                                                           *
 ******************************************************************************/

gia_graph::gia_graph( abc::Gia_Man_t* gia )
  : p_gia( gia, &abc::Gia_ManStop )
{
}

gia_graph::gia_graph( const std::string& filename )
  : p_gia( abc::Gia_AigerRead( const_cast<char*>( filename.c_str() ), 0, 0, 0 ), &abc::Gia_ManStop )
{
}

gia_graph::gia_graph( const aig_graph& aig )
  : p_gia( cirkit_to_gia( aig ), &abc::Gia_ManStop )
{
}

gia_graph::~gia_graph()
{
  if ( p_truths )
  {
    abc::Vec_WrdFree( p_truths );
  }
}

/******************************************************************************
 * GIA properties                                                             *
 ******************************************************************************/

std::string gia_graph::input_name( int input_index ) const
{
  if ( p_gia->vNamesIn && input_index < abc::Vec_PtrSize( p_gia->vNamesIn ) )
  {
    return std::string( (char*)abc::Vec_PtrGetEntry( p_gia->vNamesIn, input_index ) );
  }
  else
  {
    return boost::str( boost::format( "input_%d" ) % input_index );
  }
}

std::string gia_graph::output_name( int output_index ) const
{
  if ( p_gia->vNamesOut && output_index < abc::Vec_PtrSize( p_gia->vNamesOut ) )
  {
    return std::string( (char*)abc::Vec_PtrGetEntry( p_gia->vNamesOut, output_index ) );
  }
  else
  {
    return boost::str( boost::format( "output_%d" ) % output_index );
  }
}

int gia_graph::num_xors() const
{
  int _num_xors = 0;
  abc::Gia_Obj_t * fan0, * fan1;

  foreach_and( [&_num_xors, &fan0, &fan1]( int index, abc::Gia_Obj_t * obj ) {
      if ( abc::Gia_ObjIsMuxType( obj ) && abc::Gia_ObjRecognizeExor( obj, &fan0, &fan1 ) )
      {
        ++_num_xors;
      }
    } );

  return _num_xors;
}

/******************************************************************************
 * Operations                                                                 *
 ******************************************************************************/

gia_graph gia_graph::cofactor( int var, bool value ) const
{
  return gia_graph( abc::Gia_ManDupCofactorVar( p_gia.get(), var, value ? 1 : 0 ) );
}

gia_graph gia_graph::select_outputs( const std::vector<int>& indexes ) const
{
  auto vec = abc::Vec_IntAllocArray( const_cast<int*>( &indexes[0] ), indexes.size() );
  auto* g = abc::Gia_ManDupSelectedOutputs( p_gia.get(), vec );
  ABC_FREE( vec ); /* do not erase the array, since it's owned by indexes */
  return gia_graph( g );
}

gia_graph gia_graph::syn3() const
{
  return gia_graph( abc::Gia_ManAigSyn3( p_gia.get(), 0, 0 ) );
}

gia_graph gia_graph::syn4() const
{
  return gia_graph( abc::Gia_ManAigSyn4( p_gia.get(), 0, 0 ) );
}

gia_graph gia_graph::detect_xors() const
{
  gia_graph gia( abc::Gia_ManDupMuxes( p_gia.get(), 1 ) );

  abc::Gia_ManCreateRefs( gia );
  gia.foreach_and( [&gia]( auto index, auto obj ) {
      if ( abc::Gia_ObjIsXor( obj ) )
      {
        abc::Gia_ManSuperCollect( gia, obj, 0 );
        std::cout << "Object " << index << " has XOR superblock of size " << abc::Vec_IntSize( gia.p_gia.get()->vSuper ) << std::endl;
      }
    } );

  return gia;
}

/******************************************************************************
 * Mapping                                                                    *
 ******************************************************************************/

gia_graph gia_graph::if_mapping( const properties::ptr& settings, const properties::ptr& statistics ) const
{
  /* settings */
  const auto lut_size     = get( settings, "lut_size",     6u );
  const auto area_mapping = get( settings, "area_mapping", false );
  const auto expred_cuts  = get( settings, "expred_cuts",  true );
  const auto flow_iters   = get( settings, "flow_iters",   1u );
  const auto area_iters   = get( settings, "area_iters",   2u );

  abc::If_Par_t params;

  abc::Gia_ManSetIfParsDefault( &params );
  params.nLutSize = lut_size;
  params.pLutLib  = nullptr;
  params.fArea    = area_mapping ? 1 : 0;
  params.fExpRed  = expred_cuts ? 1 : 0;
  params.nFlowIters = flow_iters;
  params.nAreaIters = area_iters;

  auto mapped_gia = abc::Gia_ManPerformMapping( p_gia.get(), &params );
  //auto mapped_gia = gia_if2( p_gia.get(), &params );

  return gia_graph( mapped_gia );
}

gia_graph gia_graph::mf_mapping( const properties::ptr& settings, const properties::ptr& statistics ) const
{
  /* settings */
  const auto lut_size     = get( settings, "lut_size",     6u );
  const auto area_mapping = get( settings, "area_mapping", false );
  const auto rounds       = get( settings, "rounds",       2u );
  const auto rounds_ela   = get( settings, "rounds_ela",   1u );

  abc::Jf_Par_t params;

  abc::Mf_ManSetDefaultPars( &params );
  params.nLutSize = lut_size;
  params.fAreaOnly = area_mapping ? 1 : 0;
  params.nRounds = rounds;
  params.nRoundsEla = rounds_ela;
  // params.fCoarsen = 1;
  // params.nCoarseLimit = 1;

  auto mapped_gia = abc::Mf_ManPerformMapping( p_gia.get(), &params );

  return gia_graph( mapped_gia );
}

void gia_graph::satlut_mapping( const properties::ptr& settings, const properties::ptr& statistics ) const
{
  const auto window_size    = get( settings, "window_size",    128 );
  const auto improves       = get( settings, "improves",       0 );
  const auto conflict_limit = get( settings, "conflict_limit", 100 );
  const auto verbose        = get( settings, "verbose",        false );
  const auto very_verbose   = get( settings, "very_verbose",   false );

  const auto lut_size  = max_lut_size();
  const auto delay_max = 0;
  const auto edges_max = 0;
  const auto opt_delay = false;
  const auto reverse   = false;

  abc::Gia_ManLutSat( p_gia.get(), lut_size, window_size, improves, conflict_limit, delay_max, edges_max, opt_delay, reverse, verbose, very_verbose );
}

void gia_graph::init_lut_refs() const
{
  abc::Gia_ManSetLutRefs( p_gia.get() );
}

gia_graph gia_graph::extract_lut( int index ) const
{
  return gia_graph( abc::Gia_ManDupLUT( p_gia.get(), index ) );
}

void gia_graph::init_truth_tables() const
{
  if ( !p_truths )
  {
    p_truths = abc::Vec_WrdStart( abc::Gia_ManObjNum( p_gia.get() ) );
  }
}

uint64_t gia_graph::lut_truth_table( int index ) const
{
  const auto t = abc::Gia_ObjComputeTruthTable6Lut( p_gia.get(), index, p_truths );
  return t & abc::Abc_Tt6Mask( 1 << lut_size( index ) );
}

kitty::dynamic_truth_table gia_graph::truth_table( int output_index ) const
{
  const auto num_words = abc::Abc_Truth6WordNum( num_inputs() );
  const auto * words = abc::Gia_ObjComputeTruthTable( p_gia.get(), abc::Gia_ManCo( p_gia.get(), output_index ) );

  kitty::dynamic_truth_table func( num_inputs() );
  kitty::create_from_words( func, words, words + num_words );
  return func;
}

/******************************************************************************
 * Printing                                                                   *
 ******************************************************************************/

void gia_graph::print_stats() const
{
  abc::Gps_Par_t params{};
  abc::Gia_ManPrintStats( p_gia.get(), &params );
}

/******************************************************************************
 * I/O                                                                        *
 ******************************************************************************/

void gia_graph::write_aiger( const std::string& filename ) const
{
  abc::Gia_AigerWrite( p_gia.get(), const_cast<char*>( filename.c_str() ), 0, 0 );
}

void gia_graph::write_dot( const std::string& filename, const std::vector<int>& highlight ) const
{
  if ( highlight.empty() )
  {
    abc::Gia_WriteDotAigSimple( p_gia.get(), const_cast<char*>( filename.c_str() ), nullptr );
  }
  else
  {
    auto vec = abc::Vec_IntAllocArray( const_cast<int*>( &highlight[0] ), highlight.size() );
    abc::Gia_WriteDotAigSimple( p_gia.get(), const_cast<char*>( filename.c_str() ), vec );
    ABC_FREE( vec ); /* do not erase the array, since it's owned by highlight */
  }
}

void gia_graph::write_dot_with_luts( const std::string& filename ) const
{
  std::vector<int> highlight;
  foreach_lut( [&highlight]( int index ) { highlight.push_back( index ); } );
  write_dot( filename, highlight );
}

/******************************************************************************
 * Other logic representations                                                *
 ******************************************************************************/

gia_graph::esop_ptr gia_graph::compute_esop_cover( esop_cover_method method, const properties::ptr& settings ) const
{
  switch ( method )
  {
  case esop_cover_method::aig:
    {
      abc::Vec_Wec_t* esop = nullptr;
      abc::Eso_ManCompute( p_gia.get(), 0, &esop );
      return esop_ptr( esop, &abc::Vec_WecFree );
    } break;
  case esop_cover_method::aig_new:
    {
      return gia_extract_cover( *this, settings );
    } break;
  case esop_cover_method::aig_threshold:
    {
      if ( num_inputs() <= 10 )
      {
        abc::Vec_Wec_t* esop = nullptr;
        abc::Eso_ManCompute( p_gia.get(), 0, &esop );
        return esop_ptr( esop, &abc::Vec_WecFree );
      }
      else
      {
        return gia_extract_cover( *this, settings );
      }
    } break;
  case esop_cover_method::bdd:
    {
      Cudd mgr;

      const auto bdd = gia_to_bdd( *this, mgr, settings );

      /* get initial cover using exact PSDKRO optimization */
      exp_cache_t exp_cache;
      count_cubes_in_exact_psdkro( bdd.first.getManager(), bdd.second.front().getNode(), exp_cache );

      char * var_values = new char[bdd.first.ReadSize()];
      std::fill( var_values, var_values + bdd.first.ReadSize(), 2 );

      abc::Vec_Wec_t *esop = abc::Vec_WecAlloc( 0u );
      generate_exact_psdkro( bdd.first.getManager(), bdd.second.front().getNode(), var_values, -1, exp_cache, [&bdd, &esop, &var_values]() {
          auto * level = abc::Vec_WecPushLevel( esop );
          for ( auto i = 0; i < bdd.first.ReadSize(); ++i )
          {
            if ( var_values[i] == 2 ) continue;
            abc::Vec_IntPush( level, ( i << 1u ) | !var_values[i] );
          }
          abc::Vec_IntPush( level, -1 );
        } );

      delete[] var_values;

      return esop_ptr( esop, &abc::Vec_WecFree );
    } break;
  }

  return esop_ptr( nullptr, &abc::Vec_WecFree );
}

/******************************************************************************
 * Conversion functions                                                       *
 ******************************************************************************/

std::istream& operator>>( std::istream& in, gia_graph::esop_cover_method& cover_method )
{
  std::string token;
  in >> token;
  if ( token == "aig" || token == "0" )
  {
    cover_method = gia_graph::esop_cover_method::aig;
  }
  else if ( token == "bdd" || token == "1" )
  {
    cover_method = gia_graph::esop_cover_method::bdd;
  }
  else if ( token == "aignew" || token == "2" )
  {
    cover_method = gia_graph::esop_cover_method::aig_new;
  }
  else if ( token == "auto" || token == "3" )
  {
    cover_method = gia_graph::esop_cover_method::aig_threshold;
  }
  else
  {
    in.setstate( std::ios_base::failbit );
  }
  return in;
}

std::ostream& operator<<( std::ostream& out, const gia_graph::esop_cover_method& cover_method )
{
  switch ( cover_method )
  {
  case gia_graph::esop_cover_method::aig:
    return out << "aig";
  case gia_graph::esop_cover_method::bdd:
    return out << "bdd";
  case gia_graph::esop_cover_method::aig_new:
    return out << "aignew";
  case gia_graph::esop_cover_method::aig_threshold:
    return out << "auto";
  }

  return out;
}

}

// Local Variables:
// c-basic-offset: 2
// eval: (c-set-offset 'substatement-open 0)
// eval: (c-set-offset 'innamespace 0)
// End:

max_stars_repo_name: eletesta/cirkit

max_issues_repo_name: eletesta/cirkit

max_forks_repo_name: eletesta/cirkit