<commit_before>#include <string.h>
#include <set>

#include "cauchycoding.h"
#include "alloc.h"

#include "jerasure.h"
#include "cauchy.h"

void CauchyCoding::checkParams() {
    if (k <= 0 || m <= 0 || w <= 0)
        throw std::invalid_argument("Invalid Coding Parameters");
}

vector<ErlNifBinary> CauchyCoding::doEncode(unsigned char* data, size_t dataSize) {
    vector<ErlNifBinary> allBlockEntry;

    int *matrix = cauchy_good_general_coding_matrix(k, m, w);
    int *bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
    int **smart = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);

    size_t blockSize = roundTo((roundTo(dataSize, k*w) / (k*w)), sizeof(long)) * w;

    char** dataBlocks = (char**)alloc(sizeof(char*) * k);
    char** codeBlocks = (char**)alloc(sizeof(char*) * m);

    size_t offset = 0;
    for(int i = 0; i < k; ++i) {
        ErlNifBinary tmpBlock;
        enif_alloc_binary(blockSize, &tmpBlock);
        dataBlocks[i] = (char*)tmpBlock.data;

        allBlockEntry.push_back(tmpBlock);

        if (i == k - 1) {
            memset(dataBlocks[i], 0, blockSize);
            memcpy(dataBlocks[i], data + offset, dataSize - offset);
        } else {
            memcpy(dataBlocks[i], data + offset, blockSize);
        }
        offset += blockSize;
    }

    for(int i = 0; i < m; ++i) {
        ErlNifBinary tmpBlock;
        enif_alloc_binary(blockSize, &tmpBlock);
        codeBlocks[i] = (char*)tmpBlock.data;

        allBlockEntry.push_back(tmpBlock);
    }

    jerasure_schedule_encode(k, m, w, smart, dataBlocks, codeBlocks, blockSize, blockSize / w);

    jerasure_free_schedule(smart);
    free(matrix);
    free(bitmatrix);
    dealloc(dataBlocks);
    dealloc(codeBlocks);
    return allBlockEntry;
}

ErlNifBinary CauchyCoding::doDecode(vector<ErlNifBinary> blockList, vector<int> blockIdList, size_t dataSize) {

    ErlNifBinary file;

    char** dataBlocks = (char**)alloc(sizeof(char*) * k);
    char** codeBlocks = (char**)alloc(sizeof(char*) * m);
    int erasures[k + m];
    size_t blockSize = blockList[0].size;
    set<int> availSet(blockIdList.begin(), blockIdList.end());

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = (char*)alloc(blockSize) : codeBlocks[i - k] = (char*)alloc(blockSize);
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        }
    }
    erasures[j] = -1;

    for(size_t i = 0; i < blockList.size(); ++i) {
        int blockId = blockIdList[i];
        if (blockId < k) {
            memcpy(dataBlocks[blockId], blockList[i].data, blockSize);
        } else {
            memcpy(codeBlocks[blockId - k], blockList[i].data, blockSize);
        }
    }

    int *matrix = cauchy_good_general_coding_matrix(k, m, w);
    int *bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
    jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, dataBlocks, codeBlocks, blockSize, blockSize / w, 1);

    enif_alloc_binary(dataSize, &file);
    size_t offset = 0;
    int i = 0;
    while(offset < dataSize) {
        size_t copySize = min(dataSize - offset, blockSize);
        memcpy(file.data + offset, dataBlocks[i], copySize);
        i++;
        offset += copySize;
    }

    for(int i = 0; i < k + m; ++i) {
        i < k ? dealloc(dataBlocks[i]) : dealloc(codeBlocks[i - k]);
    }

    free(matrix);
    free(bitmatrix);
    dealloc(dataBlocks);
    dealloc(codeBlocks);
    return file;
}
<commit_msg>[CauchyRS] Added Parameters check for w<commit_after>#include <string.h>
#include <set>

#include "cauchycoding.h"
#include "alloc.h"

#include "jerasure.h"
#include "cauchy.h"

void CauchyCoding::checkParams() {
    if (k <= 0 || m <= 0 || w <= 0)
        throw std::invalid_argument("Invalid Coding Parameters");
    if ((k + m) > (1 << w))
        throw std::invalid_argument("Invalid Coding Parameters (larger w)");
}

vector<ErlNifBinary> CauchyCoding::doEncode(unsigned char* data, size_t dataSize) {
    vector<ErlNifBinary> allBlockEntry;

    int *matrix = cauchy_good_general_coding_matrix(k, m, w);
    int *bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
    int **smart = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);

    size_t blockSize = roundTo((roundTo(dataSize, k*w) / (k*w)), sizeof(long)) * w;

    char** dataBlocks = (char**)alloc(sizeof(char*) * k);
    char** codeBlocks = (char**)alloc(sizeof(char*) * m);

    size_t offset = 0;
    for(int i = 0; i < k; ++i) {
        ErlNifBinary tmpBlock;
        enif_alloc_binary(blockSize, &tmpBlock);
        dataBlocks[i] = (char*)tmpBlock.data;

        allBlockEntry.push_back(tmpBlock);

        if (i == k - 1) {
            memset(dataBlocks[i], 0, blockSize);
            memcpy(dataBlocks[i], data + offset, dataSize - offset);
        } else {
            memcpy(dataBlocks[i], data + offset, blockSize);
        }
        offset += blockSize;
    }

    for(int i = 0; i < m; ++i) {
        ErlNifBinary tmpBlock;
        enif_alloc_binary(blockSize, &tmpBlock);
        codeBlocks[i] = (char*)tmpBlock.data;

        allBlockEntry.push_back(tmpBlock);
    }

    jerasure_schedule_encode(k, m, w, smart, dataBlocks, codeBlocks, blockSize, blockSize / w);

    jerasure_free_schedule(smart);
    free(matrix);
    free(bitmatrix);
    dealloc(dataBlocks);
    dealloc(codeBlocks);
    return allBlockEntry;
}

ErlNifBinary CauchyCoding::doDecode(vector<ErlNifBinary> blockList, vector<int> blockIdList, size_t dataSize) {

    ErlNifBinary file;

    char** dataBlocks = (char**)alloc(sizeof(char*) * k);
    char** codeBlocks = (char**)alloc(sizeof(char*) * m);
    int erasures[k + m];
    size_t blockSize = blockList[0].size;
    set<int> availSet(blockIdList.begin(), blockIdList.end());

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = (char*)alloc(blockSize) : codeBlocks[i - k] = (char*)alloc(blockSize);
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        }
    }
    erasures[j] = -1;

    for(size_t i = 0; i < blockList.size(); ++i) {
        int blockId = blockIdList[i];
        if (blockId < k) {
            memcpy(dataBlocks[blockId], blockList[i].data, blockSize);
        } else {
            memcpy(codeBlocks[blockId - k], blockList[i].data, blockSize);
        }
    }

    int *matrix = cauchy_good_general_coding_matrix(k, m, w);
    int *bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
    jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, dataBlocks, codeBlocks, blockSize, blockSize / w, 1);

    enif_alloc_binary(dataSize, &file);
    size_t offset = 0;
    int i = 0;
    while(offset < dataSize) {
        size_t copySize = min(dataSize - offset, blockSize);
        memcpy(file.data + offset, dataBlocks[i], copySize);
        i++;
        offset += copySize;
    }

    for(int i = 0; i < k + m; ++i) {
        i < k ? dealloc(dataBlocks[i]) : dealloc(codeBlocks[i - k]);
    }

    free(matrix);
    free(bitmatrix);
    dealloc(dataBlocks);
    dealloc(codeBlocks);
    return file;
}
<|endoftext|>


<commit_before>/// @brief computes scales for CORDIC rotations in case of hyperbolic coordinates

namespace core { namespace cordic {
    template<size_t n, typename fp>
    double lut<n, fp>::hyperbolic_scale_with_repeated_iterations(size_t n)
    {
        double scale(1.0);

        size_t num(0);
        size_t repeated(4u);
        BOOST_FOREACH(size_t i, boost::irange<size_t>(1, n, 1))
        {
            scale *= std::sqrt(1 - std::powl(2.0, -2.0 * i));
            if (i == repeated && i != n - 1) {
                scale *= std::sqrt(1 - std::powl(2.0, -2.0 * i++));

                repeated = 3u * repeated  + 1u;
            }
        }

        return scale;
    }
}}
<commit_msg>hyperbolic_scale.inl: remove implicit cast + unrefenced variable<commit_after>/// @brief computes scales for CORDIC rotations in case of hyperbolic coordinates

namespace core { namespace cordic {
    template<size_t n, typename fp>
    double lut<n, fp>::hyperbolic_scale_with_repeated_iterations(size_t n)
    {
        double scale(1.0);

        size_t repeated(4u);
        BOOST_FOREACH(size_t i, boost::irange<size_t>(1, n, 1))
        {
            scale *= std::sqrt(1 - std::pow(2.0, -2.0 * i));
            if (i == repeated && i != n - 1) {
                scale *= std::sqrt(1 - std::pow(2.0, -2.0 * i++));

                repeated = 3u * repeated  + 1u;
            }
        }

        return scale;
    }
}}
<|endoftext|>


<commit_before>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_mutil_opt_least_squares_hpp
#define eli_mutil_opt_least_squares_hpp

#include "eli/code_eli.hpp"

namespace eli
{
  namespace mutil
  {
    namespace opt
    {
      template<typename data1__, typename data2__, typename data3__>
      void least_squares_uncon(Eigen::MatrixBase<data1__> &x, const Eigen::MatrixBase<data2__> &A, const Eigen::MatrixBase<data3__> &r)
      {
        unsigned int flags(0);
        if (Eigen::MatrixBase<data2__>::ColsAtCompileTime==Eigen::Dynamic)
          flags=Eigen::ComputeThinU | Eigen::ComputeThinV;
        else
          flags=Eigen::ComputeFullU | Eigen::ComputeFullV;

        Eigen::JacobiSVD<typename Eigen::MatrixBase<data2__>::PlainObject > svd(A, flags);
        x=svd.solve(r);
      }

      template<typename data1__, typename data2__, typename data3__, typename data4__, typename data5__>
      void least_squares_eqcon(Eigen::MatrixBase<data1__>  &x, const Eigen::MatrixBase<data2__> &A, const Eigen::MatrixBase<data3__> &b, const Eigen::MatrixBase<data4__> &B, const Eigen::MatrixBase<data5__> &d)
      {
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data4__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> B_matrixD;
        B_matrixD Q, R, temp_B, temp_R;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data2__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> A_matrixD;
        A_matrixD A1, A2, temp_A;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data5__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> d_matrixD;
        d_matrixD y;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data3__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> b_matrixD;
        b_matrixD z, rhs;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data1__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> x_matrixD;
        x_matrixD x_temp(A.cols(), b.cols());
        typename A_matrixD::Index p(B.rows()), n(A.cols());
  #ifdef DEBUG
        typename A_matrixD::Index m(b.rows());
  #endif

        // build Q and R
        Eigen::HouseholderQR<B_matrixD> qr(B.transpose());
        Q=qr.householderQ();
        temp_B=qr.matrixQR();
        temp_R=Eigen::TriangularView<B_matrixD, Eigen::Upper>(temp_B);
        R=temp_R.topRows(p);
        assert((R.rows()==p) && (R.cols()==p));
        assert((Q.rows()==n) && (Q.cols()==n));

        // build A1 and A2
        temp_A=A*Q;
        A1=temp_A.leftCols(p);
        A2=temp_A.rightCols(n-p);
#ifdef DEBUG
        assert((A1.rows()==m) && (A1.cols()==p));
        assert((A2.rows()==m) && (A2.cols()==n-p));
#endif
        assert(A1.cols()==p);
        assert(A2.cols()==n-p);

        // solve for y
        y=R.transpose().lu().solve(d);

        // setup the unconstrained optimization
        rhs=b-A1*y;
        least_squares_uncon(z, A2, rhs);

        // build the solution
        x_temp.topRows(p)=y;
        x_temp.bottomRows(n-p)=z;
        x=Q*x_temp;
      }
    }
  }
}

#endif
<commit_msg>Added documentation to function.<commit_after>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_mutil_opt_least_squares_hpp
#define eli_mutil_opt_least_squares_hpp

#include "eli/code_eli.hpp"

