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

#pragma hdrstop

#ifndef _SVTOOLS_SOURCEVIEWCONFIG_HXX
#include <sourceviewconfig.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif
#ifndef _SFXSMPLHINT_HXX
#include "smplhint.hxx"
#endif

#include <itemholder1.hxx>

using namespace utl;
using namespace rtl;
using namespace com::sun::star::uno;
namespace svt
{
class SourceViewConfig_Impl : public utl::ConfigItem, public SfxBroadcaster
{
private:
    OUString        m_sFontName;
    sal_Int16       m_nFontHeight;
    sal_Bool        m_bProportionalFontOnly;

    void        Load();

    static Sequence< OUString > GetPropertyNames();

public:
    SourceViewConfig_Impl();
    ~SourceViewConfig_Impl();

    virtual void    Notify( const Sequence< rtl::OUString >& aPropertyNames );
    virtual void    Commit();

    const rtl::OUString&    GetFontName() const
                                {return m_sFontName;}
    void                    SetFontName(const rtl::OUString& rName)
                                {
                                    if(rName != m_sFontName)
                                    {
                                        m_sFontName = rName;
                                        SetModified();
                                    }
                                }

    sal_Int16               GetFontHeight() const
                                {return m_nFontHeight;}
    void                    SetFontHeight(sal_Int16 nHeight)
                                {
                                    if(m_nFontHeight != nHeight)
                                    {
                                        m_nFontHeight = nHeight;
                                        SetModified();
                                    }
                                }

    sal_Bool                IsShowProportionalFontsOnly() const
                                {return m_bProportionalFontOnly;}
    void                    SetShowProportionalFontsOnly(sal_Bool bSet)
                                {
                                    if(m_bProportionalFontOnly != bSet)
                                    {
                                        m_bProportionalFontOnly = bSet;
                                        SetModified();
                                    }
                                }
};
// initialization of static members --------------------------------------
SourceViewConfig_Impl* SourceViewConfig::m_pImplConfig = 0;
sal_Int32              SourceViewConfig::m_nRefCount = 0;
namespace { struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; }
/* -----------------------------28.08.2002 16:45------------------------------

 ---------------------------------------------------------------------------*/
SourceViewConfig_Impl::SourceViewConfig_Impl() :
    ConfigItem(OUString::createFromAscii("Office.Common/Font/SourceViewFont")),
    m_nFontHeight(12),
    m_bProportionalFontOnly(sal_False)
{
    Load();
}
/* -----------------------------28.08.2002 16:45------------------------------

 ---------------------------------------------------------------------------*/
SourceViewConfig_Impl::~SourceViewConfig_Impl()
{
}
/* -----------------------------28.08.2002 16:25------------------------------

 ---------------------------------------------------------------------------*/
Sequence< OUString > SourceViewConfig_Impl::GetPropertyNames()
{
    //this list needs exactly to mach the enum PropertyNameIndex
    static const char* aPropNames[] =
    {
        "FontName"                  // 0
        ,"FontHeight"               // 1
        ,"NonProportionalFontsOnly" // 2
    };
    const int nCount = sizeof( aPropNames ) / sizeof( const char* );
    Sequence< OUString > aNames( nCount );
    OUString* pNames = aNames.getArray();
    for ( int i = 0; i < nCount; i++ )
        pNames[i] = OUString::createFromAscii( aPropNames[i] );

    return aNames;
}

/*-- 28.08.2002 16:37:59---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Load()
{
    Sequence< OUString > aNames = GetPropertyNames();
    Sequence< Any > aValues = GetProperties( aNames );
    EnableNotification( aNames );
    const Any* pValues = aValues.getConstArray();
    DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
    if ( aValues.getLength() == aNames.getLength() )
    {
        for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
        {
            if ( pValues[nProp].hasValue() )
            {
                switch( nProp )
                {
                    case 0:  pValues[nProp] >>= m_sFontName;         break;
                    case 1:  pValues[nProp] >>= m_nFontHeight;      break;
                    case 2:  pValues[nProp] >>= m_bProportionalFontOnly;     break;
                }
            }
        }
    }
}
/*-- 28.08.2002 16:38:00---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Notify( const Sequence< OUString >& aPropertyNames )
{
    Load();
}
/*-- 28.08.2002 16:38:00---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Commit()
{
    ClearModified();
    Sequence< OUString > aNames = GetPropertyNames();
    OUString* pNames = aNames.getArray();
    Sequence< Any > aValues( aNames.getLength() );
    Any* pValues = aValues.getArray();
    for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
    {
        switch( nProp )
        {
            case 0:  pValues[nProp] <<= m_sFontName;         break;
            case 1:  pValues[nProp] <<= m_nFontHeight;      break;
            case 2:  pValues[nProp] <<= m_bProportionalFontOnly;     break;
            default:
                DBG_ERRORFILE( "invalid index to save a user token" );
        }
    }
    PutProperties( aNames, aValues );

    //notify SfxListener
    {
        SfxSimpleHint aHint = SfxSimpleHint( SFX_HINT_DATACHANGED );
        Broadcast(aHint);
    }
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
SourceViewConfig::SourceViewConfig()
{
    {
        ::osl::MutexGuard aGuard( lclMutex::get() );
        if(!m_pImplConfig)
        {
            m_pImplConfig = new SourceViewConfig_Impl;
            ItemHolder1::holdConfigItem(E_SOURCEVIEWCONFIG);
        }

         ++m_nRefCount;
    }
    StartListening( *m_pImplConfig, TRUE );
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
SourceViewConfig::~SourceViewConfig()
{
    EndListening( *m_pImplConfig, TRUE );
    ::osl::MutexGuard aGuard( lclMutex::get() );
    if( !--m_nRefCount )
    {
        if( m_pImplConfig->IsModified() )
            m_pImplConfig->Commit();
        DELETEZ( m_pImplConfig );
    }
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
const OUString&  SourceViewConfig::GetFontName() const
{
    return m_pImplConfig->GetFontName();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetFontName(const OUString& rName)
{
    m_pImplConfig->SetFontName(rName);
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Int16 SourceViewConfig::GetFontHeight() const
{
    return m_pImplConfig->GetFontHeight();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetFontHeight(sal_Int16 nHeight)
{
    m_pImplConfig->SetFontHeight(nHeight);
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool SourceViewConfig::IsShowProportionalFontsOnly() const
{
    return m_pImplConfig->IsShowProportionalFontsOnly();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetShowProportionalFontsOnly(sal_Bool bSet)
{
    m_pImplConfig->SetShowProportionalFontsOnly(bSet);
}
/* -----------------------------30.08.2002 10:40------------------------------

 ---------------------------------------------------------------------------*/
void SourceViewConfig::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    Broadcast( rHint );
}
}//namespace svt
<commit_msg>INTEGRATION: CWS warnings01 (1.3.62); FILE MERGED 2006/01/25 19:43:34 sb 1.3.62.3: RESYNC: (1.3-1.4); FILE MERGED 2005/11/14 14:23:38 pl 1.3.62.2: #i55991# removed warnings 2005/10/25 12:44:24 pl 1.3.62.1: #i55991# removed warnings for linux platform<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sourceviewconfig.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 20:48:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVTOOLS_SOURCEVIEWCONFIG_HXX
#include <sourceviewconfig.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif
#ifndef _SFXSMPLHINT_HXX
#include "smplhint.hxx"
#endif

#include <itemholder1.hxx>

using namespace utl;
using namespace rtl;
using namespace com::sun::star::uno;
namespace svt
{
class SourceViewConfig_Impl : public utl::ConfigItem, public SfxBroadcaster
{
private:
    OUString        m_sFontName;
    sal_Int16       m_nFontHeight;
    sal_Bool        m_bProportionalFontOnly;

    void        Load();

    static Sequence< OUString > GetPropertyNames();

public:
    SourceViewConfig_Impl();
    ~SourceViewConfig_Impl();

    virtual void    Notify( const Sequence< rtl::OUString >& aPropertyNames );
    virtual void    Commit();

