<commit_before>/*****************************************************************************
 * ctrl_video.cpp
 *****************************************************************************
 * Copyright (C) 2004 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "ctrl_video.hpp"
#include "../src/theme.hpp"
#include "../src/vout_window.hpp"
#include "../src/os_graphics.hpp"
#include "../src/vlcproc.hpp"
#include "../src/vout_manager.hpp"
#include "../src/window_manager.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_resize.hpp"

CtrlVideo::CtrlVideo( intf_thread_t *pIntf, GenericLayout &rLayout,
                      bool autoResize, const UString &rHelp,
                      VarBool *pVisible ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_rLayout( rLayout ),
    m_xShift( 0 ), m_yShift( 0 ), m_bAutoResize( autoResize ),
    m_pVoutWindow( NULL ), m_bIsUseable( false )
{
    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    rFullscreen.addObserver( this );

    // if global parameter set to no resize, override skins behavior
    if( !var_InheritBool( pIntf, "qt-video-autoresize" ) )
        m_bAutoResize = false;
}

CtrlVideo::~CtrlVideo()
{
    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    rFullscreen.delObserver( this );
}

void CtrlVideo::handleEvent( EvtGeneric &rEvent )
{
}

bool CtrlVideo::mouseOver( int x, int y ) const
{
    return false;
}

void CtrlVideo::onResize()
{
    const Position *pPos = getPosition();
    if( pPos && m_pVoutWindow )
    {
        m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
        m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
    }
}

void CtrlVideo::onPositionChange()
{
    // Compute the difference between layout size and video size
    m_xShift = m_rLayout.getWidth() - getPosition()->getWidth();
    m_yShift = m_rLayout.getHeight() - getPosition()->getHeight();
}

void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
{
    const Position *pPos = getPosition();
    if( pPos )
    {
        // Draw a black rectangle under the video to avoid transparency
        rImage.fillRect( pPos->getLeft(), pPos->getTop(), pPos->getWidth(),
                         pPos->getHeight(), 0 );
    }
}

void CtrlVideo::setLayout( GenericLayout *pLayout,
                           const Position &rPosition )
{
    CtrlGeneric::setLayout( pLayout, rPosition );
    m_pLayout->getActiveVar().addObserver( this );

    m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();

    // register Video Control
    VoutManager::instance( getIntf() )->registerCtrlVideo( this );

    msg_Dbg( getIntf(),"New VideoControl detected(%p), useability=%s",
                           this, m_bIsUseable ? "true" : "false" );
}

void CtrlVideo::unsetLayout()
{
    m_pLayout->getActiveVar().delObserver( this );
    CtrlGeneric::unsetLayout();
}

void CtrlVideo::resizeControl( int width, int height )
{
    WindowManager &rWindowManager =
        getIntf()->p_sys->p_theme->getWindowManager();

    const Position *pPos = getPosition();

    if( width != pPos->getWidth() || height != pPos->getHeight() )
    {
        // new layout dimensions
        int newWidth = width + m_xShift;
        int newHeight = height + m_yShift;

        // Resize the layout
        rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
        rWindowManager.resize( m_rLayout, newWidth, newHeight );
        rWindowManager.stopResize();

        if( m_pVoutWindow )
        {
            m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
            m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
        }
    }
}

void CtrlVideo::onUpdate( Subject<VarBool> &rVariable, void *arg  )
{
    // Visibility changed
    if( &rVariable == m_pVisible )
    {
        msg_Dbg( getIntf(), "VideoCtrl : Visibility changed (visible=%d)",
                                  isVisible() );
    }

    // Active Layout changed
    if( &rVariable == &m_pLayout->getActiveVar() )
    {
        msg_Dbg( getIntf(), "VideoCtrl : Active Layout changed (isActive=%d)",
                      m_pLayout->getActiveVar().get() );
    }

    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    if( &rVariable == &rFullscreen )
    {
        msg_Dbg( getIntf(), "VideoCtrl : fullscreen toggled (fullscreen = %d)",
                      rFullscreen.get() );
    }

    m_bIsUseable = isVisible() &&
                   m_pLayout->getActiveVar().get() &&
                   !rFullscreen.get();

    if( m_bIsUseable && !isUsed() )
    {
        VoutManager::instance( getIntf() )->requestVout( this );
    }
    else if( !m_bIsUseable && isUsed() )
    {
        VoutManager::instance( getIntf() )->discardVout( this );
    }
}

void CtrlVideo::attachVoutWindow( VoutWindow* pVoutWindow, int width, int height )
{
    width = ( width < 0 ) ? pVoutWindow->getOriginalWidth() : width;
    height = ( height < 0 ) ? pVoutWindow->getOriginalHeight() : height;

    WindowManager &rWindowManager =
        getIntf()->p_sys->p_theme->getWindowManager();
    TopWindow* pWin = getWindow();
    rWindowManager.show( *pWin );

    if( m_bAutoResize && width && height )
    {
        int newWidth = width + m_xShift;
        int newHeight = height + m_yShift;

        rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
        rWindowManager.resize( m_rLayout, newWidth, newHeight );
        rWindowManager.stopResize();
    }

    pVoutWindow->setCtrlVideo( this );

    m_pVoutWindow = pVoutWindow;
}

void CtrlVideo::detachVoutWindow( )
{
    m_pVoutWindow->setCtrlVideo( NULL );
    m_pVoutWindow = NULL;
}

<commit_msg>skins2: fix a refresh artefact (not frequent corner case)<commit_after>/*****************************************************************************
 * ctrl_video.cpp
 *****************************************************************************
 * Copyright (C) 2004 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "ctrl_video.hpp"
#include "../src/theme.hpp"
#include "../src/vout_window.hpp"
#include "../src/os_graphics.hpp"
#include "../src/vlcproc.hpp"
#include "../src/vout_manager.hpp"
#include "../src/window_manager.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_resize.hpp"

CtrlVideo::CtrlVideo( intf_thread_t *pIntf, GenericLayout &rLayout,
                      bool autoResize, const UString &rHelp,
                      VarBool *pVisible ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_rLayout( rLayout ),
    m_xShift( 0 ), m_yShift( 0 ), m_bAutoResize( autoResize ),
    m_pVoutWindow( NULL ), m_bIsUseable( false )
{
    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    rFullscreen.addObserver( this );

    // if global parameter set to no resize, override skins behavior
    if( !var_InheritBool( pIntf, "qt-video-autoresize" ) )
        m_bAutoResize = false;
}

CtrlVideo::~CtrlVideo()
{
    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    rFullscreen.delObserver( this );
}

void CtrlVideo::handleEvent( EvtGeneric &rEvent )
{
}

bool CtrlVideo::mouseOver( int x, int y ) const
{
    return false;
}

void CtrlVideo::onResize()
{
    const Position *pPos = getPosition();
    if( pPos && m_pVoutWindow )
    {
        m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
        m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
    }
}

void CtrlVideo::onPositionChange()
{
    // Compute the difference between layout size and video size
    m_xShift = m_rLayout.getWidth() - getPosition()->getWidth();
    m_yShift = m_rLayout.getHeight() - getPosition()->getHeight();
}

void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
{
    const Position *pPos = getPosition();
    if( pPos )
    {
        // Draw a black rectangle under the video to avoid transparency
        rImage.fillRect( pPos->getLeft(), pPos->getTop(), pPos->getWidth(),
                         pPos->getHeight(), 0 );
    }
}

void CtrlVideo::setLayout( GenericLayout *pLayout,
                           const Position &rPosition )
{
    CtrlGeneric::setLayout( pLayout, rPosition );
    m_pLayout->getActiveVar().addObserver( this );

    m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();

    // register Video Control
    VoutManager::instance( getIntf() )->registerCtrlVideo( this );

    msg_Dbg( getIntf(),"New VideoControl detected(%p), useability=%s",
                           this, m_bIsUseable ? "true" : "false" );
}

void CtrlVideo::unsetLayout()
{
    m_pLayout->getActiveVar().delObserver( this );
    CtrlGeneric::unsetLayout();
}

void CtrlVideo::resizeControl( int width, int height )
{
    WindowManager &rWindowManager =
        getIntf()->p_sys->p_theme->getWindowManager();

    const Position *pPos = getPosition();

    if( width != pPos->getWidth() || height != pPos->getHeight() )
    {
        // new layout dimensions
        int newWidth = width + m_xShift;
        int newHeight = height + m_yShift;

        // Resize the layout
        rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
        rWindowManager.resize( m_rLayout, newWidth, newHeight );
        rWindowManager.stopResize();

        if( m_pVoutWindow )
        {
            m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
            m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
        }
    }
}

void CtrlVideo::onUpdate( Subject<VarBool> &rVariable, void *arg  )
{
    // Visibility changed
    if( &rVariable == m_pVisible )
    {
        msg_Dbg( getIntf(), "VideoCtrl : Visibility changed (visible=%d)",
                                  isVisible() );
        notifyLayout();
    }

    // Active Layout changed
    if( &rVariable == &m_pLayout->getActiveVar() )
    {
        msg_Dbg( getIntf(), "VideoCtrl : Active Layout changed (isActive=%d)",
                      m_pLayout->getActiveVar().get() );
    }

    VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
    if( &rVariable == &rFullscreen )
    {
        msg_Dbg( getIntf(), "VideoCtrl : fullscreen toggled (fullscreen = %d)",
                      rFullscreen.get() );
    }

    m_bIsUseable = isVisible() &&
                   m_pLayout->getActiveVar().get() &&
                   !rFullscreen.get();

    if( m_bIsUseable && !isUsed() )
    {
        VoutManager::instance( getIntf() )->requestVout( this );
    }
    else if( !m_bIsUseable && isUsed() )
    {
        VoutManager::instance( getIntf() )->discardVout( this );
    }
}

void CtrlVideo::attachVoutWindow( VoutWindow* pVoutWindow, int width, int height )
{
    width = ( width < 0 ) ? pVoutWindow->getOriginalWidth() : width;
    height = ( height < 0 ) ? pVoutWindow->getOriginalHeight() : height;

    WindowManager &rWindowManager =
        getIntf()->p_sys->p_theme->getWindowManager();
    TopWindow* pWin = getWindow();
    rWindowManager.show( *pWin );

    if( m_bAutoResize && width && height )
    {
        int newWidth = width + m_xShift;
        int newHeight = height + m_yShift;

        rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
        rWindowManager.resize( m_rLayout, newWidth, newHeight );
        rWindowManager.stopResize();
    }

    pVoutWindow->setCtrlVideo( this );

    m_pVoutWindow = pVoutWindow;
}

void CtrlVideo::detachVoutWindow( )
{
    m_pVoutWindow->setCtrlVideo( NULL );
    m_pVoutWindow = NULL;
}

<|endoftext|>


<commit_before>#include "falcon/cxx/cxx.hpp"
#include "falcon/cxx/compiler_attributes.hpp"
#include "falcon/cxx/lib.hpp"
#include "falcon/cxx/lib_experimental.hpp"
#include "falcon/cxx/move_algorithm.hpp"
#include "falcon/cxx/move.hpp"

template<class... T>
void foo(T... x)
{
  static_assert(noexcept(FALCON_UNPACK(x+1)), "must be noexcept");
}

int main()
{
  foo(1, 2);
}
<commit_msg>constexpr test for FALCON_UNPACK<commit_after>#include "falcon/cxx/cxx.hpp"
#include "falcon/cxx/compiler_attributes.hpp"
#include "falcon/cxx/lib.hpp"
#include "falcon/cxx/lib_experimental.hpp"
#include "falcon/cxx/move_algorithm.hpp"
#include "falcon/cxx/move.hpp"

template<class... T>
constexpr int foo(T... x)
{
  static_assert(noexcept(FALCON_UNPACK(x+1)), "must be noexcept");
  int sum = 0;
  FALCON_UNPACK(sum += x);
  return sum;
}

template<int i> class i_{};

int main()
{
  i_<foo(1, 2)>{};
}
<|endoftext|>


<commit_before>#include "download.h"

#include "test-helpers.h"

using namespace podboat;

TEST_CASE("Require-view-update callback gets called when download progress or status changes",
	"[Download]")
{
	GIVEN("A Download object") {
		bool got_called = false;
		std::function<void()> callback = [&got_called]() {
			got_called = true;
		};

		Download d(callback);

		REQUIRE(d.status() == DlStatus::QUEUED);

		WHEN("its progress is updated (increased)") {
			d.set_progress(1.0, 1.0);

			THEN("the require-view-update callback gets called") {
				REQUIRE(got_called);
			}
		}

		WHEN("its progress has not changed") {
			d.set_progress(0.0, 1.0);

			THEN("the require-view-update callback does not get called") {
				REQUIRE_FALSE(got_called);
			}
		}

		WHEN("its status is changed") {
			d.set_status(DlStatus::DOWNLOADING);

			THEN("the require-view-update callback gets called") {
				REQUIRE(got_called);
			}
		}

		WHEN("when its status is not changed") {
			d.set_status(DlStatus::QUEUED);

			THEN("the require-view-update callback does not get called") {
				REQUIRE_FALSE(got_called);
			}
		}
	}
}

TEST_CASE("Filename returns download's target filename", "[Download]")
{
	auto emptyCallback = []() {};

	Download d(emptyCallback);

	SECTION("filename returns empty string by default") {
		REQUIRE(d.filename().empty());
	}

	SECTION("filename returns same string which is set via set_filename") {
		d.set_filename("abc");
		REQUIRE(d.filename() == "abc");
	}

	SECTION("filename will return the latest configured filename") {
		d.set_filename("abc");
		d.set_filename("def");

		REQUIRE(d.filename() == "def");
	}
}
<commit_msg>Review comment: Make clear that `filename` is a function in test name<commit_after>#include "download.h"

#include "test-helpers.h"

using namespace podboat;

TEST_CASE("Require-view-update callback gets called when download progress or status changes",
	"[Download]")
{
	GIVEN("A Download object") {
		bool got_called = false;
		std::function<void()> callback = [&got_called]() {
			got_called = true;
		};

		Download d(callback);

		REQUIRE(d.status() == DlStatus::QUEUED);

		WHEN("its progress is updated (increased)") {
			d.set_progress(1.0, 1.0);

			THEN("the require-view-update callback gets called") {
				REQUIRE(got_called);
			}
		}

		WHEN("its progress has not changed") {
			d.set_progress(0.0, 1.0);

			THEN("the require-view-update callback does not get called") {
				REQUIRE_FALSE(got_called);
			}
		}

		WHEN("its status is changed") {
			d.set_status(DlStatus::DOWNLOADING);

			THEN("the require-view-update callback gets called") {
				REQUIRE(got_called);
			}
		}

		WHEN("when its status is not changed") {
			d.set_status(DlStatus::QUEUED);

			THEN("the require-view-update callback does not get called") {
				REQUIRE_FALSE(got_called);
			}
		}
	}
}

TEST_CASE("filename() returns download's target filename", "[Download]")
{
	auto emptyCallback = []() {};

	Download d(emptyCallback);

	SECTION("filename returns empty string by default") {
		REQUIRE(d.filename().empty());
	}

	SECTION("filename returns same string which is set via set_filename") {
		d.set_filename("abc");
		REQUIRE(d.filename() == "abc");
	}

	SECTION("filename will return the latest configured filename") {
		d.set_filename("abc");
		d.set_filename("def");

		REQUIRE(d.filename() == "def");
	}
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>

#include <gtest/gtest.h>

#include <tudocomp/io.h>
#include <tudocomp/util/Generators.hpp>
#include <tudocomp/ds/TextDS.hpp>
#include "test_util.h"

using namespace tudocomp;

typedef void (*string_test_func_t)(const std::string&);

//Check that p is a permutation of [0..n-1]
template<class T>
void ASSERT_PERMUTATION(const T& p, size_t n) {
    for(size_t i = 0; i < n; ++i)
    for(size_t j = 0; j < n; ++j)
    {
        if(i == j) continue;
        ASSERT_NE(p[i],p[j]) << "at positions " << i << " and " << j;
        ASSERT_LT(p[i],n);
    }
}

// Simple string array dispenser
class StringArrayDispenser {
private:
    static const size_t NUM_TEST_STRINGS;
    static const std::string TEST_STRINGS[];

    size_t m_next;

public:
    StringArrayDispenser() : m_next(0) {};

    bool has_next() {
        return m_next < NUM_TEST_STRINGS;
    }

    const std::string& next() {
        return TEST_STRINGS[m_next++];
    }
};

const size_t StringArrayDispenser::NUM_TEST_STRINGS = 4;
const std::string StringArrayDispenser::TEST_STRINGS[] = {
    "",
    "0",
    "aaaaaaa",
    "aabaaababaaabbaabababaab",
    "fjgwehfwbz43bngkwrp23fa"
};

//TODO: Markov chain generator

template<class generator_t>
void run_tests(string_test_func_t test) {
    generator_t generator;
    while(generator.has_next()) {
        test(generator.next());
    }
}

size_t lce(const std::string& text, size_t a, size_t b) {
	DCHECK_NE(a,b);
	size_t i = 0;
	while(text[a+i] == text[b+i]) { ++i; }
	return i;
}

template<class sa_t>
sdsl::int_vector<> create_lcp_naive(const std::string& text, const sa_t& sa) {
	sdsl::int_vector<> lcp(sa.size());
	lcp[0]=0;
	for(size_t i = 1; i < sa.size(); ++i) {
		lcp[i] = lce(text, sa[i],sa[i-1]);
	}
	return lcp;
}
template<class lcp_t, class isa_t>
sdsl::int_vector<> create_plcp_naive(const lcp_t& lcp, const isa_t& isa) {
	sdsl::int_vector<> plcp(lcp.size());
	for(size_t i = 0; i < lcp.size(); ++i) {
		DCHECK_LT(isa[i], lcp.size());
		DCHECK_GE(isa[i], 0);
		plcp[i] = lcp[isa[i]];
	}
	for(size_t i = 1; i < lcp.size(); ++i) {
		DCHECK_GE(plcp[i]+1, plcp[i-1]);
	}
	return plcp;
}

// === THE ACTUAL TESTS ===
template<class textds_t>
void test_TestSA(const std::string& str) {
    DLOG(INFO) << "str = \"" << str << "\"" << " size: " << str.length();

    size_t n = str.length();
    Input input(str);
    textds_t t(input.as_view());
    auto& sa = t.require_sa();

    ASSERT_EQ(sa.size(), n+1); //length
    ASSERT_PERMUTATION(sa, n+1); //permutation
    ASSERT_EQ(sa[0], n); //first element is $

    //check lexicographic order
    for(size_t i = 1; i < n+1; i++) {
        ASSERT_GE(t[sa[i]], t[sa[i-1]]);
		ASSERT_LT(str.substr(sa[i-1]), str.substr(sa[i])); //TODO: use basic_string_view to speed up!
    }

    auto& phi = t.require_phi();
    ASSERT_EQ(phi.size(), sa.size()); //length
    ASSERT_PERMUTATION(phi, phi.size()); //permutation

	for(size_t i = 0; i < sa.size(); ++i) {
		ASSERT_EQ(phi[sa[(i+1) % sa.size()]], sa[i]);
	}

    auto& isa = t.require_isa();
    ASSERT_EQ(isa.size(), sa.size());
	for(size_t i = 0; i < sa.size(); ++i) {
		ASSERT_EQ(isa[sa[i]], i);
	}
	const sdsl::int_vector<> lcp_naive(create_lcp_naive(str,sa));
	const auto plcp = LCP::phi_algorithm(t);
	const auto plcp_naive = create_plcp_naive(lcp_naive, isa);
	assert_eq_sequence(plcp, plcp_naive);

    auto& lcp = t.require_lcp();
	assert_eq_sequence(lcp, lcp_naive);
    ASSERT_EQ(lcp.size(), sa.size()); //length
	for(size_t i = 0; i < lcp.size(); ++i) {
		ASSERT_EQ(lcp_naive[i], plcp_naive[sa[i]]);
		ASSERT_EQ(lcp[i], plcp[sa[i]]);
		ASSERT_EQ(lcp[i], plcp_naive[sa[i]]);
	}
	for(size_t i = 1; i < lcp.size(); ++i) {
		ASSERT_EQ(lcp[i], lce(str, sa[i], sa[i-1]));
	}
}

TEST(ds, TestSA) {
    run_tests<StringArrayDispenser>(&test_TestSA<TextDS<>>);
	for(size_t i = 0; i < 4; ++i) {
		std::string s = fibonacci_word(1<<i);
		test_TestSA<TextDS<>>(s);
	}
	// for(size_t i = 0; i < 11; ++i) {
	// 	for(size_t j = 0; j < 2+50/(i+1); ++j) {
	// 		std::string s = random_uniform(1<<i,Ranges::numbers,j);
	// 		test_TestSA<TextDS<>>(s);
	// 	}
	// }
}
<commit_msg>exchanged a test with View<commit_after>#include <string>
#include <vector>

#include <gtest/gtest.h>

#include <tudocomp/io.h>
#include <tudocomp/util/Generators.hpp>
#include <tudocomp/ds/TextDS.hpp>
#include "test_util.h"

using namespace tudocomp;

typedef void (*string_test_func_t)(const std::string&);

//Check that p is a permutation of [0..n-1]
template<class T>
void ASSERT_PERMUTATION(const T& p, size_t n) {
    for(size_t i = 0; i < n; ++i)
    for(size_t j = 0; j < n; ++j)
    {
        if(i == j) continue;
        ASSERT_NE(p[i],p[j]) << "at positions " << i << " and " << j;
        ASSERT_LT(p[i],n);
    }
}

// Simple string array dispenser
class StringArrayDispenser {
private:
    static const size_t NUM_TEST_STRINGS;
    static const std::string TEST_STRINGS[];

    size_t m_next;

public:
    StringArrayDispenser() : m_next(0) {};

    bool has_next() {
        return m_next < NUM_TEST_STRINGS;
    }

    const std::string& next() {
        return TEST_STRINGS[m_next++];
    }
};

const size_t StringArrayDispenser::NUM_TEST_STRINGS = 4;
const std::string StringArrayDispenser::TEST_STRINGS[] = {
    "",
    "0",
    "aaaaaaa",
    "aabaaababaaabbaabababaab",
    "fjgwehfwbz43bngkwrp23fa"
};

//TODO: Markov chain generator

template<class generator_t>
void run_tests(string_test_func_t test) {
    generator_t generator;
    while(generator.has_next()) {
        test(generator.next());
    }
}

size_t lce(const std::string& text, size_t a, size_t b) {
	DCHECK_NE(a,b);
	size_t i = 0;
	while(text[a+i] == text[b+i]) { ++i; }
	return i;
}

template<class sa_t>
sdsl::int_vector<> create_lcp_naive(const std::string& text, const sa_t& sa) {
	sdsl::int_vector<> lcp(sa.size());
	lcp[0]=0;
	for(size_t i = 1; i < sa.size(); ++i) {
		lcp[i] = lce(text, sa[i],sa[i-1]);
	}
	return lcp;
}
template<class lcp_t, class isa_t>
sdsl::int_vector<> create_plcp_naive(const lcp_t& lcp, const isa_t& isa) {
	sdsl::int_vector<> plcp(lcp.size());
	for(size_t i = 0; i < lcp.size(); ++i) {
		DCHECK_LT(isa[i], lcp.size());
		DCHECK_GE(isa[i], 0);
		plcp[i] = lcp[isa[i]];
	}
	for(size_t i = 1; i < lcp.size(); ++i) {
		DCHECK_GE(plcp[i]+1, plcp[i-1]);
	}
	return plcp;
}

// === THE ACTUAL TESTS ===
template<class textds_t>
void test_TestSA(const std::string& str) {
    DLOG(INFO) << "str = \"" << str << "\"" << " size: " << str.length();

    size_t n = str.length();
    Input input(str);
    textds_t t(input.as_view());
    auto& sa = t.require_sa();

    ASSERT_EQ(sa.size(), n+1); //length
    ASSERT_PERMUTATION(sa, n+1); //permutation
    ASSERT_EQ(sa[0], n); //first element is $

    //check lexicographic order
    for(size_t i = 1; i < n+1; i++) {
        ASSERT_GE(t[sa[i]], t[sa[i-1]]);
		ASSERT_LT(str.substr(sa[i-1]), str.substr(sa[i])); //TODO: remove this (should be equal to below
		ASSERT_LT(View(str,sa[i-1]), View(str,sa[i]));
    }

    auto& phi = t.require_phi();
    ASSERT_EQ(phi.size(), sa.size()); //length
    ASSERT_PERMUTATION(phi, phi.size()); //permutation

	for(size_t i = 0; i < sa.size(); ++i) {
		ASSERT_EQ(phi[sa[(i+1) % sa.size()]], sa[i]);
	}

    auto& isa = t.require_isa();
    ASSERT_EQ(isa.size(), sa.size());
	for(size_t i = 0; i < sa.size(); ++i) {
		ASSERT_EQ(isa[sa[i]], i);
	}
	const sdsl::int_vector<> lcp_naive(create_lcp_naive(str,sa));
	const auto plcp = LCP::phi_algorithm(t);
	const auto plcp_naive = create_plcp_naive(lcp_naive, isa);
	assert_eq_sequence(plcp, plcp_naive);

    auto& lcp = t.require_lcp();
	assert_eq_sequence(lcp, lcp_naive);
    ASSERT_EQ(lcp.size(), sa.size()); //length
	for(size_t i = 0; i < lcp.size(); ++i) {
		ASSERT_EQ(lcp_naive[i], plcp_naive[sa[i]]);
		ASSERT_EQ(lcp[i], plcp[sa[i]]);
		ASSERT_EQ(lcp[i], plcp_naive[sa[i]]);
	}
	for(size_t i = 1; i < lcp.size(); ++i) {
		ASSERT_EQ(lcp[i], lce(str, sa[i], sa[i-1]));
	}
}

TEST(ds, TestSA) {
    run_tests<StringArrayDispenser>(&test_TestSA<TextDS<>>);
	for(size_t i = 0; i < 4; ++i) {
		std::string s = fibonacci_word(1<<i);
		test_TestSA<TextDS<>>(s);
	}
	// for(size_t i = 0; i < 11; ++i) {
	// 	for(size_t j = 0; j < 2+50/(i+1); ++j) {
	// 		std::string s = random_uniform(1<<i,Ranges::numbers,j);
	// 		test_TestSA<TextDS<>>(s);
	// 	}
	// }
}
<|endoftext|>


<commit_before>#include "dt_RunDrawTest.C"

#include "TClassTable.h"
#include "TDirectory.h"
#include "TFile.h"
#include "TH1.h"
#include "TH2.h"
#include "TSystem.h"

#ifndef __CINT__
#include "Event.h"
#endif

TH1F* RefClone(TH1F* orig) {
  TH1F *cloned = (TH1F*)orig->Clone();
  TString name = orig->GetName();
  name.Prepend("ref");
  cloned->SetName(name);
  cloned->Reset();
  return cloned;
};

TH1F* RefClone(TDirectory* from, const char* name) {
  TH1F * orig = (TH1F*)from->Get(name);
  if (!orig) {
    cerr << "Missing " << name << " from " << from->GetName() << endl;
    return 0;
  }
  return RefClone(orig);
}

void MakeHisto(TTree *tree, TDirectory* To) {

   cout << "Generating histograms from TTree::Draw" << endl;
   TDirectory* where = GenerateDrawHist(tree);
   To->cd();

   Event *event = new Event();
   tree->SetBranchAddress("event",&event);

   //We make clones of the generated histograms
   //We set new names and reset the clones.
   //We want to have identical histogram limits
   TH1F *refNtrack = RefClone(where,"hNtrack");
   TH1F *refGetNtrack = RefClone(where,"hGetNtrack");
   TH1F *refNseg   = RefClone(where,"hNseg");
   TH1F *refTemp   = RefClone(where,"hTemp");
   TH1F *refHmean  = RefClone(where,"hHmean");
   TH1F *refHAxisMax = RefClone(where,"hHAxisMax");
   TH1F *refHAxisGetMax = RefClone(where,"hHAxisGetMax");
   TH1F *refHGetAxisGetMax  = RefClone(where,"hHGetAxisGetMax");
   TH1F *refHGetAxisMax  = RefClone(where,"hHGetAxisMax");
   TH1F *refGetHGetAxisMax  = RefClone(where,"hGetHGetAxisMax");
   TH1F *refGetRefHGetAxisMax  = RefClone(where,"hGetRefHGetAxisMax");

   TH1F *refPx     = RefClone(where,"hPx");
   TH1F *refPy     = RefClone(where,"hPy");
   TH1F *refPz     = RefClone(where,"hPz");
   TH1F *refRandom = RefClone(where,"hRandom");
   TH1F *refMass2  = RefClone(where,"hMass2");
   TH1F *refBx     = RefClone(where,"hBx");
   TH1F *refBy     = RefClone(where,"hBy");
   TH1F *refXfirst = RefClone(where,"hXfirst");
   TH1F *refYfirst = RefClone(where,"hYfirst");
   TH1F *refZfirst = RefClone(where,"hZfirst");
   TH1F *refXlast  = RefClone(where,"hXlast");
   TH1F *refYlast  = RefClone(where,"hYlast");
   TH1F *refZlast  = RefClone(where,"hZlast");
   TH1F *refCharge = RefClone(where,"hCharge");
   TH1F *refNpoint = RefClone(where,"hNpoint");
   TH1F *refValid  = RefClone(where,"hValid");
   TH1F *refPointValue  = RefClone(where,"hPointValue");
   TH1F *refAlias  = RefClone(where,"hAlias");

   TH1F *refFullMatrix   = RefClone(where,"hFullMatrix");
   TH1F *refColMatrix    = RefClone(where,"hColMatrix");
   TH1F *refRowMatrix    = RefClone(where,"hRowMatrix");
   TH1F *refCellMatrix   = RefClone(where,"hCellMatrix");
   TH1F *refFullOper     = RefClone(where,"hFullOper");
   TH1F *refCellOper     = RefClone(where,"hCellOper");
   TH1F *refColOper      = RefClone(where,"hColOper");
   TH1F *refRowOper      = RefClone(where,"hRowOper");
   TH1F *refMatchRowOper = RefClone(where,"hMatchRowOper");
   TH1F *refMatchColOper = RefClone(where,"hMatchColOper");
   TH1F *refRowMatOper   = RefClone(where,"hRowMatOper");
   TH1F *refMatchDiffOper= RefClone(where,"hMatchDiffOper");
   TH1F *refFullOper2    = RefClone(where,"hFullOper2");

   TH1F *refClosestDistance  = RefClone(where,"hClosestDistance");
   TH1F *refClosestDistance2 = RefClone(where,"hClosestDistance2");
   TH1F *refClosestDistance9 = RefClone(where,"hClosestDistance9");

   TH1F *refClosestDistanceIndex = RefClone(where, "hClosestDistanceIndex");
   TH2F *refPxInd = (TH2F*)RefClone(where,"hPxInd");

   TH1F *refSqrtNtrack = RefClone(where,"hSqrtNtrack");
   TH1F *refShiftValid = RefClone(where,"hShiftValid");
   TH1F *refAndValid = RefClone(where,"hAndValid");

   TH1F *refString = RefClone(where,"hString");
   TH1F *refAliasStr = RefClone(where,"hAliasStr");

   TH1F *refPxBx = RefClone(where,"hPxBx");
   TH1F *refPxBxWeight =  RefClone(where,"hPxBxWeight");

   TH1F *refTriggerBits = RefClone(where,"hTriggerBits");
   TH1F *refTriggerBitsFunc = RefClone(where,"hTriggerBitsFunc");
   TH1F *refFiltTriggerBits = RefClone(where,"hFiltTriggerBits");

   TH1F *refTrackTrigger = RefClone(where,"hTrackTrigger");
   TH1F *refFiltTrackTrigger = RefClone(where,"hFiltTrackTrigger");

   TH1F *refBreit = RefClone(where,"hBreit");

   // Loop with user code on all events and fill the ref histograms
   // The code below should produce identical results to the tree->Draw above

   cout << "Recalculating the histograms with custom loop." << endl;

   TClonesArray *tracks = event->GetTracks();
   Int_t nev = (Int_t)tree->GetEntries();
   Int_t i, ntracks, evmod,i0,i1, Nvertex;
   Track *t;
   EventHeader *head;
   Int_t nbin = 0;
   for (Int_t ev=0;ev<nev;ev++) {
      nbin += tree->GetEntry(ev);
      head = event->GetHeader();
      evmod = head->GetEvtNum()%10;
      refNtrack->Fill(event->GetNtrack());
      refGetNtrack->Fill(event->GetNtrack());
      refNseg->Fill(event->GetNseg());
      refTemp->Fill(event->GetTemperature());
      refHmean->Fill(event->GetHistogram()->GetMean());
      refHAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHAxisGetMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHGetAxisGetMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refGetHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refGetRefHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refSqrtNtrack->Fill(sqrt(event->GetNtrack()));

      if (!strcmp("type1",event->GetType()))
        refString->Fill(event->GetHeader()->GetEvtNum());
      if (strstr(event->GetType(),"1")) {
        refString->Fill(event->GetHeader()->GetEvtNum());
      }
      refAliasStr->Fill(strstr(event->GetType(),"1")!=0);

      Nvertex = event->GetNvertex();
      for(i0=0;i0<Nvertex;i0++) {
         refClosestDistance->Fill(event->GetClosestDistance(i0));
      }
      if (Nvertex>2) refClosestDistance2->Fill(event->GetClosestDistance(2));
      if (Nvertex>9) refClosestDistance9->Fill(event->GetClosestDistance(9));
      refClosestDistanceIndex->Fill(event->GetClosestDistance(Nvertex/2));

      for(i0=0;i0<4;i0++) {
         for(i1=0;i1<4;i1++) {
            refFullMatrix->Fill(event->GetMatrix(i0,i1));
         }
         refColMatrix->Fill(event->GetMatrix(i0,0));
         refRowMatrix->Fill(event->GetMatrix(1,i0)); // done here because the matrix is square!
      }
      refCellMatrix->Fill(event->GetMatrix(2,2));

      TBits bits = event->GetTriggerBits();
      Int_t nbits = bits.GetNbits();
      Int_t ncx = refTriggerBits->GetXaxis()->GetNbins();
      Int_t nextbit = -1;
      while(1) {
         nextbit = bits->FirstSetBit(nextbit+1);
         if (nextbit >= nbits) break;
         if (nextbit > ncx) refTriggerBits->Fill(ncx+1);
         else               refTriggerBits->Fill(nextbit);
         if (nextbit > ncx) refTriggerBitsFunc->Fill(ncx+1);
         else               refTriggerBitsFunc->Fill(nextbit);
      }
      if (bits.TestBitNumber(10)) refFiltTriggerBits->Fill(nbits);

      ntracks = event->GetNtrack();
      if ( 5 < ntracks ) {
         t = (Track*)tracks->UncheckedAt(5);
         for(i0=0;i0<4;i0++) {
            for(i1=0;i1<4;i1++) {
            }
            refColOper->Fill( event->GetMatrix(i0,1) - t->GetVertex(1) );
            refRowOper->Fill( event->GetMatrix(2,i0) - t->GetVertex(2) );
         }
         for(i0=0;i0<3;i0++) {
            refMatchRowOper->Fill( event->GetMatrix(2,i0) - t->GetVertex(i0) );
            refMatchDiffOper->Fill( event->GetMatrix(i0,2) - t->GetVertex(i0) );
         }
         refCellOper->Fill( event->GetMatrix(2,1) - t->GetVertex(1) );
      }
      for (i=0;i<ntracks;i++) {
         t = (Track*)tracks->UncheckedAt(i);
         if (evmod == 0) refPx->Fill(t->GetPx());
         if (evmod == 0) refPy->Fill(t->GetPy());
         if (evmod == 0) refPz->Fill(t->GetPz());
         if (evmod == 1) refRandom->Fill(t->GetRandom(),3);
         if (evmod == 1) refMass2->Fill(t->GetMass2());
         if (evmod == 1) refBx->Fill(t->GetBx());
         if (evmod == 1) refBy->Fill(t->GetBy());
         if (evmod == 2) refXfirst->Fill(t->GetXfirst());
         if (evmod == 2) refYfirst->Fill(t->GetYfirst());
         if (evmod == 2) refZfirst->Fill(t->GetZfirst());
         if (evmod == 3) refXlast->Fill(t->GetXlast());
         if (evmod == 3) refYlast->Fill(t->GetYlast());
         if (evmod == 3) refZlast->Fill(t->GetZlast());
         if (t->GetPx() < 0) {
            refCharge->Fill(t->GetCharge());
            refNpoint->Fill(t->GetNpoint());
            refValid->Fill(t->GetValid());
         }
         Int_t valid = t->GetValid();
         refShiftValid->Fill(valid << 4);
         refShiftValid->Fill( (valid << 4) >> 2 );
         if (event->GetNvertex()>10 && event->GetNseg()<=6000) {
            refAndValid->Fill( t->GetValid() & 0x1 );
         }

         Track * t2 = (Track*)tracks->At(t->GetNpoint()/6);
         if (t2 && t2->GetPy()>0) {
            refPxInd->Fill(t2->GetPy(),t->GetPx());
         }
         float Bx,By;
         Bx = t->GetBx();
         By = t->GetBy();
         if ((Bx>.15) || (By<=-.15)) refPxBx->Fill(t->GetPx());
         double weight = Bx*Bx*(Bx>.15) + By*By*(By<=-.15);
         if (weight) refPxBxWeight->Fill(t->GetPx(),weight);

         if (i<4) {
            for(i1=0;i1<3;i1++) { // 3 is the min of the 2nd dim of Matrix and Vertex
               refFullOper ->Fill( event->GetMatrix(i,i1) - t->GetVertex(i1) );
               refFullOper2->Fill( event->GetMatrix(i,i1) - t->GetVertex(i1) );
               refRowMatOper->Fill( event->GetMatrix(i,2) - t->GetVertex(i1) );
            }
            refMatchColOper->Fill( event->GetMatrix(i,2) - t->GetVertex(1) );
         }
         for(i1=0; i1<t->GetN(); i1++) {
            refPointValue->Fill( t->GetPointValue(i1) );
         }
         TBits bits = t->GetTriggerBits();
         Int_t nbits = bits.GetNbits();
         Int_t ncx = refTrackTrigger->GetXaxis()->GetNbins();
         Int_t nextbit = -1;
         while(1) {
            nextbit = bits->FirstSetBit(nextbit+1);
            if (nextbit >= nbits) break;
            if (nextbit > ncx) refTrackTrigger->Fill(ncx+1);
            else               refTrackTrigger->Fill(nextbit);
         }
         if (bits.TestBitNumber(5)) refFiltTrackTrigger->Fill(t->GetPx());
         refBreit->Fill(TMath::BreitWigner(t->GetPx(),3,2));

         refAlias->Fill(head->GetEvtNum()*6+t->GetPx()*t->GetPy());
      }
   }

   delete event;
   Event::Reset();

}

void dt_MakeRef(const char* from, Int_t verboseLevel = 2) {
   SetVerboseLevel(verboseLevel);

   if (!TClassTable::GetDict("Event")) {
      gSystem->Load("libEvent");
      gHasLibrary = kTRUE;
   }

   gROOT->GetList()->Delete();

   TFile *hfile = new TFile(from);
   TTree *tree = (TTree*)hfile->Get("T");

   TFile* f= new TFile("dt_reference.root","recreate");
   MakeHisto(tree,f);
   f->Write();
   delete f;

   delete hfile;

   gROOT->cd();
   cout << "Checking histograms" << endl;
   Compare(gDirectory);

    //   gROOT->GetList()->Delete();

}
<commit_msg>Fix a CINT warning: Warning: wrong member access operator '->' FILE:dt_MakeRef.C LINE:172 Warning: wrong member access operator '->' FILE:dt_MakeRef.C LINE:250<commit_after>#include "dt_RunDrawTest.C"

#include "TClassTable.h"
#include "TDirectory.h"
#include "TFile.h"
#include "TH1.h"
#include "TH2.h"
#include "TSystem.h"

#ifndef __CINT__
#include "Event.h"
#endif

TH1F* RefClone(TH1F* orig) {
  TH1F *cloned = (TH1F*)orig->Clone();
  TString name = orig->GetName();
  name.Prepend("ref");
  cloned->SetName(name);
  cloned->Reset();
  return cloned;
};

TH1F* RefClone(TDirectory* from, const char* name) {
  TH1F * orig = (TH1F*)from->Get(name);
  if (!orig) {
    cerr << "Missing " << name << " from " << from->GetName() << endl;
    return 0;
  }
  return RefClone(orig);
}

void MakeHisto(TTree *tree, TDirectory* To) {

   cout << "Generating histograms from TTree::Draw" << endl;
   TDirectory* where = GenerateDrawHist(tree);
   To->cd();

   Event *event = new Event();
   tree->SetBranchAddress("event",&event);

   //We make clones of the generated histograms
   //We set new names and reset the clones.
   //We want to have identical histogram limits
   TH1F *refNtrack = RefClone(where,"hNtrack");
   TH1F *refGetNtrack = RefClone(where,"hGetNtrack");
   TH1F *refNseg   = RefClone(where,"hNseg");
   TH1F *refTemp   = RefClone(where,"hTemp");
   TH1F *refHmean  = RefClone(where,"hHmean");
   TH1F *refHAxisMax = RefClone(where,"hHAxisMax");
   TH1F *refHAxisGetMax = RefClone(where,"hHAxisGetMax");
   TH1F *refHGetAxisGetMax  = RefClone(where,"hHGetAxisGetMax");
   TH1F *refHGetAxisMax  = RefClone(where,"hHGetAxisMax");
   TH1F *refGetHGetAxisMax  = RefClone(where,"hGetHGetAxisMax");
   TH1F *refGetRefHGetAxisMax  = RefClone(where,"hGetRefHGetAxisMax");

   TH1F *refPx     = RefClone(where,"hPx");
   TH1F *refPy     = RefClone(where,"hPy");
   TH1F *refPz     = RefClone(where,"hPz");
   TH1F *refRandom = RefClone(where,"hRandom");
   TH1F *refMass2  = RefClone(where,"hMass2");
   TH1F *refBx     = RefClone(where,"hBx");
   TH1F *refBy     = RefClone(where,"hBy");
   TH1F *refXfirst = RefClone(where,"hXfirst");
   TH1F *refYfirst = RefClone(where,"hYfirst");
   TH1F *refZfirst = RefClone(where,"hZfirst");
   TH1F *refXlast  = RefClone(where,"hXlast");
   TH1F *refYlast  = RefClone(where,"hYlast");
   TH1F *refZlast  = RefClone(where,"hZlast");
   TH1F *refCharge = RefClone(where,"hCharge");
   TH1F *refNpoint = RefClone(where,"hNpoint");
   TH1F *refValid  = RefClone(where,"hValid");
   TH1F *refPointValue  = RefClone(where,"hPointValue");
   TH1F *refAlias  = RefClone(where,"hAlias");

   TH1F *refFullMatrix   = RefClone(where,"hFullMatrix");
   TH1F *refColMatrix    = RefClone(where,"hColMatrix");
   TH1F *refRowMatrix    = RefClone(where,"hRowMatrix");
   TH1F *refCellMatrix   = RefClone(where,"hCellMatrix");
   TH1F *refFullOper     = RefClone(where,"hFullOper");
   TH1F *refCellOper     = RefClone(where,"hCellOper");
   TH1F *refColOper      = RefClone(where,"hColOper");
   TH1F *refRowOper      = RefClone(where,"hRowOper");
   TH1F *refMatchRowOper = RefClone(where,"hMatchRowOper");
   TH1F *refMatchColOper = RefClone(where,"hMatchColOper");
   TH1F *refRowMatOper   = RefClone(where,"hRowMatOper");
   TH1F *refMatchDiffOper= RefClone(where,"hMatchDiffOper");
   TH1F *refFullOper2    = RefClone(where,"hFullOper2");

   TH1F *refClosestDistance  = RefClone(where,"hClosestDistance");
   TH1F *refClosestDistance2 = RefClone(where,"hClosestDistance2");
   TH1F *refClosestDistance9 = RefClone(where,"hClosestDistance9");

   TH1F *refClosestDistanceIndex = RefClone(where, "hClosestDistanceIndex");
   TH2F *refPxInd = (TH2F*)RefClone(where,"hPxInd");

   TH1F *refSqrtNtrack = RefClone(where,"hSqrtNtrack");
   TH1F *refShiftValid = RefClone(where,"hShiftValid");
   TH1F *refAndValid = RefClone(where,"hAndValid");

   TH1F *refString = RefClone(where,"hString");
   TH1F *refAliasStr = RefClone(where,"hAliasStr");

   TH1F *refPxBx = RefClone(where,"hPxBx");
   TH1F *refPxBxWeight =  RefClone(where,"hPxBxWeight");

   TH1F *refTriggerBits = RefClone(where,"hTriggerBits");
   TH1F *refTriggerBitsFunc = RefClone(where,"hTriggerBitsFunc");
   TH1F *refFiltTriggerBits = RefClone(where,"hFiltTriggerBits");

   TH1F *refTrackTrigger = RefClone(where,"hTrackTrigger");
   TH1F *refFiltTrackTrigger = RefClone(where,"hFiltTrackTrigger");

   TH1F *refBreit = RefClone(where,"hBreit");

   // Loop with user code on all events and fill the ref histograms
   // The code below should produce identical results to the tree->Draw above

   cout << "Recalculating the histograms with custom loop." << endl;

   TClonesArray *tracks = event->GetTracks();
   Int_t nev = (Int_t)tree->GetEntries();
   Int_t i, ntracks, evmod,i0,i1, Nvertex;
   Track *t;
   EventHeader *head;
   Int_t nbin = 0;
   for (Int_t ev=0;ev<nev;ev++) {
      nbin += tree->GetEntry(ev);
      head = event->GetHeader();
      evmod = head->GetEvtNum()%10;
      refNtrack->Fill(event->GetNtrack());
      refGetNtrack->Fill(event->GetNtrack());
      refNseg->Fill(event->GetNseg());
      refTemp->Fill(event->GetTemperature());
      refHmean->Fill(event->GetHistogram()->GetMean());
      refHAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHAxisGetMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHGetAxisGetMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refGetHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refGetRefHGetAxisMax->Fill(event->GetHistogram()->GetXaxis()->GetXmax());
      refSqrtNtrack->Fill(sqrt(event->GetNtrack()));

      if (!strcmp("type1",event->GetType()))
        refString->Fill(event->GetHeader()->GetEvtNum());
      if (strstr(event->GetType(),"1")) {
        refString->Fill(event->GetHeader()->GetEvtNum());
      }
      refAliasStr->Fill(strstr(event->GetType(),"1")!=0);

      Nvertex = event->GetNvertex();
      for(i0=0;i0<Nvertex;i0++) {
         refClosestDistance->Fill(event->GetClosestDistance(i0));
      }
      if (Nvertex>2) refClosestDistance2->Fill(event->GetClosestDistance(2));
      if (Nvertex>9) refClosestDistance9->Fill(event->GetClosestDistance(9));
      refClosestDistanceIndex->Fill(event->GetClosestDistance(Nvertex/2));

      for(i0=0;i0<4;i0++) {
         for(i1=0;i1<4;i1++) {
            refFullMatrix->Fill(event->GetMatrix(i0,i1));
         }
         refColMatrix->Fill(event->GetMatrix(i0,0));
         refRowMatrix->Fill(event->GetMatrix(1,i0)); // done here because the matrix is square!
      }
      refCellMatrix->Fill(event->GetMatrix(2,2));

      TBits bits = event->GetTriggerBits();
      Int_t nbits = bits.GetNbits();
      Int_t ncx = refTriggerBits->GetXaxis()->GetNbins();
      Int_t nextbit = -1;
      while(1) {
         nextbit = bits.FirstSetBit(nextbit+1);
         if (nextbit >= nbits) break;
         if (nextbit > ncx) refTriggerBits->Fill(ncx+1);
         else               refTriggerBits->Fill(nextbit);
         if (nextbit > ncx) refTriggerBitsFunc->Fill(ncx+1);
         else               refTriggerBitsFunc->Fill(nextbit);
      }
      if (bits.TestBitNumber(10)) refFiltTriggerBits->Fill(nbits);

      ntracks = event->GetNtrack();
      if ( 5 < ntracks ) {
         t = (Track*)tracks->UncheckedAt(5);
         for(i0=0;i0<4;i0++) {
            for(i1=0;i1<4;i1++) {
            }
            refColOper->Fill( event->GetMatrix(i0,1) - t->GetVertex(1) );
            refRowOper->Fill( event->GetMatrix(2,i0) - t->GetVertex(2) );
         }
         for(i0=0;i0<3;i0++) {
            refMatchRowOper->Fill( event->GetMatrix(2,i0) - t->GetVertex(i0) );
            refMatchDiffOper->Fill( event->GetMatrix(i0,2) - t->GetVertex(i0) );
         }
         refCellOper->Fill( event->GetMatrix(2,1) - t->GetVertex(1) );
      }
      for (i=0;i<ntracks;i++) {
         t = (Track*)tracks->UncheckedAt(i);
         if (evmod == 0) refPx->Fill(t->GetPx());
         if (evmod == 0) refPy->Fill(t->GetPy());
         if (evmod == 0) refPz->Fill(t->GetPz());
         if (evmod == 1) refRandom->Fill(t->GetRandom(),3);
         if (evmod == 1) refMass2->Fill(t->GetMass2());
         if (evmod == 1) refBx->Fill(t->GetBx());
         if (evmod == 1) refBy->Fill(t->GetBy());
         if (evmod == 2) refXfirst->Fill(t->GetXfirst());
         if (evmod == 2) refYfirst->Fill(t->GetYfirst());
         if (evmod == 2) refZfirst->Fill(t->GetZfirst());
         if (evmod == 3) refXlast->Fill(t->GetXlast());
         if (evmod == 3) refYlast->Fill(t->GetYlast());
         if (evmod == 3) refZlast->Fill(t->GetZlast());
         if (t->GetPx() < 0) {
            refCharge->Fill(t->GetCharge());
            refNpoint->Fill(t->GetNpoint());
            refValid->Fill(t->GetValid());
         }
         Int_t valid = t->GetValid();
         refShiftValid->Fill(valid << 4);
         refShiftValid->Fill( (valid << 4) >> 2 );
         if (event->GetNvertex()>10 && event->GetNseg()<=6000) {
            refAndValid->Fill( t->GetValid() & 0x1 );
         }

         Track * t2 = (Track*)tracks->At(t->GetNpoint()/6);
         if (t2 && t2->GetPy()>0) {
            refPxInd->Fill(t2->GetPy(),t->GetPx());
         }
         float Bx,By;
         Bx = t->GetBx();
         By = t->GetBy();
         if ((Bx>.15) || (By<=-.15)) refPxBx->Fill(t->GetPx());
         double weight = Bx*Bx*(Bx>.15) + By*By*(By<=-.15);
         if (weight) refPxBxWeight->Fill(t->GetPx(),weight);

         if (i<4) {
            for(i1=0;i1<3;i1++) { // 3 is the min of the 2nd dim of Matrix and Vertex
               refFullOper ->Fill( event->GetMatrix(i,i1) - t->GetVertex(i1) );
               refFullOper2->Fill( event->GetMatrix(i,i1) - t->GetVertex(i1) );
               refRowMatOper->Fill( event->GetMatrix(i,2) - t->GetVertex(i1) );
            }
            refMatchColOper->Fill( event->GetMatrix(i,2) - t->GetVertex(1) );
         }
         for(i1=0; i1<t->GetN(); i1++) {
            refPointValue->Fill( t->GetPointValue(i1) );
         }
         TBits bits = t->GetTriggerBits();
         Int_t nbits = bits.GetNbits();
         Int_t ncx = refTrackTrigger->GetXaxis()->GetNbins();
         Int_t nextbit = -1;
         while(1) {
            nextbit = bits.FirstSetBit(nextbit+1);
            if (nextbit >= nbits) break;
            if (nextbit > ncx) refTrackTrigger->Fill(ncx+1);
            else               refTrackTrigger->Fill(nextbit);
         }
         if (bits.TestBitNumber(5)) refFiltTrackTrigger->Fill(t->GetPx());
         refBreit->Fill(TMath::BreitWigner(t->GetPx(),3,2));

         refAlias->Fill(head->GetEvtNum()*6+t->GetPx()*t->GetPy());
      }
   }

   delete event;
   Event::Reset();

}

void dt_MakeRef(const char* from, Int_t verboseLevel = 2) {
   SetVerboseLevel(verboseLevel);

   if (!TClassTable::GetDict("Event")) {
      gSystem->Load("libEvent");
      gHasLibrary = kTRUE;
   }

   gROOT->GetList()->Delete();

   TFile *hfile = new TFile(from);
   TTree *tree = (TTree*)hfile->Get("T");

   TFile* f= new TFile("dt_reference.root","recreate");
   MakeHisto(tree,f);
   f->Write();
   delete f;

   delete hfile;

   gROOT->cd();
   cout << "Checking histograms" << endl;
   Compare(gDirectory);

    //   gROOT->GetList()->Delete();

}
<|endoftext|>


<commit_before>/*
 * geo_test.cpp
 *
 *  Created on: 201487
 *      Author: wangqiying
 */