namespace eli
{
  namespace mutil
  {
    namespace opt
    {
      template<typename data1__, typename data2__, typename data3__>
      void least_squares_uncon(Eigen::MatrixBase<data1__> &x, const Eigen::MatrixBase<data2__> &A, const Eigen::MatrixBase<data3__> &r)
      {
        unsigned int flags(0);
        if (Eigen::MatrixBase<data2__>::ColsAtCompileTime==Eigen::Dynamic)
          flags=Eigen::ComputeThinU | Eigen::ComputeThinV;
        else
          flags=Eigen::ComputeFullU | Eigen::ComputeFullV;

        Eigen::JacobiSVD<typename Eigen::MatrixBase<data2__>::PlainObject > svd(A, flags);
        x=svd.solve(r);
      }

      /**
        This solves a linear least squares problem of the form \f$ \min_{B\vec{x}=\vec{d}}\left|\left| A\vec{x}-\vec{b} \right|\right|^2 \f$
       */
      template<typename data1__, typename data2__, typename data3__, typename data4__, typename data5__>
      void least_squares_eqcon(Eigen::MatrixBase<data1__>  &x, const Eigen::MatrixBase<data2__> &A, const Eigen::MatrixBase<data3__> &b, const Eigen::MatrixBase<data4__> &B, const Eigen::MatrixBase<data5__> &d)
      {
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data4__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> B_matrixD;
        B_matrixD Q, R, temp_B, temp_R;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data2__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> A_matrixD;
        A_matrixD A1, A2, temp_A;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data5__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> d_matrixD;
        d_matrixD y;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data3__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> b_matrixD;
        b_matrixD z, rhs;
        typedef Eigen::Matrix<typename Eigen::MatrixBase<data1__>::Scalar, Eigen::Dynamic, Eigen::Dynamic> x_matrixD;
        x_matrixD x_temp(A.cols(), b.cols());
        typename A_matrixD::Index p(B.rows()), n(A.cols());
  #ifdef DEBUG
        typename A_matrixD::Index m(b.rows());
  #endif

        // build Q and R
        Eigen::HouseholderQR<B_matrixD> qr(B.transpose());
        Q=qr.householderQ();
        temp_B=qr.matrixQR();
        temp_R=Eigen::TriangularView<B_matrixD, Eigen::Upper>(temp_B);
        R=temp_R.topRows(p);
        assert((R.rows()==p) && (R.cols()==p));
        assert((Q.rows()==n) && (Q.cols()==n));

        // build A1 and A2
        temp_A=A*Q;
        A1=temp_A.leftCols(p);
        A2=temp_A.rightCols(n-p);
#ifdef DEBUG
        assert((A1.rows()==m) && (A1.cols()==p));
        assert((A2.rows()==m) && (A2.cols()==n-p));
#endif
        assert(A1.cols()==p);
        assert(A2.cols()==n-p);

        // solve for y
        y=R.transpose().lu().solve(d);

        // setup the unconstrained optimization
        rhs=b-A1*y;
        least_squares_uncon(z, A2, rhs);

        // build the solution
        x_temp.topRows(p)=y;
        x_temp.bottomRows(n-p)=z;
        x=Q*x_temp;
      }
    }
  }
}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Mar 10, 2014
 */

#ifndef MethodMockingContext_h__
#define MethodMockingContext_h__

#include <functional>
#include <type_traits>
#include <tuple>
#include <memory>
#include <vector>
#include <unordered_set>
#include <set>
#include <iosfwd>

#include "fakeit/RecordedMethodBody.hpp"
#include "fakeit/StubbingProgress.hpp"
#include "fakeit/Sequence.hpp"
#include "fakeit/ActualInvocation.hpp"
#include "fakeit/EventHandler.hpp"
#include "fakeit/ActionSequence.hpp"
#include "fakeit/DomainObjects.hpp"
#include "fakeit/SpyingContext.hpp"
#include "fakeit/StubbingContext.hpp"
#include "fakeit/MatchersCollector.hpp"
#include "mockutils/type_utils.hpp"

namespace fakeit {
/**
 * Build recorded sequence and the matching criteria.
 * For example, for the following line:
 * When(Method(mock,foo)).Return(1).Return(2_Times(2)).Throw(e1);
 * The matching criteria is: Any invocation of mock.foo
 * The recorded sequence is: {Return(1), Return(2), Return(2), Throw(e1)}
 */
template<typename R, typename ... arglist>
class MethodMockingContext: //
public Sequence,                // For use in Verify(sequence1,...)... phrases.
		public ActualInvocationsSource, // For use in Using(source1,souece2,...) and VerifyNoOtherInvocations(source1,souece2...) phrases.
		public virtual StubbingContext<R, arglist...>, // For use in Fake, Spy & When phrases
		public virtual SpyingContext<R, arglist...>, // For use in Fake, Spy & When phrases
		private Invocation::Matcher {

public:

	struct Context: public Destructable {

		virtual ~Context() = default;

		/**
		 * Return the original method. not the mock.
		 */
		virtual std::function<R(arglist&...)> getOriginalMethod() = 0;

		virtual std::string getMethodName() = 0;

		virtual void addMethodInvocationHandler(typename ActualInvocation<arglist...>::Matcher* matcher,
				MethodInvocationHandler<R, arglist...>* invocationHandler) = 0;

		virtual void scanActualInvocations(const std::function<void(ActualInvocation<arglist...>&)>& scanner) = 0;

		virtual void setMethodDetails(std::string mockName, std::string methodName) = 0;

		virtual bool isOfMethod(Method& method) = 0;

		virtual ActualInvocationsSource& getInvolvedMock() = 0;
	};

private:
	class Implementation {

		Context* _stubbingContext;
		ActionSequence<R, arglist...>* _recordedActionSequence;
		typename ActualInvocation<arglist...>::Matcher* _invocationMatcher;bool _commited;

		Context& getStubbingContext() const {
			return *_stubbingContext;
		}

	public:

		Implementation(Context* stubbingContext)
				: _stubbingContext(stubbingContext), _recordedActionSequence(new ActionSequence<R, arglist...>()), _invocationMatcher {
						new DefaultInvocationMatcher<arglist...>() }, _commited(false) {
		}

		~Implementation() {
			delete _stubbingContext;
			if (!_commited) {
				// no commit. delete the created objects.
				delete _recordedActionSequence;
				delete _invocationMatcher;
			}
		}

		ActionSequence<R, arglist...>& getRecordedActionSequence() {
			return *_recordedActionSequence;
		}

		std::string format() const {
			std::string s = getStubbingContext().getMethodName();
			s += _invocationMatcher->format();
			return s;
		}

		void getActualInvocations(std::unordered_set<Invocation*>& into) const {
			auto scanner = [&](ActualInvocation<arglist...>& a) {
				if (_invocationMatcher->matches(a)) {
					into.insert(&a);
				}
			};
			getStubbingContext().scanActualInvocations(scanner);
		}

		/**
		 * Used only by Verify phrase.
		 */
		bool matches(Invocation& invocation) {
			Method& actualMethod = invocation.getMethod();
			if (!getStubbingContext().isOfMethod(actualMethod)) {
				return false;
			}

			ActualInvocation<arglist...>& actualInvocation = dynamic_cast<ActualInvocation<arglist...>&>(invocation);
			return _invocationMatcher->matches(actualInvocation);
		}

		void commit() {
			getStubbingContext().addMethodInvocationHandler(_invocationMatcher, _recordedActionSequence);
			_commited = true;
		}

		void appendAction(Action<R, arglist...>* action) {
			getRecordedActionSequence().AppendDo(action);
		}

		void setMethodBodyByAssignment(std::function<R(arglist&...)> method) {
			appendAction(new RepeatForever<R, arglist...>(method));
			commit();
		}

		void setMethodDetails(std::string mockName, std::string methodName) {
			getStubbingContext().setMethodDetails(mockName, methodName);
		}

		void getInvolvedMocks(std::set<const ActualInvocationsSource*>& into) const {
			into.insert(&getStubbingContext().getInvolvedMock());
		}

		typename std::function<R(arglist&...)> getOriginalMethod() {
			return getStubbingContext().getOriginalMethod();
		}

		void setInvocationMatcher(typename ActualInvocation<arglist...>::Matcher* matcher) {
			delete _invocationMatcher;
			_invocationMatcher = matcher;
		}
	};

protected:

	MethodMockingContext(Context* stubbingContext)
			: _impl { new Implementation(stubbingContext) } {
	}

	//Move ctor for use by derived classes.
	MethodMockingContext(MethodMockingContext& other)
			: _impl(other._impl) {
	}

	virtual ~MethodMockingContext() = default;

	std::string format() const {
		return _impl->format();
	}

	unsigned int size() const override {
		return 1;
	}

	/**
	 * Used only by Verify phrase.
	 */
	void getInvolvedMocks(std::set<const ActualInvocationsSource*>& into) const override {
		_impl->getInvolvedMocks(into);
	}

	void getExpectedSequence(std::vector<Invocation::Matcher*>& into) const override {
		const Invocation::Matcher* b = this;
		Invocation::Matcher* c = const_cast<Invocation::Matcher*>(b);
		into.push_back(c);
	}

	/**
	 * Used only by Verify phrase.
	 */
	void getActualInvocations(std::unordered_set<Invocation*>& into) const override {
		_impl->getActualInvocations(into);
	}

	/**
	 * Used only by Verify phrase.
	 */
	virtual bool matches(Invocation& invocation) override {
		return _impl->matches(invocation);
	}

	virtual void commit() override {
		_impl->commit();
	}

	void setMethodDetails(std::string mockName, std::string methodName) {
		_impl->setMethodDetails(mockName, methodName);
	}

//	void setMatchingCriteria(const arglist&... args) {
//		_impl->setMatchingCriteria(args...);
//	}

	void setMatchingCriteria(std::function<bool(arglist&...)> predicate) {
		typename ActualInvocation<arglist...>::Matcher* matcher { new UserDefinedInvocationMatcher<arglist...>(predicate) };
		_impl->setInvocationMatcher(matcher);
	}

	void setMatchingCriteria(const std::vector<Destructable*>& matchers) {
		typename ActualInvocation<arglist...>::Matcher* matcher { new ArgumentsMatcherInvocationMatcher<arglist...>(matchers) };
		_impl->setInvocationMatcher(matcher);
	}

	/**
	 * Used by Fake, Spy & When functors
	 */
	void appendAction(Action<R, arglist...>* action) override {
		_impl->appendAction(action);
	}

	void setMethodBodyByAssignment(std::function<R(arglist&...)> method) {
		_impl->setMethodBodyByAssignment(method);
	}

	template<class ...matcherCreators, class = typename std::enable_if<sizeof...(matcherCreators)==sizeof...(arglist)>::type>
	void setMatchingCriteria(const matcherCreators& ... matcherCreator) {
		std::vector<Destructable*> matchers;

		MatchersCollector<0, arglist...> c(matchers);
		c.CollectMatchers(matcherCreator...);

		MethodMockingContext<R, arglist...>::setMatchingCriteria(matchers);
	}
private:

	typename std::function<R(arglist&...)> getOriginalMethod() override {
		return _impl->getOriginalMethod();
	}

	std::shared_ptr<Implementation> _impl;
};

template<typename R, typename ... arglist>
class MockingContext: //
public virtual MethodMockingContext<R, arglist...> //
{
	MockingContext & operator=(const MockingContext&) = delete;

public:

	MockingContext(typename MethodMockingContext<R, arglist...>::Context* stubbingContext)
			: MethodMockingContext<R, arglist...>(stubbingContext) {
	}

	MockingContext(MockingContext<R, arglist...>&other)
			: MethodMockingContext<R, arglist...>(other) {
	}
	MockingContext(MockingContext<R, arglist...> &&other)
			: MethodMockingContext<R, arglist...>(other) {
	}

	virtual ~MockingContext() THROWS {
	}

	MockingContext<R, arglist...>& setMethodDetails(std::string mockName, std::string methodName) {
		MethodMockingContext<R, arglist...>::setMethodDetails(mockName, methodName);
		return *this;
	}

	MockingContext<R, arglist...>& Using(const arglist&... args) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	template<class ...matcherCreator>
	MockingContext<R, arglist...>& Using(const matcherCreator& ... matcherCreators) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcherCreators...);
		return *this;
	}

	MockingContext<R, arglist...>& Matching(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	MockingContext<R, arglist...>& operator()(const arglist&... args) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	MockingContext<R, arglist...>& operator()(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	void operator=(std::function<R(arglist&...)> method) {
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}

	template<typename U = R>
	typename std::enable_if<!std::is_reference<U>::value, void>::type operator=(const R& r) {
		auto method = [r](arglist&...) -> R {return r;};
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}

	template<typename U = R>
	typename std::enable_if<std::is_reference<U>::value, void>::type operator=(const R& r) {
		auto method = [&r](arglist&...) -> R {return r;};
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}
};

template<typename ... arglist>
class MockingContext<void, arglist...> : //
public virtual MethodMockingContext<void, arglist...> {

	MockingContext & operator=(const MockingContext&) = delete;

public:
	MockingContext(typename MethodMockingContext<void, arglist...>::Context* stubbingContext)
			: MethodMockingContext<void, arglist...>(stubbingContext) {
	}

	virtual ~MockingContext() THROWS {
	}

	MockingContext(MockingContext<void, arglist...>& other)
			: MethodMockingContext<void, arglist...>(other) {
	}
	MockingContext(MockingContext<void, arglist...> && other)
			: MethodMockingContext<void, arglist...>(other) {
	}

	void operator=(std::function<void(arglist&...)> method) {
		MethodMockingContext<void, arglist...>::setMethodBodyByAssignment(method);
	}

	MockingContext<void, arglist...>& setMethodDetails(std::string mockName, std::string methodName) {
		MethodMockingContext<void, arglist...>::setMethodDetails(mockName, methodName);
		return *this;
	}

	MockingContext<void, arglist...>& Using(const arglist&... args) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	template<class ...matcherCreator>
	MockingContext<void, arglist...>& Using(const matcherCreator& ... matcherCreators) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcherCreators...);
		return *this;
	}

	MockingContext<void, arglist...>& Matching(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	MockingContext<void, arglist...>& operator()(const arglist&... args) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	MockingContext<void, arglist...>& operator()(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}
};

}
#endif
<commit_msg>cleanup<commit_after>/*
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Mar 10, 2014
 */