    const rtl::OUString&    GetFontName() const
                                {return m_sFontName;}
    void                    SetFontName(const rtl::OUString& rName)
                                {
                                    if(rName != m_sFontName)
                                    {
                                        m_sFontName = rName;
                                        SetModified();
                                    }
                                }

    sal_Int16               GetFontHeight() const
                                {return m_nFontHeight;}
    void                    SetFontHeight(sal_Int16 nHeight)
                                {
                                    if(m_nFontHeight != nHeight)
                                    {
                                        m_nFontHeight = nHeight;
                                        SetModified();
                                    }
                                }

    sal_Bool                IsShowProportionalFontsOnly() const
                                {return m_bProportionalFontOnly;}
    void                    SetShowProportionalFontsOnly(sal_Bool bSet)
                                {
                                    if(m_bProportionalFontOnly != bSet)
                                    {
                                        m_bProportionalFontOnly = bSet;
                                        SetModified();
                                    }
                                }
};
// initialization of static members --------------------------------------
SourceViewConfig_Impl* SourceViewConfig::m_pImplConfig = 0;
sal_Int32              SourceViewConfig::m_nRefCount = 0;
namespace { struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; }
/* -----------------------------28.08.2002 16:45------------------------------

 ---------------------------------------------------------------------------*/
SourceViewConfig_Impl::SourceViewConfig_Impl() :
    ConfigItem(OUString::createFromAscii("Office.Common/Font/SourceViewFont")),
    m_nFontHeight(12),
    m_bProportionalFontOnly(sal_False)
{
    Load();
}
/* -----------------------------28.08.2002 16:45------------------------------

 ---------------------------------------------------------------------------*/
SourceViewConfig_Impl::~SourceViewConfig_Impl()
{
}
/* -----------------------------28.08.2002 16:25------------------------------

 ---------------------------------------------------------------------------*/
Sequence< OUString > SourceViewConfig_Impl::GetPropertyNames()
{
    //this list needs exactly to mach the enum PropertyNameIndex
    static const char* aPropNames[] =
    {
        "FontName"                  // 0
        ,"FontHeight"               // 1
        ,"NonProportionalFontsOnly" // 2
    };
    const int nCount = sizeof( aPropNames ) / sizeof( const char* );
    Sequence< OUString > aNames( nCount );
    OUString* pNames = aNames.getArray();
    for ( int i = 0; i < nCount; i++ )
        pNames[i] = OUString::createFromAscii( aPropNames[i] );

    return aNames;
}

/*-- 28.08.2002 16:37:59---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Load()
{
    Sequence< OUString > aNames = GetPropertyNames();
    Sequence< Any > aValues = GetProperties( aNames );
    EnableNotification( aNames );
    const Any* pValues = aValues.getConstArray();
    DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
    if ( aValues.getLength() == aNames.getLength() )
    {
        for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
        {
            if ( pValues[nProp].hasValue() )
            {
                switch( nProp )
                {
                    case 0:  pValues[nProp] >>= m_sFontName;         break;
                    case 1:  pValues[nProp] >>= m_nFontHeight;      break;
                    case 2:  pValues[nProp] >>= m_bProportionalFontOnly;     break;
                }
            }
        }
    }
}
/*-- 28.08.2002 16:38:00---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Notify( const Sequence< OUString >& )
{
    Load();
}
/*-- 28.08.2002 16:38:00---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig_Impl::Commit()
{
    ClearModified();
    Sequence< OUString > aNames = GetPropertyNames();
    Sequence< Any > aValues( aNames.getLength() );
    Any* pValues = aValues.getArray();
    for ( int nProp = 0; nProp < aNames.getLength(); nProp++ )
    {
        switch( nProp )
        {
            case 0:  pValues[nProp] <<= m_sFontName;         break;
            case 1:  pValues[nProp] <<= m_nFontHeight;      break;
            case 2:  pValues[nProp] <<= m_bProportionalFontOnly;     break;
            default:
                DBG_ERRORFILE( "invalid index to save a user token" );
        }
    }
    PutProperties( aNames, aValues );

    //notify SfxListener
    {
        SfxSimpleHint aHint = SfxSimpleHint( SFX_HINT_DATACHANGED );
        Broadcast(aHint);
    }
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
SourceViewConfig::SourceViewConfig()
{
    {
        ::osl::MutexGuard aGuard( lclMutex::get() );
        if(!m_pImplConfig)
        {
            m_pImplConfig = new SourceViewConfig_Impl;
            ItemHolder1::holdConfigItem(E_SOURCEVIEWCONFIG);
        }

         ++m_nRefCount;
    }
    StartListening( *m_pImplConfig, TRUE );
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
SourceViewConfig::~SourceViewConfig()
{
    EndListening( *m_pImplConfig, TRUE );
    ::osl::MutexGuard aGuard( lclMutex::get() );
    if( !--m_nRefCount )
    {
        if( m_pImplConfig->IsModified() )
            m_pImplConfig->Commit();
        DELETEZ( m_pImplConfig );
    }
}
/*-- 28.08.2002 16:32:19---------------------------------------------------

  -----------------------------------------------------------------------*/
const OUString&  SourceViewConfig::GetFontName() const
{
    return m_pImplConfig->GetFontName();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetFontName(const OUString& rName)
{
    m_pImplConfig->SetFontName(rName);
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Int16 SourceViewConfig::GetFontHeight() const
{
    return m_pImplConfig->GetFontHeight();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetFontHeight(sal_Int16 nHeight)
{
    m_pImplConfig->SetFontHeight(nHeight);
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool SourceViewConfig::IsShowProportionalFontsOnly() const
{
    return m_pImplConfig->IsShowProportionalFontsOnly();
}
/*-- 28.08.2002 16:32:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void SourceViewConfig::SetShowProportionalFontsOnly(sal_Bool bSet)
{
    m_pImplConfig->SetShowProportionalFontsOnly(bSet);
}
/* -----------------------------30.08.2002 10:40------------------------------

 ---------------------------------------------------------------------------*/
void SourceViewConfig::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
    Broadcast( rHint );
}
}//namespace svt
<|endoftext|>


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

#include "main.h"

template<typename MatrixType> void trmv(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

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

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  VectorType v1 = VectorType::Random(rows);

  Scalar s1 = internal::random<Scalar>();

  m1 = MatrixType::Random(rows, cols);

  // check with a column-major matrix
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (col-major)
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps));

  // check with a row-major matrix
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (row-major)
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();

  // check transposed cases:
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps));

  // TODO check with sub-matrices
}

void test_product_trmv()
{
  int s;
  for(int i = 0; i < g_repeat ; i++) {
    CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( trmv(Matrix3d()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_4( trmv(MatrixXcf(s,internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
    CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
  }
}
<commit_msg>fix trmv unit test<commit_after>// This file is triangularView of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void trmv(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

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

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  VectorType v1 = VectorType::Random(rows);

  Scalar s1 = internal::random<Scalar>();

  m1 = MatrixType::Random(rows, cols);

  // check with a column-major matrix
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (col-major)
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps));

  // check with a row-major matrix
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (row-major)
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();

  // check transposed cases:
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps));

  // TODO check with sub-matrices
}