#include "ardb.hpp"
using namespace ardb;

void test_geo_common(Context& ctx, Ardb& db)
{
    db.GetConfig().zset_max_ziplist_entries = 16;
    RedisCommandFrame del;
    del.SetFullCommand("del mygeo");
    db.Call(ctx, del, 0);
    double x = 300.3;
    double y = 300.3;

    double p_x = 1000.0;
    double p_y = 1000.0;
    uint32 raius = 1000;
    uint32 total = 100000;
    GeoPointArray cmp;
    for (uint32 i = 0; i < total; i++)
    {
        char name[100];
        sprintf(name, "p%u", i);
        double xx = x + i * 0.1;
        double yy = y + i * 0.1;
        if (((xx - p_x) * (xx - p_x) + (yy - p_y) * (yy - p_y)) < raius * raius)
        {
            GeoPoint p;
            p.x = xx;
            p.y = yy;
            cmp.push_back(p);
        }
        RedisCommandFrame geoadd;
        geoadd.SetFullCommand("geoadd mygeo MERCATOR %.2f %.2f %s", xx, yy, name);
        db.Call(ctx, geoadd, 0);
    }

    RedisCommandFrame zcard;
    zcard.SetFullCommand("zcard mygeo");
    db.Call(ctx, zcard, 0);
    CHECK_FATAL(ctx.reply.integer != total, "geoadd failed");
    RedisCommandFrame geosearch;
    geosearch.SetFullCommand("geosearch mygeo MERCATOR %.2f %.2f radius %d ASC WITHCOORDINATES WITHDISTANCES", p_x, p_y,
            raius);
    db.Call(ctx, geosearch, 0);
    CHECK_FATAL(ctx.reply.MemberSize() != cmp.size() * 4, "geosearch failed");
}