#ifndef MethodMockingContext_h__
#define MethodMockingContext_h__

#include <functional>
#include <type_traits>
#include <tuple>
#include <memory>
#include <vector>
#include <unordered_set>
#include <set>
#include <iosfwd>

#include "fakeit/RecordedMethodBody.hpp"
#include "fakeit/StubbingProgress.hpp"
#include "fakeit/Sequence.hpp"
#include "fakeit/ActualInvocation.hpp"
#include "fakeit/EventHandler.hpp"
#include "fakeit/ActionSequence.hpp"
#include "fakeit/DomainObjects.hpp"
#include "fakeit/SpyingContext.hpp"
#include "fakeit/StubbingContext.hpp"
#include "fakeit/MatchersCollector.hpp"
#include "mockutils/type_utils.hpp"

namespace fakeit {
/**
 * Build recorded sequence and the matching criteria.
 * For example, for the following line:
 * When(Method(mock,foo)).Return(1).Return(2_Times(2)).Throw(e1);
 * The matching criteria is: Any invocation of mock.foo
 * The recorded sequence is: {Return(1), Return(2), Return(2), Throw(e1)}
 */
template<typename R, typename ... arglist>
class MethodMockingContext: //
public Sequence,                // For use in Verify(sequence1,...)... phrases.
		public ActualInvocationsSource, // For use in Using(source1,souece2,...) and VerifyNoOtherInvocations(source1,souece2...) phrases.
		public virtual StubbingContext<R, arglist...>, // For use in Fake, Spy & When phrases
		public virtual SpyingContext<R, arglist...>, // For use in Fake, Spy & When phrases
		private Invocation::Matcher {

public:

	struct Context: public Destructable {

		virtual ~Context() = default;

		/**
		 * Return the original method. not the mock.
		 */
		virtual std::function<R(arglist&...)> getOriginalMethod() = 0;

		virtual std::string getMethodName() = 0;

		virtual void addMethodInvocationHandler(typename ActualInvocation<arglist...>::Matcher* matcher,
				MethodInvocationHandler<R, arglist...>* invocationHandler) = 0;

		virtual void scanActualInvocations(const std::function<void(ActualInvocation<arglist...>&)>& scanner) = 0;

		virtual void setMethodDetails(std::string mockName, std::string methodName) = 0;

		virtual bool isOfMethod(Method& method) = 0;

		virtual ActualInvocationsSource& getInvolvedMock() = 0;
	};

private:
	class Implementation {

		Context* _stubbingContext;
		ActionSequence<R, arglist...>* _recordedActionSequence;
		typename ActualInvocation<arglist...>::Matcher* _invocationMatcher;bool _commited;

		Context& getStubbingContext() const {
			return *_stubbingContext;
		}

	public:

		Implementation(Context* stubbingContext)
				: _stubbingContext(stubbingContext), _recordedActionSequence(new ActionSequence<R, arglist...>()), _invocationMatcher {
						new DefaultInvocationMatcher<arglist...>() }, _commited(false) {
		}

		~Implementation() {
			delete _stubbingContext;
			if (!_commited) {
				// no commit. delete the created objects.
				delete _recordedActionSequence;
				delete _invocationMatcher;
			}
		}

		ActionSequence<R, arglist...>& getRecordedActionSequence() {
			return *_recordedActionSequence;
		}

		std::string format() const {
			std::string s = getStubbingContext().getMethodName();
			s += _invocationMatcher->format();
			return s;
		}

		void getActualInvocations(std::unordered_set<Invocation*>& into) const {
			auto scanner = [&](ActualInvocation<arglist...>& a) {
				if (_invocationMatcher->matches(a)) {
					into.insert(&a);
				}
			};
			getStubbingContext().scanActualInvocations(scanner);
		}

		/**
		 * Used only by Verify phrase.
		 */
		bool matches(Invocation& invocation) {
			Method& actualMethod = invocation.getMethod();
			if (!getStubbingContext().isOfMethod(actualMethod)) {
				return false;
			}

			ActualInvocation<arglist...>& actualInvocation = dynamic_cast<ActualInvocation<arglist...>&>(invocation);
			return _invocationMatcher->matches(actualInvocation);
		}

		void commit() {
			getStubbingContext().addMethodInvocationHandler(_invocationMatcher, _recordedActionSequence);
			_commited = true;
		}

		void appendAction(Action<R, arglist...>* action) {
			getRecordedActionSequence().AppendDo(action);
		}

		void setMethodBodyByAssignment(std::function<R(arglist&...)> method) {
			appendAction(new RepeatForever<R, arglist...>(method));
			commit();
		}

		void setMethodDetails(std::string mockName, std::string methodName) {
			getStubbingContext().setMethodDetails(mockName, methodName);
		}

		void getInvolvedMocks(std::set<const ActualInvocationsSource*>& into) const {
			into.insert(&getStubbingContext().getInvolvedMock());
		}

		typename std::function<R(arglist&...)> getOriginalMethod() {
			return getStubbingContext().getOriginalMethod();
		}

		void setInvocationMatcher(typename ActualInvocation<arglist...>::Matcher* matcher) {
			delete _invocationMatcher;
			_invocationMatcher = matcher;
		}
	};

protected:

	MethodMockingContext(Context* stubbingContext)
			: _impl { new Implementation(stubbingContext) } {
	}

	//Move ctor for use by derived classes.
	MethodMockingContext(MethodMockingContext& other)
			: _impl(other._impl) {
	}

	virtual ~MethodMockingContext() {}

	std::string format() const {
		return _impl->format();
	}

	unsigned int size() const override {
		return 1;
	}

	/**
	 * Used only by Verify phrase.
	 */
	void getInvolvedMocks(std::set<const ActualInvocationsSource*>& into) const override {
		_impl->getInvolvedMocks(into);
	}

	void getExpectedSequence(std::vector<Invocation::Matcher*>& into) const override {
		const Invocation::Matcher* b = this;
		Invocation::Matcher* c = const_cast<Invocation::Matcher*>(b);
		into.push_back(c);
	}

	/**
	 * Used only by Verify phrase.
	 */
	void getActualInvocations(std::unordered_set<Invocation*>& into) const override {
		_impl->getActualInvocations(into);
	}

	/**
	 * Used only by Verify phrase.
	 */
	virtual bool matches(Invocation& invocation) override {
		return _impl->matches(invocation);
	}

	virtual void commit() override {
		_impl->commit();
	}

	void setMethodDetails(std::string mockName, std::string methodName) {
		_impl->setMethodDetails(mockName, methodName);
	}

//	void setMatchingCriteria(const arglist&... args) {
//		_impl->setMatchingCriteria(args...);
//	}

	void setMatchingCriteria(std::function<bool(arglist&...)> predicate) {
		typename ActualInvocation<arglist...>::Matcher* matcher { new UserDefinedInvocationMatcher<arglist...>(predicate) };
		_impl->setInvocationMatcher(matcher);
	}

	void setMatchingCriteria(const std::vector<Destructable*>& matchers) {
		typename ActualInvocation<arglist...>::Matcher* matcher { new ArgumentsMatcherInvocationMatcher<arglist...>(matchers) };
		_impl->setInvocationMatcher(matcher);
	}

	/**
	 * Used by Fake, Spy & When functors
	 */
	void appendAction(Action<R, arglist...>* action) override {
		_impl->appendAction(action);
	}

	void setMethodBodyByAssignment(std::function<R(arglist&...)> method) {
		_impl->setMethodBodyByAssignment(method);
	}

	template<class ...matcherCreators, class = typename std::enable_if<sizeof...(matcherCreators)==sizeof...(arglist)>::type>
	void setMatchingCriteria(const matcherCreators& ... matcherCreator) {
		std::vector<Destructable*> matchers;

		MatchersCollector<0, arglist...> c(matchers);
		c.CollectMatchers(matcherCreator...);

		MethodMockingContext<R, arglist...>::setMatchingCriteria(matchers);
	}
private:

	typename std::function<R(arglist&...)> getOriginalMethod() override {
		return _impl->getOriginalMethod();
	}

	std::shared_ptr<Implementation> _impl;
};

template<typename R, typename ... arglist>
class MockingContext: //
public virtual MethodMockingContext<R, arglist...> //
{
	MockingContext & operator=(const MockingContext&) = delete;

public:

	MockingContext(typename MethodMockingContext<R, arglist...>::Context* stubbingContext)
			: MethodMockingContext<R, arglist...>(stubbingContext) {
	}

	MockingContext(MockingContext<R, arglist...>&other)
			: MethodMockingContext<R, arglist...>(other) {
	}
	MockingContext(MockingContext<R, arglist...> &&other)
			: MethodMockingContext<R, arglist...>(other) {
	}

	virtual ~MockingContext() THROWS {
	}

	MockingContext<R, arglist...>& setMethodDetails(std::string mockName, std::string methodName) {
		MethodMockingContext<R, arglist...>::setMethodDetails(mockName, methodName);
		return *this;
	}

	MockingContext<R, arglist...>& Using(const arglist&... args) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	template<class ...matcherCreator>
	MockingContext<R, arglist...>& Using(const matcherCreator& ... matcherCreators) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcherCreators...);
		return *this;
	}

	MockingContext<R, arglist...>& Matching(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	MockingContext<R, arglist...>& operator()(const arglist&... args) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	MockingContext<R, arglist...>& operator()(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	void operator=(std::function<R(arglist&...)> method) {
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}

	template<typename U = R>
	typename std::enable_if<!std::is_reference<U>::value, void>::type operator=(const R& r) {
		auto method = [r](arglist&...) -> R {return r;};
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}

	template<typename U = R>
	typename std::enable_if<std::is_reference<U>::value, void>::type operator=(const R& r) {
		auto method = [&r](arglist&...) -> R {return r;};
		MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
	}
};

template<typename ... arglist>
class MockingContext<void, arglist...> : //
public virtual MethodMockingContext<void, arglist...> {

	MockingContext & operator=(const MockingContext&) = delete;

public:
	MockingContext(typename MethodMockingContext<void, arglist...>::Context* stubbingContext)
			: MethodMockingContext<void, arglist...>(stubbingContext) {
	}

	virtual ~MockingContext() THROWS {
	}

	MockingContext(MockingContext<void, arglist...>& other)
			: MethodMockingContext<void, arglist...>(other) {
	}
	MockingContext(MockingContext<void, arglist...> && other)
			: MethodMockingContext<void, arglist...>(other) {
	}

	void operator=(std::function<void(arglist&...)> method) {
		MethodMockingContext<void, arglist...>::setMethodBodyByAssignment(method);
	}

	MockingContext<void, arglist...>& setMethodDetails(std::string mockName, std::string methodName) {
		MethodMockingContext<void, arglist...>::setMethodDetails(mockName, methodName);
		return *this;
	}

	MockingContext<void, arglist...>& Using(const arglist&... args) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	template<class ...matcherCreator>
	MockingContext<void, arglist...>& Using(const matcherCreator& ... matcherCreators) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcherCreators...);
		return *this;
	}

	MockingContext<void, arglist...>& Matching(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}

	MockingContext<void, arglist...>& operator()(const arglist&... args) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
		return *this;
	}

	MockingContext<void, arglist...>& operator()(std::function<bool(arglist&...)> matcher) {
		MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
		return *this;
	}
};

}
#endif
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	NMEA デコード・クラス @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cstring>
#include "common/time.h"

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  NMEA デコード・クラス
		@param[in]	SCI_IO	シリアルＩ／Ｏ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SCI_IO>
	class nmea_dec {

	public:

		static const uint32_t sinfo_num_ = 12;		///< 衛星情報の最大数

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  衛星パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct sat_info {
			char	no_[4];  	///< 衛星番号
			char	elv_[4];	///< 衛星仰角(Elevation)、０～９０度
			char	azi_[4];	///< 衛星方位角(Azimuth)、０～３５９度
			char	cn_[4];		///< キャリア／ノイズ比、０～９９dB

			sat_info() {
				no_[0] = 0;
				elv_[0] = 0;
				azi_[0] = 0;
				cn_[0] = 0;
			}
		};

	private:
		SCI_IO&		sci_;

		uint16_t	pos_;
		char		line_[128];

		char		time_[12];  // 時間
		char		lat_[12];   // 緯度(latitude)
		char		ns_[2];     // 北緯、南緯
		char		lon_[12];   // 経度(longitude)
		char		ew_[2];     // 東経、西経
		char		q_[2];      // 品質
		char		satellite_[4];  // 衛星数
		char		hq_[4];		// 水平精度低下率
		char		alt_[6];	// 海抜高度(Altitude above sea level)
		char		alt_unit_[2];	// 海抜高度単位

		char		date_[8];   // 日付

		uint16_t	sidx_;
		sat_info	sinfo_[sinfo_num_];	// 衛星情報

		uint32_t	id_;
		uint32_t	iid_;

		static uint16_t word_(const char* src)
		{
			const char* top = src;
			char ch;
			while((ch = *src++) != 0) {
				if(ch == ',' || ch == '*') return src - top;
			}
			return 0;
		}

		static void copy_word_(char* dst, const char* src, uint16_t len)
		{
			std::strncpy(dst, src, len);
			dst[len] = 0;
		}

		static int32_t get_dec_(const char* t, uint16_t n = 0)
		{
			int32_t val = 0;
			char ch;
			while((ch = *t++) != 0) {
				if('0' <= ch && ch <= '9') {
					val *= 10;
					val += ch - '0';
				} else {
					break;
				}
				if(n > 0) {
					--n;
					if(n == 0) break;
				}
			}
			return val;
		}

		bool decode_()
		{
			if(line_[0] != '$') return false;

			if(std::strncmp(&line_[1], "GPGGA,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 0) copy_word_(time_, p, l - 1);
					else if(n == 1) copy_word_(lat_, p, l - 1);
					else if(n == 2) copy_word_(ns_, p, l - 1);
					else if(n == 3) copy_word_(lon_, p, l - 1);
					else if(n == 4) copy_word_(ew_, p, l - 1);
					else if(n == 5) copy_word_(q_, p, l - 1);
					else if(n == 6) copy_word_(satellite_, p, l - 1);
					else if(n == 7) copy_word_(hq_, p, l - 1);
					else if(n == 8) copy_word_(alt_, p, l - 1);
					else if(n == 9) copy_word_(alt_unit_, p, l - 1);
					else {
						break;
					}
					p += l;
					++n;
				}
			} else if(std::strncmp(&line_[1], "GPRMC,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 8) copy_word_(date_, p, l - 1);
					p += l;
					++n;
				}
			} else if(std::strncmp(&line_[1], "GPGSV,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 0) ;
					else if(n == 1) ;
// std::strncpy(date_, p, l - 1);
					p += l;
					++n;
				}
				++iid_;
			} else if(std::strncmp(&line_[1], "GPVTG,", 6) == 0) {
				++id_;
				return true;
			}
			return false;
		}

	public:
        //-----------------------------------------------------------------//
        /*!
            @brief  コンストラクター
        */
        //-----------------------------------------------------------------//
		nmea_dec(SCI_IO& sci) : sci_(sci), pos_(0), sidx_(0), id_(0), iid_(0) {
			line_[0] = 0;
			time_[0] = 0;
			lat_[0] = 0;
			ns_[0] = 0;
			lon_[0] = 0;
			ew_[0] = 0;
			q_[0] = 0;
			satellite_[0] = 0;
			hq_[0] = 0;
			alt_[0] = 0;
			alt_unit_[0] = 0;

			date_[0] = 0;
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  処理ＩＤを取得
			@return 処理ＩＤ
        */
        //-----------------------------------------------------------------//
		uint32_t get_id() const { return id_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  情報処理ＩＤを取得
			@return 情報処理ＩＤ
        */
        //-----------------------------------------------------------------//
		uint32_t get_iid() const { return iid_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  時間を取得
			@return 時間
        */
        //-----------------------------------------------------------------//
		const char* get_time() const { return time_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  日付を取得
			@return 日付
        */
        //-----------------------------------------------------------------//
		const char* get_date() const { return date_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  時間「time_t」を取得（グリニッチ時間）
			@return 時間「time_t」
        */
        //-----------------------------------------------------------------//
		time_t get_tm() const {
			tm ts;
			ts.tm_sec  = get_dec_(&time_[4], 2);
			ts.tm_min  = get_dec_(&time_[2], 2);
			ts.tm_hour = get_dec_(&time_[0], 2);
			ts.tm_mday = get_dec_(&date_[0], 2);
			ts.tm_mon  = get_dec_(&date_[2], 2);
			ts.tm_year = get_dec_(&date_[4], 2);
			ts.tm_year += 100;  // 起点１９００年
			return mktime_gmt(&ts);
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  緯度を取得
			@return 緯度
        */
        //-----------------------------------------------------------------//
		const char* get_lat() const { return lat_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  経度を取得
			@return 経度
        */
        //-----------------------------------------------------------------//
		const char* get_lon() const { return lon_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  品質を取得
			@return 品質
        */
        //-----------------------------------------------------------------//
		const char* get_quality() const { return q_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  衛星数を取得
			@return 衛星数
        */
        //-----------------------------------------------------------------//
		const char* get_satellite() const { return satellite_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  水平品質を取得
			@return 水平品質
        */
        //-----------------------------------------------------------------//
		const char* get_holizontal_quality() const { return hq_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  海抜高度を取得
			@return 海抜高度
        */
        //-----------------------------------------------------------------//
		const char* get_altitude() const { return alt_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  海抜高度単位を取得
			@return 海抜高度単位
        */
        //-----------------------------------------------------------------//
		const char* get_altitude_unit() const { return alt_unit_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  衛星情報の取得
			@param[in]	idx	衛星インデックス
			@return 衛星情報
        */
        //-----------------------------------------------------------------//
		const sat_info& get_satellite_info(uint16_t idx) const
		{
			if(idx < sinfo_num_) {
				return sinfo_[idx];
			} else {
				static sat_info si;
				return si;
			}
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  スタート
        */
        //-----------------------------------------------------------------//
		void start()
		{
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  サービス @n
					情報量に応じて呼ぶ（通常毎フレーム呼ぶ）
			@return 更新されたら「true」
        */
        //-----------------------------------------------------------------//
		bool service()
		{
			char ch;
			bool ret = false;
			while(sci_.recv_length() > 0) {
				ch = sci_.getch();
				if(ch == 0x0d) {
					line_[pos_] = 0;
					ret = decode_();
					pos_ = 0;
				} else {
					if(ch >= ' ' && ch <= 0x7f) {
						if(pos_ < sizeof(line_)) {
							line_[pos_] = ch;
							++pos_;
						}
					}
				}
			}
			return ret;
		}
	};
}

<commit_msg>fix time_t convert<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	NMEA デコード・クラス @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cstring>
#include "common/time.h"

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  NMEA デコード・クラス
		@param[in]	SCI_IO	シリアルＩ／Ｏ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SCI_IO>
	class nmea_dec {

	public:

		static const uint32_t sinfo_num_ = 12;		///< 衛星情報の最大数

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  衛星パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct sat_info {
			char	no_[4];  	///< 衛星番号
			char	elv_[4];	///< 衛星仰角(Elevation)、０～９０度
			char	azi_[4];	///< 衛星方位角(Azimuth)、０～３５９度
			char	cn_[4];		///< キャリア／ノイズ比、０～９９dB

			sat_info() {
				no_[0] = 0;
				elv_[0] = 0;
				azi_[0] = 0;
				cn_[0] = 0;
			}
		};

	private:
		SCI_IO&		sci_;

		uint16_t	pos_;
		char		line_[128];

		char		time_[12];  // 時間
		char		lat_[12];   // 緯度(latitude)
		char		ns_[2];     // 北緯、南緯
		char		lon_[12];   // 経度(longitude)
		char		ew_[2];     // 東経、西経
		char		q_[2];      // 品質
		char		satellite_[4];  // 衛星数
		char		hq_[4];		// 水平精度低下率
		char		alt_[6];	// 海抜高度(Altitude above sea level)
		char		alt_unit_[2];	// 海抜高度単位

		char		date_[8];   // 日付

		uint16_t	sidx_;
		sat_info	sinfo_[sinfo_num_];	// 衛星情報

		uint32_t	id_;
		uint32_t	iid_;

		static uint16_t word_(const char* src)
		{
			const char* top = src;
			char ch;
			while((ch = *src++) != 0) {
				if(ch == ',' || ch == '*') return src - top;
			}
			return 0;
		}

		static void copy_word_(char* dst, const char* src, uint16_t len)
		{
			std::strncpy(dst, src, len);
			dst[len] = 0;
		}

		static int32_t get_dec_(const char* t, uint16_t n = 0)
		{
			int32_t val = 0;
			char ch;
			while((ch = *t++) != 0) {
				if('0' <= ch && ch <= '9') {
					val *= 10;
					val += ch - '0';
				} else {
					break;
				}
				if(n > 0) {
					--n;
					if(n == 0) break;
				}
			}
			return val;
		}

		bool decode_()
		{
			if(line_[0] != '$') return false;

			if(std::strncmp(&line_[1], "GPGGA,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 0) copy_word_(time_, p, l - 1);
					else if(n == 1) copy_word_(lat_, p, l - 1);
					else if(n == 2) copy_word_(ns_, p, l - 1);
					else if(n == 3) copy_word_(lon_, p, l - 1);
					else if(n == 4) copy_word_(ew_, p, l - 1);
					else if(n == 5) copy_word_(q_, p, l - 1);
					else if(n == 6) copy_word_(satellite_, p, l - 1);
					else if(n == 7) copy_word_(hq_, p, l - 1);
					else if(n == 8) copy_word_(alt_, p, l - 1);
					else if(n == 9) copy_word_(alt_unit_, p, l - 1);
					else {
						break;
					}
					p += l;
					++n;
				}
			} else if(std::strncmp(&line_[1], "GPRMC,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 8) copy_word_(date_, p, l - 1);
					p += l;
					++n;
				}
			} else if(std::strncmp(&line_[1], "GPGSV,", 6) == 0) {
				const char* p = &line_[7];
				uint16_t n = 0;
				uint16_t l;
				while((l = word_(p)) != 0) {
					if(n == 0) ;
					else if(n == 1) ;
// std::strncpy(date_, p, l - 1);
					p += l;
					++n;
				}
				++iid_;
			} else if(std::strncmp(&line_[1], "GPVTG,", 6) == 0) {
				++id_;
				return true;
			}
			return false;
		}

	public:
        //-----------------------------------------------------------------//
        /*!
            @brief  コンストラクター
        */
        //-----------------------------------------------------------------//
		nmea_dec(SCI_IO& sci) : sci_(sci), pos_(0), sidx_(0), id_(0), iid_(0) {
			line_[0] = 0;
			time_[0] = 0;
			lat_[0] = 0;
			ns_[0] = 0;
			lon_[0] = 0;
			ew_[0] = 0;
			q_[0] = 0;
			satellite_[0] = 0;
			hq_[0] = 0;
			alt_[0] = 0;
			alt_unit_[0] = 0;

			date_[0] = 0;
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  処理ＩＤを取得
			@return 処理ＩＤ
        */
        //-----------------------------------------------------------------//
		uint32_t get_id() const { return id_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  情報処理ＩＤを取得
			@return 情報処理ＩＤ
        */
        //-----------------------------------------------------------------//
		uint32_t get_iid() const { return iid_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  時間を取得
			@return 時間
        */
        //-----------------------------------------------------------------//
		const char* get_time() const { return time_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  日付を取得
			@return 日付
        */
        //-----------------------------------------------------------------//
		const char* get_date() const { return date_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  時間「time_t」を取得（グリニッチ時間）
			@return 時間「time_t」
        */
        //-----------------------------------------------------------------//
		time_t get_gmtime() const {
			tm ts;
			ts.tm_sec  = get_dec_(&time_[4], 2);
			ts.tm_min  = get_dec_(&time_[2], 2);
			ts.tm_hour = get_dec_(&time_[0], 2);
			ts.tm_mday = get_dec_(&date_[0], 2);
			ts.tm_mon  = get_dec_(&date_[2], 2) - 1;
			ts.tm_year = get_dec_(&date_[4], 2);
			ts.tm_year += 100;  // 起点１９００年
			return mktime_gmt(&ts);
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  緯度を取得
			@return 緯度
        */
        //-----------------------------------------------------------------//
		const char* get_lat() const { return lat_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  経度を取得
			@return 経度
        */
        //-----------------------------------------------------------------//
		const char* get_lon() const { return lon_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  品質を取得
			@return 品質
        */
        //-----------------------------------------------------------------//
		const char* get_quality() const { return q_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  衛星数を取得
			@return 衛星数
        */
        //-----------------------------------------------------------------//
		const char* get_satellite() const { return satellite_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  水平品質を取得
			@return 水平品質
        */
        //-----------------------------------------------------------------//
		const char* get_holizontal_quality() const { return hq_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  海抜高度を取得
			@return 海抜高度
        */
        //-----------------------------------------------------------------//
		const char* get_altitude() const { return alt_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  海抜高度単位を取得
			@return 海抜高度単位
        */
        //-----------------------------------------------------------------//
		const char* get_altitude_unit() const { return alt_unit_; }

        //-----------------------------------------------------------------//
        /*!
            @brief  衛星情報の取得
			@param[in]	idx	衛星インデックス
			@return 衛星情報
        */
        //-----------------------------------------------------------------//
		const sat_info& get_satellite_info(uint16_t idx) const
		{
			if(idx < sinfo_num_) {
				return sinfo_[idx];
			} else {
				static sat_info si;
				return si;
			}
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  スタート
        */
        //-----------------------------------------------------------------//
		void start()
		{
		}

        //-----------------------------------------------------------------//
        /*!
            @brief  サービス @n
					情報量に応じて呼ぶ（通常毎フレーム呼ぶ）
			@return 更新されたら「true」
        */
        //-----------------------------------------------------------------//
		bool service()
		{
			char ch;
			bool ret = false;
			while(sci_.recv_length() > 0) {
				ch = sci_.getch();
				if(ch == 0x0d) {
					line_[pos_] = 0;
					ret = decode_();
					pos_ = 0;
				} else {
					if(ch >= ' ' && ch <= 0x7f) {
						if(pos_ < sizeof(line_)) {
							line_[pos_] = ch;
							++pos_;
						}
					}
				}
			}
			return ret;
		}
	};
}

<|endoftext|>


<commit_before>//
//  basic_iostream.hpp
//  fibio
//
//  Created by Chen Xu on 14-3-8.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#ifndef fibio_basic_iostream_hpp
#define fibio_basic_iostream_hpp

#include <streambuf>
#include <iostream>
#include <chrono>
#include <fibio/fibers/fiber.hpp>

namespace fibio { namespace stream {
    constexpr size_t bf_size=4096;
    constexpr std::streamsize pb_size=4;

    template<typename StreamDescriptor>
    class streambuf : public std::streambuf {
    public:
        streambuf()
        : sd_(fibio::fibers::this_fiber::detail::get_io_service())
        {
            memset(buffer_in_, 0, bf_size);
            memset(buffer_out_, 0, bf_size);
            setg(buffer_in_ + pb_size,
                 buffer_in_ + pb_size,
                 buffer_in_ + pb_size);
            setp(buffer_out_,
                 buffer_out_ + bf_size - 1 );
        }

        streambuf(asio::io_service &iosvc)
        : sd_(iosvc)
        {
            memset(buffer_in_, 0, bf_size);
            memset(buffer_out_, 0, bf_size);
            setg(buffer_in_ + pb_size,
                 buffer_in_ + pb_size,
                 buffer_in_ + pb_size);
            setp(buffer_out_,
                 buffer_out_ + bf_size - 1 );
        }

        /**
         * Constructor
         *
         * @param sd underlying stream device, such as socket or pipe
         */
        streambuf(StreamDescriptor &&sd)
        : sd_(std::move(sd))
        {
            memset(buffer_in_, 0, bf_size);
            memset(buffer_out_, 0, bf_size);
            setg(buffer_in_ + pb_size,
                 buffer_in_ + pb_size,
                 buffer_in_ + pb_size);
            setp(buffer_out_,
                 buffer_out_ + bf_size - 1 );
        }

        // Movable
        streambuf(streambuf &&src)
        : sd_(std::move(src.sd_))
        {
            memcpy(buffer_in_, src.buffer_in_, bf_size);
            memcpy(buffer_out_, src.buffer_out_, bf_size);
        }

        // Non-copyable
        streambuf(const streambuf&) = delete;
        streambuf& operator=(const streambuf&) = delete;

        ~streambuf()
        { close(); }

        template <typename... T>
        std::error_code open(T... x) {
            return fibio::io::open(sd_, x...);
        }

        template <typename... T>
        std::error_code connect(T... x) {
            sd_.close();
            typename StreamDescriptor::protocol_type::resolver::query q(x...);
            typename StreamDescriptor::protocol_type::endpoint ep=fibio::io::resolve(q);
            typedef typename StreamDescriptor::protocol_type::endpoint endpoint_t;
            return fibio::io::connect(sd_, ep, endpoint_t(), connect_timeout_);
        }

        inline bool is_open() const
        { return sd_.is_open(); }

        inline void close() {
            if(sd_.is_open()) {
                std::error_code ec;
                sd_.close(ec);
            }
        }

        typename StreamDescriptor::native_handle_type release()
        { return sd_.release(); }

        inline StreamDescriptor &stream_descriptor()
        { return sd_; }

        template<typename Rep, typename Period>
        void set_connect_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { connect_timeout_=std::chrono::duration_cast<std::chrono::microseconds>(timeout_duration).count(); }

        template<typename Rep, typename Period>
        void set_read_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { read_timeout_=std::chrono::duration_cast<std::chrono::microseconds>(timeout_duration).count(); }

        template<typename Rep, typename Period>
        void set_write_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { write_timeout_=std::chrono::duration_cast<std::chrono::microseconds>(timeout_duration).count(); }

    protected:
        virtual int_type overflow(int_type c) override {
            if (unbuffered_) {
                if (traits_type::eq_int_type(c, traits_type::eof())) {
                    // Nothing to do.
                    return traits_type::not_eof(c);
                }
                std::error_code ec;
                async_write_char_with_timeout(c, ec);
                if(ec)
                    return traits_type::eof();
                return c;
            } else {
                if ( c != traits_type::eof() ) {
                    *pptr() = c;
                    pbump(1);
                    if (nudge_())
                        return c;
                } else {
                    c = 0;
                }

                return traits_type::eof();
            }
        }

        virtual int_type underflow() override {
            if ( gptr() < egptr() )
                return traits_type::to_int_type( *gptr() );

            if ( 0 > fetch_() )
                return traits_type::eof();
            else
                return traits_type::to_int_type( *gptr() );
        }

        virtual int sync() override
        { return nudge_()==0 ? 0 : -1; }

        virtual std::streamsize showmanyc() override {
            if ( gptr() == egptr() ) {
                // Getting area is empty
                return fetch_();
            }
            return egptr()-gptr();
        }

        virtual std::streambuf* setbuf(char_type* s, std::streamsize n) override {
            if (pptr() == pbase() && s == 0 && n == 0) {
                // Turn off output buffering
                unbuffered_ = true;
                setp(0, 0);
                return this;
            }
            return 0;
        }

    private:
        void async_write_char_with_timeout(char c, std::error_code &ec) {
            fibio::io::write_some(sd_, &c, 1, write_timeout_, ec);
        }

        size_t async_read_some_with_timeout(std::error_code &ec) {
            return fibio::io::read_some(sd_,
                                        buffer_in_ + pb_size,
                                        bf_size - pb_size,
                                        read_timeout_,
                                        ec);
        }

        void async_write_with_timeout(std::error_code &ec) {
            char *ptr=pbase();
            size_t size=pptr()-pbase();
            while(size>0) {
                size_t bytes_transferred=fibio::io::write_some(sd_,
                                                               ptr,
                                                               size,
                                                               write_timeout_,
                                                               ec);
                ptr+=bytes_transferred;
                size-=bytes_transferred;
            }
        }

        int_type fetch_() {
            std::streamsize num = std::min(static_cast<std::streamsize>(gptr() - eback()),
                                           pb_size);

            std::memmove(buffer_in_ + (pb_size - num),
                         gptr() - num,
                         num);

            std::error_code ec;
            std::size_t n = async_read_some_with_timeout(ec);
            if (ec) {
                setg(0, 0, 0);
                return -1;
            }
            setg(buffer_in_ + pb_size - num,
                 buffer_in_ + pb_size,
                 buffer_in_ + pb_size + n);
            return n;
        }

        int_type nudge_() {
            // Don't flush empty buffer
            if(pptr()<=pbase()) return 0;
            std::error_code ec;
            async_write_with_timeout(ec);
            setp(buffer_out_,
                 buffer_out_ + bf_size - 1);
            return ec ? traits_type::eof() : 0;
        }

        StreamDescriptor sd_;
        char buffer_in_[bf_size];
        char buffer_out_[bf_size];
        int connect_timeout_=0;
        int read_timeout_=0;
        int write_timeout_=0;
        bool unbuffered_=false;
    };

    template<typename StreamDescriptor>
    struct iostream_base {
        typedef streambuf<StreamDescriptor> streambuf_t;

        iostream_base()=default;

        iostream_base(StreamDescriptor &&s)
        : sbuf_(std::move(s))
        {}

        iostream_base(iostream_base<StreamDescriptor> &&other)
        : sbuf_(std::move(other.sbuf_))
        {}

        streambuf_t sbuf_;
    };

    template<typename StreamDescriptor>
    class basic_iostream : private iostream_base<StreamDescriptor>, public std::iostream {
    public:
        typedef streambuf<StreamDescriptor> streambuf_t;
        typedef iostream_base<StreamDescriptor> streambase_t;

        basic_iostream()
        : streambase_t()
        , std::iostream(&(this->sbuf_))
        {}

        /**
         * Constructor
         *
         * @param s underlying stream device, such as socket or pipe
         */
        basic_iostream(StreamDescriptor &&s)
        : streambase_t(std::move(s))
        , std::iostream(&(this->sbuf_))
        {}

        // Non-movable
        basic_iostream(basic_iostream &&src)=delete;

        // Non-copyable
        basic_iostream(const basic_iostream&) = delete;
        basic_iostream& operator=(const basic_iostream&) = delete;

        template <typename... T>
        std::error_code open(T... x) {
            return this->sbuf_.open(x...);
        }

        template <typename... T>
        std::error_code connect(T... x) {
            return this->sbuf_.connect(x...);
        }

        /**
         * Close underlying stream device, flushing if necessary
         */
        inline void close() {
            if(streambuf().is_open()) {
                flush();
            }
            streambuf().close();
        }

        inline bool is_open() const
        { return this->sbuf_.is_open(); }

        inline streambuf_t &streambuf()
        { return this->sbuf_; }

        inline const streambuf_t &streambuf() const
        { return this->sbuf_; }

        inline StreamDescriptor &stream_descriptor()
        { return streambuf().stream_descriptor(); }

        template<typename Rep, typename Period>
        void set_connect_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { this->sbuf_.set_connect_timeout(timeout_duration); }

        template<typename Rep, typename Period>
        void set_read_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { this->sbuf_.set_read_timeout(timeout_duration); }

        template<typename Rep, typename Period>
        void set_write_timeout(const std::chrono::duration<Rep, Period>& timeout_duration)
        { this->sbuf_.set_write_timeout(timeout_duration); }

    };
}}  // End of namespace fibio::stream

#endif
<commit_msg>remove unused file<commit_after><|endoftext|>


<commit_before>#ifndef __ABSTRACT_DOMAINS_HH__
#define __ABSTRACT_DOMAINS_HH__

#include "crab_llvm/crab_cfg.hh"

#include "crab/domains/linear_constraints.hpp"
#include "crab/domains/intervals.hpp"
#include "crab/domains/dis_intervals.hpp"
#include "crab/domains/sparse_dbm.hpp"
#include "crab/domains/split_dbm.hpp"
#include "crab/domains/boxes.hpp"
#include "crab/domains/apron_domains.hpp"
//#include "crab/domains/array_sparse_graph.hpp"
#include "crab/domains/array_smashing.hpp"
#include "crab/domains/term_equiv.hpp"
//#include "crab/domains/nullity.hpp"
#include "crab/domains/flat_boolean_domain.hpp"
#include "crab/domains/combined_domains.hpp"

/*
   Definition of the abstract domains (no instantiation done here)
*/

namespace crab_llvm {

  using namespace crab::domains;
  using namespace ikos;

  /// --- Types for linear constraints and expressions
  typedef ikos::linear_expression<z_number, varname_t> z_lin_exp_t;
  typedef ikos::linear_constraint<z_number, varname_t> z_lin_cst_t;
  typedef ikos::linear_constraint_system<z_number, varname_t> z_lin_cst_sys_t;

  /* BEGIN MACROS only for internal use */
  // The base numerical domain
  #define BASE(DOM) base_ ## DOM
  // Array functor domain where the base domain is a reduced product
  // of a boolean domain with the numerical domain DOM.
  #define ARRAY_BOOL_NUM(DOM) \
    typedef array_smashing<flat_boolean_numerical_domain<BASE(DOM)> > DOM
  // Array functor domain where the base domain is DOM
  #define ARRAY_NUM(DOM) \
    typedef array_smashing<BASE(DOM)> DOM;
  /* END MACROS only for internal use */

  //////
  // Base domains
  //////

  /// -- Intervals
  #if 1
  typedef interval_domain<z_number, varname_t> BASE(interval_domain_t);
  #else
  // -- enable apron version for more precise backward operations
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_INT>
  BASE(interval_domain_t);
  #endif
  /// -- Zones using sparse DBMs (SAS'16)
  typedef SpDBM_impl::DefaultParams<z_number> SparseDBMGraph;
  typedef SparseDBM<z_number, varname_t, SparseDBMGraph> BASE(dbm_domain_t);
  /// -- Zones using sparse DBMs in split normal form (SAS'16)
  typedef SDBM_impl::DefaultParams<z_number> SplitDBMGraph;
  typedef SplitDBM<z_number, varname_t, SplitDBMGraph> BASE(split_dbm_domain_t);
  /// -- Boxes
  typedef boxes_domain<z_number, varname_t> BASE(boxes_domain_t);
  /// -- DisIntervals
  typedef dis_interval_domain <z_number, varname_t> BASE(dis_interval_domain_t);
  /// -- Elina/Apron domains
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_OPT_OCT>
  BASE(opt_oct_apron_domain_t);
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_PK>
  BASE(pk_apron_domain_t);
  /// -- Reduced product of intervals with congruences
  typedef numerical_congruence_domain<BASE(interval_domain_t)> BASE(ric_domain_t);
  /// -- Term functor domain with Intervals (VMCAI'16)
  typedef crab::cfg::var_factory_impl::str_var_alloc_col::varname_t str_varname_t;
  typedef interval_domain<z_number, str_varname_t> str_interval_dom_t;
  typedef term::TDomInfo<z_number, varname_t, str_interval_dom_t> idom_info;
  typedef term_domain<idom_info> BASE(term_int_domain_t);
  /// -- Term functor domain with DisIntervals (VMCAI'16)
  typedef dis_interval_domain<z_number, str_varname_t> str_dis_interval_dom_t;
  typedef term::TDomInfo<z_number, varname_t, str_dis_interval_dom_t> dis_idom_info;
  typedef term_domain<dis_idom_info> BASE(term_dis_int_domain_t);
  /// -- Reduced product of Term(DisIntervals) with split zones
  typedef reduced_numerical_domain_product2<BASE(term_dis_int_domain_t),
					    BASE(split_dbm_domain_t)> BASE(num_domain_t);

  ARRAY_BOOL_NUM(interval_domain_t);
  ARRAY_BOOL_NUM(dbm_domain_t);
  ARRAY_BOOL_NUM(split_dbm_domain_t);
  ARRAY_BOOL_NUM(dis_interval_domain_t);
  ARRAY_BOOL_NUM(opt_oct_apron_domain_t);
  ARRAY_BOOL_NUM(pk_apron_domain_t);
  ARRAY_BOOL_NUM(ric_domain_t);
  ARRAY_BOOL_NUM(term_int_domain_t);
  ARRAY_BOOL_NUM(term_dis_int_domain_t);
  ARRAY_BOOL_NUM(num_domain_t);
  // Boxes can reason natively about booleans so that's why we don't
  // combine it with a boolean domain.
  ARRAY_NUM(boxes_domain_t);

} // end namespace crab-llvm

#endif
<commit_msg>Domain used only for debugging<commit_after>#ifndef __ABSTRACT_DOMAINS_HH__
#define __ABSTRACT_DOMAINS_HH__

#include "crab_llvm/crab_cfg.hh"

#include "crab/domains/linear_constraints.hpp"
#include "crab/domains/intervals.hpp"
#include "crab/domains/dis_intervals.hpp"
#include "crab/domains/sparse_dbm.hpp"
#include "crab/domains/split_dbm.hpp"
#include "crab/domains/boxes.hpp"
#include "crab/domains/apron_domains.hpp"
//#include "crab/domains/array_sparse_graph.hpp"
#include "crab/domains/array_smashing.hpp"
#include "crab/domains/term_equiv.hpp"
//#include "crab/domains/nullity.hpp"
#include "crab/domains/flat_boolean_domain.hpp"
#include "crab/domains/combined_domains.hpp"
//#include "crab/domains/diff_domain.hpp" /* only debugging */

/*
   Definition of the abstract domains (no instantiation done here)
*/

namespace crab_llvm {

  using namespace crab::domains;
  using namespace ikos;

  /// --- Types for linear constraints and expressions
  typedef ikos::linear_expression<z_number, varname_t> z_lin_exp_t;
  typedef ikos::linear_constraint<z_number, varname_t> z_lin_cst_t;
  typedef ikos::linear_constraint_system<z_number, varname_t> z_lin_cst_sys_t;

  /* BEGIN MACROS only for internal use */
  // The base numerical domain
  #define BASE(DOM) base_ ## DOM
  // Array functor domain where the base domain is a reduced product
  // of a boolean domain with the numerical domain DOM.
  #define ARRAY_BOOL_NUM(DOM) \
    typedef array_smashing<flat_boolean_numerical_domain<BASE(DOM)> > DOM
  // Array functor domain where the base domain is DOM
  #define ARRAY_NUM(DOM) \
    typedef array_smashing<BASE(DOM)> DOM;
  /* END MACROS only for internal use */

  //////
  // Base domains
  //////

  /// -- Intervals
  #if 1
  typedef interval_domain<z_number, varname_t> BASE(interval_domain_t);
  #else
  // -- enable apron version for more precise backward operations
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_INT>
  BASE(interval_domain_t);
  #endif
  /// -- Zones using sparse DBMs (SAS'16)
  typedef SpDBM_impl::DefaultParams<z_number> SparseDBMGraph;
  typedef SparseDBM<z_number, varname_t, SparseDBMGraph> BASE(dbm_domain_t);
  /// -- Zones using sparse DBMs in split normal form (SAS'16)
  typedef SDBM_impl::DefaultParams<z_number> SplitDBMGraph;
  typedef SplitDBM<z_number, varname_t, SplitDBMGraph> BASE(split_dbm_domain_t);
  /// -- Boxes
  typedef boxes_domain<z_number, varname_t> BASE(boxes_domain_t);
  // typedef diff_domain<flat_boolean_numerical_domain<BASE(interval_domain_t)>,
  // 		         boxes_domain<z_number, varname_t> > BASE(boxes_domain_t);
  /// -- DisIntervals
  typedef dis_interval_domain <z_number, varname_t> BASE(dis_interval_domain_t);
  /// -- Elina/Apron domains
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_OPT_OCT>
  BASE(opt_oct_apron_domain_t);
  typedef apron_domain<z_number, varname_t, apron_domain_id_t::APRON_PK>
  BASE(pk_apron_domain_t);
  /// -- Reduced product of intervals with congruences
  typedef numerical_congruence_domain<BASE(interval_domain_t)> BASE(ric_domain_t);
  /// -- Term functor domain with Intervals (VMCAI'16)
  typedef crab::cfg::var_factory_impl::str_var_alloc_col::varname_t str_varname_t;
  typedef interval_domain<z_number, str_varname_t> str_interval_dom_t;
  typedef term::TDomInfo<z_number, varname_t, str_interval_dom_t> idom_info;
  typedef term_domain<idom_info> BASE(term_int_domain_t);
  /// -- Term functor domain with DisIntervals (VMCAI'16)
  typedef dis_interval_domain<z_number, str_varname_t> str_dis_interval_dom_t;
  typedef term::TDomInfo<z_number, varname_t, str_dis_interval_dom_t> dis_idom_info;
  typedef term_domain<dis_idom_info> BASE(term_dis_int_domain_t);
  /// -- Reduced product of Term(DisIntervals) with split zones
  typedef reduced_numerical_domain_product2<BASE(term_dis_int_domain_t),
					    BASE(split_dbm_domain_t)> BASE(num_domain_t);

  ARRAY_BOOL_NUM(interval_domain_t);
  ARRAY_BOOL_NUM(dbm_domain_t);
  ARRAY_BOOL_NUM(split_dbm_domain_t);
  ARRAY_BOOL_NUM(dis_interval_domain_t);
  ARRAY_BOOL_NUM(opt_oct_apron_domain_t);
  ARRAY_BOOL_NUM(pk_apron_domain_t);
  ARRAY_BOOL_NUM(ric_domain_t);
  ARRAY_BOOL_NUM(term_int_domain_t);
  ARRAY_BOOL_NUM(term_dis_int_domain_t);
  ARRAY_BOOL_NUM(num_domain_t);
  // Boxes can reason natively about booleans so that's why we don't
  // combine it with a boolean domain.
  ARRAY_NUM(boxes_domain_t);

} // end namespace crab-llvm

#endif
<|endoftext|>


<commit_before>#include <cstdlib>
#include "astutil.h"
#include "bb.h"
#include "bitVec.h"
#include "expr.h"
#include "stmt.h"
#include "view.h"

BasicBlock::BasicBlock()
  : id(nextid++) {}

#define BB_START()                              \
  basicBlock = new BasicBlock()

// The assert tests that the expression we are adding to this basic block
// has not already been deleted.
#define BB_ADD(expr)                            \
  do {                                          \
    INT_ASSERT(expr);                           \
    basicBlock->exprs.add(expr);                \
  } while (0)

#define BB_STOP()                               \
  fn->basicBlocks->add(Steal())

#define BB_RESTART()                            \
  do {                                          \
    BB_STOP();                                  \
    BB_START();                                 \
  } while (0)

#define BBB(stmt)                               \
    buildBasicBlocks(fn, stmt)

#define BB_THREAD(src, dst)                     \
  do {                                          \
    dst->ins.add(src);                          \
    src->outs.add(dst);                         \
  } while (0)

//# Statics
BasicBlock* BasicBlock::basicBlock;
Map<LabelSymbol*,Vec<BasicBlock*>*> BasicBlock::gotoMaps;
Map<LabelSymbol*,BasicBlock*> BasicBlock::labelMaps;
int BasicBlock::nextid;

// Returns true if the class invariants have been preserved.
bool BasicBlock::isOK()
{
  // Right now we just test that all entries are valid.
  forv_Vec(Expr, expr, exprs)
    if (expr == 0) return false;
  return true;
}

// Reset the shared statics.
void BasicBlock::reset(FnSymbol* fn)
{
  if (fn->basicBlocks)
  {
    forv_Vec(BasicBlock, bb, *fn->basicBlocks)
      delete bb;
    delete fn->basicBlocks;
  }
  fn->basicBlocks = new Vec<BasicBlock*>();
  gotoMaps.clear();
  labelMaps.clear();
  nextid = 0;
}

BasicBlock* BasicBlock::Steal()
{
  BasicBlock* temp = basicBlock;
  basicBlock = 0;
  return temp;
}

// This is the top-level (public) builder function.
void buildBasicBlocks(FnSymbol* fn)
{
  BasicBlock::reset(fn);
  BasicBlock::basicBlock = new BasicBlock();
  BasicBlock::buildBasicBlocks(fn, fn->body);
  fn->basicBlocks->add(BasicBlock::Steal());
}

void BasicBlock::buildBasicBlocks(FnSymbol* fn, Expr* stmt)
{
  if (!stmt) return;

  if (BlockStmt* s = toBlockStmt(stmt))
  {
    // If a loop statement.
    if (s->blockInfo)
    {
      BasicBlock* top = basicBlock;
      BB_RESTART();
      // Assumes that blockInfo is never null.
      BB_ADD(s->blockInfo);
      BasicBlock* loopTop = basicBlock;
      for_alist(stmt, s->body) {
        BBB(stmt);
      }
      BasicBlock* loopBottom = basicBlock;
      BB_RESTART();
      BasicBlock* bottom = basicBlock;
      BB_THREAD(top, loopTop);
      BB_THREAD(loopBottom, bottom);
      BB_THREAD(loopBottom, loopTop);
      BB_THREAD(top, bottom);
    }
    else
    {
      for_alist(stmt, s->body)
        BBB(stmt);
    }
  }
  else if (CondStmt* s = toCondStmt(stmt))
  {
    INT_ASSERT(s->condExpr);
    BB_ADD(s->condExpr);
    BasicBlock* top = basicBlock;
    BB_RESTART();
    BB_THREAD(top, basicBlock);
    BBB(s->thenStmt);
    BasicBlock* thenBottom = basicBlock;
    BB_RESTART();
    if (s->elseStmt)
    {
      BB_THREAD(top, basicBlock);
      BBB(s->elseStmt);
      BasicBlock* elseBottom = basicBlock;
      BB_RESTART();
      BB_THREAD(elseBottom, basicBlock);
    }
    else
    {
      BB_THREAD(top, basicBlock);
    }
    BB_THREAD(thenBottom, basicBlock);
  } else if (GotoStmt* s = toGotoStmt(stmt)) {
    LabelSymbol* label = toLabelSymbol(toSymExpr(s->label)->var);
    if (BasicBlock* bb = labelMaps.get(label)) {
      BB_THREAD(basicBlock, bb);
    } else {
      Vec<BasicBlock*>* vbb = gotoMaps.get(label);
      if (!vbb)
        vbb = new Vec<BasicBlock*>();
      vbb->add(basicBlock);
      gotoMaps.put(label, vbb);
    }
    BB_ADD(s); // Put the goto at the end of its block.
    BB_RESTART();
  } else {
    DefExpr* def = toDefExpr(stmt);
    if (def && toLabelSymbol(def->sym)) {
      // If a label appears in the middle of a block,
      // we start a new block.
      if (basicBlock->exprs.count() > 0)
      {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BB_THREAD(top, basicBlock);
      }
      BB_ADD(def); // Put the label def at the start of its block.

      // OK, this statement is a label def, so get the label.
      LabelSymbol* label = toLabelSymbol(def->sym);

      // See if we have any unresolved references to this label,
      // and resolve them.
      if (Vec<BasicBlock*>* vbb = gotoMaps.get(label)) {
        forv_Vec(BasicBlock, bb, *vbb) {
          BB_THREAD(bb, basicBlock);
        }
      }
      labelMaps.put(label, basicBlock);
    } else {
      BB_ADD(stmt);
    }
  }
}

// Returns true if the basic block structure is OK, false otherwise.
bool verifyBasicBlocks(FnSymbol* fn)
{
  forv_Vec(BasicBlock, bb, *fn->basicBlocks)
  {
    if (! bb->isOK())
      return false;
  }
  return true;
}

void buildLocalsVectorMap(FnSymbol* fn,
                          Vec<Symbol*>& locals,
                          Map<Symbol*,int>& localMap) {
  int i = 0;
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    forv_Vec(Expr, expr, bb->exprs) {
      if (DefExpr* def = toDefExpr(expr)) {
        if (toVarSymbol(def->sym)) {
          locals.add(def->sym);
          localMap.put(def->sym, i++);
        }
      }
    }
  }
}

//#define DEBUG_FLOW
void backwardFlowAnalysis(FnSymbol* fn,
                          Vec<BitVec*>& GEN,
                          Vec<BitVec*>& KILL,
                          Vec<BitVec*>& IN,
                          Vec<BitVec*>& OUT) {
  bool iterate = true;
  while (iterate) {
    iterate = false;
    int i = 0;
    forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
      for (int j = 0; j < IN.v[i]->ndata; j++) {
        unsigned new_in = (OUT.v[i]->data[j] & ~KILL.v[i]->data[j]) | GEN.v[i]->data[j];
        if (new_in != IN.v[i]->data[j]) {
          IN.v[i]->data[j] = new_in;
          iterate = true;
        }
        unsigned new_out = 0;
        forv_Vec(BasicBlock, bbout, bb->outs) {
          new_out = new_out | IN.v[bbout->id]->data[j];
        }
        if (new_out != OUT.v[i]->data[j]) {
          OUT.v[i]->data[j] = new_out;
          iterate = true;
        }
      }
      i++;
    }
#ifdef DEBUG_FLOW
    printf("IN\n"); printBitVectorSets(IN);
    printf("OUT\n"); printBitVectorSets(OUT);
#endif
  }
}

void forwardFlowAnalysis(FnSymbol* fn,
                         Vec<BitVec*>& GEN,
                         Vec<BitVec*>& KILL,
                         Vec<BitVec*>& IN,
                         Vec<BitVec*>& OUT,
                         bool intersect) {
  int nbbq = fn->basicBlocks->n; // size of bb queue
  Vec<int> bbq;
  BitVec bbs(nbbq);
  int iq = -1, nq = nbbq-1;      // index to first and last bb in bbq
  for (int i = 0; i < fn->basicBlocks->n; i++) {
    bbq.add(i);
    bbs.set(i);
  }
  while (iq != nq) {
    iq = (iq + 1) % nbbq;
    int i = bbq.v[iq];
    bbs.unset(i);
#ifdef DEBUG_FLOW
    if (iq == 0) {
      printf("IN\n"); printBitVectorSets(IN);
      printf("OUT\n"); printBitVectorSets(OUT);
    }
#endif
    BasicBlock* bb = fn->basicBlocks->v[i];
    bool change = false;
    for (int j = 0; j < IN.v[i]->ndata; j++) {
      if (bb->ins.n > 0) {
        unsigned new_in = (intersect) ? (unsigned)(-1) : 0;
        forv_Vec(BasicBlock, bbin, bb->ins) {
          if (intersect)
            new_in &= OUT.v[bbin->id]->data[j];
          else
            new_in |= OUT.v[bbin->id]->data[j];
        }
        if (new_in != IN.v[i]->data[j]) {
          IN.v[i]->data[j] = new_in;
          change = true;
        }
      }
      unsigned new_out = (IN.v[i]->data[j] & ~KILL.v[i]->data[j]) | GEN.v[i]->data[j];
      if (new_out != OUT.v[i]->data[j]) {
        OUT.v[i]->data[j] = new_out;
        change = true;
      }
    }
    if (change) {
      forv_Vec(BasicBlock, bbout, bb->outs) {
        if (!bbs.get(bbout->id)) {
          nq = (nq + 1) % nbbq;
          bbs.set(bbout->id);
          bbq.v[nq] = bbout->id;
        }
      }
    }
  }
}

void printBasicBlocks(FnSymbol* fn) {
  forv_Vec(BasicBlock, b, *fn->basicBlocks) {
    printf("%2d:  ", b->id);
    forv_Vec(BasicBlock, bb, b->ins) {
      printf("%d ", bb->id);
    }
    printf(" >  ");
    forv_Vec(BasicBlock, bb, b->outs) {
      printf("%d ", bb->id);
    }
    printf("\n");
    forv_Vec(Expr, expr, b->exprs) {
      if (expr)
        list_view_noline(expr);
      else
        printf("0 (null)\n");
    }
    printf("\n");
  }
}

void printLocalsVector(Vec<Symbol*> locals, Map<Symbol*,int>& localMap) {
  printf("Local Variables\n");
  forv_Vec(Symbol, local, locals) {
    printf("%2d: %s[%d]\n", localMap.get(local), local->name, local->id);
  }
  printf("\n");
}

void printDefsVector(Vec<SymExpr*> defs, Map<SymExpr*,int>& defMap) {
  printf("Variable Definitions\n");
  forv_Vec(SymExpr, def, defs) {
    printf("%2d: %s[%d] in %d\n", defMap.get(def), def->var->name,
           def->var->id, def->getStmtExpr()->id);
  }
  printf("\n");
}

void printLocalsVectorSets(Vec<BitVec*>& sets, Vec<Symbol*> locals) {
  int i = 0;
  forv_Vec(BitVec, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->size; j++) {
      if (set->get(j))
        printf("%s[%d] ", locals.v[j]->name, locals.v[j]->id);
    }
    printf("\n");
    i++;
  }
  printf("\n");
}

void printBitVectorSets(Vec<BitVec*>& sets) {
  int i = 0;
  forv_Vec(BitVec, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->size; j++) {
      printf("%d", (set->get(j)) ? 1 : 0);
      if ((j+1) % 10 == 0) printf(" ");
    }
    printf("\n");
    i++;
  }
  printf("\n");
}
<commit_msg>Add consistency checking to basic block analysis.<commit_after>#include <cstdlib>
#include "astutil.h"
#include "bb.h"
#include "bitVec.h"
#include "expr.h"
#include "stmt.h"
#include "view.h"

BasicBlock::BasicBlock()
  : id(nextid++) {}

#define BB_START()                              \
  basicBlock = new BasicBlock()

// The assert tests that the expression we are adding to this basic block
// has not already been deleted.
#define BB_ADD(expr)                            \
  do {                                          \
    INT_ASSERT(expr);                           \
    basicBlock->exprs.add(expr);                \
  } while (0)

#define BB_STOP()                               \
  fn->basicBlocks->add(Steal())

#define BB_RESTART()                            \
  do {                                          \
    BB_STOP();                                  \
    BB_START();                                 \
  } while (0)

#define BBB(stmt)                               \
    buildBasicBlocks(fn, stmt)

#define BB_THREAD(src, dst)                     \
  do {                                          \
    dst->ins.add(src);                          \
    src->outs.add(dst);                         \
  } while (0)

//# Statics
BasicBlock* BasicBlock::basicBlock;
Map<LabelSymbol*,Vec<BasicBlock*>*> BasicBlock::gotoMaps;
Map<LabelSymbol*,BasicBlock*> BasicBlock::labelMaps;
int BasicBlock::nextid;

// Returns true if the class invariants have been preserved.
bool BasicBlock::isOK()
{
  // Expressions must be live (non-NULL);
  forv_Vec(Expr, expr, exprs)
    if (expr == 0) return false;

  // Every in edge must have a corresponding out edge in the source block.
  forv_Vec(BasicBlock, source, ins) {
    bool found = false;
    forv_Vec(BasicBlock, bb, source->outs)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  // Every out edge must have a corresponding in edge in the target block.
  forv_Vec(BasicBlock, target, outs) {
    bool found = false;
    forv_Vec(BasicBlock, bb, target->ins)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  return true;
}

// Reset the shared statics.
void BasicBlock::reset(FnSymbol* fn)
{
  if (fn->basicBlocks)
  {
    forv_Vec(BasicBlock, bb, *fn->basicBlocks)
      delete bb;
    delete fn->basicBlocks;
  }
  fn->basicBlocks = new Vec<BasicBlock*>();
  gotoMaps.clear();
  labelMaps.clear();
  nextid = 0;
}

BasicBlock* BasicBlock::Steal()
{
  BasicBlock* temp = basicBlock;
  basicBlock = 0;
  return temp;
}

// This is the top-level (public) builder function.
void buildBasicBlocks(FnSymbol* fn)
{
  BasicBlock::reset(fn);
  BasicBlock::basicBlock = new BasicBlock();    // BB_START();
  BasicBlock::buildBasicBlocks(fn, fn->body);   // BBB(fn->body);
  fn->basicBlocks->add(BasicBlock::Steal());    // BB_STOP();

  INT_ASSERT(verifyBasicBlocks(fn));
}

void BasicBlock::buildBasicBlocks(FnSymbol* fn, Expr* stmt)
{
  if (!stmt) return;

  if (BlockStmt* s = toBlockStmt(stmt))
  {
    // If a loop statement.
    if (s->blockInfo)
    {
      BasicBlock* top = basicBlock;
      BB_RESTART();
      // Assumes that blockInfo is never null.
      BB_ADD(s->blockInfo);
      BasicBlock* loopTop = basicBlock;
      for_alist(stmt, s->body) {
        BBB(stmt);
      }
      BasicBlock* loopBottom = basicBlock;
      BB_RESTART();
      BasicBlock* bottom = basicBlock;
      BB_THREAD(top, loopTop);
      BB_THREAD(loopBottom, bottom);
      BB_THREAD(loopBottom, loopTop);
      BB_THREAD(top, bottom);
    }
    else
    {
      for_alist(stmt, s->body)
        BBB(stmt);
    }
  }
  else if (CondStmt* s = toCondStmt(stmt))
  {
    INT_ASSERT(s->condExpr);
    BB_ADD(s->condExpr);
    BasicBlock* top = basicBlock;
    BB_RESTART();
    BB_THREAD(top, basicBlock);
    BBB(s->thenStmt);
    BasicBlock* thenBottom = basicBlock;
    BB_RESTART();
    if (s->elseStmt)
    {
      BB_THREAD(top, basicBlock);
      BBB(s->elseStmt);
      BasicBlock* elseBottom = basicBlock;
      BB_RESTART();
      BB_THREAD(elseBottom, basicBlock);
    }
    else
    {
      BB_THREAD(top, basicBlock);
    }
    BB_THREAD(thenBottom, basicBlock);
  } else if (GotoStmt* s = toGotoStmt(stmt)) {
    LabelSymbol* label = toLabelSymbol(toSymExpr(s->label)->var);
    if (BasicBlock* bb = labelMaps.get(label)) {
      BB_THREAD(basicBlock, bb);
    } else {
      Vec<BasicBlock*>* vbb = gotoMaps.get(label);
      if (!vbb)
        vbb = new Vec<BasicBlock*>();
      vbb->add(basicBlock);
      gotoMaps.put(label, vbb);
    }
    BB_ADD(s); // Put the goto at the end of its block.
    BB_RESTART();
  } else {
    DefExpr* def = toDefExpr(stmt);
    if (def && toLabelSymbol(def->sym)) {
      // If a label appears in the middle of a block,
      // we start a new block.
      if (basicBlock->exprs.count() > 0)
      {
        BasicBlock* top = basicBlock;
        BB_RESTART();
        BB_THREAD(top, basicBlock);
      }
      BB_ADD(def); // Put the label def at the start of its block.

      // OK, this statement is a label def, so get the label.
      LabelSymbol* label = toLabelSymbol(def->sym);

      // See if we have any unresolved references to this label,
      // and resolve them.
      if (Vec<BasicBlock*>* vbb = gotoMaps.get(label)) {
        forv_Vec(BasicBlock, bb, *vbb) {
          BB_THREAD(bb, basicBlock);
        }
      }
      labelMaps.put(label, basicBlock);
    } else {
      BB_ADD(stmt);
    }
  }
}

// Returns true if the basic block structure is OK, false otherwise.
bool verifyBasicBlocks(FnSymbol* fn)
{
  forv_Vec(BasicBlock, bb, *fn->basicBlocks)
  {
    if (! bb->isOK())
      return false;
  }
  return true;
}

void buildLocalsVectorMap(FnSymbol* fn,
                          Vec<Symbol*>& locals,
                          Map<Symbol*,int>& localMap) {
  int i = 0;
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    forv_Vec(Expr, expr, bb->exprs) {
      if (DefExpr* def = toDefExpr(expr)) {
        if (toVarSymbol(def->sym)) {
          locals.add(def->sym);
          localMap.put(def->sym, i++);
        }
      }
    }
  }
}

//#define DEBUG_FLOW
void backwardFlowAnalysis(FnSymbol* fn,
                          Vec<BitVec*>& GEN,
                          Vec<BitVec*>& KILL,
                          Vec<BitVec*>& IN,
                          Vec<BitVec*>& OUT) {
  bool iterate = true;
  while (iterate) {
    iterate = false;
    int i = 0;
    forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
      for (int j = 0; j < IN.v[i]->ndata; j++) {
        unsigned new_in = (OUT.v[i]->data[j] & ~KILL.v[i]->data[j]) | GEN.v[i]->data[j];
        if (new_in != IN.v[i]->data[j]) {
          IN.v[i]->data[j] = new_in;
          iterate = true;
        }
        unsigned new_out = 0;
        forv_Vec(BasicBlock, bbout, bb->outs) {
          new_out = new_out | IN.v[bbout->id]->data[j];
        }
        if (new_out != OUT.v[i]->data[j]) {
          OUT.v[i]->data[j] = new_out;
          iterate = true;
        }
      }
      i++;
    }
#ifdef DEBUG_FLOW
    printf("IN\n"); printBitVectorSets(IN);
    printf("OUT\n"); printBitVectorSets(OUT);
#endif
  }
}

void forwardFlowAnalysis(FnSymbol* fn,
                         Vec<BitVec*>& GEN,
                         Vec<BitVec*>& KILL,
                         Vec<BitVec*>& IN,
                         Vec<BitVec*>& OUT,
                         bool intersect) {
  int nbbq = fn->basicBlocks->n; // size of bb queue
  Vec<int> bbq;
  BitVec bbs(nbbq);
  int iq = -1, nq = nbbq-1;      // index to first and last bb in bbq
  for (int i = 0; i < fn->basicBlocks->n; i++) {
    bbq.add(i);
    bbs.set(i);
  }
  while (iq != nq) {
    iq = (iq + 1) % nbbq;
    int i = bbq.v[iq];
    bbs.unset(i);
#ifdef DEBUG_FLOW
    if (iq == 0) {
      printf("IN\n"); printBitVectorSets(IN);
      printf("OUT\n"); printBitVectorSets(OUT);
    }
#endif
    BasicBlock* bb = fn->basicBlocks->v[i];
    bool change = false;
    for (int j = 0; j < IN.v[i]->ndata; j++) {
      if (bb->ins.n > 0) {
        unsigned new_in = (intersect) ? (unsigned)(-1) : 0;
        forv_Vec(BasicBlock, bbin, bb->ins) {
          if (intersect)
            new_in &= OUT.v[bbin->id]->data[j];
          else
            new_in |= OUT.v[bbin->id]->data[j];
        }
        if (new_in != IN.v[i]->data[j]) {
          IN.v[i]->data[j] = new_in;
          change = true;
        }
      }
      unsigned new_out = (IN.v[i]->data[j] & ~KILL.v[i]->data[j]) | GEN.v[i]->data[j];
      if (new_out != OUT.v[i]->data[j]) {
        OUT.v[i]->data[j] = new_out;
        change = true;
      }
    }
    if (change) {
      forv_Vec(BasicBlock, bbout, bb->outs) {
        if (!bbs.get(bbout->id)) {
          nq = (nq + 1) % nbbq;
          bbs.set(bbout->id);
          bbq.v[nq] = bbout->id;
        }
      }
    }
  }
}

void printBasicBlocks(FnSymbol* fn) {
  forv_Vec(BasicBlock, b, *fn->basicBlocks) {
    printf("%2d:  ", b->id);
    forv_Vec(BasicBlock, bb, b->ins) {
      printf("%d ", bb->id);
    }
    printf(" >  ");
    forv_Vec(BasicBlock, bb, b->outs) {
      printf("%d ", bb->id);
    }
    printf("\n");
    forv_Vec(Expr, expr, b->exprs) {
      if (expr)
        list_view_noline(expr);
      else
        printf("0 (null)\n");
    }
    printf("\n");
  }
}

void printLocalsVector(Vec<Symbol*> locals, Map<Symbol*,int>& localMap) {
  printf("Local Variables\n");
  forv_Vec(Symbol, local, locals) {
    printf("%2d: %s[%d]\n", localMap.get(local), local->name, local->id);
  }
  printf("\n");
}

void printDefsVector(Vec<SymExpr*> defs, Map<SymExpr*,int>& defMap) {
  printf("Variable Definitions\n");
  forv_Vec(SymExpr, def, defs) {
    printf("%2d: %s[%d] in %d\n", defMap.get(def), def->var->name,
           def->var->id, def->getStmtExpr()->id);
  }
  printf("\n");
}

void printLocalsVectorSets(Vec<BitVec*>& sets, Vec<Symbol*> locals) {
  int i = 0;
  forv_Vec(BitVec, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->size; j++) {
      if (set->get(j))
        printf("%s[%d] ", locals.v[j]->name, locals.v[j]->id);
    }
    printf("\n");
    i++;
  }
  printf("\n");
}

void printBitVectorSets(Vec<BitVec*>& sets) {
  int i = 0;
  forv_Vec(BitVec, set, sets) {
    printf("%2d: ", i);
    for (int j = 0; j < set->size; j++) {
      printf("%d", (set->get(j)) ? 1 : 0);
      if ((j+1) % 10 == 0) printf(" ");
    }
    printf("\n");
    i++;
  }
  printf("\n");
}
<|endoftext|>


<commit_before>/*
 * Particle.hpp
 *
 *  Created on: 28.04.2010
 *      Author: gmueller
 */

#ifndef SMOOTH_PARTICLE_HPP_
#define SMOOTH_PARTICLE_HPP_

#include <ostream>
#include "gadget/Vector3.hpp"

class SmoothParticle {
public:
	Vector3f position;
	Vector3f bfield;
	float smoothingLength;

	static float kernel(float r) {
		if (r < 1.0) {
			return 1.0 - 1.5 * r * r + 0.75 * r * r * r;
		} else if (r < 2.0) {
			float x = (2.0 - r);
			return 0.25 * x * x * x;
		} else {
			return 0.0;
		}
	}

	static float kernel(float value, float center, float position, float hsml) {
		return value * kernel(std::fabs((center - position) / hsml));
	}

	static float kernel(float value, const Vector3f &center, const Vector3f &position, float hsml) {
		return value * kernel(std::fabs((center - position).length() / hsml));
	}

	float kernel(const Vector3f &center) {
		return value * kernel(std::fabs((center - position).length() / smoothingLength));
	}

};

inline std::ostream &operator <<(std::ostream &out, const SmoothParticle &v) {
	out << "(" << v.position.x << "," << v.position.x << "," << v.position.x
			<< "), " << "(" << v.bfield.x << "," << v.bfield.x << ","
			<< v.bfield.x << "), " << v.smoothingLength;
	return out;
}

#endif /* PARTICLE_HPP_ */
<commit_msg>fixed smooting kernel to match Dolag et al<commit_after>/*
 * Particle.hpp
 *
 *  Created on: 28.04.2010
 *      Author: gmueller
 */

#ifndef SMOOTH_PARTICLE_HPP_
#define SMOOTH_PARTICLE_HPP_

#include <ostream>
#include "gadget/Vector3.hpp"

class SmoothParticle {
public:
	Vector3f position;
	Vector3f bfield;
	float smoothingLength;

	static float kernel(float r) {
		if (r < 0.5) {
			return 1.0 + 6 * r * r * (r - 1);
		} else if (r < 1.0) {
			float x = (1 - r);
			return 2 * x * x * x;
		} else {
			return 0.0;
		}
	}

	static float kernel(float value, float center, float position, float hsml) {
		return value * kernel(std::fabs((center - position) / hsml));
	}

	static float kernel(float value, const Vector3f &center, const Vector3f &position, float hsml) {
		return value * kernel(std::fabs((center - position).length() / hsml));
	}

	float kernel(const Vector3f &center) {
		return value * kernel(std::fabs((center - position).length() / smoothingLength));
	}

};

inline std::ostream &operator <<(std::ostream &out, const SmoothParticle &v) {
	out << "(" << v.position.x << "," << v.position.x << "," << v.position.x
			<< "), " << "(" << v.bfield.x << "," << v.bfield.x << ","
			<< v.bfield.x << "), " << v.smoothingLength;
	return out;
}

#endif /* PARTICLE_HPP_ */
<|endoftext|>