void test_product_trmv()
{
  int s;
  for(int i = 0; i < g_repeat ; i++) {
    CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( trmv(Matrix3d()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_4( trmv(MatrixXcf(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
    CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
  }
}
<|endoftext|>


<commit_before>#include "./constraint_updater.h"
#include <Eigen/Geometry>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <vector>
#include "../graphics/vertex_array.h"
#include "../graphics/render_data.h"

namespace bg = boost::geometry;

BOOST_GEOMETRY_REGISTER_POINT_2D(Eigen::Vector2i, int, cs::cartesian, x(), y())

// ccw, open polygon
typedef bg::model::polygon<Eigen::Vector2i, false, false> polygon;

ConstraintUpdater::ConstraintUpdater(
    Graphics::Gl *gl, std::shared_ptr<Graphics::ShaderManager> shaderManager,
    int width, int height)
  : gl(gl), shaderManager(shaderManager), width(width), height(height)
{
  shaderId = shaderManager->addShader(":/shader/constraint.vert",
                                      ":/shader/colorImmediate.frag");

  Eigen::Affine3f pixelToNDCTransform(
      Eigen::Translation3f(Eigen::Vector3f(-1, 1, 0)) *
      Eigen::Scaling(Eigen::Vector3f(2.0f / width, -2.0f / height, 1)));
  pixelToNDC = pixelToNDCTransform.matrix();
}

polygon createBoxPolygon(Eigen::Vector2i center, Eigen::Vector2i size)
{
  polygon p;
  p.outer().push_back(
      Eigen::Vector2i(center.x() - size.x(), center.y() - size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() + size.x(), center.y() - size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() + size.x(), center.y() + size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() - size.x(), center.y() + size.y()));

  return p;
}

void ConstraintUpdater::addLabel(Eigen::Vector2i anchorPosition,
                                 Eigen::Vector2i labelSize,
                                 Eigen::Vector2i lastAnchorPosition,
                                 Eigen::Vector2i lastLabelPosition,
                                 Eigen::Vector2i lastLabelSize)
{
  // directly include label size to circumvent dilation
  int border = 2;
  Eigen::Vector2i size =
      lastLabelSize / 2 + labelSize / 2 + Eigen::Vector2i(border, border);

  polygon oldLabel = createBoxPolygon(lastLabelPosition, size);

  polygon oldLabelExtruded(oldLabel);
  for (auto point : oldLabel.outer())
  {
    Eigen::Vector2i p = anchorPosition + 1000 * (point - anchorPosition);
    oldLabelExtruded.outer().push_back(p);
  }

  polygon oldLabelExtrudedConvexHull;
  bg::convex_hull(oldLabelExtruded, oldLabelExtrudedConvexHull);

  drawPolygon(oldLabelExtrudedConvexHull.outer());
}

void ConstraintUpdater::drawPolygon(std::vector<Eigen::Vector2i> polygon)
{
  std::vector<float> positions;
  if (polygon.size() > 0)
  {
    auto point = polygon[0];
    positions.push_back(point.x());
    positions.push_back(height - point.y());
    positions.push_back(0.0f);
  }
  for (auto point : polygon)
  {
    positions.push_back(point.x());
    positions.push_back(height - point.y());
    positions.push_back(0.0f);
  }

  Graphics::VertexArray *vertexArray =
      new Graphics::VertexArray(gl, GL_TRIANGLE_FAN);
  vertexArray->addStream(positions);

  RenderData renderData;
  renderData.modelMatrix = Eigen::Matrix4f::Identity();
  renderData.viewMatrix = pixelToNDC;
  renderData.projectionMatrix = Eigen::Matrix4f::Identity();
  shaderManager->bind(shaderId, renderData);
  vertexArray->draw();
}

<commit_msg>Add shadow region stemming from connector line to constraints.<commit_after>#include "./constraint_updater.h"
#include <Eigen/Geometry>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <vector>
#include "../graphics/vertex_array.h"
#include "../graphics/render_data.h"

namespace bg = boost::geometry;

BOOST_GEOMETRY_REGISTER_POINT_2D(Eigen::Vector2i, int, cs::cartesian, x(), y())

// ccw, open polygon
typedef bg::model::polygon<Eigen::Vector2i, false, false> polygon;
typedef bg::model::multi_polygon<polygon> mpolygon;

ConstraintUpdater::ConstraintUpdater(
    Graphics::Gl *gl, std::shared_ptr<Graphics::ShaderManager> shaderManager,
    int width, int height)
  : gl(gl), shaderManager(shaderManager), width(width), height(height)
{
  shaderId = shaderManager->addShader(":/shader/constraint.vert",
                                      ":/shader/colorImmediate.frag");

  Eigen::Affine3f pixelToNDCTransform(
      Eigen::Translation3f(Eigen::Vector3f(-1, 1, 0)) *
      Eigen::Scaling(Eigen::Vector3f(2.0f / width, -2.0f / height, 1)));
  pixelToNDC = pixelToNDCTransform.matrix();
}

polygon createBoxPolygon(Eigen::Vector2i center, Eigen::Vector2i size)
{
  polygon p;
  p.outer().push_back(
      Eigen::Vector2i(center.x() - size.x(), center.y() - size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() + size.x(), center.y() - size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() + size.x(), center.y() + size.y()));
  p.outer().push_back(
      Eigen::Vector2i(center.x() - size.x(), center.y() + size.y()));

  return p;
}

void ConstraintUpdater::addLabel(Eigen::Vector2i anchorPosition,
                                 Eigen::Vector2i labelSize,
                                 Eigen::Vector2i lastAnchorPosition,
                                 Eigen::Vector2i lastLabelPosition,
                                 Eigen::Vector2i lastLabelSize)
{
  // directly include label size to circumvent dilation
  int border = 2;
  Eigen::Vector2i size = labelSize / 2 + Eigen::Vector2i(border, border);

  polygon oldLabel =
      createBoxPolygon(lastLabelPosition, size + lastLabelSize / 2);

  polygon oldLabelExtruded(oldLabel);
  for (auto point : oldLabel.outer())
  {
    Eigen::Vector2i p = anchorPosition + 1000 * (point - anchorPosition);
    oldLabelExtruded.outer().push_back(p);
  }
  polygon oldLabelExtrudedConvexHull;
  bg::convex_hull(oldLabelExtruded, oldLabelExtrudedConvexHull);
  drawPolygon(oldLabelExtrudedConvexHull.outer());

  polygon aroundOldAnchor = createBoxPolygon(lastAnchorPosition, size);
  polygon aroundOldLabelCenter = createBoxPolygon(lastLabelPosition, size);
  mpolygon aroundCombined({ aroundOldAnchor, aroundOldLabelCenter });
  polygon aroundCombinedConvex;
  bg::convex_hull(aroundCombined, aroundCombinedConvex);

  polygon connectorPolygon(aroundCombinedConvex);
  for (auto point : aroundCombinedConvex.outer())
  {
    Eigen::Vector2i dir = point - anchorPosition;
    connectorPolygon.outer().push_back(anchorPosition + 1000 * dir);
  }
  polygon connectorPolygonConvex;
  bg::convex_hull(connectorPolygon, connectorPolygonConvex);
  drawPolygon(connectorPolygonConvex.outer());
}

void ConstraintUpdater::drawPolygon(std::vector<Eigen::Vector2i> polygon)
{
  std::vector<float> positions;
  if (polygon.size() > 0)
  {
    auto point = polygon[0];
    positions.push_back(point.x());
    positions.push_back(height - point.y());
    positions.push_back(0.0f);
  }
  for (auto point : polygon)
  {
    positions.push_back(point.x());
    positions.push_back(height - point.y());
    positions.push_back(0.0f);
  }

  Graphics::VertexArray *vertexArray =
      new Graphics::VertexArray(gl, GL_TRIANGLE_FAN);
  vertexArray->addStream(positions);

  RenderData renderData;
  renderData.modelMatrix = Eigen::Matrix4f::Identity();
  renderData.viewMatrix = pixelToNDC;
  renderData.projectionMatrix = Eigen::Matrix4f::Identity();
  shaderManager->bind(shaderId, renderData);
  vertexArray->draw();
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2009 Digital Bazaar, Inc. All rights reserved.
 */
#include "db/rt/HazardPtrList.h"

#include "db/rt/Atomic.h"

using namespace db::rt;

HazardPtrList::HazardPtrList() :
   mHead(NULL)
{
}

HazardPtrList::~HazardPtrList()
{
}

HazardPtr* HazardPtrList::acquire()
{
   volatile HazardPtr* rval = NULL;

   // find a hazard pointer that is inactive
   for(HazardPtr* ptr = const_cast<HazardPtr*>(mHead); ptr != NULL;
       ptr = ptr->next)
   {
      // try to mark an inactive pointer as active
      if(!ptr->active && Atomic::compareAndSwap(&ptr->active, false, true))
      {
         // successfully acquired
         rval = ptr;
      }
   }

   // no inactive pointer found, create a new one
   if(rval == NULL)
   {
      rval = new HazardPtr;
      rval->active = true;
      rval->value = NULL;

      // atomically push the pointer onto the head of the list
      volatile HazardPtr* old;
      do
      {
         old = mHead;
         rval->next = const_cast<HazardPtr*>(old);
      }
      while(!Atomic::compareAndSwap(&mHead, old, rval));
   }

   return const_cast<HazardPtr*>(rval);
}

void HazardPtrList::release(HazardPtr* ptr)
{
   ptr->value = NULL;
   ptr->active = false;
}

bool HazardPtrList::isProtected(void* addr)
{
   bool rval = false;

   // search the list for the given address
   for(HazardPtr* ptr = const_cast<HazardPtr*>(mHead); !rval && ptr != NULL;
       ptr = ptr->next)
   {
      if(ptr->value == addr)
      {
         // address found
         rval = true;
      }
   }

   return rval;
}
<commit_msg>Fixed leak in hazard pointer list.<commit_after>/*
 * Copyright (c) 2009 Digital Bazaar, Inc. All rights reserved.
 */
#include "db/rt/HazardPtrList.h"

#include "db/rt/Atomic.h"

using namespace db::rt;

HazardPtrList::HazardPtrList() :
   mHead(NULL)
{
}

HazardPtrList::~HazardPtrList()
{
   // clean up all hazard pointers
   HazardPtr* head = const_cast<HazardPtr*>(mHead);
   while(head != NULL)
   {
      HazardPtr* tmp = head;
      head = head->next;
      delete tmp;
   }
}

HazardPtr* HazardPtrList::acquire()
{
   volatile HazardPtr* rval = NULL;

   // find a hazard pointer that is inactive
   for(HazardPtr* ptr = const_cast<HazardPtr*>(mHead); ptr != NULL;
       ptr = ptr->next)
   {
      // try to mark an inactive pointer as active
      if(!ptr->active && Atomic::compareAndSwap(&ptr->active, false, true))
      {
         // successfully acquired
         rval = ptr;
      }
   }

   // no inactive pointer found, create a new one
   if(rval == NULL)
   {
      rval = new HazardPtr;
      rval->active = true;
      rval->value = NULL;

      // atomically push the pointer onto the head of the list
      volatile HazardPtr* old;
      do
      {
         old = mHead;
         rval->next = const_cast<HazardPtr*>(old);
      }
      while(!Atomic::compareAndSwap(&mHead, old, rval));
   }

   return const_cast<HazardPtr*>(rval);
}

void HazardPtrList::release(HazardPtr* ptr)
{
   ptr->value = NULL;
   ptr->active = false;
}

bool HazardPtrList::isProtected(void* addr)
{
   bool rval = false;

   // search the list for the given address
   for(HazardPtr* ptr = const_cast<HazardPtr*>(mHead); !rval && ptr != NULL;
       ptr = ptr->next)
   {
      if(ptr->value == addr)
      {
         // address found
         rval = true;
      }
   }

   return rval;
}
<|endoftext|>


<commit_before>#ifndef __CPREL_PROP_PROJECTION_HH__
#define __CPREL_PROP_PROJECTION_HH__

#include <cprel/cprel.hh>

namespace MPG { namespace CPRel { namespace Prop {
/**
 * \brief Propagates: \f$ \Pi_{p}A = B \f$.
 *
 * \f$ A \subseteq \mathcal{U}_{n},\; B \subseteq \mathcal{U}_{n-p} \f$ and \f$p\f$
 * is the number of righ most columns to project on.
 * \ingroup RelProp
 */
template <typename ViewLeft, typename ViewRight>
class Project : public Gecode::Propagator {
protected:
  /// Left relation of the contraint
  ViewLeft left_;
  /// Right relation of the constraint
  ViewRight right_;
  /// Number of columns (on the right) to project on.
  int p_;
public:
  /// Constructor
  Project(Gecode::Home home, int p, ViewLeft left, ViewRight right)
    : Gecode::Propagator(home), left_(left), right_(right), p_(p) {
    left_.subscribe(home,*this,CPRel::PC_CPREL_BND);
    right_.subscribe(home,*this,CPRel::PC_CPREL_BND);
  }
  /// Propagator posting
  static Gecode::ExecStatus post(Gecode::Home home, int p, ViewLeft left,
                                 ViewRight right) {

    // check that the relations has the right arities
    if (left.arity()-p != right.arity()) {
      std::cerr << "Invalid arity for the relations or the size of the descriptor"
                << std::endl;
      return Gecode::ES_FAILED;
    }

    // If left and right are the same variable then the constraint is eihter trivially
    // entailed (p refers to all the columns) or failed as there is no way to satisfy
    // it.
    if (same(left,right)) {
      if (p != 0) return Gecode::ES_FAILED;
      return Gecode::ES_OK;
    }

    (void) new (home) Project(home,p,left,right);
    return Gecode::ES_OK;
  }
  /// Propagator disposal
  virtual size_t dispose(Gecode::Space& home) {
    left_.cancel(home,*this,CPRel::PC_CPREL_BND);
    right_.cancel(home,*this,CPRel::PC_CPREL_BND);
    (void) Propagator::dispose(home);
    return sizeof(*this);
  }
  /// Copy constructor
  Project(Gecode::Space& home, bool share, Project& p)
    : Gecode::Propagator(home,share,p), p_(p.p_) {
    left_.update(home,share,p.left_);
    right_.update(home,share,p.right_);
  }
  /// Copy
  virtual Gecode::Propagator* copy(Gecode::Space& home, bool share) {
    return new (home) Project(home,share,*this);
  }
  /// Cost
  virtual Gecode::PropCost cost(const Gecode::Space&,
                                const Gecode::ModEventDelta&) const {
    return Gecode::PropCost::binary(Gecode::PropCost::LO);
  }
public:
  /// Main propagation algorithm
  virtual Gecode::ExecStatus propagate(Gecode::Space& home,
                                       const Gecode::ModEventDelta&)  {
    // implements: \Pi_{p}A = B
    // First part: \Pi_{p}A \implies B
    //    \Pi_{p}glb(A) \subseteq B
    GRelation glbLeft_p = left_.glb().project(p_);
    GECODE_ME_CHECK(right_.include(home,glbLeft_p));

    //    \Pi_{p}lub(A) \supseteq B
    GRelation lubLeft_p = left_.lub().project(p_);
    GECODE_ME_CHECK(right_.exclude(home,lubLeft_p.complement()));

    // lub(A) \subseteq (U_{B.arity()-p}\times lub(B)) \cap lub(B)
    GRelation maxIntersection =
        right_.lub().timesU(left_.arity()-p_,true).intersect(left_.lub());

    GECODE_ME_CHECK(left_.exclude(home,maxIntersection.complement()));
    /// \todo Missing the other direction of the propagator

    // Propagator subsumpiton
    if (left_.assigned() && right_.assigned())
      return home.ES_SUBSUMED(*this);

    return Gecode::ES_FIX;
  }
};
}}}
#endif
<commit_msg>Minor doc. changes<commit_after>#ifndef __CPREL_PROP_PROJECTION_HH__
#define __CPREL_PROP_PROJECTION_HH__

#include <cprel/cprel.hh>

namespace MPG { namespace CPRel { namespace Prop {
/**
 * \brief Propagates: \f$ \Pi_{p}A = B \f$.
 *
 * \f$ A \subseteq \mathcal{U}_{n},\; B \subseteq \mathcal{U}_{n-p} \f$ and \f$p\f$
 * is the number of right most columns to project on.
 * \ingroup RelProp
 */
template <typename ViewLeft, typename ViewRight>
class Project : public Gecode::Propagator {
protected:
  /// Left relation of the contraint
  ViewLeft left_;
  /// Right relation of the constraint
  ViewRight right_;
  /// Number of columns (on the right) to project on.
  int p_;
public:
  /// Constructor
  Project(Gecode::Home home, int p, ViewLeft left, ViewRight right)
    : Gecode::Propagator(home), left_(left), right_(right), p_(p) {
    left_.subscribe(home,*this,CPRel::PC_CPREL_BND);
    right_.subscribe(home,*this,CPRel::PC_CPREL_BND);
  }
  /// Propagator posting
  static Gecode::ExecStatus post(Gecode::Home home, int p, ViewLeft left,
                                 ViewRight right) {

    // check that the relations has the right arities
    if (left.arity()-p != right.arity()) {
      std::cerr << "Invalid arity for the relations or the size of the descriptor"
                << std::endl;
      return Gecode::ES_FAILED;
    }

    // If left and right are the same variable then the constraint is eihter trivially
    // entailed (p refers to all the columns) or failed as there is no way to satisfy
    // it.
    if (same(left,right)) {
      if (p != 0) return Gecode::ES_FAILED;
      return Gecode::ES_OK;
    }

    (void) new (home) Project(home,p,left,right);
    return Gecode::ES_OK;
  }
  /// Propagator disposal
  virtual size_t dispose(Gecode::Space& home) {
    left_.cancel(home,*this,CPRel::PC_CPREL_BND);
    right_.cancel(home,*this,CPRel::PC_CPREL_BND);
    (void) Propagator::dispose(home);
    return sizeof(*this);
  }
  /// Copy constructor
  Project(Gecode::Space& home, bool share, Project& p)
    : Gecode::Propagator(home,share,p), p_(p.p_) {
    left_.update(home,share,p.left_);
    right_.update(home,share,p.right_);
  }
  /// Copy
  virtual Gecode::Propagator* copy(Gecode::Space& home, bool share) {
    return new (home) Project(home,share,*this);
  }
  /// Cost
  virtual Gecode::PropCost cost(const Gecode::Space&,
                                const Gecode::ModEventDelta&) const {
    return Gecode::PropCost::binary(Gecode::PropCost::LO);
  }
public:
  /// Main propagation algorithm
  virtual Gecode::ExecStatus propagate(Gecode::Space& home,
                                       const Gecode::ModEventDelta&)  {
    // implements: \Pi_{p}A = B
    // First part: \Pi_{p}A \implies B
    //    \Pi_{p}glb(A) \subseteq B
    GRelation glbLeft_p = left_.glb().project(p_);
    GECODE_ME_CHECK(right_.include(home,glbLeft_p));

    //    \Pi_{p}lub(A) \supseteq B
    GRelation lubLeft_p = left_.lub().project(p_);
    GECODE_ME_CHECK(right_.exclude(home,lubLeft_p.complement()));

    // lub(A) \subseteq (U_{B.arity()-p}\times lub(B)) \cap lub(B)
    GRelation maxIntersection =
        right_.lub().timesU(left_.arity()-p_,true).intersect(left_.lub());
    GECODE_ME_CHECK(left_.exclude(home,maxIntersection.complement()));

    /// \todo Missing 1/4 of the propagator: unique quantifier.

    // Propagator subsumpiton
    if (left_.assigned() && right_.assigned())
      return home.ES_SUBSUMED(*this);

    return Gecode::ES_FIX;
  }
};
}}}
#endif
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015-2018 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/defer_to_scope_end.hxx>
#include <lofty/event.hxx>
#include <lofty/io/text.hxx>
#include <lofty/keyed_demux.hxx>
#include <lofty/logging.hxx>
#include <lofty/range.hxx>
#include <lofty/testing/test_case.hxx>
#include <lofty/thread.hxx>
#include <lofty/to_str.hxx>

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_concurrency,
   "lofty::thread – concurrent operation"
) {
   LOFTY_TRACE_FUNC();

   _std::atomic<bool> thread1_completed(false), thread2_completed(false), thread3_completed(false);
   event thread3_terminated;

   thread thread1([this, &thread1_completed] () {
      LOFTY_TRACE_FUNC();

      thread1_completed.store(true);
   });
   thread thread2([this, &thread2_completed] () {
      LOFTY_TRACE_FUNC();

      thread2_completed.store(true);
   });
   thread thread3([this, &thread3_completed, &thread3_terminated] () {
      LOFTY_TRACE_FUNC();

      thread3_completed.store(true);
      thread3_terminated.trigger();
   });
   thread3.detach();
   thread thread4;

   LOFTY_TESTING_ASSERT_TRUE(thread1.joinable());
   LOFTY_TESTING_ASSERT_TRUE(thread2.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread3.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread4.joinable());

   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread2.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_EQUAL    (thread3.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_EQUAL    (thread4.id(), thread::id_type(0));

   /* Verify that the string representations are different for joinable thread, and identical for non-joinable
   ones. */
   str thread1_str(to_str(thread1)), thread2_str(to_str(thread2));
   str thread3_str(to_str(thread3)), thread4_str(to_str(thread4));
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1_str, thread2_str);
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1_str, thread3_str);
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread2_str, thread3_str);
   LOFTY_TESTING_ASSERT_EQUAL(thread3_str, thread4_str);
   LOFTY_TESTING_ASSERT_EQUAL(thread4_str, LOFTY_SL("TID:-"));

   // Wait for thread1 and thread2 to complete.
   thread1.join();
   thread2.join();
   LOFTY_TESTING_ASSERT_FALSE(thread1.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread2.joinable());
   // Wait for thread3 to complete.
   thread3_terminated.wait();

   LOFTY_TESTING_ASSERT_TRUE(thread1_completed.load());
   LOFTY_TESTING_ASSERT_TRUE(thread2_completed.load());
   LOFTY_TESTING_ASSERT_TRUE(thread3_completed.load());
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_interruption,
   "lofty::thread – interruption"
) {
   LOFTY_TRACE_FUNC();

   static std::size_t const workers_size = 5;
   _std::atomic<bool> workers_completed[workers_size], workers_interrupted[workers_size];
   thread worker_threads[workers_size];
   for (std::size_t i = 0; i < workers_size; ++i) {
      auto worker_completed = &workers_completed[i];
      auto worker_interrupted = &workers_interrupted[i];
      worker_completed->store(false);
      worker_interrupted->store(false);
      worker_threads[i] = thread([this, worker_completed, worker_interrupted] () {
         LOFTY_TRACE_FUNC();

         try {
            /* Expect to be interrupted by the main thread. Make this sleep long enough so as not to cause
            sporadic test failures, but avoid slowing the test down by too much. */
            this_thread::sleep_for_ms(150);
            worker_completed->store(true);
         } catch (execution_interruption const &) {
            worker_interrupted->store(true);
         }
      });
   }

   // lofty::thread guarantees that the threads are are already running at this point.
   worker_threads[1].interrupt();
   worker_threads[2].interrupt();

   LOFTY_FOR_EACH(auto & thread, worker_threads) {
      thread.join();
   }

   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [0].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[0].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_completed  [1].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_interrupted[1].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_completed  [2].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_interrupted[2].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [3].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[3].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [4].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[4].load());
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_exception_propagation,
   "lofty::thread – exception propagation"
) {
   LOFTY_TRACE_FUNC();

   bool exception_caught = false;
   /* Temporarily redirect stderr to a local string stream, so the exception trace from the thread won’t show
   in the test output. */
   auto capturing_stderr(_std::make_shared<io::text::str_ostream>());
   {
      auto old_stderr(io::text::stderr);
      io::text::stderr = capturing_stderr;
      LOFTY_DEFER_TO_SCOPE_END(io::text::stderr = _std::move(old_stderr));

      /* Expect to be interrupted by an exception in thread1 any time from its creation to the sleep, which
      should be longer than the time it takes for thread1 to throw its exception. Can’t make any test
      assertions in this scope, since their output would end up in capturing_stderr instead of the real
      stderr. */
      try {
         thread thread1([this] () {
            LOFTY_TRACE_FUNC();

            LOFTY_THROW(execution_interruption, ());
         });
         /* Wait for the termination of thread1. Since thread1 will terminate with an exception, the current
         thread will be interrupted as well, right after thread1’s termination. */
         thread1.join();
      } catch (execution_interruption const &) {
         /* TODO: use a more specific exception subclass of execution_interruption, such as
         “other_thread_execution_interrupted”. */
         exception_caught = true;
      }
   }
   LOFTY_TESTING_ASSERT_TRUE(exception_caught);
   // While we’re at it, verify that something was written to stderr while *capturing_stderr was stderr.
   LOFTY_TESTING_ASSERT_NOT_EQUAL(capturing_stderr->get_str(), str::empty);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_interruption_exception_propagation,
   "lofty::thread – interruption exception propagation"
) {
   LOFTY_TRACE_FUNC();

   bool exception_caught = false;
   _std::atomic<bool> thread1_completed(false);
   thread thread1([this, &thread1_completed] () {
      LOFTY_TRACE_FUNC();

      /* Make the sleep long enough so as not to cause sporadic test failures, but avoid slowing the test down
      by too much. */
      this_thread::sleep_for_ms(150);
      thread1_completed.store(true);
   });

   /* Temporarily redirect stderr to a local string stream, so the exception trace from the thread won’t show
   in the test output. */
   auto capturing_stderr(_std::make_shared<io::text::str_ostream>());
   {
      auto old_stderr(io::text::stderr);
      io::text::stderr = capturing_stderr;
      LOFTY_DEFER_TO_SCOPE_END(io::text::stderr = _std::move(old_stderr));

      /* Expect to be interrupted by an exception in thread1 any time from its creation to the sleep, which
      should be longer than the time it takes for thread1 to throw its exception. Can’t make any test
      assertions in this scope, since their output would end up in capturing_stderr instead of the real
      stderr. */
      try {
         thread1.interrupt();
         /* Wait for the termination of thread1. Since we’re interrupting it, the current thread will be
         interrupted as well, right after thread1’s termination. */
         thread1.join();
      } catch (execution_interruption const &) {
         /* TODO: use a more specific exception subclass of execution_interruption, such as
         “other_thread_execution_interrupted”. */
         exception_caught = true;
      }
   }

   LOFTY_TESTING_ASSERT_TRUE(exception_caught);
   LOFTY_TESTING_ASSERT_FALSE(thread1_completed.load());
   // While we’re at it, verify that something was written to stderr while *capturing_stderr was stderr.
   LOFTY_TESTING_ASSERT_NOT_EQUAL(capturing_stderr->get_str(), str::empty);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_event,
   "lofty::event (using threads)"
) {
   LOFTY_TRACE_FUNC();

   static unsigned const threads_size = 4;
   thread threads[threads_size];
   event events[threads_size];
   unsigned resumed[threads_size], timedout[threads_size];
   memory::clear(&resumed);
   _std::atomic<unsigned> next_resumed_index(0);
   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i] = thread([i, &events, &timedout, &resumed, &next_resumed_index] () {
         LOFTY_TRACE_FUNC();

         try {
            // For i == 0 there will be no timeout.
            events[i].wait(i * 10);
            timedout[i] = false;
         } catch (io::timeout const &) {
            timedout[i] = true;
         }
         resumed[next_resumed_index.fetch_add(1)] = i + 1;
      });
   }

   events[2].trigger();
   // Process the first event.
   this_thread::sleep_for_ms(1);
   events[0].trigger();
   // Avoid triggering events[1], which will timeout.

   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i].join();
   }

   LOFTY_TESTING_ASSERT_EQUAL(resumed[0], 3u);
   LOFTY_TESTING_ASSERT_EQUAL(resumed[1], 1u);
   LOFTY_TESTING_ASSERT_EQUAL(resumed[2], 2u);
   LOFTY_TESTING_ASSERT_FALSE(timedout[0]);
   LOFTY_TESTING_ASSERT_TRUE(timedout[1]);
   LOFTY_TESTING_ASSERT_FALSE(timedout[2]);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_keyed_demux,
   "lofty::keyed_demux (using threads)"
) {
   LOFTY_TRACE_FUNC();

   keyed_demux<short, long> number_demux;
   unsigned step = 0;
   number_demux.set_source([&step] (short * key) -> long {
      LOFTY_TRACE_FUNC();

      // In this test, the keys are the same as the values.

      this_thread::sleep_for_ms(1);
      switch (++step) {
         case 1:
            *key = 4;
            return 4;
         case 2:
            *key = 2;
            return 2;
         default:
            // Report EOF.
            return 0;
      }
   });

   static std::size_t const threads_size = 4;
   thread threads[threads_size];
   long get_returns[threads_size];
   LOFTY_FOR_EACH(short key, make_range<short>(1, static_cast<short>(threads_size + 1))) {
      threads[key - 1] = thread([this, &number_demux, &get_returns, key] () {
         LOFTY_TRACE_FUNC();

         get_returns[key - 1] = number_demux.get(key, 10 * 1000);
      });
   }

   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i].join();
   }

   LOFTY_TESTING_ASSERT_EQUAL(step, 3u);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[0], 0);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[1], 2u);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[2], 0);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[3], 4u);
}

}} //namespace lofty::test
<commit_msg>Increase timeout to avoid sporadic test failures<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015-2018 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/defer_to_scope_end.hxx>
#include <lofty/event.hxx>
#include <lofty/io/text.hxx>
#include <lofty/keyed_demux.hxx>
#include <lofty/logging.hxx>
#include <lofty/range.hxx>
#include <lofty/testing/test_case.hxx>
#include <lofty/thread.hxx>
#include <lofty/to_str.hxx>

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_concurrency,
   "lofty::thread – concurrent operation"
) {
   LOFTY_TRACE_FUNC();

   _std::atomic<bool> thread1_completed(false), thread2_completed(false), thread3_completed(false);
   event thread3_terminated;

   thread thread1([this, &thread1_completed] () {
      LOFTY_TRACE_FUNC();

      thread1_completed.store(true);
   });
   thread thread2([this, &thread2_completed] () {
      LOFTY_TRACE_FUNC();

      thread2_completed.store(true);
   });
   thread thread3([this, &thread3_completed, &thread3_terminated] () {
      LOFTY_TRACE_FUNC();

      thread3_completed.store(true);
      thread3_terminated.trigger();
   });
   thread3.detach();
   thread thread4;

   LOFTY_TESTING_ASSERT_TRUE(thread1.joinable());
   LOFTY_TESTING_ASSERT_TRUE(thread2.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread3.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread4.joinable());

   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread2.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_EQUAL    (thread3.id(), thread::id_type(0));
   LOFTY_TESTING_ASSERT_EQUAL    (thread4.id(), thread::id_type(0));

   /* Verify that the string representations are different for joinable thread, and identical for non-joinable
   ones. */
   str thread1_str(to_str(thread1)), thread2_str(to_str(thread2));
   str thread3_str(to_str(thread3)), thread4_str(to_str(thread4));
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1_str, thread2_str);
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread1_str, thread3_str);
   LOFTY_TESTING_ASSERT_NOT_EQUAL(thread2_str, thread3_str);
   LOFTY_TESTING_ASSERT_EQUAL(thread3_str, thread4_str);
   LOFTY_TESTING_ASSERT_EQUAL(thread4_str, LOFTY_SL("TID:-"));

   // Wait for thread1 and thread2 to complete.
   thread1.join();
   thread2.join();
   LOFTY_TESTING_ASSERT_FALSE(thread1.joinable());
   LOFTY_TESTING_ASSERT_FALSE(thread2.joinable());
   // Wait for thread3 to complete.
   thread3_terminated.wait();

   LOFTY_TESTING_ASSERT_TRUE(thread1_completed.load());
   LOFTY_TESTING_ASSERT_TRUE(thread2_completed.load());
   LOFTY_TESTING_ASSERT_TRUE(thread3_completed.load());
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_interruption,
   "lofty::thread – interruption"
) {
   LOFTY_TRACE_FUNC();

   static std::size_t const workers_size = 5;
   _std::atomic<bool> workers_completed[workers_size], workers_interrupted[workers_size];
   thread worker_threads[workers_size];
   for (std::size_t i = 0; i < workers_size; ++i) {
      auto worker_completed = &workers_completed[i];
      auto worker_interrupted = &workers_interrupted[i];
      worker_completed->store(false);
      worker_interrupted->store(false);
      worker_threads[i] = thread([this, worker_completed, worker_interrupted] () {
         LOFTY_TRACE_FUNC();

         try {
            /* Expect to be interrupted by the main thread. Make this sleep long enough so as not to cause
            sporadic test failures, but avoid slowing the test down by too much. */
            this_thread::sleep_for_ms(150);
            worker_completed->store(true);
         } catch (execution_interruption const &) {
            worker_interrupted->store(true);
         }
      });
   }

   // lofty::thread guarantees that the threads are are already running at this point.
   worker_threads[1].interrupt();
   worker_threads[2].interrupt();

   LOFTY_FOR_EACH(auto & thread, worker_threads) {
      thread.join();
   }

   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [0].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[0].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_completed  [1].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_interrupted[1].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_completed  [2].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_interrupted[2].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [3].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[3].load());
   LOFTY_TESTING_ASSERT_TRUE (workers_completed  [4].load());
   LOFTY_TESTING_ASSERT_FALSE(workers_interrupted[4].load());
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_exception_propagation,
   "lofty::thread – exception propagation"
) {
   LOFTY_TRACE_FUNC();

   bool exception_caught = false;
   /* Temporarily redirect stderr to a local string stream, so the exception trace from the thread won’t show
   in the test output. */
   auto capturing_stderr(_std::make_shared<io::text::str_ostream>());
   {
      auto old_stderr(io::text::stderr);
      io::text::stderr = capturing_stderr;
      LOFTY_DEFER_TO_SCOPE_END(io::text::stderr = _std::move(old_stderr));

      /* Expect to be interrupted by an exception in thread1 any time from its creation to the sleep, which
      should be longer than the time it takes for thread1 to throw its exception. Can’t make any test
      assertions in this scope, since their output would end up in capturing_stderr instead of the real
      stderr. */
      try {
         thread thread1([this] () {
            LOFTY_TRACE_FUNC();

            LOFTY_THROW(execution_interruption, ());
         });
         /* Wait for the termination of thread1. Since thread1 will terminate with an exception, the current
         thread will be interrupted as well, right after thread1’s termination. */
         thread1.join();
      } catch (execution_interruption const &) {
         /* TODO: use a more specific exception subclass of execution_interruption, such as
         “other_thread_execution_interrupted”. */
         exception_caught = true;
      }
   }
   LOFTY_TESTING_ASSERT_TRUE(exception_caught);
   // While we’re at it, verify that something was written to stderr while *capturing_stderr was stderr.
   LOFTY_TESTING_ASSERT_NOT_EQUAL(capturing_stderr->get_str(), str::empty);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_interruption_exception_propagation,
   "lofty::thread – interruption exception propagation"
) {
   LOFTY_TRACE_FUNC();

   bool exception_caught = false;
   _std::atomic<bool> thread1_completed(false);
   thread thread1([this, &thread1_completed] () {
      LOFTY_TRACE_FUNC();

      /* Make the sleep long enough so as not to cause sporadic test failures, but avoid slowing the test down
      by too much. */
      this_thread::sleep_for_ms(150);
      thread1_completed.store(true);
   });

   /* Temporarily redirect stderr to a local string stream, so the exception trace from the thread won’t show
   in the test output. */
   auto capturing_stderr(_std::make_shared<io::text::str_ostream>());
   {
      auto old_stderr(io::text::stderr);
      io::text::stderr = capturing_stderr;
      LOFTY_DEFER_TO_SCOPE_END(io::text::stderr = _std::move(old_stderr));

      /* Expect to be interrupted by an exception in thread1 any time from its creation to the sleep, which
      should be longer than the time it takes for thread1 to throw its exception. Can’t make any test
      assertions in this scope, since their output would end up in capturing_stderr instead of the real
      stderr. */
      try {
         thread1.interrupt();
         /* Wait for the termination of thread1. Since we’re interrupting it, the current thread will be
         interrupted as well, right after thread1’s termination. */
         thread1.join();
      } catch (execution_interruption const &) {
         /* TODO: use a more specific exception subclass of execution_interruption, such as
         “other_thread_execution_interrupted”. */
         exception_caught = true;
      }
   }

   LOFTY_TESTING_ASSERT_TRUE(exception_caught);
   LOFTY_TESTING_ASSERT_FALSE(thread1_completed.load());
   // While we’re at it, verify that something was written to stderr while *capturing_stderr was stderr.
   LOFTY_TESTING_ASSERT_NOT_EQUAL(capturing_stderr->get_str(), str::empty);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_event,
   "lofty::event (using threads)"
) {
   LOFTY_TRACE_FUNC();

   static unsigned const threads_size = 4;
   thread threads[threads_size];
   event events[threads_size];
   unsigned resumed[threads_size], timedout[threads_size];
   memory::clear(&resumed);
   _std::atomic<unsigned> next_resumed_index(0);
   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i] = thread([i, &events, &timedout, &resumed, &next_resumed_index] () {
         LOFTY_TRACE_FUNC();

         try {
            // For i == 0 there will be no timeout.
            events[i].wait(i * 50);
            timedout[i] = false;
         } catch (io::timeout const &) {
            timedout[i] = true;
         }
         resumed[next_resumed_index.fetch_add(1)] = i + 1;
      });
   }

   events[2].trigger();
   // Process the first event.
   this_thread::sleep_for_ms(1);
   events[0].trigger();
   // Avoid triggering events[1], which will timeout.

   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i].join();
   }

   LOFTY_TESTING_ASSERT_EQUAL(resumed[0], 3u);
   LOFTY_TESTING_ASSERT_EQUAL(resumed[1], 1u);
   LOFTY_TESTING_ASSERT_EQUAL(resumed[2], 2u);
   LOFTY_TESTING_ASSERT_FALSE(timedout[0]);
   LOFTY_TESTING_ASSERT_TRUE(timedout[1]);
   LOFTY_TESTING_ASSERT_FALSE(timedout[2]);
}

}} //namespace lofty::test

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