void test_geo(Ardb& db)
{
    Context tmpctx;
    test_geo_common(tmpctx, db);
}
<commit_msg>fix ut for geosearch<commit_after>/*
 * geo_test.cpp
 *
 *  Created on: 201487
 *      Author: wangqiying
 */

#include "ardb.hpp"
using namespace ardb;

void test_geo_common(Context& ctx, Ardb& db)
{
    db.GetConfig().zset_max_ziplist_entries = 16;
    RedisCommandFrame del;
    del.SetFullCommand("del mygeo");
    db.Call(ctx, del, 0);
    double x = 300.3;
    double y = 300.3;

    double p_x = 1000.0;
    double p_y = 1000.0;
    uint32 raius = 1000;
    uint32 total = 100000;
    GeoPointArray cmp;
    for (uint32 i = 0; i < total; i++)
    {
        char name[100];
        sprintf(name, "p%u", i);
        /*
         * min accuracy is 0.2meters
         */
        double xx = x + i * 0.3;
        double yy = y + i * 0.3;
        if (((xx - p_x) * (xx - p_x) + (yy - p_y) * (yy - p_y)) <= raius * raius)
        {
            GeoPoint p;
            p.x = xx;
            p.y = yy;
            cmp.push_back(p);
        }
        RedisCommandFrame geoadd;
        geoadd.SetFullCommand("geoadd mygeo MERCATOR %.2f %.2f %s", xx, yy, name);
        db.Call(ctx, geoadd, 0);
    }

    RedisCommandFrame zcard;
    zcard.SetFullCommand("zcard mygeo");
    db.Call(ctx, zcard, 0);
    CHECK_FATAL(ctx.reply.integer != total, "geoadd failed");
    RedisCommandFrame geosearch;
    geosearch.SetFullCommand("geosearch mygeo MERCATOR %.2f %.2f radius %d ASC WITHCOORDINATES WITHDISTANCES", p_x, p_y,
            raius);
    db.Call(ctx, geosearch, 0);
    CHECK_FATAL(ctx.reply.MemberSize() != cmp.size() * 4, "geosearch failed");
}