namespace lofty { namespace test {

LOFTY_TESTING_TEST_CASE_FUNC(
   thread_keyed_demux,
   "lofty::keyed_demux (using threads)"
) {
   LOFTY_TRACE_FUNC();

   keyed_demux<short, long> number_demux;
   unsigned step = 0;
   number_demux.set_source([&step] (short * key) -> long {
      LOFTY_TRACE_FUNC();

      // In this test, the keys are the same as the values.

      this_thread::sleep_for_ms(1);
      switch (++step) {
         case 1:
            *key = 4;
            return 4;
         case 2:
            *key = 2;
            return 2;
         default:
            // Report EOF.
            return 0;
      }
   });

   static std::size_t const threads_size = 4;
   thread threads[threads_size];
   long get_returns[threads_size];
   LOFTY_FOR_EACH(short key, make_range<short>(1, static_cast<short>(threads_size + 1))) {
      threads[key - 1] = thread([this, &number_demux, &get_returns, key] () {
         LOFTY_TRACE_FUNC();

         get_returns[key - 1] = number_demux.get(key, 10 * 1000);
      });
   }

   for (unsigned i = 0; i < threads_size; ++i) {
      threads[i].join();
   }

   LOFTY_TESTING_ASSERT_EQUAL(step, 3u);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[0], 0);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[1], 2u);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[2], 0);
   LOFTY_TESTING_ASSERT_EQUAL(get_returns[3], 4u);
}

}} //namespace lofty::test
<|endoftext|>


<commit_before>/*
 * ErrorCodes.hpp
 *
 *  Created on: Apr 5, 2013
 *      Author: link
 */

#ifndef ERRORCODES_HPP_
#define ERRORCODES_HPP_

const int USER_TRIGGERED_EXIT = 1;
const int READ_CAMERA_PARAMETERS_FAILED = -1;

#endif /* ERRORCODES_HPP_ */
<commit_msg>Added doxygne documentation to ErrorCodes<commit_after>/*
 * ErrorCodes.hpp
 *
 *  Created on: Apr 5, 2013
 *      Author: link
 */

#ifndef ERRORCODES_HPP_
#define ERRORCODES_HPP_

const int USER_TRIGGERED_EXIT = 1;
/// Code indicating that camera parameters could not be read.
const int READ_CAMERA_PARAMETERS_FAILED = -1;

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


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

  Program:   Visualization Library
  Module:    StrData.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Description:
---------------------------------------------------------------------------
This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Structured data (described by dimensions)
//
#ifndef __vlStructuredDataSet_h
#define __vlStructuredDataSet_h

#include "DataSet.hh"
#include "CArray.hh"

#define SINGLE_POINT 0
#define X_LINE 1
#define Y_LINE 2
#define Z_LINE 3
#define XY_PLANE 4
#define YZ_PLANE 5
#define XZ_PLANE 6
#define XYZ_GRID 7