void test_geo(Ardb& db)
{
    Context tmpctx;
    test_geo_common(tmpctx, db);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPNMReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/

#include "vtkPNMReader.h"
#include <stdio.h>
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkPNMReader* vtkPNMReader::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkPNMReader");
  if(ret)
    {
    return (vtkPNMReader*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkPNMReader;
}

char vtkPNMReaderGetChar(FILE *fp)
{
  char c;
  int result;

  if ((result = getc(fp)) == EOF )
    {
    return '\0';
    }

  c = (char)result;
  if (c == '#')
    {
    do
      {
      if ((result = getc(fp)) == EOF )
	{
	return '\0';
	}
      c = (char)result;
      }
    while (c != '\n');
    }

  return c;
}

int vtkPNMReaderGetInt(FILE *fp)
{
  char c;
  int result = 0;

  do
    {
    c = vtkPNMReaderGetChar(fp);
    }
  while ((c < '1')||(c > '9'));
  do
    {
    result = result * 10 + (c - '0');
    c = vtkPNMReaderGetChar(fp);
    }
  while ((c >= '0')&&(c <= '9'));

  // put the CR/LF or whitespace back.....
  ungetc(c, fp);
  return result;
}

void vtkPNMReader::ExecuteInformation()
{
  int xsize, ysize, comp;
  char magic[80];
  char c;
  FILE *fp;

  // if the user has not set the extent, but has set the VOI
  // set the zaxis extent to the VOI z axis
  if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
      (this->DataVOI[4] || this->DataVOI[5]))
    {
    this->DataExtent[4] = this->DataVOI[4];
    this->DataExtent[5] = this->DataVOI[5];
    }

  // Allocate the space for the filename
  this->ComputeInternalFileName(this->DataExtent[4]);

  // get the magic number by reading in a file
  fp = fopen(this->InternalFileName,"rb");
  if (!fp)
    {
    vtkErrorMacro("Unable to open file " << this->InternalFileName);
    return;
    }

  do
    {
    c = vtkPNMReaderGetChar(fp);
    }
  while (c != 'P');
  magic[0] = c;
  magic[1] = vtkPNMReaderGetChar(fp);
  magic[2] = '\0';

  // now get the dimensions
  xsize = vtkPNMReaderGetInt(fp);
  ysize = vtkPNMReaderGetInt(fp);

  // read max pixel value into comp for now
  comp = vtkPNMReaderGetInt(fp);
  // if file is ascii, any amount of whitespace may follow.
  // if file is binary, a single whitespace character will follow.
  // We only support binary ppm and pgm files right now.  So the next
  // character IS always ignored.
  c = getc(fp);

  // if this file was "written" on the PC, then a CR will have been
  // written as a CR/LF combination.  So, if this single whitespace
  // character is a CR and it is followed by a LF, then swallow the
  // linefeed character as well. (Not part of the PPM standard, but a
  // a hard fact of life.
  if ( c == 0x0d )
     {
     c = getc(fp);
     if ( c != 0x0a )
        {
	ungetc( c, fp );
        }
     }

  // Set the header size now that we have parsed it
  this->SetHeaderSize(ftell(fp));

  fclose(fp);

  // compare magic number to determine file type
  if ( ! strcmp(magic,"P5") )
    {
    comp = 1;
    }
  else if ( ! strcmp(magic,"P6") )
    {
    comp = 3;
    }
  else
    {
    vtkErrorMacro(<<"Unknown file type! Not a binary PGM or PPM");
    return;
    }

  // if the user has set the VOI, just make sure its valid
  if (this->DataVOI[0] || this->DataVOI[1] ||
      this->DataVOI[2] || this->DataVOI[3] ||
      this->DataVOI[4] || this->DataVOI[5])
    {
    if ((this->DataVOI[0] < 0) ||
	(this->DataVOI[1] >= xsize) ||
	(this->DataVOI[2] < 0) ||
	(this->DataVOI[3] >= ysize))
      {
      vtkWarningMacro("The requested VOI is larger than the file's (" << this->InternalFileName << ") extent ");
      this->DataVOI[0] = 0;
      this->DataVOI[1] = xsize - 1;
      this->DataVOI[2] = 0;
      this->DataVOI[3] = ysize - 1;
      }
    }

  this->DataExtent[0] = 0;
  this->DataExtent[1] = xsize - 1;
  this->DataExtent[2] = 0;
  this->DataExtent[3] = ysize - 1;

  this->SetDataScalarTypeToUnsignedChar();
  this->SetNumberOfScalarComponents(comp);

  vtkImageReader::UpdateInformation();
}

<commit_msg>Fixed recursive call bug<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPNMReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/

#include "vtkPNMReader.h"
#include <stdio.h>
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkPNMReader* vtkPNMReader::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkPNMReader");
  if(ret)
    {
    return (vtkPNMReader*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkPNMReader;
}

char vtkPNMReaderGetChar(FILE *fp)
{
  char c;
  int result;

  if ((result = getc(fp)) == EOF )
    {
    return '\0';
    }

  c = (char)result;
  if (c == '#')
    {
    do
      {
      if ((result = getc(fp)) == EOF )
	{
	return '\0';
	}
      c = (char)result;
      }
    while (c != '\n');
    }

  return c;
}

int vtkPNMReaderGetInt(FILE *fp)
{
  char c;
  int result = 0;

  do
    {
    c = vtkPNMReaderGetChar(fp);
    }
  while ((c < '1')||(c > '9'));
  do
    {
    result = result * 10 + (c - '0');
    c = vtkPNMReaderGetChar(fp);
    }
  while ((c >= '0')&&(c <= '9'));

  // put the CR/LF or whitespace back.....
  ungetc(c, fp);
  return result;
}

void vtkPNMReader::ExecuteInformation()
{
  int xsize, ysize, comp;
  char magic[80];
  char c;
  FILE *fp;

  // if the user has not set the extent, but has set the VOI
  // set the zaxis extent to the VOI z axis
  if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
      (this->DataVOI[4] || this->DataVOI[5]))
    {
    this->DataExtent[4] = this->DataVOI[4];
    this->DataExtent[5] = this->DataVOI[5];
    }

  // Allocate the space for the filename
  this->ComputeInternalFileName(this->DataExtent[4]);

  // get the magic number by reading in a file
  fp = fopen(this->InternalFileName,"rb");
  if (!fp)
    {
    vtkErrorMacro("Unable to open file " << this->InternalFileName);
    return;
    }

  do
    {
    c = vtkPNMReaderGetChar(fp);
    }
  while (c != 'P');
  magic[0] = c;
  magic[1] = vtkPNMReaderGetChar(fp);
  magic[2] = '\0';

  // now get the dimensions
  xsize = vtkPNMReaderGetInt(fp);
  ysize = vtkPNMReaderGetInt(fp);

  // read max pixel value into comp for now
  comp = vtkPNMReaderGetInt(fp);
  // if file is ascii, any amount of whitespace may follow.
  // if file is binary, a single whitespace character will follow.
  // We only support binary ppm and pgm files right now.  So the next
  // character IS always ignored.
  c = getc(fp);

  // if this file was "written" on the PC, then a CR will have been
  // written as a CR/LF combination.  So, if this single whitespace
  // character is a CR and it is followed by a LF, then swallow the
  // linefeed character as well. (Not part of the PPM standard, but a
  // a hard fact of life.
  if ( c == 0x0d )
     {
     c = getc(fp);
     if ( c != 0x0a )
        {
	ungetc( c, fp );
        }
     }

  // Set the header size now that we have parsed it
  this->SetHeaderSize(ftell(fp));

  fclose(fp);

  // compare magic number to determine file type
  if ( ! strcmp(magic,"P5") )
    {
    comp = 1;
    }
  else if ( ! strcmp(magic,"P6") )
    {
    comp = 3;
    }
  else
    {
    vtkErrorMacro(<<"Unknown file type! Not a binary PGM or PPM");
    return;
    }

  // if the user has set the VOI, just make sure its valid
  if (this->DataVOI[0] || this->DataVOI[1] ||
      this->DataVOI[2] || this->DataVOI[3] ||
      this->DataVOI[4] || this->DataVOI[5])
    {
    if ((this->DataVOI[0] < 0) ||
	(this->DataVOI[1] >= xsize) ||
	(this->DataVOI[2] < 0) ||
	(this->DataVOI[3] >= ysize))
      {
      vtkWarningMacro("The requested VOI is larger than the file's (" << this->InternalFileName << ") extent ");
      this->DataVOI[0] = 0;
      this->DataVOI[1] = xsize - 1;
      this->DataVOI[2] = 0;
      this->DataVOI[3] = ysize - 1;
      }
    }

  this->DataExtent[0] = 0;
  this->DataExtent[1] = xsize - 1;
  this->DataExtent[2] = 0;
  this->DataExtent[3] = ysize - 1;

  this->SetDataScalarTypeToUnsignedChar();
  this->SetNumberOfScalarComponents(comp);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *   MindTheGap: Integrated detection and assembly of insertion variants
 *   A tool from the GATB (Genome Assembly Tool Box)
 *   Copyright (C) 2014  INRIA
 *   Authors: C.Lemaitre, G.Rizk, P.Marijon
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#ifndef _TOOL_FindDeletion_HPP_
#define _TOOL_FindDeletion_HPP_

/*****************************************************************************/
#include <IFindObserver.hpp>
#include <FindBreakpoints.hpp>

template<size_t span>
class FindDeletion : public IFindObserver
{
public :
    typedef typename gatb::core::kmer::impl::Kmer Kmer;

    typedef typename Kmer::ModelCanonical KmerModel;
    typedef typename KmerModel::Iterator KmerIterator;

public :

    /** \copydoc IFindObserver
     */
    FindDeletion(FindBreakpoints * find);

    /** \copydoc IFindObserver::IFindObserver
     */
    bool update();
};

template<size_t span>
FindDeletion::FindDeletion(FindBreakpoints * find) : IFindObserver(find){}

template<size_t span>
bool FindDeletion::update()
{
    if((this->_find->kmer_begin().isValid() && this->_find->kmer_end().isValid()) == false)
    {
	return false;
    }

    // Test if deletion is a fuzzy deletion
    std::string begin = this->_find->model().toString(this->_find->kmer_begin().forward());
    std::string end = this->_find->model().toString(this->_find->kmer_end().forward());

    unsigned int repeat_size = 0;

    for(repeat_size = 0; begin.substr(begin.length() - 1 - repeat_size, 1) == end.substr(repeat_size, 1); repeat_size++);

    // Compute del_size
    unsigned int del_size = this->_find->gap_stretch_size() - this->_find->kmer_size() + repeat_size;

    if(repeat_size != 0)
    {
	unsigned char hist_begin_pos = this->_find->position() - del_size - 1 % 256;
	begin = this->_find->model().toString(this->_find->het_kmer_history(hist_begin_pos).kmer);
    }

    // Check gap is a deletion
    std::string seq = begin + end;

    KmerModel local_m(this->_find->kmer_size());
    KmerIterator local_it(local_m);
    Data local_d(const_cast<char*>(seq.c_str()));
    local_d.setRef(const_cast<char*>(seq.c_str()), (size_t)seq.length());
    local_it.setData(local_d);

    for(local_it.first(); !local_it.isDone(); local_it.next())
    {
        if(!this->contains(local_it->forward()))
    	{
    	    return false;
    	}
    }

    // Write the breakpoint
    this->_find->writeBreakpoint(this->_find->breakpoint_id(), this->_find->chrom_name(), this->_find->position() - del_size - 2, begin, end, repeat_size, STR_DEL_TYPE);
    this->_find->breakpoint_id_iterate();

    if(repeat_size != 0)
	this->_find->fuzzy_deletion_iterate();
    else
	this->_find->clean_deletion_iterate();

    return true;
}

#endif /* _TOOL_FindDeletion_HPP_ */
<commit_msg>MTG: for fuzzy deletion didn't use history just reduce size of kmer begin<commit_after>/*****************************************************************************
 *   MindTheGap: Integrated detection and assembly of insertion variants
 *   A tool from the GATB (Genome Assembly Tool Box)
 *   Copyright (C) 2014  INRIA
 *   Authors: C.Lemaitre, G.Rizk, P.Marijon
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#ifndef _TOOL_FindDeletion_HPP_
#define _TOOL_FindDeletion_HPP_

/*****************************************************************************/
#include <IFindObserver.hpp>
#include <FindBreakpoints.hpp>

template<size_t span>
class FindDeletion : public IFindObserver
{
public :
    typedef typename gatb::core::kmer::impl::Kmer Kmer;

    typedef typename Kmer::ModelCanonical KmerModel;
    typedef typename KmerModel::Iterator KmerIterator;

public :

    /** \copydoc IFindObserver
     */
    FindDeletion(FindBreakpoints * find);

    /** \copydoc IFindObserver::IFindObserver
     */
    bool update();
};

template<size_t span>
FindDeletion::FindDeletion(FindBreakpoints * find) : IFindObserver(find){}

template<size_t span>
bool FindDeletion::update()
{
    if((this->_find->kmer_begin().isValid() && this->_find->kmer_end().isValid()) == false)
    {
	return false;
    }

    // Test if deletion is a fuzzy deletion
    std::string begin = this->_find->model().toString(this->_find->kmer_begin().forward());
    std::string end = this->_find->model().toString(this->_find->kmer_end().forward());

    unsigned int repeat_size = 0;

    for(repeat_size = 0; begin.substr(begin.length() - 1 - repeat_size, 1) == end.substr(repeat_size, 1); repeat_size++);

    // Compute del_size
    unsigned int del_size = this->_find->gap_stretch_size() - this->_find->kmer_size() + repeat_size + 1;

    if(repeat_size != 0)
    {
	begin = begin.substr(0, begin.length() - repeat_size)
    }

    // Check gap is a deletion
    std::string seq = begin + end;

    KmerModel local_m(this->_find->kmer_size());
    KmerIterator local_it(local_m);
    Data local_d(const_cast<char*>(seq.c_str()));
    local_d.setRef(const_cast<char*>(seq.c_str()), (size_t)seq.length());
    local_it.setData(local_d);

    for(local_it.first(); !local_it.isDone(); local_it.next())
    {
        if(!this->contains(local_it->forward()))
    	{
    	    return false;
    	}
    }

    // Write the breakpoint
    this->_find->writeBreakpoint(this->_find->breakpoint_id(), this->_find->chrom_name(), this->_find->position() - del_size - 1, begin, end, repeat_size, STR_DEL_TYPE);
    this->_find->breakpoint_id_iterate();

    if(repeat_size != 0)
	this->_find->fuzzy_deletion_iterate();
    else
	this->_find->clean_deletion_iterate();

    return true;
}

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


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Selector for the "sum" reduction implementations.
 *
 * The functions are responsible for selecting the most efficient
 * implementation for each case, based on what is available. The selection of
 * parallel versus serial is also done at this level. The implementation
 * functions should never be used directly, only functions of this header can
 * be used directly.
 */

#pragma once

#include "etl/config.hpp"
#include "etl/traits_lite.hpp"

//Include the implementations
#include "etl/impl/std/sum.hpp"
#include "etl/impl/sse/sum.hpp"

namespace etl {

namespace detail {

enum class sum_imple {
    STD,
    SSE,
    AVX
};

template <typename E>
cpp14_constexpr sum_imple select_sum_impl() {
    //Note: since the constexpr values will be known at compile time, the
    //conditions will be a lot simplified

    //Only standard access elements through the expression itself
    if(!has_direct_access<E>::value){
        return sum_imple::STD;
    }

    if(decay_traits<E>::vectorizable){
        constexpr const bool sse = vectorize_impl && vector_mode == vector_mode_t::SSE3;
        constexpr const bool avx = vectorize_impl && vector_mode == vector_mode_t::AVX;

        if (avx) {
            return sum_imple::AVX;
        } else if (sse) {
            return sum_imple::SSE;
        }
    }

    return sum_imple::STD;
}

template <typename E, typename Enable = void>
struct sum_impl {
    static value_t<E> apply(const E& e) {
        cpp14_constexpr auto impl = select_sum_impl<E>();

        if (impl == sum_imple::AVX) {
            return impl::standard::sum(e);
        } else if (impl == sum_imple::SSE) {
            return impl::sse::sum(e);
        } else {
            return impl::standard::sum(e);
        }
    }
};

} //end of namespace detail

} //end of namespace etl
<commit_msg>Add note<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief Selector for the "sum" reduction implementations.
 *
 * The functions are responsible for selecting the most efficient
 * implementation for each case, based on what is available. The selection of
 * parallel versus serial is also done at this level. The implementation
 * functions should never be used directly, only functions of this header can
 * be used directly.
 *
 * Note: In a perfect world (full constexpr function and variable templates),
 * the selection should be done with a template parameter in a variable
 * template full sspecialization (alias for each real functions).
 */

#pragma once

#include "etl/config.hpp"
#include "etl/traits_lite.hpp"

//Include the implementations
#include "etl/impl/std/sum.hpp"
#include "etl/impl/sse/sum.hpp"

namespace etl {

namespace detail {

enum class sum_imple {
    STD,
    SSE,
    AVX
};

template <typename E>
cpp14_constexpr sum_imple select_sum_impl() {
    //Note: since the constexpr values will be known at compile time, the
    //conditions will be a lot simplified

    //Only standard access elements through the expression itself
    if(!has_direct_access<E>::value){
        return sum_imple::STD;
    }

    if(decay_traits<E>::vectorizable){
        constexpr const bool sse = vectorize_impl && vector_mode == vector_mode_t::SSE3;
        constexpr const bool avx = vectorize_impl && vector_mode == vector_mode_t::AVX;

        if (avx) {
            return sum_imple::AVX;
        } else if (sse) {
            return sum_imple::SSE;
        }
    }

    return sum_imple::STD;
}

template <typename E, typename Enable = void>
struct sum_impl {
    static value_t<E> apply(const E& e) {
        cpp14_constexpr auto impl = select_sum_impl<E>();

        if (impl == sum_imple::AVX) {
            return impl::standard::sum(e);
        } else if (impl == sum_imple::SSE) {
            return impl::sse::sum(e);
        } else {
            return impl::standard::sum(e);
        }
    }
};

} //end of namespace detail

} //end of namespace etl
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file meta.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__META_HPP
#define FL__UTIL__META_HPP

#include <Eigen/Dense>
#include <fl/util/traits.hpp>

namespace fl
{

/**
 * \ingroup meta
 *
 * \tparam Sizes    Variadic argument containing a list of sizes. Each size
 *                  is a result of a constexpr or a const of a signed integral
 *                  type. Unknown sizes are represented by -1 or Eigen::Dynamic.
 *
 *
 * Joins the sizes within the \c Sizes argument list if all sizes are
 * non-dynamic. That is, all sizes are greater -1 (\c Eigen::Dynamic). If one of
 * the passed sizes is \c Eigen::Dynamic, the total size collapses to
 * \c Eigen::Dynamic.
 */
template <int... Sizes> struct JoinSizes;

/**
 * \internal
 * \ingroup meta
 * \copydoc JoinSizes
 *
 * \tparam Head     Head of the \c Sizes list of the previous recursive call
 *
 * Variadic counting recursion
 */
template <int Head, int... Sizes> struct JoinSizes<Head, Sizes...>
{
    enum : signed int
    {
        Size = IsFixed<Head>() && IsFixed<JoinSizes<Sizes...>::Size>()
                   ? Head + JoinSizes<Sizes...>::Size
                   : Eigen::Dynamic
    };
};

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization of JoinSizes<...>
 */
template <> struct JoinSizes<> { enum: signed int { Size = 0 }; } ;

/**
 * \ingroup meta
 *
 * \brief Function form of JoinSizes for two sizes
 */
inline constexpr int join_sizes(int a, int b)
{
    return (a > Eigen::Dynamic && b > Eigen::Dynamic) ? a + b : Eigen::Dynamic;
}

/**
 * \ingroup meta
 *
 * Computes the product of LocalSize times Factor. If one of the parameters is
 * set to Eigen::Dynamic, the factor size will collapse to Eigen::Dynbamic as
 * well.
 */
template <int ... Sizes> struct ExpandSizes;

/**
 * \internal
 * \ingroup meta
 */
template <int Head, int... Sizes> struct ExpandSizes<Head, Sizes...>
{
    enum: signed int
    {
        Size = IsFixed<Head>() && IsFixed<ExpandSizes<Sizes...>::Size>()
                   ? Head * ExpandSizes<Sizes...>::Size
                   : Eigen::Dynamic
    };
};

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization of ExpandSizes<...>
 */
template <> struct ExpandSizes<> { enum: signed int { Size = 1 }; } ;

/**
 * \ingroup meta
 *
 * Provides access to the the first type element in the specified variadic list
 */
template <typename...T> struct FirstTypeIn;

/**
 * \internal
 * \ingroup meta
 *
 * Implementation of FirstTypeIn
 */
template <typename First, typename...T> struct FirstTypeIn<First, T...>
{
    typedef First Type;
};

/**
 * \ingroup meta
 *
 * Represents a sequence of indices IndexSequence<0, 1, 2, 3, ...>
 *
 * This is particularly useful to expand tuples
 *
 * \tparam Indices  List of indices starting from 0
 */
template <int ... Indices> struct IndexSequence
{
    enum { Size = sizeof...(Indices) };
};

/**
 * \ingroup meta
 *
 * Creates an IndexSequence<0, 1, 2, ...> for a specified size.
 */
template <int Size, int ... Indices>
struct CreateIndexSequence
    : CreateIndexSequence<Size - 1, Size - 1, Indices...>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization CreateIndexSequence
 */
template <int ... Indices>
struct CreateIndexSequence<0, Indices...>
    : IndexSequence<Indices...>
{ };

/**
 * \ingroup meta
 *
 * Meta type defined in terms of a sequence of types
 */
template <typename ... T>
struct TypeSequence
{
    enum : signed int { Size = sizeof...(T) };
};

/**
 * \internal
 * \ingroup meta
 *
 * Empty TypeSequence
 */
template <> struct TypeSequence<>
{
    enum : signed int { Size = Eigen::Dynamic };
};

/**
 * \ingroup meta
 *
 * Creates a \c TypeSequence<T...> by expanding the specified \c Type \c Count
 * times.
 */
template <int Count, typename Type, typename...T>
struct CreateTypeSequence
    : CreateTypeSequence<Count - 1, Type, Type, T...>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Terminal type of CreateTypeSequence
 */
template <typename Type, typename...T>
struct CreateTypeSequence<1, Type, T...>
    : TypeSequence<Type, T...>
{ };

/**
 * \ingroup meta
 *
 * Creates an empty \c TypeSequence<> for a \c Count = Eigen::Dynamic
 */
template <typename Type>
struct CreateTypeSequence<Eigen::Dynamic, Type>
  : TypeSequence<>
{ };

/**
 * \ingroup meta
 *
 * Same as CreateTypeSequence, however with a reversed parameter order. This is
 * an attempt to make the use of \c CreateTypeSequence more natural.
 */
template <typename Type, int Count>
struct MultipleOf
    : CreateTypeSequence<Count, Type>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Creates an empty TypeSequence for dynamic count
 */
template <typename Type>
struct MultipleOf<Type, Eigen::Dynamic>
    : CreateTypeSequence<Eigen::Dynamic, Type>
{ };

}

#endif

<commit_msg>Implemented some "meta operators" AdaptiveModel, Join and the collapse of Join.<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file meta.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__META_HPP
#define FL__UTIL__META_HPP

#include <Eigen/Dense>
#include <fl/util/traits.hpp>

namespace fl
{

/**
 * \ingroup meta
 *
 * \tparam Sizes    Variadic argument containing a list of sizes. Each size
 *                  is a result of a constexpr or a const of a signed integral
 *                  type. Unknown sizes are represented by -1 or Eigen::Dynamic.
 *
 *
 * Joins the sizes within the \c Sizes argument list if all sizes are
 * non-dynamic. That is, all sizes are greater -1 (\c Eigen::Dynamic). If one of
 * the passed sizes is \c Eigen::Dynamic, the total size collapses to
 * \c Eigen::Dynamic.
 */
template <int... Sizes> struct JoinSizes;

/**
 * \internal
 * \ingroup meta
 * \copydoc JoinSizes
 *
 * \tparam Head     Head of the \c Sizes list of the previous recursive call
 *
 * Variadic counting recursion
 */
template <int Head, int... Sizes> struct JoinSizes<Head, Sizes...>
{
    enum : signed int
    {
        Size = IsFixed<Head>() && IsFixed<JoinSizes<Sizes...>::Size>()
                   ? Head + JoinSizes<Sizes...>::Size
                   : Eigen::Dynamic
    };
};

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization of JoinSizes<...>
 */
template <> struct JoinSizes<> { enum: signed int { Size = 0 }; } ;

/**
 * \ingroup meta
 *
 * \brief Function form of JoinSizes for two sizes
 */
inline constexpr int join_sizes(int a, int b)
{
    return (a > Eigen::Dynamic && b > Eigen::Dynamic) ? a + b : Eigen::Dynamic;
}

/**
 * \ingroup meta
 *
 * Computes the product of LocalSize times Factor. If one of the parameters is
 * set to Eigen::Dynamic, the factor size will collapse to Eigen::Dynbamic as
 * well.
 */
template <int ... Sizes> struct ExpandSizes;

/**
 * \internal
 * \ingroup meta
 */
template <int Head, int... Sizes> struct ExpandSizes<Head, Sizes...>
{
    enum: signed int
    {
        Size = IsFixed<Head>() && IsFixed<ExpandSizes<Sizes...>::Size>()
                   ? Head * ExpandSizes<Sizes...>::Size
                   : Eigen::Dynamic
    };
};

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization of ExpandSizes<...>
 */
template <> struct ExpandSizes<> { enum: signed int { Size = 1 }; } ;

/**
 * \ingroup meta
 *
 * Provides access to the the first type element in the specified variadic list
 */
template <typename...T> struct FirstTypeIn;

/**
 * \internal
 * \ingroup meta
 *
 * Implementation of FirstTypeIn
 */
template <typename First, typename...T> struct FirstTypeIn<First, T...>
{
    typedef First Type;
};

/**
 * \ingroup meta
 *
 * Represents a sequence of indices IndexSequence<0, 1, 2, 3, ...>
 *
 * This is particularly useful to expand tuples
 *
 * \tparam Indices  List of indices starting from 0
 */
template <int ... Indices> struct IndexSequence
{
    enum { Size = sizeof...(Indices) };
};

/**
 * \ingroup meta
 *
 * Creates an IndexSequence<0, 1, 2, ...> for a specified size.
 */
template <int Size, int ... Indices>
struct CreateIndexSequence
    : CreateIndexSequence<Size - 1, Size - 1, Indices...>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Terminal specialization CreateIndexSequence
 */
template <int ... Indices>
struct CreateIndexSequence<0, Indices...>
    : IndexSequence<Indices...>
{ };

/**
 * \ingroup meta
 *
 * Meta type defined in terms of a sequence of types
 */
template <typename ... T>
struct TypeSequence
{
    enum : signed int { Size = sizeof...(T) };
};

/**
 * \internal
 * \ingroup meta
 *
 * Empty TypeSequence
 */
template <> struct TypeSequence<>
{
    enum : signed int { Size = Eigen::Dynamic };
};

/**
 * \ingroup meta
 *
 * Creates a \c TypeSequence<T...> by expanding the specified \c Type \c Count
 * times.
 */
template <int Count, typename Type, typename...T>
struct CreateTypeSequence
    : CreateTypeSequence<Count - 1, Type, Type, T...>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Terminal type of CreateTypeSequence
 */
template <typename Type, typename...T>
struct CreateTypeSequence<1, Type, T...>
    : TypeSequence<Type, T...>
{ };

/**
 * \ingroup meta
 *
 * Creates an empty \c TypeSequence<> for a \c Count = Eigen::Dynamic
 */
template <typename Type>
struct CreateTypeSequence<Eigen::Dynamic, Type>
  : TypeSequence<>
{ };

template <typename Model, typename ParameterModel>
struct AdaptiveModel { };

/**
 * \ingroup meta
 *
 * Same as CreateTypeSequence, however with a reversed parameter order. This is
 * an attempt to make the use of \c CreateTypeSequence more natural. It also
 * allows dynamic sizes if needed.
 */
template <typename Type, int Count = Eigen::Dynamic>
struct MultipleOf
    : CreateTypeSequence<Count, Type>
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Creates an empty TypeSequence for dynamic count
 */
template <typename Type>
struct MultipleOf<Type, Eigen::Dynamic>
    : CreateTypeSequence<Eigen::Dynamic, Type>
{ };

/**
 * \c Join represents a meta operator taking an argument pack which should be
 * unified in a specific way. The operator is defined by the following axioms
 *
 * - pack of Join<P1, P2, ...>  {P1, P2, ...}
 * - positive pack:             sizeof...(T) of Join<T...>
 * - nesting:                   Join<P1, Join<P2, P3>> = {P1, P2, P3}
 * - Comm.                      Join<P1, Join<P2, P3>> = Join<Join<P1, P2>, P3>
 * - MultipleOf operator:       Join<MultipleOf<P, #>>
 *
 * \ingroup meta
 */
template <typename...T> struct Join;

/**
 * \internal
 * \ingroup meta
 *
 * Collapes the argument pack of the Join operator into Model<T...> of ay given
 * Join<...> operator.
 */
template <typename...T> struct CollapseJoin;

/**
 * \internal
 * \ingroup meta
 *
 * CollapseJoin specialization which expands the type sequence by the Head
 * element assuming Head is neither a Join<...> nor a MultipleOf<P, #> operator.
 */
template <
    typename...S,
    typename Head,
    typename...T,
    template <typename...> class Model
>
struct CollapseJoin<
           Model<>,                 // Final model type
           TypeSequence<S...>,      // Type sequence holding the pack expansion
           Head,                    // Current non-operator pack head element
           T...>                    // Remaining Tail
  : CollapseJoin<
        Model<>,                    // Final model type
        TypeSequence<Head, S...>,   // updated type sequence
        T...>                       // Remaining Tail
{ };

/**
 * \internal
 * \ingroup meta
 *
 * CollapseJoin specialization which unifies a Join<...> pack Head into the
 * outer Join pack, i.e.
 *
 * Join<T1..., Join<T2...>, T3 > = Join<T1..., T2..., T3...>
 */
template <
    typename...S,
    typename...T,
    typename...U,
    template <typename...> class Model
>
struct CollapseJoin<
           Model<>,                 // Final model type
           TypeSequence<S...>,      // Type sequence holding the pack expansion
           Join<T...>,              // Current pack head element
           U...>                    // Remaining Tail
  : CollapseJoin<
        Model<>,                    // Final model type
        TypeSequence<S...>,         // Type sequence holding the pack expansion
        T...,                       // Extracted pack from inner Join operator
        U...>                       // Remaining Tail
{ };

/**
 * \internal
 * \ingroup meta
 *
 * CollapseJoin specialization which translates a MultipleOf<P,#> operator,
 * at the head of the pack, into Model<MultipleOf<P, #>>, i.e
 *
 * Join<T1..., MultipleOf<P, 10>, T2...> =
 * Join<T1..., Model<MultipleOf<P, 10>>, T2...>.
 */
template <
    typename...S,
    typename...T,
    typename U,
    int Count,
    template <typename...> class Model
>
struct CollapseJoin<
           Model<>,                 // Final model type
           TypeSequence<S...>,      // Type sequence holding the pack expansion
           MultipleOf<U, Count>,    // Current pack head element
           T...>                    // Remaining Join pack, the tail
  : CollapseJoin<
        Model<>,                    // Final model type
        TypeSequence<S...>,         // Type sequence holding the pack expansion
        Model<MultipleOf<U, Count>>,// Redefine head in terms of Model<>
        T...>                       // Remaining Tail
{ };

/**
 * \internal
 * \ingroup meta
 *
 * Terminal case of Join operator collapsing. The final result of Join<T...>
 * is Model<U...> where U are all the expanded non operator types.
 */
template <
    typename...S,
    template <typename...> class Model
>
struct CollapseJoin<
           Model<>,
           TypeSequence<S...>>
{
    /**
     * \brief Final type outcome of the Join Operator
     */
    typedef Model<S...> Type;

  static_assert(sizeof...(S) > 1, "Join<A, B, ...> operator must take 2 or more"
                                  " operands");
};

/**
 * \internal
 * \ingroup meta
 *
 * Terminal case of Join operator collapsing for a Join of the form
 * Join<MultipleOf<P, #>> resulting in Model<MultipleOf<P, #>>
 */
template <
    typename M,
    int Count,
    template <typename...> class Model
>
struct CollapseJoin<Model<>, TypeSequence<Model<MultipleOf<M, Count>>>>
{
    typedef Model<MultipleOf<M, Count>> Type;

    static_assert(Count > 0 || Count == -1,
                  "Cannot expand Join<MultipleOf<M, Count>> operator on M. "
                  "Count must be positive or set to -1 for the dynamic size "
                  "case.");
};

}

#endif

<|endoftext|>