class vlStructuredDataSet : public vlDataSet {
public:
  vlStructuredDataSet();
  vlStructuredDataSet(const vlStructuredDataSet& sds);
  ~vlStructuredDataSet();
  char *GetClassName() {return "vlStructuredDataSet";};
  void PrintSelf(ostream& os, vlIndent indent);

  // dataset interface
  int GetNumberOfCells();
  int GetNumberOfPoints();
  void Initialize();
  void GetPointCells(int ptId, vlIdList *cellIds);

  void SetDimensions(int i, int j, int k);
  void SetDimensions(int dim[3]);
  vlGetVectorMacro(Dimensions,int);

  void BlankingOn();
  void BlankingOff();
  int GetBlanking() {return this->Blanking;};
  void BlankPoint(int ptId);
  void UnBlankPoint(int ptId);
  int IsPointVisible(int ptId) {if (!this->Blanking) return 1;
                                else return this->PointVisibility->GetValue(ptId);}

protected:
  int Dimensions[3];
  int DataDescription;
  int Blanking;
  vlCharArray *PointVisibility;
};

#endif
<commit_msg>*** empty log message ***<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    StrData.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Description:
---------------------------------------------------------------------------
This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Structured data (described by dimensions)
//
#ifndef __vlStructuredDataSet_h
#define __vlStructuredDataSet_h

#include "DataSet.hh"
#include "CArray.hh"

#define SINGLE_POINT 0
#define X_LINE 1
#define Y_LINE 2
#define Z_LINE 3
#define XY_PLANE 4
#define YZ_PLANE 5
#define XZ_PLANE 6
#define XYZ_GRID 7

class vlStructuredDataSet : virtual public vlDataSet {
public:
  vlStructuredDataSet();
  vlStructuredDataSet(const vlStructuredDataSet& sds);
  ~vlStructuredDataSet();
  char *GetClassName() {return "vlStructuredDataSet";};
  void PrintSelf(ostream& os, vlIndent indent);

  // dataset interface
  int GetNumberOfCells();
  int GetNumberOfPoints();
  void Initialize();
  void GetPointCells(int ptId, vlIdList *cellIds);

  void SetDimensions(int i, int j, int k);
  void SetDimensions(int dim[3]);
  vlGetVectorMacro(Dimensions,int);

  void BlankingOn();
  void BlankingOff();
  int GetBlanking() {return this->Blanking;};
  void BlankPoint(int ptId);
  void UnBlankPoint(int ptId);
  int IsPointVisible(int ptId) {if (!this->Blanking) return 1;
                                else return this->PointVisibility->GetValue(ptId);}

protected:
  int Dimensions[3];
  int DataDescription;
  int Blanking;
  vlCharArray *PointVisibility;
};

#endif
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "registration.h"

#include "crop_image_process.h"
#include "grayscale_process.h"
#include "image_reader_process.h"
#include "image_writer_process.h"
#include "video_reader_process.h"
#include "warp_image_process.h"

#include <vistk/pipeline/process_registry.h>

#include <boost/make_shared.hpp>

/**
 * \file image/registration.cxx
 *
 * \brief Register processes for use.
 */

using namespace vistk;

static process_t create_crop_image_process(config_t const& config);
static process_t create_grayscale_process(config_t const& config);
static process_t create_image_reader_process(config_t const& config);
static process_t create_image_writer_process(config_t const& config);
static process_t create_video_reader_process(config_t const& config);
static process_t create_warp_image_process(config_t const& config);

void
register_processes()
{
  static process_registry::module_t const module_name = process_registry::module_t("image_processes");

  process_registry_t const registry = process_registry::self();

  if (registry->is_module_loaded(module_name))
  {
    return;
  }

  registry->register_process("crop_image", "Crop an image to a specific size.", create_crop_image_process);
  registry->register_process("grayscale", "Convert an RGB image into grayscale.", create_grayscale_process);
  registry->register_process("image_reader", "Read images from files given a list of images.", create_image_reader_process);
  registry->register_process("image_writer", "Write images to files.", create_image_writer_process);
  registry->register_process("video_reader", "Reads images from a video.", create_video_reader_process);
  registry->register_process("warp_image", "Warps images using tranformation matrices.", create_warp_image_process);

  registry->mark_module_as_loaded(module_name);
}

process_t
create_crop_image_process(config_t const& config)
{
  return boost::make_shared<crop_image_process>(config);
}

process_t
create_grayscale_process(config_t const& config)
{
  return boost::make_shared<grayscale_process>(config);
}

process_t
create_image_reader_process(config_t const& config)
{
  return boost::make_shared<image_reader_process>(config);
}

process_t
create_image_writer_process(config_t const& config)
{
  return boost::make_shared<image_writer_process>(config);
}

process_t
create_video_reader_process(config_t const& config)
{
  return boost::make_shared<video_reader_process>(config);
}

process_t
create_warp_image_process(config_t const& config)
{
  return boost::make_shared<warp_image_process>(config);
}
<commit_msg>Add process type for getting images from a source<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "registration.h"

#include "crop_image_process.h"
#include "grayscale_process.h"
#include "image_reader_process.h"
#include "image_writer_process.h"
#include "video_reader_process.h"
#include "warp_image_process.h"

#include <vistk/pipeline/process_registry.h>

#include <boost/make_shared.hpp>

/**
 * \file image/registration.cxx
 *
 * \brief Register processes for use.
 */

using namespace vistk;

static process_t create_crop_image_process(config_t const& config);
static process_t create_grayscale_process(config_t const& config);
static process_t create_image_reader_process(config_t const& config);
static process_t create_image_writer_process(config_t const& config);
static process_t create_video_reader_process(config_t const& config);
static process_t create_image_source_process(config_t const& config);
static process_t create_warp_image_process(config_t const& config);

void
register_processes()
{
  static process_registry::module_t const module_name = process_registry::module_t("image_processes");

  process_registry_t const registry = process_registry::self();

  if (registry->is_module_loaded(module_name))
  {
    return;
  }

  registry->register_process("crop_image", "Crop an image to a specific size.", create_crop_image_process);
  registry->register_process("grayscale", "Convert an RGB image into grayscale.", create_grayscale_process);
  registry->register_process("image_reader", "Read images from files given a list of images.", create_image_reader_process);
  registry->register_process("image_writer", "Write images to files.", create_image_writer_process);
  registry->register_process("video_reader", "Reads images from a video.", create_video_reader_process);
  registry->register_process("image_source", "Reads images using different sources.", create_image_source_process);
  registry->register_process("warp_image", "Warps images using tranformation matrices.", create_warp_image_process);

  registry->mark_module_as_loaded(module_name);
}

process_t
create_crop_image_process(config_t const& config)
{
  return boost::make_shared<crop_image_process>(config);
}

process_t
create_grayscale_process(config_t const& config)
{
  return boost::make_shared<grayscale_process>(config);
}

process_t
create_image_reader_process(config_t const& config)
{
  return boost::make_shared<image_reader_process>(config);
}

process_t
create_image_writer_process(config_t const& config)
{
  return boost::make_shared<image_writer_process>(config);
}

process_t
create_video_reader_process(config_t const& config)
{
  return boost::make_shared<video_reader_process>(config);
}

process_t
create_image_source_process(config_t const& config)
{
  static config::key_t const type_key = config::key_t("type");
  static config::value_t const image_list_type = config::value_t("list");
  static config::value_t const vidl_type = config::value_t("vidl");
  static config::value_t const& default_type = image_list_type;

  config::value_t const type_value = config->get_value<config::value_t>(type_key, default_type);

  if (type_value == image_list_type)
  {
    return create_image_reader_process(config);
  }
  else if (type_value == vidl_type)
  {
    return create_video_reader_process(config);
  }

  /// \todo Throw an exception.

  return process_t();
}

process_t
create_warp_image_process(config_t const& config)
{
  return boost::make_shared<warp_image_process>(config);
}
<|endoftext|>